### Selective State Saving with StateRecorderFilter Source: https://jrouwe.github.io/JoltPhysics/index.html/JoltPhysics Illustrates using a StateRecorderFilter to selectively save physics state, optimizing snapshot size. For example, excluding static or inactive bodies can significantly reduce the data stored. ```c++ class MyStateRecorderFilter : public JPH::StateRecorderFilter { public: bool ShouldSaveBody(const JPH::BodyID& inBodyID) const override { // Example: Don't save static or inactive bodies // return !mPhysicsSystem->IsStatic(inBodyID) && mPhysicsSystem->IsActive(inBodyID); return true; // Default: save all bodies } }; // ... in your simulation setup ... JPH::StateRecorder stateRecorder; MyStateRecorderFilter filter; stateRecorder.SetFilter(&filter); physicsSystem.SaveState(stateRecorder); ``` -------------------------------- ### Registering Collision Detection Functions Source: https://jrouwe.github.io/JoltPhysics/index.html/index This example shows the structure for registering collision detection functions for a custom shape. It involves calling a static registration function after the initial type registration. ```cpp void MyShape::sRegister() { // Ensure this is called after RegisterTypes() // ... registration logic ... } ``` -------------------------------- ### Adjusting Local Bounds to Original Space Source: https://jrouwe.github.io/JoltPhysics/index.html/JoltPhysics Illustrates how to retrieve the local bounds of a shape and then translate them using the shape's Center of Mass (COM) to get the bounds in the original space where the shape was created. This is useful for understanding the shape's extents relative to its initial transformation. ```cpp JPH::AABox shape_bounds = translated_box_shape->GetLocalBounds(); shape_bounds.Translate(translated_box_shape->GetCenterOfMass()); JPH_ASSERT(shape_bounds == JPH::AABox(JPH::Vec3(9, -1, -1), JPH::Vec3(11, 1, 1))); // Now we have the box relative to how we created it ``` -------------------------------- ### Manage Multiple Physics Systems Source: https://jrouwe.github.io/JoltPhysics/index.html/index Illustrates the concept of creating and managing multiple independent Jolt Physics systems. Key restrictions include not sharing bodies or constraints, as BodyIDs are unique per system. However, shapes and certain global factory/utility instances can be shared. ```c++ #include #include #include // Create the first physics system JPH::PhysicsSystem physicsSystem1; physicsSystem1.Init(10000, JPH::BroadPhaseLayerInterface::sDefault, JPH::ObjectLayerPairFilter::sDefault, JPH::BodyFilter::sDefault, JPH::ContactListener::sNull); // Create the second physics system JPH::PhysicsSystem physicsSystem2; physicsSystem2.Init(10000, JPH::BroadPhaseLayerInterface::sDefault, JPH::ObjectLayerPairFilter::sDefault, JPH::BodyFilter::sDefault, JPH::ContactListener::sNull); // Bodies created in physicsSystem1 cannot be shared with physicsSystem2. // However, shapes can be shared: JPH::SphereShapeSettings sphereSettings(1.0f); JPH::Shape::ShapeResult sphereResult = sphereSettings.Create(); JPH::Ref sharedSphere = sphereResult.Get(); // You can get body creation settings from one system and use them to create // a similar body in another system. // JPH::BodyCreationSettings bodySettings = physicsSystem1.GetBody(bodyID1).GetBodyCreationSettings(); // JPH::BodyID bodyID2 = physicsSystem2.GetBodyInterface().CreateBody(bodySettings); // Note: Global instances like Factory::sInstance, PhysicsMaterial::sDefault, // and DebugRenderer::sInstance are shared across all systems. ``` -------------------------------- ### Create Soft Body in Jolt Physics Source: https://jrouwe.github.io/JoltPhysics/index.html/index Illustrates the process of creating a soft body, which involves allocating shared settings, defining creation properties, and then adding the soft body to the simulation world. ```cpp auto* settings = new JPH::SoftBodySharedSettings(); // ... initialize settings (particle positions, constraints) ... JPH::SoftBodyCreationSettings creationSettings; // ... fill in desired properties ... JPH::BodyID softBodyID = bodyInterface.CreateAndAddSoftBody(settings, creationSettings); ``` -------------------------------- ### Physics System Simulation Step (C++) Source: https://jrouwe.github.io/JoltPhysics/index.html/index Outlines the structure of a single physics simulation step, highlighting the use of jobs for parallel processing and the sequential impulse solver. It also details the breakdown into collision and integration phases. ```cpp PhysicsSystem::Update(); // Uses JobSystem // ... internally performs collision and integration steps. ``` -------------------------------- ### Soft Body Contact Validation Callback Source: https://jrouwe.github.io/JoltPhysics/index.html/index Provides an example of overriding the SoftBodyContactListener to validate soft body contacts. This callback allows modification of contact properties like mass and enables sensor contacts before the simulation response. ```cpp class MySoftBodyContactListener : public JPH::SoftBodyContactListener { public: virtual void OnSoftBodyContactValidate( const JPH::SoftBodyContactValidate& inSoftBodyContactValidate) override { // ... specify interaction, override mass, or make sensor ... } // ... other callbacks ... }; ``` -------------------------------- ### Deterministic Updates with Flexible Ordering Source: https://jrouwe.github.io/JoltPhysics/index.html/JoltPhysics Discusses how to achieve deterministic simulation results even when the order of certain operations varies. While strict ordering guarantees determinism, liberties can be taken if the final binary state of the physics system is consistent for each update step. This applies to setting properties like friction or adding bodies. ```c++ // Order doesn't matter for determinism if final state is the same: // BodyA.SetFriction(...); BodyB.SetFriction(...); // vs // BodyB.SetFriction(...); BodyA.SetFriction(...); // Adding bodies A then B is same as B then A if BodyIDs are consistent. ``` -------------------------------- ### CharacterVirtual Collision Query (C++) Source: https://jrouwe.github.io/JoltPhysics/index.html/index Explains how to perform raycasts that include CharacterVirtual objects. Since CharacterVirtual is not a rigid body, standard raycasts do not detect it, requiring a combined approach with NarrowPhaseQuery. ```cpp NarrowPhaseQuery::CastRay(..., collector); character_virtual->GetTransformedShape().CastRay(..., collector); ``` -------------------------------- ### Working with Multiple Physics Systems Source: https://jrouwe.github.io/JoltPhysics/index.html/JoltPhysics Explains how to utilize multiple independent PhysicsSystems concurrently. Key restrictions include not sharing bodies or constraints, as BodyIDs are unique per system. Shapes, however, can be shared. ```c++ // Create multiple physics systems JPH::PhysicsSystem system1; JPH::PhysicsSystem system2; // Bodies cannot be shared between systems. // Shapes can be shared. // To move a body, get its creation settings and recreate it in the other system: // JPH::BodyCreationSettings settings = system1.GetBodyInterface().GetBodyCreationSettings(bodyID); // system2.CreateBody(settings); ``` -------------------------------- ### Ray Casting Collision Detection in Jolt Physics Source: https://jrouwe.github.io/JoltPhysics/index.html/JoltPhysics Demonstrates various methods for casting a ray to detect collisions in Jolt Physics. This can be performed against the world using BroadPhaseQuery or NarrowPhaseQuery, against a transformed shape using TransformedShape, or against a specific shape using Shape::CastRay. ```cpp broadPhaseQuery.CastRay(ray, ...); narrowPhaseQuery.CastRay(ray, ...); transformedShape.CastRay(ray, ...); shape.CastRay(ray, ...); ``` -------------------------------- ### CharacterVirtual Extended Update (C++) Source: https://jrouwe.github.io/JoltPhysics/index.html/index Demonstrates the extended update functionality for CharacterVirtual, which includes features like stair stepping and sticking to slopes. This provides more refined control over character movement on complex terrain. ```cpp character_virtual->ExtendedUpdate(); ``` -------------------------------- ### Character Controller Update (C++) Source: https://jrouwe.github.io/JoltPhysics/index.html/index Demonstrates how to update the Character controller after a physics simulation step. This is crucial for updating ground contacts and ensuring proper character behavior. ```cpp PhysicsSystem::Update(); Character::PostSimulation(); ``` -------------------------------- ### Enable/Disable Constraints in Jolt Physics Source: https://jrouwe.github.io/JoltPhysics/index.html/JoltPhysics Demonstrates how to enable or disable constraints in Jolt Physics. Constraints can be toggled using the SetEnabled method. After each simulation step, the total lambda applied to a constraint should be checked, and the constraint disabled if it exceeds a threshold. ```cpp Constraint::SetEnabled(true); // ... simulation step ... float totalLambda = SliderConstraint::GetTotalLambdaPosition(constraint); if (totalLambda > threshold) { Constraint::SetEnabled(false); } ``` -------------------------------- ### Create Convex Hull Shape - C++ Source: https://jrouwe.github.io/JoltPhysics/index.html/JoltPhysics Demonstrates how to create a convex hull shape using Jolt Physics. It involves defining vertices, creating a ConvexHullShapeSettings object, and then calling the Create method to generate the shape. Error handling for the creation process is also indicated. ```cpp // Shapes are refcounted and can be shared between bodies JPH::Ref shape; // The ShapeSettings object is only required for building the shape, all information is copied into the Shape class { // Create an array of vertices JPH::Array vertices = { ... }; // Create the settings object for a convex hull JPH::ConvexHullShapeSettings settings(vertices, JPH::cDefaultConvexRadius); // Create shape JPH::Shape::ShapeResult result = settings.Create(); if (result.IsValid()) shape = result.Get(); else ... // Error handling } ``` -------------------------------- ### Activate Body in Jolt Physics Source: https://jrouwe.github.io/JoltPhysics/index.html/index Demonstrates how to wake up a specific body or bodies within a given area using the BodyInterface API. This is useful after removing bodies or when external forces might not automatically trigger a wake-up. ```cpp bodyInterface.ActivateBody(bodyID); // Or activate bodies within a bounding box bodyInterface.ActivateBodiesInAABox(aabb); // Setting linear velocity also requires BodyInterface bodyInterface.SetLinearVelocity(bodyID, velocity); ``` -------------------------------- ### Creating a Sensor Body Source: https://jrouwe.github.io/JoltPhysics/index.html/index This code demonstrates how to create a sensor body in Jolt Physics. Sensors detect contacts but do not resolve them, useful for triggers. This can be done during body creation or after. ```cpp // During creation: BodyCreationSettings settings; settings.mIsSensor = true; // After creation: Body* body = BodyInterface::CreateBody(settings); body->SetIsSensor(true); ``` -------------------------------- ### Driving Character Kinematically (C++) Source: https://jrouwe.github.io/JoltPhysics/index.html/index Illustrates the common method of driving character controllers kinematically by setting their linear velocity before the physics update. This approach is typical for player-controlled characters. ```cpp character->SetLinearVelocity(new_velocity); // or character_virtual->SetLinearVelocity(new_velocity); ``` -------------------------------- ### Save and Load Shape in Binary Format (C++) Source: https://jrouwe.github.io/JoltPhysics/index.html/JoltPhysics Demonstrates how to serialize a JoltPhysics shape (e.g., a sphere) into a binary stream and then deserialize it back. It utilizes StreamOutWrapper and StreamInWrapper for handling binary data and ShapeToIDMap/MaterialToIDMap for efficient saving of shared shapes. Error handling for deserialization is also included. ```cpp // Create a sphere of radius 1 JPH::Ref sphere = new JPH::SphereShape(1.0f); // For this example we'll be saving the shape in a STL string stream, but if you implement StreamOut you don't have to use STL. // Note that this will be storing a binary string of bytes that can contain 0-bytes, it is not an ASCII string! stringstream data; JPH::StreamOutWrapper stream_out(data); // Save the shape (note this function handles CompoundShape too). // The maps are there to avoid saving the same shape twice (it will assign an ID to each shape the first time it encounters them). // If you don't want certain shapes to be saved, add them to the map and give them an ID. // You can save many shapes to the same stream by repeatedly calling SaveWithChildren on different shapes. JPH::Shape::ShapeToIDMap shape_to_id; JPH::Shape::MaterialToIDMap material_to_id; sphere->SaveWithChildren(stream_out, shape_to_id, material_to_id); // Wrap the STL stream in a StreamIn JPH::StreamInWrapper stream_in(data); // Load the shape // If you have assigned custom ID's on save, you need to ensure that the shapes exist in this map on restore too. JPH::Shape::IDToShapeMap id_to_shape; JPH::Shape::IDToMaterialMap id_to_material; JPH::Shape::ShapeResult result = JPH::Shape::sRestoreWithChildren(stream_in, id_to_shape, id_to_material); JPH::Ref restored_shape; if (result.IsValid()) restored_shape = result.Get(); else ... // Error handling ``` -------------------------------- ### Create Body with Specific ID Source: https://jrouwe.github.io/JoltPhysics/index.html/index Shows how to create a physics body with a pre-defined ID. This is important for ensuring BodyIDs are consistent across networked simulations, which is necessary for compatible save state snapshots when rolling back. ```c++ #include #include #include // Assuming 'physicsSystem' is a valid Jolt PhysicsSystem instance // Assuming 'bodyInterface' is physicsSystem->GetBodyInterface() JPH::BodyID bodyID; JPH::BodyCreationSettings settings; // ... configure settings (e.g., shape, mass, position) ... // Create a body with a specific ID bodyID = bodyInterface.CreateBodyWithID(123, settings); // 123 is the desired BodyID // If you need to remove and re-add a body to maintain its ID during rollback: // bodyInterface.DestroyBody(bodyID); // bodyID = bodyInterface.CreateBodyWithID(bodyID, settings); // Re-create with the same ID ``` -------------------------------- ### Breakable Constraints Source: https://jrouwe.github.io/JoltPhysics/index.html/index Information on how to manage breakable constraints based on applied lambda values. ```APIDOC ## Breakable Constraints Constraints can be turned on / off by calling `Constraint::SetEnabled`. After every simulation step, check the total 'lambda' applied on each constraint and disable the constraint if the value goes over a certain threshold. Use e.g. `SliderConstraint::GetTotalLambdaPosition` / `HingeConstraint::GetTotalLambdaRotation`. You can see 'lambda' as the linear/angular impulse applied at the constraint in the last physics step to keep the constraint together. ``` -------------------------------- ### Creating a Sensor Body Source: https://jrouwe.github.io/JoltPhysics/index.html/JoltPhysics Sets a body to function as a sensor. Sensors detect collisions but do not resolve them, making them suitable for triggers. This can be done during body creation or after. ```cpp BodyCreationSettings::mIsSensor = true; // or Body::SetIsSensor(true); ``` -------------------------------- ### Soft Body Contact Inspection Callback Source: https://jrouwe.github.io/JoltPhysics/index.html/index Demonstrates how to use the SoftBodyContactListener::OnSoftBodyContactAdded callback to inspect collisions after the simulation step. It shows how to iterate through collided vertices and their contact information. ```cpp class MySoftBodyContactListener : public JPH::SoftBodyContactListener { public: virtual void OnSoftBodyContactAdded( const JPH::SoftBodyContactAdded& inSoftBodyContactAdded) override { for (const JPH::SoftBodyManifold::SubManifest& subManifest : inSoftBodyContactAdded.mSubManifests) { // ... loop over vertices and inspect collisions ... } } // ... other callbacks ... }; ``` -------------------------------- ### CharacterVirtual Update (C++) Source: https://jrouwe.github.io/JoltPhysics/index.html/index Shows the basic update call for the CharacterVirtual class. This class uses collision detection and applies impulses, offering more advanced features than the basic Character class. ```cpp character_virtual->Update(); ``` -------------------------------- ### Managing Constraints for Determinism Source: https://jrouwe.github.io/JoltPhysics/index.html/JoltPhysics Details how constraint ordering affects determinism and serialization. For consistent results, ConstraintSettings::mConstraintPriority should be unique. If PhysicsSystem::SaveState is used, constraints must be handled manually via Constraint::SaveState/RestoreState. ```c++ // Ensure unique mConstraintPriority for all constraints // Example: // constraintSettings.mConstraintPriority = 1; // otherConstraintSettings.mConstraintPriority = 2; // Manual constraint state handling if not using EStateRecorderState::Constraints: // constraint->SaveState(...); // ... restore ... // constraint->RestoreState(...); ``` -------------------------------- ### Multithreaded Body Access with Locking Interface (C++) Source: https://jrouwe.github.io/JoltPhysics/index.html/JoltPhysics Demonstrates how to safely access and read body data from multiple threads using Jolt Physics' locking interface. It shows how to obtain a lock, check for success, and retrieve a const reference to the body. This prevents race conditions when other threads might modify or remove the body. ```cpp JPH::BodyLockInterface lock_interface = physics_system.GetBodyLockInterface(); // Or GetBodyLockInterfaceNoLock JPH::BodyID body_id = ...; // Obtain ID to body // Scoped lock { JPH::BodyLockRead lock(lock_interface, body_id); if (lock.Succeeded()) // body_id may no longer be valid { const JPH::Body &body = lock.GetBody(); // Do something with body ... } } ``` -------------------------------- ### Collision Detection Interfaces Source: https://jrouwe.github.io/JoltPhysics/index.html/index Overview of the different interfaces used for collision detection in Jolt Physics. ```APIDOC ## Collision Detection Collision detection can be performed through various interfaces: * **Coarse collision detection** against the world, using only the bounding box of each body is done through the `BroadPhaseQuery` interface (see `PhysicsSystem::GetBroadPhaseQuery`). * **Detailed collision detection** against the world is done through `NarrowPhaseQuery` interface (see `PhysicsSystem::GetNarrowPhaseQuery`). * **Checking collisions with a single body** is done through `TransformedShape` (see `Body::GetTransformedShape`). * **Checking collisions against a single shape** is done through various interfaces on the `Shape` class (see e.g. `Shape::CastRay`) or through the `CollisionDispatch` interface. The most common collision tests are: * **Casting a ray**: `BroadPhaseQuery::CastRay`, `NarrowPhaseQuery::CastRay`, `TransformedShape::CastRay`, `Shape::CastRay`. * **Colliding a shape** (e.g. a sphere) in a static position: `NarrowPhaseQuery::CollideShape`, `TransformedShape::CollideShape`, `CollisionDispatch::sCollideShapeVsShape`. * **Casting a shape** (sweeping it from a start to an end position and finding collisions along the way): `NarrowPhaseQuery::CastShape`, `TransformedShape::CastShape`, `CollisionDispatch::sCastShapeVsShapeWorldSpace`. * **Checking if a shape contains a point**: `BroadPhaseQuery::CollidePoint`, `NarrowPhaseQuery::CollidePoint`, `TransformedShape::CollidePoint`, `Shape::CollidePoint`. The following sections describe the collision detection system in more detail. ```