Jolt Physics Documentation

repository·master·Indexed 27 days ago

https://github.com/jrouwe/joltphysics

A high-performance, multi-core optimized rigid body physics and collision detection library designed for modern games and VR applications. It features a deterministic simulation, concurrent access to physics data, and support for a wide range of platforms including Windows, Linux, Android, macOS, iOS, and WebAssembly. The library is written in C++17 and supports various CPU instruction sets such as SSE, AVX, and NEON.

Tokens
20.6K
Snippets
10
Records
106
Agent score
95%

What's inside Jolt Physics

  1. Overview of Jolt Physics

    master
    Jolt Physics is a multi-core friendly rigid body physics and collision detection library designed for games and VR applications. It emphasizes concurrent access to physics data, allowing for background loading/unloading of bodies and parallel collision queries (both broadphase and narrowphase) without locking the main simulation update. The simulation is deterministic, making it suitable for replicating physics states to remote clients.
  2. Understand the Physics Simulation Step

    master

    The PhysicsSystem::Update call executes a job graph to advance the simulation. Key stages include:

    • Broad Phase Update: Refits AABBs and swaps the new tree with the old one.
    • Step Listeners: Calls PhysicsStepListener::OnStep for registered listeners.
    • Apply Gravity: Parallel jobs apply gravity and damping to active bodies.
    • Build Islands: Recreates islands from scratch every step by processing non-contact constraints. If a constraint connects an active and non-active body, the non-active body is woken up.
    • Find Collisions: Performs broad and narrow phase checks. Uses GJK and EPA algorithms to determine contact points and creates contact manifolds. This stage uses a lock-free contact cache.
    • Setup Velocity Constraints: Calculates Jacobians and effective masses for non-contact constraints.
    • Finalize Islands: Finalizes simulation islands so they can be simulated separately in subsequent jobs.
  3. Understand Body types and Motion Properties

    master

    Bodies in Jolt are objects with attached collision shapes. They are categorized by EMotionType:

    • static: Not moving or simulating. To save space, static bodies do not have MotionProperties unless BodyCreationSettings::mAllowDynamicOrKinematic is enabled (allowing them to become dynamic later).
    • dynamic: Moved by forces.
    • kinematic: Moved by velocities only.

    Moving bodies (dynamic and kinematic) utilize a MotionProperties object to track movement information.

  4. Understand Body Sleeping Logic

    master

    To optimize performance, Jolt puts bodies to sleep when they move very little.

    Mechanism:

    • The engine tracks three bounding spheres based on the two largest axes of the shape's local space bounding box and the center of mass (all in world space).
    • If these bounding spheres expand beyond a certain size, the timer resets.
    • If the spheres remain stable for a specific duration, the body is considered non-moving and is put to sleep.
  5. Understand the Physics Simulation Step

    master

    The PhysicsSystem::Update uses a JobSystem to distribute work across multiple CPUs. It employs a Sequential Impulse solver with warm starting.

    Each physics step can be divided into multiple collision steps. For example, running at 60 Hz with 2 collision steps results in the following sequence:

    1. Collision (1/120s)
    2. Integration (1/120s)
    3. Collision (1/120s)
    4. Integration (1/120s)

    The system is generally stable when running at 60 Hz with 1 collision step.

  6. Explore Jolt Physics feature categories in Samples

    master

    The Samples application demonstrates several core physics capabilities:

    • Vehicles: Demonstrates VehicleConstraint using ray- or shape casts for engine, gearbox, differential, and suspension simulation.
    • Rig (Ragdolls): Shows ragdoll creation and control via keyframing or motors (including kinematic ragdolls and skeleton mapping).
    • Soft Body: Simulates cloth and soft balls, including contact listeners, bend constraints (distance and dihedral angle), and skin constraints for skinned meshes.
    • Character: Demonstrates humanoid character simulation using a capsule (movement, sliding, crouching, jumping).
    • Water: Shows buoyancy and friction simulation for various shapes.
    • Constraints: Demonstrates various connection types like Path, Swing-Twist, Gear, Rack and Pinion, and Pulley constraints.
    • General: Covers friction, restitution, damping, gravity modification, continuous collision detection (CCD), and multithreaded island simulation.
    • Shapes & Scaled Shapes: Demonstrates supported shapes and runtime scaling (Uniform, Non-uniform, Mirrored, Inside out).
  7. Manage the Body lifecycle via BodyInterface

    master

    Bodies must be managed through the BodyInterface. You cannot use standard C++ new or delete for bodies.

    Lifecycle steps:

    1. BodyInterface::CreateBody: Construct and initialize a Body object.
    2. BodyInterface::AddBody: Add the body to the PhysicsSystem to participate in simulation.
    3. BodyInterface::RemoveBody: Remove the body from the simulation.
    4. BodyInterface::DestroyBody: Deinitialize and destruct the Body. Note: This does not automatically remove the body from the PhysicsSystem first.

    Batch Operations (Recommended): Always use batching functions when adding many bodies to avoid inefficient broadphase updates or internal node exhaustion:

    • BodyInterface::AddBodiesPrepare: Prepares bodies (can be done on a background thread).
    • BodyInterface::AddBodiesFinalize: Atomically adds all prepared bodies to the system.
    • BodyInterface::AddBodiesAbort: Cancels a pending batch addition.
    • BodyInterface::RemoveBodies: Batch removes multiple bodies.

    If you must add bodies one by one, call PhysicsSystem::OptimizeBroadPhase to rebuild the tree.

  8. Follow Jolt Physics coordinate and unit conventions

    master

    To ensure simulation stability and accuracy, follow these conventions:

    • Coordinate System: Right-handed, Y-up. To use a different up-axis, use PhysicsSystem::SetGravity and wrap shapes like HeightFieldShape in a RotatedTranslatedShape. Specify the new up-axis for VehicleConstraint and CharacterBaseSettings.
    • Math: Uses column-major vectors and matrices. Transformation formula: TransformedPoint = Matrix * Point.
    • Units (SI):
      • Dynamic Objects: Length [0.1, 10] m, Speed [0, 500] m/s, Gravity [0, 10] m/s².
      • Static Objects: Length [0.1, 2000] m.
      • If using different units, scale objects before passing them to the simulation.
  9. Breaking API Changes in v5.5.0

    master

    The following breaking changes were introduced in version 5.5.0:

    • CPU Architecture Bits: JPH_CPU_ADDRESS_BITS has been renamed to JPH_CPU_ARCH_BITS to clarify that it refers to the architecture bits rather than the pointer size.
    • Bounds Querying: BroadPhaseQuery::GetBounds has been added, and PhysicsSystem::GetBounds is now deprecated.
  10. Enable Cross-Platform Determinism

    master

    By default, Jolt is deterministic on the same binary/platform. To achieve cross-platform determinism (e.g., between Windows, Linux, and ARM), you must enable the CROSS_PLATFORM_DETERMINISTIC option in CMake. This incurs an approximately 8% performance penalty.

    Requirements for Cross-Platform Determinism:

    • Use the same source code and the same defines (e.g., do not mix JPH_DOUBLE_PRECISION across platforms).
    • Compile with Precise floating-point mode:
      • Clang: -ffp-model=precise and -ffp-contract=off
      • MSVC: /fp:precise
    • Ensure consistent FPU state: Floating point rounding should be set to 'nearest', and Denormals-Are-Zero (DAZ) and Flush-To-Zero (FTZ) flags must be set consistently.
    • Avoid standard library functions that vary by platform. Use Jolt's replacements:
      • Use Jolt::Sin, Jolt::Cos, etc., instead of std::sin, std::cos.
      • Use Jolt::QuickSort instead of std::sort.
      • Use Jolt::BinaryHeapPush/Pop instead of std::push_heap/pop_heap.
      • Use Jolt::Hash instead of std::hash.

    Non-deterministic elements to watch out for:

    • Broadphase queries (BroadPhaseQuery): Results may vary because the broadphase is modified across multiple threads. To get deterministic results, use a custom CollisionCollector that validates hits against Body::GetWorldSpaceBounds and ensures consistent result ordering.
    • Narrowphase queries (NarrowPhaseQuery): Results are consistent, but the order of received results may change.
    • Listeners: BodyActivationListener, PhysicsStepListener, SoftBodyContactListener, and ContactListener are called from multiple threads; callback order is not guaranteed.
    • PhysicsSystem::GetActiveBodies: Returns bodies in a non-deterministic order.
  11. Manage Sleeping Bodies

    master

    Jolt Physics uses 'islands' to group dynamic bodies in contact or connected by constraints. To conserve CPU, entire islands are put to sleep when all bodies in them come to rest.

    Key Behaviors

    • Waking Up: Sleeping bodies wake up automatically when contacted by non-sleeping objects. You can also wake them explicitly using BodyInterface::ActivateBody.
    • Removing Bodies: Removing a body from the world does not automatically wake up surrounding bodies. To wake them, call BodyInterface::ActivateBodiesInAABox using the bounding box of the removed body.
    • Velocity and Waking: Using Body::SetLinearVelocity will not wake a body. You must use BodyInterface::SetLinearVelocity instead.

    Configuration

    Adjust the definition of a body 'at rest' via PhysicsSettings:

    • PhysicsSettings::mTimeBeforeSleep
    • PhysicsSettings::mPointVelocitySleepThreshold
  12. Breaking API Changes in v5.6.0

    master

    The following breaking changes were introduced in version 5.6.0:

    • Friction Model: The friction model has changed, which may slightly alter simulation results over time. EstimateCollisionResponse now returns 2 linear and 1 angular friction impulse instead of per-contact point friction impulses.
    • Character Virtual Renaming:
      • CharacterVirtual::Contact is now CharacterContact.
      • CharacterVirtual::ContactKey is now CharacterContactKey.
      • CharacterContactListener now receives a full CharacterContact object. When replacing the old inContactNormal parameter, use -inContact.mContactNormal.
    • Soft Body Contact Callbacks: Contacts for bodies with motion quality LinearCast vs a soft body are now properly reported through SoftBodyContactListener instead of the regular ContactListener.
    • HeightFieldShape Serialization (SBS): Support for HeightFieldShapeSettings::mBitsPerSample > 8 was added. This adds 1 byte to the binary serialization format, making it incompatible with previous versions.
    • GPU Compute Shader Support: New interfaces for running compute shaders on DX12, Vulkan, and Metal are available.
      • To disable these, set JPH_USE_DX12, JPH_USE_VK, or JPH_USE_MTL to OFF.
      • macOS Requirement: To build on macOS, you must have dxc and spirv-cross installed (e.g., via the Vulkan SDK).