项目简介
Jolt Physics 是一个用 C++ 编写的高性能、多核友好的刚体物理与碰撞检测库。适用于游戏和 VR 应用,已被《地平线:西之绝境》和《死亡搁浅 2》等大作采用。该库支持约束、软体、载具以及广泛的碰撞查询等功能。
README 预览
[](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
常见问题 (5)
故障排除如何修复在 ARM/AArch64 上 Jolt Physics 的 CountLeadingZeros 中出现的 __builtin_clz(0) 未定义行为错误?
修改 Jolt/Math/Math.h 中的 ARM 分支,使其在调用 __builtin_clz 之前先处理零值:
return inValue ? __builtin_clz(inValue) : 32;
在 v5.6.0 版本的代码中,将:
#else
return __builtin_clz(inValue);
#endif
替换为:
#else
return inValue ? __builtin_clz(inValue) : 32;
#endif
这样便与其他架构分支以及 ARM clz 指令的行为保持一致,该指令在输入为零时返回 32。在 Clang 上,UBSan 的报告实际上是误报,因为 Clang 会将该操作降低(lower)为零结果有定义的形式;而 GCC 将零视为未定义,并可能基于 0–31 的结果范围进行优化。维护者接受了这一零值检查,因为它只会编译成一条指令。应用补丁后,重新构建 Jolt 以及你的项目,包括使用 -fsanitize=undefined 进行构建。
故障排除如何解决从 JoltPhysics 静态库创建 XCFramework 时出现的 "Unknown header: 0xb17c0de" 错误?
出现该错误的原因是 Release/Distribution 构建启用了 CMake 的 INTERPROCEDURAL_OPTIMIZATION,这会传递 -flto=thin 并在 .a 文件中嵌入 LLVM bitcode。xcodebuild -create-xcframework 无法打包这些目标文件。请在禁用 IPO 的情况下为 XCFramework 构建重新编译 Jolt:
cmake -S Build -B build-apple -DCMAKE_BUILD_TYPE=Release -DINTERPROCEDURAL_OPTIMIZATION=OFF
cmake --build build-apple --config Release
然后使用新构建的 .a 文件创建 XCFramework。如果通过 CMake 集成,也可以在添加 Jolt 之前将 CMAKE_INTERPROCEDURAL_OPTIMIZATION 设置为 OFF,或者应用 set_target_properties(Jolt PROPERTIES INTERPROCEDURAL_OPTIMIZATION OFF)。对于常规的直接静态链接,LTO 可以保持启用;仅在打包进 XCFramework 时才专门禁用它。
故障排除如何在使用 Jolt Physics 的 Godot 中修复弯曲球形行星上扁平 RigidBody 的抖动问题?
将行星的 SphereShape3D 碰撞替换为由球体网格生成的 ConcavePolygonShape3D 三角网格(trimesh)。对于较简单的几何体,也可以使用 ConvexPolygonShape3D。Jolt 目前对于大球体仅报告一个接触点,这不足以与平坦的刚体保持稳定的接触;而 trimesh 可以提供多个接触点。在 RigidBody 上启用 Continuous Collision Detection(连续碰撞检测)可以减少初始穿透,但无法解决根本的单接触点不稳定问题。
故障排除如何修复在 Jolt Physics 5.6 中堆叠物体进入睡眠状态时刚体消失或 transform 变为 NaN 的问题?
这是 Jolt 5.6 在 AngularFrictionConstraintPart 中的一个回归问题。在接近休眠状态时,inv_effective_mass 可能变为次正规值(denormal),例如 1.40129846e-45;此时计算 1.0f / inv_effective_mass 会溢出为 INF,进而污染角速度和刚体变换。该修复已包含在标题为 "Avoiding overflow to INF if inverse effective mass is denormal" 的上游更改中,此更改修复了 issue #2092。请将 JoltPhysics 更新到最新的 master 分支,或 5.6.0 之后第一个包含该修复的发布版本,然后对 UPBGE 执行干净的重新构建。作为临时变通方案,可以将 JoltPhysics 降级到 5.5.0 的提交 23dadd0e603f1b321142d4c74df07fce85064989,该提交中不存在 AngularFrictionConstraintPart。更改平面细分或停用设置只会影响求解器的顺序,并不能修复底层的溢出问题。
故障排除如何修复 Jolt CharacterVirtual 在三角形网格上将胶囊体侧面或边缘接触错误分类为地面的问题?
正确配置 CharacterVirtualSettings::mSupportingVolume。如果配置不当,胶囊体底部半球上半部分附近的接触点可能会被当作支撑接触点处理,导致角色粘在边缘上而不是掉落。
将支撑体积平面设置在胶囊体底部球体的中心,即胶囊体底部向上一个胶囊半径的位置。对于半径为 0.3 m 的胶囊体,使用 0.3 m;不要使用 0.1 m 或 0.2 m,因为低于球体中心的值会导致爬楼梯失败。
如果你的上轴是 Z 轴,则使用法线 (0, 0, 1) 定义平面,使其通过局部点 (0, 0, 0.3)。对于默认的 Y 轴向上设置,使用法线 (0, 1, 0) 并通过 (0, 0.3, 0)。概念上:
settings.mSupportingVolume = Plane::sFromPointNormal(
Vec3(0, 0, 1), // 上轴
Vec3(0, 0, settings.mShape->GetInnerRadius()) // 底部球体中心
);
如果形状没有暴露半径,请直接使用胶囊体半径。这可以防止底部球体中心以上的侧面接触点被选为地面接触点。