Getting Started with Physics
This guide demonstrates adding physics simulation to entities using the Astralix physics module powered by PhysX.
Creating Dynamic Objects
Add physics to a falling box:
#include <astralix/physics.hpp>
// Create entity
EntityID box = entity_manager().create_entity();
// Add transform
auto& transform = box->add_component<TransformComponent>();
transform.position = glm::vec3(0, 10, 0);
transform.rotation = glm::quat(1, 0, 0, 0);
transform.scale = glm::vec3(1, 1, 1);
// Add rigid body (dynamic) with parameters: rigid_type, gravity, velocity, acceleration, drag, mass
auto& rb = box->add_component<RigidBodyComponent>(
RigidType::Dynamic, // rigid_type
0.5f, // gravity
2.0f, // velocity
2.0f, // acceleration
0.0f, // drag
1.0f // mass (note: currently hardcoded to 10.0f in implementation)
);
// Add mesh collision (creates AABB box from mesh bounds)
auto& collision = box->add_component<MeshCollisionComponent>();
// Vertices will be populated from mesh dataCreating Static Colliders
Create a static ground plane:
EntityID ground = entity_manager().create_entity();
auto& transform = ground->add_component<TransformComponent>();
transform.position = glm::vec3(0, 0, 0);
// Add rigid body (static) - only rigid_type parameter is required for static bodies
auto& rb = ground->add_component<RigidBodyComponent>(
RigidType::Static // rigid_type
);
// Add mesh collision component
auto& collision = ground->add_component<MeshCollisionComponent>();
// Collision shape is automatically generated from mesh boundsPhysics Simulation Control
The physics simulation can be toggled on and off:
// Physics simulation is off by default
// Press F4 to toggle simulation on/off
// The simulation state is controlled internally by the PhysicsSystem
// When enabled, it runs at a fixed timestep during fixed_update()Note: Direct force/impulse application API is not currently exposed. Physics updates are handled automatically by the PhysicsSystem based on component properties.
Collision Detection
The physics module provides GJK-based collision detection through MeshCollisionComponent:
// Get collision components
auto* collision_a = entity_a->get_component<MeshCollisionComponent>();
auto* collision_b = entity_b->get_component<MeshCollisionComponent>();
// Check AABB intersection (fast broad-phase)
if (collision_a->aabb_intersect(collision_b)) {
// Check precise collision using GJK algorithm
if (collision_a->has_intersect(collision_b)) {
// Entities are colliding
std::cout << "Collision detected!" << std::endl;
}
}Note: Raycasting API is not currently implemented. Collision detection uses the GJK (Gilbert-Johnson-Keerthi) algorithm with AABB broad-phase.
Transform Synchronization
The PhysicsSystem automatically synchronizes between TransformComponent and PhysX actors:
// TransformComponent changes are synced to PhysX actors in pre_update()
auto& transform = entity->get_component<TransformComponent>();
transform.position = glm::vec3(10, 5, 0);
transform.rotation = glm::quat(1, 0, 0, 0);
// After simulation, PhysX results are synced back to TransformComponent in fixed_update()
// The system uses a dirty flag to avoid unnecessary updatesNote: Character controller and ground detection are not currently implemented. Direct impulse/force APIs are not exposed.
PhysX Visual Debugger (PVD)
The PhysicsSystem supports PhysX Visual Debugger for real-time simulation inspection:
// Configure PVD connection in PhysicsSystemConfig
PhysicsSystemConfig config;
config.pvd_host = "127.0.0.1";
config.pvd_port = 5425;
config.pvd_timeout = 10;
// PVD connection is established during PhysicsSystem initialization
// Connect with PhysX Visual Debugger tool to inspect simulation stateNote: Collision callbacks (OnCollisionEnter/Exit, OnTriggerEnter/Exit) are not currently implemented.
Math Type Conversions
The physics module provides conversion utilities between GLM and PhysX types:
#include <astralix/physics/utils/math.hpp>
// GLM to PhysX
glm::vec3 glm_position(1.0f, 2.0f, 3.0f);
physx::PxVec3 px_position = GlmVec3ToPxVec3(glm_position);
glm::quat glm_rotation(1.0f, 0.0f, 0.0f, 0.0f);
physx::PxQuat px_rotation = GlmQuatToPxQuat(glm_rotation);
glm::mat4 glm_transform(1.0f);
physx::PxMat44 px_transform = GlmMat4ToPxMat44(glm_transform);
// PhysX to GLM
glm::mat4 result_transform = PxMat44ToGlmMat4(px_transform);
glm::quat result_rotation = PxQuatToGlmQuat(px_rotation);Physics System Configuration
Configure the physics system via PhysicsSystemConfig:
PhysicsSystemConfig config;
// Backend selection (e.g., "PhysX")
config.backend = "PhysX";
// Gravity vector
config.gravity = glm::vec3(0, -9.81f, 0);
// PhysX Visual Debugger settings
config.pvd_host = "127.0.0.1";
config.pvd_port = 5425;
config.pvd_timeout = 10;
// Create physics system with config
auto physics_system = PhysicsSystem(config);Implementation details:
- CPU dispatcher uses 2 threads (hardcoded)
- Default material properties: 0.5 static friction, 0.5 dynamic friction, 0.6 restitution
- Simulation is off by default; toggle with F4 key
Collision Shape Details
MeshCollisionComponent creates axis-aligned bounding box (AABB) collision shapes:
// Add mesh collision component
auto& collision = entity->add_component<MeshCollisionComponent>();
// Populate vertices from mesh data
collision.vertices = mesh->get_vertices();
// The component will:
// 1. Calculate AABB from vertices
// 2. Create PhysX box geometry from bounds
// 3. Attach shape to rigid body with material propertiesCurrent limitations:
- Only box collision shapes are supported (generated from mesh AABB)
- No sphere, capsule, or custom mesh colliders
- Trigger volumes are not implemented
Component Serialization
Both physics components support serialization:
#include <astralix/physics/components/rigidbody/serializers/rigidbody-component-serializer.hpp>
#include <astralix/physics/components/mesh-collision/serializers/mesh-collision-component-serializer.hpp>
// Create serializers
auto rb_serializer = RigidBodyComponentSerializer(rigidbody_component);
auto collision_serializer = MeshCollisionComponentSerializer(mesh_collision_component);
// Serialize components
rb_serializer.serialize();
collision_serializer.serialize();
// Deserialize components
rb_serializer.deserialize();
collision_serializer.deserialize();Note: Serializer implementations are currently stubs with empty deserialize() methods.
Known Issues
- Mass parameter ignored: RigidBodyComponent constructor accepts a mass parameter, but the implementation hardcodes 10.0f when calling PxRigidBodyExt::updateMassAndInertia()
- AABB bug: The aabb_intersect() logic appears inverted (returns false on intersection, true on no intersection)
- Commented gravity: RigidBodyComponent::update() has gravity application code commented out
Next Steps
- Review Physics Overview for architecture details
- Explore PhysX documentation for underlying simulation details
- See PhysX Visual Debugger for debugging tools