Skip to content

Physics Overview

The Physics module integrates NVIDIA PhysX to provide rigid body dynamics and collision detection in Astra.

Architecture

PhysicsSystem is the sole entry point for the physics module. It owns the PhysX globals directly - there is no intermediate PhysicsWorld wrapper.

ECS Integration

Physics components integrate with the engine's ECS:

Simulation Loop

PhysicsSystem::fixed_update(double fixed_dt) receives a pre-computed fixed delta from the engine layer. This module does not manage a timestep accumulator.

Simulation is off by default (gSimulate = false). Press F4 at runtime to toggle it on or off.

Configuration

PhysicsSystem is constructed from a PhysicsSystemConfig, which is defined in the project module:

cpp
struct PhysicsSystemConfig {
  std::string backend;
  glm::vec3   gravity;
  std::string pvd_host    = "127.0.0.1";
  int         pvd_port;
  int         pvd_timeout = 5;
};
  • backend - reserved for future multi-backend support; currently unused at runtime.
  • gravity - scene gravity vector passed directly to PxSceneDesc.
  • pvd_host, pvd_port, pvd_timeout - connection parameters for NVIDIA PhysX Visual Debugger (PVD).

Component Types

RigidBodyComponent

Attaches a PhysX actor to an entity and controls its physics behaviour.

cpp
enum RigidType { Static = 0, Dynamic = 1 };

class RigidBodyComponent : public Component<RigidBodyComponent> {
public:
  RigidBodyComponent(COMPONENT_INIT_PARAMS,
    RigidType rigid_type   = RigidType::Dynamic,
    float     gravity      = 0.5f,
    float     velocity     = 2.0f,
    float     acceleration = 2.0f,
    float     drag         = 0.0f,
    float     mass         = 1.0f);

private:
  float     velocity;
  float     gravity;
  float     drag;
  float     mass;
  float     acceleration;
  RigidType m_rigid_type;
};
  • RigidType::Static - creates a PxRigidStatic; the actor does not move under simulation.
  • RigidType::Dynamic - creates a PxRigidDynamic; the actor is fully simulated.

INFO

There is no Kinematic body type. RigidBodyComponent::update() is currently a no-op; per-frame force/gravity application via this component is not active.

MeshCollisionComponent

Computes an AABB from the entity's MeshComponent vertex data and attaches a PxBoxGeometry shape to the PhysX actor owned by RigidBodyComponent. Collision shapes are always axis-aligned bounding boxes derived from mesh bounds - there are no selectable shape types and no trigger flag.

cpp
class MeshCollisionComponent : public Component<MeshCollisionComponent> {
public:
  MeshCollisionComponent(COMPONENT_INIT_PARAMS);

  void attach_shape(physx::PxRigidActor* body,
                    glm::mat4 transform_matrix,
                    physx::PxPhysics* physics);

  bool aabb_intersect(MeshCollisionComponent* other);
  bool has_intersect(MeshCollisionComponent* other);

  std::vector<glm::vec3> vertices;
};

attach_shape iterates over all mesh vertices, computes the AABB extents scaled by the entity's transform, then creates and attaches a PxBoxGeometry shape with a local pose offset to the mesh center.

aabb_intersect performs a coarse AABB overlap test. has_intersect runs a full GJK (Gilbert-Johnson-Keerthi) algorithm using the Minkowski difference of both components' vertex sets. Neither method produces event callbacks - overlap results are returned as booleans only.

Collision Detection

Collision detection in this module operates at two levels:

  1. PhysX simulation - PxScene::simulate handles contact resolution between actors that have shapes attached via MeshCollisionComponent::attach_shape.
  2. GJK overlap queries - MeshCollisionComponent::has_intersect provides an independent GJK-based boolean overlap test using stored vertices. This does not fire any engine events.

There are no OnTriggerEnter, OnTriggerExit, OnCollisionEnter, or OnCollisionExit callbacks. Collision event notifications are not implemented.

Key Responsibilities

  • Simulation - Step the PhysX scene at a fixed rate when gSimulate is true.
  • Collision Detection - Detect overlaps via PhysX contact resolution and GJK queries.
  • Transform Sync - Synchronize ECS TransformComponent data with PhysX actor poses in both directions.

Known Limitations

  • Hardcoded mass: RigidBodyComponent::start() ignores the mass parameter and uses a hardcoded value of 10.0f for PxRigidBodyExt::updateMassAndInertia().
  • Hardcoded material: create_box_shape() uses fixed material properties (0.5f static friction, 0.5f dynamic friction, 0.6f restitution) for all shapes.
  • AABB bug: aabb_intersect() has inverted logic - returns false on intersection, true on no intersection.
  • Commented update logic: RigidBodyComponent::update() exists but its gravity application code is commented out; the component does not apply forces per-frame.

Integration Points

  • Engine - Provides ECS for components and systems; drives fixed_update calls with a pre-computed delta.
  • Project - Supplies PhysicsSystemConfig (gravity, PVD settings).
  • Editor - Can toggle simulation at runtime via the F4 key.

For detailed implementation, see Physics Core Concepts.