JoltPhysics

Library

jrouwe/JoltPhysics

Multi-core friendly rigid body physics and collision detection library for games and VR.

Overview

Jolt Physics is a high-performance, multi-core friendly rigid body physics and collision detection library written in C++. It is suitable for games and VR applications, and has been used in major titles like Horizon Forbidden West and Death Stranding 2. The library supports a wide range of features including constraints, soft bodies, vehicles, and extensive collision queries.

README Preview

[](https://cla-assistant.io/jrouwe/JoltPhysics)\n[](https://github.com/jrouwe/JoltPhysics/actions/)\n[](https://sonarcloud.io/dashboard?id=jrouwe_JoltPhysics)\n[](https://sonarcloud.io/dashboard?id=jrouwe_JoltPhysics)\n[](https://sonarcloud.io/dashboard?id=jrouwe_JoltPhysics)\n[](https://sonarcloud.io/dashboard?id=jrouwe_JoltPhysics)\n\n# Jolt Physics\n\nA multi core friendly rigid body physics and collision detection library. Suitable for games and VR applications. Used by Horizon Forbidden West and Death Stranding 2: On the Beach.\n\n[](https://www.playstation.com/en-us/games/horizon-forbidden-west/)\n[](https://www.playstation.com/en-us/games/death-stranding-2-on-the-beach/)\n\n|[](https://www.youtube.com/watch?v=pwyCW0yNKMA)|\n|:-|\n|*A YouTube video showing a ragdoll pile simulated with Jolt Physics.*|\n\nFor more demos and [videos](https://www.youtube.com/watch?v=pwyCW0yNKMA&list=PLYXVwtOr1CBxbA50jVg2dKUQvHW_5OOom) go to the [Samples](Docs/Samples.md) section.\n\n## Design considerations\n\nWhy create yet another physics engine? Firstly, it has been a personal learning project. Secondly, I wanted to address some issues that I had with existing physics engines:\n\n* Games do more than simulating physics. These things happen across multiple threads. We emphasize on concurrently accessing physics data outside of the main simulation update:\n	* Sections of the simulation can be loaded / unloaded in the background. We prepare a batch of physics bodies on a background thread without locking or affecting the simulation. We insert the batch into the simulation with a minimal impact on performance.\n	* Collision queries can run parallel to adding / removing or updating a body. If a change to a body happened on the same thread, the change will be immediately visible. If the change happened on another thread, the query will see a consistent before or after state. An alternative would be to have a read and write version of the world. This prevents changes from being visib

FAQ (5)

Troubleshooting
How to fix the __builtin_clz(0) undefined behavior error in Jolt Physics CountLeadingZeros on ARM/AArch64?

Patch the ARM branch in Jolt/Math/Math.h so zero is handled before calling __builtin_clz:

return inValue ? __builtin_clz(inValue) : 32;

In the v5.6.0 code, replace:

#else
return __builtin_clz(inValue);
#endif

with:

#else
return inValue ? __builtin_clz(inValue) : 32;
#endif

This matches the behavior of the other architecture branches and the ARM clz instruction, which returns 32 for zero. On Clang the UBSan report is effectively a false positive because Clang lowers the operation to a defined-zero-result form, but GCC treats zero as undefined and can optimize based on a result range of 0–31. The maintainer accepted the zero check because it compiles to a single instruction. Rebuild Jolt and your project, including with -fsanitize=undefined, after applying the patch.

GitHub Issue #2149
Troubleshooting
How do I fix 'Unknown header: 0xb17c0de' when creating an XCFramework from a JoltPhysics static library?

The error occurs because Release/Distribution builds enable CMake's INTERPROCEDURAL_OPTIMIZATION, which passes -flto=thin and embeds LLVM bitcode in the .a files. xcodebuild -create-xcframework cannot package those objects. Rebuild Jolt with IPO disabled for the XCFramework build:

cmake -S Build -B build-apple -DCMAKE_BUILD_TYPE=Release -DINTERPROCEDURAL_OPTIMIZATION=OFF
cmake --build build-apple --config Release

Then create the XCFramework from the newly built .a files. If integrating via CMake, you can also set CMAKE_INTERPROCEDURAL_OPTIMIZATION to OFF before adding Jolt, or apply set_target_properties(Jolt PROPERTIES INTERPROCEDURAL_OPTIMIZATION OFF). LTO can remain enabled for normal direct static linking; disable it specifically when bundling into an XCFramework.

GitHub Issue #1261
Troubleshooting
How do I fix flat RigidBody jitter on a curved spherical planet in Godot with Jolt Physics?

Replace the planet's SphereShape3D collision with a ConcavePolygonShape3D trimesh generated from a sphere mesh. For simpler geometry, a ConvexPolygonShape3D can also work. Jolt currently reports only one contact point for a large sphere, which is insufficient for stable contact with flat rigid bodies; a trimesh provides multiple contact points. Enabling Continuous Collision Detection on the RigidBody can reduce initial penetration, but it does not resolve the underlying single-contact instability.

GitHub Issue #2111
Troubleshooting
How do I fix rigid bodies disappearing or getting NaN transforms when stacked objects go to sleep in Jolt Physics 5.6?

This is a Jolt 5.6 regression in AngularFrictionConstraintPart. Near sleep, inv_effective_mass can become a subnormal value such as 1.40129846e-45; calculating 1.0f / inv_effective_mass overflows to INF, contaminating angular velocity and body transforms. The fix is included in the upstream change titled "Avoiding overflow to INF if inverse effective mass is denormal", which fixes issue #2092. Update JoltPhysics to the latest master or the first release after 5.6.0 containing that fix, then perform a clean rebuild of UPBGE. As a temporary workaround, downgrade JoltPhysics to 5.5.0 commit 23dadd0e603f1b321142d4c74df07fce85064989, where AngularFrictionConstraintPart does not exist. Changing plane subdivision or deactivation settings only affects solver ordering and does not fix the underlying overflow.

GitHub Issue #2092
Troubleshooting
How to fix Jolt CharacterVirtual incorrectly classifying capsule side or edge contacts as ground on triangle meshes?

Configure CharacterVirtualSettings::mSupportingVolume correctly. Without it, contacts near the upper part of the capsule's bottom hemisphere can be treated as supporting contacts, causing the character to stick to edges instead of falling.

Set the supporting-volume plane at the center of the capsule's bottom sphere, which is one capsule radius above the bottom of the capsule. For a capsule radius of 0.3 m, use 0.3 m; do not use 0.1 m or 0.2 m, because values below the sphere center can cause stair stepping to fail.

If your up axis is Z, define the plane with normal (0, 0, 1) through local point (0, 0, 0.3). For the default Y-up setup, use normal (0, 1, 0) through (0, 0.3, 0). Conceptually:

settings.mSupportingVolume = Plane::sFromPointNormal(
    Vec3(0, 0, 1),   // up axis
    Vec3(0, 0, settings.mShape->GetInnerRadius()) // bottom-sphere center
);

Use the capsule radius directly if the radius is not exposed by the shape. This prevents side contacts above the center of the bottom sphere from being selected as ground contacts.

GitHub Issue #2122