JoltPhysics Agent Skills & AI Rules

GitHub

A multi core friendly rigid body physics and collision detection library. Written in C++. Suitable for games and VR applications.

RAW Rules
1 Discovered Rules โ€ข ~11,101 Estimated Tokens
Loading skill content...

Docs - System Architecture & Module Boundaries

Docs/Architecture.md project-spec ~11,101 tokens
Raw
# Architecture of Jolt Physics {#architecture-jolt-physics}

# Getting Started {#getting-started}

To get started, look at the [HelloWorld](https://github.com/jrouwe/JoltPhysics/blob/master/HelloWorld/HelloWorld.cpp) example. A [HelloWorld example using CMake FetchContent](https://github.com/jrouwe/JoltPhysicsHelloWorld) is also available to show how you can integrate Jolt Physics in a CMake project.

Every feature in Jolt has its own sample. [Running the Samples application](Samples.md) and browsing through the [code](https://github.com/jrouwe/JoltPhysics/tree/master/Samples/Tests) is a great way to learn about the library!

The rest of this document describes the concepts used in Jolt in more detail.

# Bodies {#bodies}

We use a pretty traditional physics engine setup, so \ref Body "bodies" in our simulation are objects which have attached collision \ref Shape "shapes"

## Types {#body-types}

Bodies can either be:
- [static](@ref EMotionType) (not moving or simulating)
- [dynamic](@ref EMotionType) (moved by forces) or
- [kinematic](@ref EMotionType) (moved by velocities only).

Moving bodies have a [MotionProperties](@ref MotionProperties) object that contains information about the movement of the object. Static bodies do not have this to save space (but they can be configured to have it if a static body needs to become dynamic during its lifetime by setting [BodyCreationSettings::mAllowDynamicOrKinematic](@ref BodyCreationSettings::mAllowDynamicOrKinematic)).

## Creating Bodies {#creating-bodies}

Bodies are inserted into the [PhysicsSystem](@ref PhysicsSystem) and interacted with through the [BodyInterface](@ref BodyInterface).

The general life cycle of a body is:

- BodyInterface::CreateBody - Construct a Body object and initialize it. You cannot use `new` to create a Body.
- BodyInterface::AddBody - Add the body to the PhysicsSystem and make it participate in the simulation.
- BodyInterface::RemoveBody - Remove it from the PhysicsSystem.
- BodyInterface::DestroyBody - Deinitialize and destruct the Body. You cannot use `delete` to delete a Body. This function will not automatically remove the Body from the PhysicsSystem.

If you need to add many bodies at the same time then use the batching functions:

- BodyInterface::AddBodiesPrepare - Prepares bodies to be added to the PhysicsSystem. Doesn't affect simulation and can be done from a background thread.
- BodyInterface::AddBodiesFinalize - Finalize insertion. This atomically adds all bodies to the PhysicsSystem.
- BodyInterface::AddBodiesAbort - If you've called AddBodiesPrepare but changed your mind and no longer want to add the bodies to the PhysicsSystem. Useful when streaming in level sections and the player decides to go the other way.
- BodyInterface::RemoveBodies - Batch remove a lot of bodies from the PhysicsSystem.

Always use the batch adding functions when possible! Adding many bodies, one at a time, results in a really inefficient broadphase (a trace will notify when this happens) and in extreme cases may lead to the broadphase running out of internal nodes (std::abort will be called in that case). If you cannot avoid adding many bodies one at a time, use PhysicsSystem::OptimizeBroadPhase to rebuild the tree.

You can call AddBody, RemoveBody, AddBody, RemoveBody to temporarily remove and later reinsert a body into the simulation.

## Mass Properties {#mass-properties}

By default, the mass and inertia of a body are automatically calculated from its shape and density. This behavior is controlled by [BodyCreationSettings::mOverrideMassProperties](@ref BodyCreationSettings::mOverrideMassProperties) (see [EOverrideMassProperties](@ref EOverrideMassProperties)):

* EOverrideMassProperties::CalculateMassAndInertia (default) - Both mass and inertia are derived from the shape density.
* EOverrideMassProperties::CalculateInertia - The mass is taken from [BodyCreationSettings::mMassPropertiesOverride](@ref BodyCreationSettings::mMassPropertiesOverride).mMass and the inertia is calculated from the shape density and then scaled to match the provided mass.
* EOverrideMassProperties::MassAndInertiaProvided - Both mass and inertia are taken directly from [BodyCreationSettings::mMassPropertiesOverride](@ref BodyCreationSettings::mMassPropertiesOverride). This is required for shapes that cannot compute their own mass and inertia, such as [MeshShape](@ref MeshShape).

The [BodyCreationSettings::mInertiaMultiplier](@ref BodyCreationSettings::mInertiaMultiplier) can be used to scale the calculated inertia tensor. A value larger than 1 makes the body harder to rotate (as if mass is distributed further from the center), and a value smaller than 1 makes it easier to rotate. This applies whenever the inertia is computed by the system (i.e. not when `MassAndInertiaProvided` is used).

Creating a dynamic mesh body with explicit mass and inertia:

	JPH::BodyCreationSettings settings(mesh_shape, position, rotation, JPH::EMotionType::Dynamic, layer);
	settings.mOverrideMassProperties = JPH::EOverrideMassProperties::MassAndInertiaProvided;
	settings.mMassPropertiesOverride.mMass = 100.0f;
	settings.mMassPropertiesOverride.mInertia = JPH::Mat44::sScale(10.0f); // Diagonal inertia tensor

Using the shape's inertia but scaling it up to make a body more resistant to rotation:

	JPH::BodyCreationSettings settings(shape, position, rotation, JPH::EMotionType::Dynamic, layer);
	settings.mInertiaMultiplier = 2.0f; // Twice the resistance to rotation

## Degrees of Freedom {#degrees-of-freedom}

By default, dynamic and kinematic bodies are free to translate and rotate along all three world-space axes. You can restrict this using [BodyCreationSettings::mAllowedDOFs](@ref BodyCreationSettings::mAllowedDOFs) which takes a combination of flags from [EAllowedDOFs](@ref EAllowedDOFs):

* EAllowedDOFs::TranslationX, EAllowedDOFs::TranslationY, EAllowedDOFs::TranslationZ - Allow translation along the respective world-space axis.
* EAllowedDOFs::RotationX, EAllowedDOFs::RotationY, EAllowedDOFs::RotationZ - Allow rotation around the respective world-space axis.
* EAllowedDOFs::All (default) - All six degrees of freedom are allowed.
* EAllowedDOFs::Plane2D - A preset equivalent to `TranslationX | TranslationY | RotationZ`, which constrains the body to move in the XY plane and rotate only around the Z axis. Useful for 2D simulations.

Note that EAllowedDOFs::None is not valid and will crash. Use a static body instead.

## Friction and Restitution {#friction-and-restitution}

Each body has a friction and a restitution value, set through [BodyCreationSettings::mFriction](@ref BodyCreationSettings::mFriction) and [BodyCreationSettings::mRestitution](@ref BodyCreationSettings::mRestitution). Both are dimensionless numbers, usually in the range [0, 1]:

* Friction - Controls how much a body resists sliding against another surface. A value of 0 means no friction (perfectly slippery), and a value of 1 means the friction force equals the normal force pressing the two bodies together.
* Restitution - Controls how elastic (bouncy) a collision is. A value of 0 means a completely inelastic collision (no bounce), and a value of 1 means a completely elastic collision (full bounce).

Note that bodies can have negative friction or restitution values, but the *combined* value (see below) should never go below zero.

When two bodies collide, their individual friction and restitution values are combined into a single value using a combine function. The defaults are:

* Friction - Geometric mean (`sqrt(friction1 * friction2)`)
* Restitution - Maximum (`max(restitution1, restitution2)`)

You can override these defaults per `PhysicsSystem` using [PhysicsSystem::SetCombineFriction](@ref PhysicsSystem::SetCombineFriction) and [PhysicsSystem::SetCombineRestitution](@ref PhysicsSystem::SetCombineRestitution). The combine function receives both bodies and their sub shape IDs (an indication of where the contact was), so you can implement per-material behavior:

	physics_system.SetCombineFriction([](const JPH::Body &inBody1, const JPH::SubShapeID &, const JPH::Body &inBody2, const JPH::SubShapeID &)
	{
		// Use the minimum friction of the two bodies instead of the geometric mean
		return min(inBody1.GetFriction(), inBody2.GetFriction());
	});

Friction and restitution can be changed after body creation using [BodyInterface::SetFriction](@ref BodyInterface::SetFriction) and [BodyInterface::SetRestitution](@ref BodyInterface::SetRestitution).

To vary friction or restitution per triangle of a [MeshShape](@ref MeshShape) see the following [example](https://github.com/jrouwe/JoltPhysics/blob/master/Samples/Tests/General/FrictionPerTriangleTest.cpp).

## Linear and Angular Damping {#linear-and-angular-damping}

Damping gradually reduces the velocity of a body over time, simulating energy loss due to air resistance or internal friction. It is applied every simulation step, independently of any contact or constraint forces.

Two damping coefficients are available on [BodyCreationSettings](@ref BodyCreationSettings):

* [mLinearDamping](@ref BodyCreationSettings::mLinearDamping) - Reduces linear velocity according to `dv/dt = -c * v`.
* [mAngularDamping](@ref BodyCreationSettings::mAngularDamping) - Reduces angular velocity according to `dw/dt = -c * w`.

Both values must be zero or positive and are usually close to 0. A value of 0 disables the respective damping entirely. Higher values cause the body to slow down more quickly.

These can be changed after body creation using [MotionProperties::SetLinearDamping](@ref MotionProperties::SetLinearDamping) and [MotionProperties::SetAngularDamping](@ref MotionProperties::SetAngularDamping), accessed via [Body::GetMotionProperties](@ref Body::GetMotionProperties).

Creating a body that comes to rest quickly and does not spin for long:

	JPH::BodyCreationSettings settings(shape, position, rotation, JPH::EMotionType::Dynamic, layer);
	settings.mLinearDamping = 0.2f;
	settings.mAngularDamping = 0.5f;

Note that damping is a simple exponential decay and is not physically based.

## Multithreaded Access {#multi-threaded-access}

Jolt is designed to be accessed from multiple threads so the body interface comes in two flavors: A locking and a non-locking variant. The locking variant uses a mutex array (a fixed size array of mutexes, bodies are associated with a mutex through hashing and multiple bodies use the same mutex, see [MutexArray](@ref MutexArray)) to prevent concurrent access to the same body. The non-locking variant doesn't use mutexes, so requires the user to be careful.

In general, body ID's ([BodyID](@ref BodyID)) are used to refer to bodies. You can access a body through the following construct:

	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
			...
		}
	}

When another thread has removed the body between the time the body ID was obtained and the lock, the lock will fail. While the lock is taken, other threads cannot modify the body, so it is safe to work with it. Each body ID contains a sequence number, so body ID's will only be reused after many add/remove cycles. To write to a body use [BodyLockWrite](@ref BodyLockWrite).

You cannot use BodyLockRead to lock multiple bodies (if two threads lock the same bodies in opposite order you'll get a deadlock). Use [BodyLockMultiRead](@ref BodyLockMultiRead) or [BodyLockMultiWrite](@ref BodyLockMultiWrite) to lock them in a consistent order.

Note that a lot of convenience functions are exposed through the BodyInterface, but not all functionality is available, so you may need to lock the body to get the pointer and then call the function directly on the body.

## Single Threaded Access {#single-threaded-access}

If you're only accessing the physics system from a single thread, you can use Body pointers instead of BodyID's. In this case you can also use the non-locking variant of the body interface.

Note that there are still some restrictions:

* You cannot read from / write to bodies or constraints while PhysicsSystem::Update is running. As soon as the Update starts, all body / constraint mutexes are locked.
* Collision callbacks (see ContactListener, SoftBodyContactListener) are called from within the PhysicsSystem::Update call from multiple threads. You can only read the body data during a callback.
* Activation callbacks (see BodyActivationListener) are called in the same way. Again you should only read the body during the callback and not make any modifications.
* Step callbacks (see PhysicsStepListener) are also called from PhysicsSystem::Update from multiple threads. You're responsible for making sure that there are no race conditions. In a step listener you can read/write bodies or constraints but you cannot add/remove them.

If you are accessing the physics system from multiple threads, you should probably use BodyID's and the locking variant of the body interface. It is however still possible to use Body pointers if you're really careful. E.g. if there is a clear owner of a Body and you ensure that this owner does not read/write state during PhysicsSystem::Update or while other threads are reading the Body there will not be any race conditions.

## Shapes {#shapes}

Each body has a shape attached that determines the collision volume. The following shapes are available (in order of computational complexity):

* [SphereShape](@ref SphereShape) - A sphere centered around zero.
* [BoxShape](@ref BoxShape) - A box centered around zero.
* [CapsuleShape](@ref CapsuleShape) - A capsule centered around zero.
* [TaperedCapsuleShape](@ref TaperedCapsuleShape) - A capsule with different radii at the bottom and top.
* [CylinderShape](@ref CylinderShape) - A cylinder shape. Note that cylinders are the least stable of all shapes, so use another shape if possible.
* [TaperedCylinderShape](@ref TaperedCylinderShape) - A cylinder with different radii at the bottom and top. Note that cylinders are the least stable of all shapes, so use another shape if possible.
* [ConvexHullShape](@ref ConvexHullShape) - A convex hull defined by a set of points.
* [TriangleShape](@ref TriangleShape) - A single triangle. Use a MeshShape if you have multiple triangles.
* [PlaneShape](@ref PlaneShape) - An infinite plane. Negative half space is considered solid.
* [StaticCompoundShape](@ref StaticCompoundShape) - A shape containing other shapes. This shape is constructed once and cannot be changed afterwards. Child shapes are organized in a tree to speed up collision detection.
* [MutableCompoundShape](@ref MutableCompoundShape) - A shape containing other shapes. This shape can be constructed/changed at runtime and trades construction time for runtime performance. Child shapes are organized in a list to make modification easy.
* [MeshShape](@ref MeshShape) - A shape consisting of triangles. They are mostly used for static geometry.
* [HeightFieldShape](@ref HeightFieldShape) - A shape consisting of NxN points that define the height at each point, very suitable for representing hilly terrain. Any body that uses this shape needs to be static.
* [EmptyShape](@ref EmptyShape) - A shape that collides with nothing and that can be used as a placeholder or for dummy bodies.

Next to this there are a number of decorator shapes that change the behavior of their children:

* [ScaledShape](@ref ScaledShape) - This shape can scale a child shape. Note that if a shape is rotated first and then scaled, you can introduce shearing which is not supported by the library.
* [RotatedTranslatedShape](@ref RotatedTranslatedShape) - This shape can rotate and translate a child shape, it can e.g. be used to offset a sphere from the origin.
* [OffsetCenterOfMassShape](@ref OffsetCenterOfMassShape) - This shape does not change its child shape but it does shift the calculated center of mass for that shape. It allows you to e.g. shift the center of mass of a vehicle down to improve its handling.

### Sub Shape IDs {#sub-shape-ids}

A [SubShapeID](@ref SubShapeID) is a compact 32-bit identifier that encodes the full path through a shape hierarchy down to a specific leaf element, such as a triangle in a [MeshShape](@ref MeshShape) or a child shape within a [CompoundShape](@ref CompoundShape).

The bits of a `SubShapeID` are allocated from the least-significant end, one level at a time as the hierarchy is traversed. Each level of the hierarchy consumes as many bits as needed to address all of its children. For example:

* `CompoundShape A` has 5 children -> needs 3 bits (`AAA`).
* Child `CompoundShape B` has 3 children -> needs 2 bits (`BB`).
* Child `MeshShape C` needs 7 bits to identify a triangle (`CCCCCCC`), exact number of bits needed depends on the structure of the mesh shape.

The resulting bit pattern for a triangle in `C` is: `CCCCCCC BB AAA` (least-significant bits first).

A fully empty `SubShapeID` has all bits set to 1 (`0xFFFFFFFF`). You can check for this using [SubShapeID::IsEmpty](@ref SubShapeID::IsEmpty).

Sub shape IDs are provided whenever collision results are returned. Given a `SubShapeID` and the root shape, you can query various properties of the leaf, e.g.:

* [Shape::GetLeafShape](@ref Shape::GetLeafShape) - Traverses the hierarchy and returns the leaf `Shape` pointer, along with any remainder bits in the ID.
* [Shape::GetMaterial](@ref Shape::GetMaterial) - Returns the [PhysicsMaterial](@ref PhysicsMaterial) assigned to that sub shape.
* [Shape::GetSubShapeUserData](@ref Shape::GetSubShapeUserData) - Returns the user data value stored on that sub shape, which can be used to identify the shape in application code.

A `SubShapeID` becomes invalid when the structure of the shape it refers to changes. For example, removing a child from a `MutableCompoundShape` will invalidate any previously obtained sub shape IDs for that compound. This is particularly relevant when caching sub shape IDs across frames - see the notes in [ContactListener::OnContactPersisted](@ref ContactListener::OnContactPersisted) and [ContactListener::OnContactRemoved](@ref ContactListener::OnContactRemoved).

### Dynamic Mesh Shapes {#dynamic-mesh-shapes}

Meshes are usually static, but they can be made kinematic or dynamic provided that they don't collide with other mesh- or heightfield shapes (an assert will trigger when this happens and the collision will be ignored).

Mesh shapes also cannot calculate their mass and inertia, so when you want a dynamic mesh, you need to provide these yourself by setting BodyCreationSettings::mOverrideMassProperties = EOverrideMassProperties::MassAndInertiaProvided and supplying the mass and inertia in BodyCreationSettings::mMassPropertiesOverride.

An example can be found [here](https://github.com/jrouwe/JoltPhysics/blob/master/Samples/Tests/General/DynamicMeshTest.cpp).

Note that you should try to avoid dynamic mesh shapes as they are fairly expensive to simulate. Also, mesh shapes don't have a clear inside/outside so a mesh is only considered to be colliding when one of its triangles intersect with the other object. This can result in objects getting stuck inside the mesh without knowing which way is out.

### Creating Shapes {#creating-shapes}

Simple shapes like spheres and boxes can be constructed immediately by simply new-ing them. Other shapes need to be converted into an optimized format in order to be usable in the physics simulation. The uncooked data is usually stored in a [ShapeSettings](@ref ShapeSettings) object and then converted to cooked format by a [Create](@ref ShapeSettings::Create) function that returns a [Result](@ref Result) object that indicates success or failure and provides the cooked object.

Creating a convex hull for example looks like:

	// Shapes are refcounted and can be shared between bodies
	JPH::Ref<Shape> 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<JPH::Vec3> 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
	}

Note that after you call Create, the shape is cached and ShapeSettings keeps a reference to your shape (see @ref memory-management). If you call Create again, the same shape will be returned regardless of what changed to the settings object (unless you call [ClearCachedResult](@ref ShapeSettings::ClearCachedResult) to clear the cache).

### Saving Shapes {#saving-shapes}

There are two ways of serializing data:

* The uncooked data can be serialized using the [ObjectStream](@ref ObjectStream) system (either in [binary](@ref ObjectStreamBinaryOut) or in [text](@ref ObjectStreamTextOut) format), data stored in this way is likely to be compatible with future versions of the library (although there is no 100% guarantee of this).
* The cooked data can be serialized using the [SaveBinaryState](@ref Shape::SaveBinaryState) interface that various objects provide. Data stored in this way is optimized for simulation performance and loading speed but is very likely to change between versions of the library, so this should never be your primary data format. Check for [API changes marked with SBS](APIChanges.md) to see if library versions are compatible. The serialization format also depends on the `JPH_DOUBLE_PRECISION` and `JPH_OBJECT_LAYER_BITS` defines.

An example of saving a shape in binary format:

	// Create a sphere of radius 1
	JPH::Ref<Shape> 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<Shape> restored_shape;
	if (result.IsValid())
		restored_shape = result.Get();
	else
		... // Error handling

As the library does not offer an exporter from content creation packages and since most games will have their own content pipeline, we encourage you to store data in your own format, cook data while cooking the game data and store the result using the SaveBinaryState interface (and provide a way to force a re-cook when the library is updated).

A possible pattern for serializing binary data in your own engine could be:

* EngineBody at runtime creates a Body. Note that the prefix 'Engine' means that it's a class in your own engine.
* It links to an EngineShape, which wraps a Shape.
* EngineShape comes in different flavors, e.g. EngineMeshShape, EngineSphereShape etc.
* EngineMeshShape contains the uncompressed mesh data (in a format that's editable in your tools).
* When 'cooking' the game data:
  * Create a MeshShape.
  * Save it using Shape::SaveWithChildren in a binary blob that's associated with the EngineMeshShape (could be in an attribute that's an array of bytes).
  * Throw away the uncompressed mesh data.
* When loading the EngineMeshShape using your own serialization system, also restore the MeshShape from the binary blob using Shape::sRestoreWithChildren.
* Your serialization system should take care that the pointer between EngineBody and EngineShape is restored.
* There are some tricks for sharing Shapes, e.g. an EngineCompoundShape links to multiple child EngineShapes:
  * At cooking time create a StaticCompoundShape.
  * Before writing the shape to the binary blob with Shape::SaveWithChildren it inserts all leaf shapes (the Shape associated with the child EngineShape) in the Shape::ShapeToIDMap so they won't be included in the binary blob.
  * Before loading the binary blob with Shape::sRestoreWithChildren prepopulate the Shape::IDToShapeMap with the pointers to the restored Shape's from the child EngineShapes (this again assumes that your own serialization system is capable of restoring the pointers between EngineCompoundShape and the child EntityShapes).
  
Please use the serialization functions on trusted data only. ObjectStreamIn verifies the structure of the input stream, but doesn't validate individual members. E.g. maniplulate the data so an array has `UINT_MAX` entries and the library will most likely crash while trying to allocate a very large data block. The RestoreBinaryState function doesn't even validate the structure (for performance reasons) and will crash on any corrupted data or data stored by an incompatible version of the library. If the data cannot be trusted, use a checksum or a digital signature to verify the integrity of the data before passing it to the library.

### Convex Radius {#convex-radius}

In order to speed up the collision detection system, all convex shapes use a convex radius. The provided shape will first be shrunken by the convex radius and then inflated again by the same amount, resulting in a rounded off shape:

![In this example a box (green) was created with a fairly large convex radius. The shape is shrunken first (dashed green line) and then inflated again equally on all sides. The resulting shape as seen by the collision detection system is shown in blue. A larger convex radius results in better performance but a less accurate simulation. A convex radius of 0 is allowed.](Images/ConvexRadius.jpg)

### Center of Mass {#center-of-mass}

__Beware: When a shape is created, it will automatically recenter itself around its center of mass.__ The center of mass can be obtained by calling [Shape::GetCenterOfMass](@ref Shape::GetCenterOfMass) and most functions operate in this Center of Mass (COM) space. Some functions work in the original space the shape was created in, they usually have World Space (WS) or Shape Space (SS) in their name (or documentation).

![Shape Center of Mass](Images/ShapeCenterOfMass.jpg)

As an example, say we create a box and then translate it:

	// Create box of 2x2x2 m (you specify half the side)
	JPH::BoxShapeSettings box(JPH::Vec3(1, 1, 1));
	JPH::Ref<Shape> box_shape = box.Create().Get();

	// Offset it by 10 m
	JPH::RotatedTranslatedShapeSettings translated_box(JPH::Vec3(10, 0, 0), JPH::Quat::sIdentity(), box_shape);
	JPH::Ref<Shape> translated_box_shape = translated_box.Create().Get();

	// Cast a ray against the offset box (WRONG!)
	JPH::RayCast ray;
	ray.mOrigin = JPH::Vec3(10, 2, 0);
	ray.mDirection = JPH::Vec3(0, -2, 0);

	// Cast ray
	JPH::RayCastResult hit;
	bool had_hit = translated_box_shape->CastRay(ray, JPH::SubShapeIDCreator(), hit);
	JPH_ASSERT(!had_hit); // There's no hit because we did not correct for COM!

	// Convert the ray to center of mass space for the shape (CORRECT!)
	ray.mOrigin -= translated_box_shape->GetCenterOfMass();

	// Cast ray
	had_hit = translated_box_shape->CastRay(ray, JPH::SubShapeIDCreator(), hit);
	JPH_ASSERT(had_hit); // Ray was in COM space, now there's a hit!

In the same way calling:

	translated_box_shape->GetLocalBounds();

will return a box of size 2x2x2 centered around the origin, so in order to get it back to the space in which it was originally created you need to offset the bounding box:

	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

Note that when you work with interface of [BroadPhaseQuery](@ref BroadPhaseQuery), [NarrowPhaseQuery](@ref NarrowPhaseQuery) or [TransformedShape](@ref TransformedShape) this transformation is done for you.

### Scaling Shapes {#scaling-shapes}

Shapes can be scaled using the [ScaledShape](@ref ScaledShape) class. You can scale a shape like:

	JPH::RefConst<Shape> my_scaled_shape = new JPH::ScaledShape(my_non_scaled_shape, JPH::Vec3(x_scale, y_scale, z_scale));

Not all scales are valid for every shape. Use Shape::IsValidScale to check if a scale is valid for a particular shape (the documentation for this function also lists the rules for all shape types).

A safer way of scaling shapes is provided by the Shape::ScaleShape function:

	JPH::Shape::ShapeResult my_scaled_shape = my_non_scaled_shape->ScaleShape(JPH::Vec3(x_scale, y_scale, z_scale));

This function will check if a scale is valid for a particular shape and if a scale is not valid, it will produce the closest scale that is valid.
For example, if you scale a CompoundShape that has rotated sub shapes, a non-uniform scale would cause shearing. In that case the Shape::ScaleShape function will create a new compound shape and scale the sub shapes (losing the shear) rather than creating a ScaledShape around the entire CompoundShape.

Updating scaling after a body is created is also possible, but should be done with care. Imagine a sphere in a pipe, scaling the sphere so that it becomes bigger than the pipe creates an impossible situation as there is no way to resolve the collision anymore.
Please take a look at the [DynamicScaledShape](https://github.com/jrouwe/JoltPhysics/blob/master/Samples/Tests/ScaledShapes/DynamicScaledShape.cpp) demo. The reason that no ScaledShape::SetScale function exists is to ensure thread safety when collision queries are being executed while shapes are modified.

Note that there are many functions that take a scale in Jolt (e.g. CollisionDispatch::sCollideShapeVsShape), usually the shape is scaled relative to its center of mass. The Shape::ScaleShape function scales the shape relative to the origin of the shape.

### Creating Custom Shapes {#creating-custom-shapes}

If the defined Shape classes are not sufficient, or if your application can make a more efficient implementation because it has specific domain knowledge, it is possible to create a custom collision shape:

* Derive a new class from Shape (e.g. MyShape). If your shape is convex you can consider deriving from ConvexShape, if it contains multiple sub shapes you can derive from CompoundShape or if it wraps a single other shape it can be derived from DecoratedShape.
* Create a settings class that configures your shape (e.g. MyShapeSettings) and inherit it from the corresponding settings class (e.g. ShapeSettings, CompoundShapeSettings or DecoratedShapeSettings).
* Override the ```MyShapeSettings::Create``` function to construct an instance of MyShape.
* If you want to serialize the settings class, register it with the factory: ```Factory::sInstance->Register(RTTI_OF(MyShapeSettings))```
* If you inherited from Shape you need to select a shape type, use e.g. ```EShapeType::User1```
* In all cases you will need to specify a sub shape type, use e.g. ```EShapeSubType::User1```
* If you inherited from ConvexShape you can also specify a convex sub shape type, e.g. ```EShapeSubType::UserConvex1```, in which case you don't need to implement or register the collision detection functions mentioned below.
* Implement the virtual functions that your selected base class exposes. Some functions could be implemented as a dummy if you don't care about the functionality, e.g. if you don't care about buoyancy then GetSubmergedVolume does not need to be implemented.
* Create a ```MyShape::sRegister()``` function to register all collision functions, make sure you call this function after calling ```RegisterTypes()```, see [MeshShape::sRegister](@ref MeshShape::sRegister) for an example.
* Now write collision detection functions to test collision with all other shape types that this shape could collide with and register them with [CollisionDispatch::sRegisterCollideShape](@ref CollisionDispatch::sRegisterCollideShape) and [CollisionDispatch::sRegisterCastShape](@ref CollisionDispatch::sRegisterCastShape). This can be a lot of work, but there are some helper functions that you can use to reduce the work:
 * If you have implemented a collision test for type A vs B then you can register [CollisionDispatch::sReversedCastShape](@ref CollisionDispatch::sReversedCastShape) and [CollisionDispatch::sReversedCollideShape](@ref CollisionDispatch::sReversedCollideShape) for B vs A.
 * If your shape is triangle based, you can forward the testing of a shape vs a single triangle to the [CollideConvexVsTriangles](@ref CollideConvexVsTriangles) and [CastConvexVsTriangles](@ref CastConvexVsTriangles) classes.
 * If your shape contains sub shapes and you have determined that the shape intersects with one of the sub shapes you can forward the sub shape to the collision dispatch again through [CollisionDispatch::sCollideShapeVsShape](@ref CollisionDispatch::sCollideShapeVsShape) and [CollisionDispatch::sCastShapeVsShapeLocalSpace](@ref CollisionDispatch::sCastShapeVsShapeLocalSpace).

## Sensors {#sensors}

Sensors are normal rigid bodies that report contacts with other Dynamic or Kinematic bodies through the [ContactListener](@ref ContactListener) interface. Any detected penetrations will however not be resolved. Sensors can be used to implement triggers that detect when an object enters their area.

The cheapest sensor has a Static motion type. This type of sensor will only detect active bodies entering their area. As soon as a body goes to sleep, the contact will be lost. Note that you can still move a Static sensor around using [BodyInterface::SetPosition](@ref BodyInterface::SetPosition).

When you make a sensor Kinematic or Dynamic and activate it, it will also detect collisions with sleeping bodies, albeit with a higher run-time cost.

To create a sensor, either set [BodyCreationSettings::mIsSensor](@ref BodyCreationSettings::mIsSensor) to true when constructing a body or set it after construction through [Body::SetIsSensor](@ref Body::SetIsSensor). A sensor can only use the discrete motion quality type at this moment.

To make sensors detect collisions with static objects, set the [BodyCreationSettings::mCollideKinematicVsNonDynamic](@ref BodyCreationSettings::mCollideKinematicVsNonDynamic) to true or call [Body::SetCollideKinematicVsNonDynamic](@ref Body::SetCollideKinematicVsNonDynamic). Note that it can place a large burden on the collision detection system if you have a large sensor intersect with e.g. a large mesh terrain or a height field as you will get many contact callbacks and these contacts will take up a lot of space in the contact cache. Ensure that your sensor is in an object layer that collides with as few static bodies as possible.

To temporarily disable a sensor, choose between:

* Remove the sensor by calling BodyInterface::RemoveBody and re-add it later again with BodyInterface::AddBody.
* Change the collision layer using BodyInterface::SetObjectLayer to a layer that doesn't collide with anything (possibly also in a BroadPhaseLayer that doesn't collide with anything)

## Sleeping {#sleeping-bodies}

During the simulation step, bodies are divided in 'islands'. Each island consists of a set of dynamic bodies that are either in contact with each other, or that are connected through a constraint:

![Simulation islands are enclosed by a red box. Note that the floor is static so not part of an island.](Images/SimulationIsland.jpg)

At the end of each step, all the bodies in an island are checked to see if they have come to rest, if this is the case then the entire island is put to sleep. When a body is sleeping, it can still detect collisions with other objects that are not sleeping, but it will not move or otherwise participate in the simulation to conserve CPU cycles. Sleeping bodies wake up automatically when they're in contact with non-sleeping objects or they can be explicitly woken through an API call like BodyInterface::ActivateBody. Unlike some other physics engines, removing a Body from the world doesn't wake up any surrounding bodies. If you want this you can call BodyInterface::ActivateBodiesInAABox with the bounding box of the removed body (or the combined bounding box if you're removing multiple bodies). Also, things like setting the velocity through Body::SetLinearVelocity will not wake up the Body, use BodyInterface::SetLinearVelocity instead. You can configure the definition of a body 'at rest' through PhysicsSettings::mTimeBeforeSleep and PhysicsSettings::mPointVelocitySleepThreshold.

## Soft Bodies {#soft-bodies}

Soft bodies (also known as deformable bodies) can be used to create e.g. a soft ball or a piece of cloth. They are created in a very similar way to normal rigid bodies:

* First allocate a new SoftBodySharedSettings object on the heap. This object will contain the initial positions of all particles and the constraints between the particles. This object can be shared between multiple soft bodies and should remain constant during its lifetime.
* Then create a SoftBodyCreationSettings object (e.g. on the stack) and fill in the desired properties of the soft body.
* Finally construct the body and add it to the world through BodyInterface::CreateAndAddSoftBody.

Soft bodies use the Body class just like rigid bodies but can be identified by checking Body::IsSoftBody. To get to the soft body state, cast the result of Body::GetMotionProperties to SoftBodyMotionProperties and use its API.

Soft bodies try to implement as much as possible of the normal Body interface, but this interface provides a simplified version of reality, e.g. Body::GetLinearVelocity will return the average particle speed and Body::GetPosition returns the average particle position. During simulation, a soft body will never update its rotation. Internally it stores particle velocities in local space, so if you rotate a soft body e.g. by calling BodyInterface::SetRotation, the body will rotate but its velocity will as well.

### Soft Body Contact Listeners {#soft-body-contact-listener}

Soft Bodies provide contacts with other bodies through the SoftBodyContactListener class. This contact listener works a little bit different from the normal contact listener as you will not receive a contact callback per colliding vertex.

After the broad phase has detected an overlap and the normal layer / collision group filters have had a chance to reject the collision, you will receive a SoftBodyContactListener::OnSoftBodyContactValidate callback. This callback allows you to specify how the vertices of the soft body should interact with the other body. You can override the mass for both bodies and you can turn the contact into a sensor contact.

The simulation will then proceed to do all collision detection and response and after that is finished, you will receive a SoftBodyContactListener::OnSoftBodyContactAdded callback that allows you to inspect all collisions that happened during the simulation step. In order to do this a SoftBodyManifold is provided which allows you to loop over the vertices and ask each vertex what it collided with.

Note that at the time of the callback, multiple threads are operating at the same time. The soft body is stable and can be safely read. The other body that is collided with is not stable however, so you cannot safely read its position/orientation and velocity as it may be modified by another soft body collision at the same time.

### Skinning Soft Bodies {#skinning-soft-bodies}

Using the [skinning](@ref SoftBodySharedSettings::Skinned) constraints, a soft body can be (partially) skinned to joints. This can be used e.g. to partially drive cloth with a character animation. The [vertices](@ref SoftBodySharedSettings::Vertex::mPosition) of the soft body need to be placed in the neutral pose of the character and the joints for this pose need to be calculated in model space (relative to these vertices). The inverted matrices of this neutral pose need to be stored as the [inverse bind matrices](@ref SoftBodySharedSettings::InvBind) and the skinning constraints can then be [weighted](@ref SoftBodySharedSettings::SkinWeight) to these joints. SoftBodySharedSettings::CalculateSkinnedConstraintNormals must be called to gather information needed to calculate the face normals at run-time.

At run-time, you need to provide the animated joints every simulation step through the SoftBodyMotionProperties::SkinVertices call. During simulation, each skinned vertex will calculate its position and this position will be used to limit the movement of its simulated counterpart.

![A Skinned Constraint](Images/SoftBodySkinnedConstraint.jpg)

The adjacent faces of the soft body will be used to calculate the normal of each vertex (shown in red), the vertex is then free to move inside the sphere formed by the skinned vertex position with radius [MaxDistance](@ref SoftBodySharedSettings::Skinned::mMaxDistance) (green sphere). To prevent the vertex from intersecting with the character, it is possible to specify a [BackStopDistance](@ref SoftBodySharedSettings::Skinned::mBackStopDistance) and [BackStopRadius](@ref SoftBodySharedSettings::Skinned::mBackStopRadius), together these form the red sphere. The vertex is not allowed to move inside this sphere.

### Soft Body Work In Progress {#soft-body-wip}

Soft bodies are currently in development, please note the following:

* Soft bodies can only collide with rigid bodies, collisions between soft bodies are not implemented yet.
* AddTorque/SetLinearVelocity/SetLinearVelocityClamped/SetAngularVelocity/SetAngularVelocityClamped/AddImpulse/AddAngularImpulse have no effect on soft bodies as the velocity is stored per particle rather than per body.
* Buoyancy calculations have not been implemented yet.
* Constraints cannot operate on soft bodies, set the inverse mass of a particle to zero and move it by setting a velocity to constrain a soft body to something else.
* When calculating friction / restitution an empty SubShapeID will be passed to the ContactConstraintManager::CombineFunction because this is called once per body pair rather than once per sub shape as is common for rigid bodies.

# Constraints {#constraints}

Bodies can be connected to each other using constraints ([Constraint](@ref Constraint)).

The following constraints are available:

* [FixedConstraint](@ref FixedConstraintSettings) - Will attach a body to another without any degrees of freedom.
* [DistanceConstraint](@ref DistanceConstraintSettings) - Will attach two bodies with a stick (removing 1 degree of freedom).
* [PointConstraint](@ref PointConstraintSettings) - Will attach two bodies in a single point (removing 3 degrees of freedom)
* [HingeConstraint](@ref HingeConstraintSettings) - Will attach two bodies through a hinge.
* [ConeConstraint](@ref ConeConstraintSettings) - Attaches two bodies in a point and will limit the rotation within a cone.
* [SliderConstraint](@ref SliderConstraintSettings) - Attaches two bodies and allows only movement in a single translation axis (also known as prismatic constraint).
* [SwingTwistConstraint](@ref SwingTwistConstraintSettings) - Attaches two bodies using a point constraint and a swing-twist constraint which approximates the shoulder joint of a human.
* [SixDOFConstraint](@ref SixDOFConstraintSettings) - The most configurable joint allows specifying per translation axis and rotation axis what the limits are.
* [PathConstraint](@ref PathConstraintSettings) - This constraint allows attaching two bodies connected through a Hermite spline path.
* [GearConstraint](@ref GearConstraintSettings) - This constraint connects to two hinge joints and constrains them to connect two gears.
* [RackAndPinionConstraint](@ref RackAndPinionConstraintSettings) - This constraint connects a hinge and a slider constraint to connect a rack and pinion.
* [PulleyConstraint](@ref PulleyConstraintSettings) - This constraint connects two bodies through two fixed points creating something that behaves like two bodies connected through a rope.
* [VehicleConstraint](@ref VehicleConstraintSettings) - This constraint adds virtual wheels or tracks to a body and allows it to behave as a vehicle.

If you want to constrain a dynamic object to the unmovable 'world' you can use [Body::sFixedToWorld](@ref Body::sFixedToWorld) instead of creating a static body.

Bodies do not keep track of the constraints that are connected to them. This means that you're responsible for removing any constraints attached to a body before removing the body from the PhysicsSystem.

Adding and removing constraints can be done from multiple threads, but the constraints themselves do not have any protection against concurrent access. We assume that constraints are owned by some object (e.g. a Ragdoll) and that object ensures that it only modifies its own constraints and contains its own synchronization logic. Constraints can be freely modified except during the physics simulation step.

Contact constraints (when bodies collide) are not handled through the [Constraint](@ref Constraint) class but through the [ContactConstraintManager](@ref ContactConstraintManager) which is considered an internal class.

## Constraint Motors {#constraint-motors}

Most of the constraints support motors (see [MotorSettings](@ref MotorSettings)) which allow you to apply forces / torques on two constrained bodies to drive them to a relative position / orientation. There are two types of motors:
* Linear motors: These motors drive the relative position between two bodies. A linear motor would, for example, slide a body along a straight line when you use a slider constraint.
* Angular motors: These motors drive the relative rotation between two bodies. An example is a hinge constraint. The motor drives the rotation along the hinge axis.

The applied force of a motor is proportional to: stiffness * (target_position - current_position) + damping * (target_velocity - current_velocity).

Motors can have three states (see [EMotorState](@ref EMotorState) or e.g. SliderConstraint::SetMotorState):
* Off: The motor is not doing any work. In the equation above: stiffness = 0 and damping = 0.
* Velocity: This type of motor drives the relative velocity between bodies. In the equation above: stiffness = 0 and damping = infinite. For a slider constraint, you would push the bodies towards / away from each other with constant velocity. For a hinge constraint, you would rotate the bodies relative to each other with constant velocity. Set the target velocity through e.g. SliderConstraint::SetTargetVelocity / HingeConstraint::SetTargetAngularVelocity.
* Position: This type of motor drives the relative position between bodies. In the equation above: target_velocity = 0. For a slider constraint, you can specify the relative distance you want to achieve between the bodies. For a hinge constraint you can specify the relative angle you want to achieve between the bodies. Set the target position through e.g. SliderConstraint::SetTargetPosition / HingeConstraint::SetTargetAngle.
* PositionAndVelocity: This type of motor drives both the position and velocity. This uses the full equation above.

Motors apply a force (when driving position) or torque (when driving angle) every simulation step to achieve the desired velocity or position. You can control the maximum force / torque that the motor can apply through MotorSettings::mMinForceLimit, MotorSettings::mMaxForceLimit, MotorSettings::mMinTorqueLimit and MotorSettings::mMaxTorqueLimit. Note that if a motor is driving to a position, the torque limits are not used. If a constraint is driving to an angle, the force limits are not used.

Usually the limits are symmetric, so you would set -mMinForceLimit = mMaxForceLimit. This way the motor can push at an equal rate as it can pull. If you would set the range to e.g. [0, FLT_MAX] then the motor would only be able to push in the positive direction. The units for the force limits are Newtons and the values can get pretty big. If your motor doesn't seem to do anything, chances are that you have set the value too low. Since Force = Mass * Acceleration you can calculate the approximate force that a motor would need to supply in order to be effective. Usually the range is set to [-FLT_MAX, FLT_MAX] which lets the motor achieve its target as fast as possible.

For an angular motor, the units are Newton Meters. The formula is Torque = Inertia * Angular Acceleration. Inertia of a solid sphere is 2 / 5 * Mass * Radius^2. You can use this to get a sense of the amount of torque needed to get the angular acceleration you want. Again, you'd usually set the range to [-FLT_MAX, FLT_MAX] to not limit the motor.

When settings the force or torque limits to [-FLT_MAX, FLT_MAX] a velocity motor will accelerate the bodies to the desired relative velocity in a single time step (if no other forces act on those bodies).

How a Position or PositionAndVelocity motor works can be configured through MotorSettings::mSpringSettings.m