box3d

库

erincatto/box3d

面向游戏的3D物理引擎,支持碰撞检测与刚体模拟。

项目简介

Box3D 是一款可移植的 C17 物理引擎,具备连续碰撞检测、软步刚体求解器与数据导向设计。支持多线程、SIMD 和跨平台确定性,适用于大量刚体堆叠场景。

README 预览

# Box3D\n\n[](https://github.com/erincatto/box3d/actions)\n[](https://cla-assistant.io/erincatto/box3d)\n\n\n\nBox3D is a 3D physics engine for games.\n\n[](https://www.youtube.com/watch?v=jr_Fzl2XwKU)\n\n## Features\n\n### Collision\n\n- Continuous collision detection\n- Contact events\n- Convex hulls, capsules, spheres, triangle meshes, and height fields\n- Multiple shapes per body\n- Collision filtering\n- Ray casts, shape casts, and overlap queries\n- Sensor system\n- Character mover\n\n### Physics\n\n- Robust _Soft Step_ rigid body solver\n- Continuous physics for fast translations and rotations\n- Island based sleep\n- Revolute, prismatic, distance, motor, weld, and wheel joints\n- Joint limits, motors, springs, and friction\n- Joint and contact forces\n- Body movement events and sleep notification\n\n### System\n\n- Data-oriented design\n- Written in portable C17\n- Extensive multithreading and SIMD\n- Optimized for large piles of bodies\n- Cross platform determinism\n- Recording and replay\n\n### Samples\n\n- Uses sokol to run with D3D11 on Windows, Metal on macOS, and OpenGL 4.5 on Linux.\n- Graphical user interface with imgui.\n- Many samples to demonstrate features and performance.\n\n## Building all platforms\n\n- Install [CMake](https://cmake.org/)\n- Install [git](https://git-scm.com/)\n- Ensure these run from the command line\n\n## Building with CMake presets (recommended)\n\nThis uses the presets in `CMakePresets.json`.\n\n- Windows: `cmake --preset windows` then `cmake --build --preset windows-release`\n- Linux: `cmake --preset linux-release` then `cmake --build --preset linux-release`\n- macOS: `cmake --preset macos` then `cmake --build --preset macos-release`\n- Windows MinGW: `cmake --preset mingw-release` then `cmake --build --preset mingw-release`\n\nRun the samples app (must be in the Box3D directory).\n\n- Windows: `.\build\bin\Release\samples.exe`\n- Linux: `./build/bin/samples`\n- macOS: `./build/bin/Release/samples`\n\n## Building for Visu

常见问题 (5)

故障排除
为什么在 Box3D 中创建许多体素形状的盒体凸包时,b3AddHullToDatabase 会非常慢?

性能下降是由严重的哈希表冲突引起的。旧的 djb2 风格的凸包哈希未能充分混合规则间隔的浮点坐标(例如 0.25f 的倍数),而桶的选择仅使用了哈希值的低位(hash & buckets_mask)。因此,数千个体素凸包可能会映射到同一条桶链上,从而被迫进行反复的凸包比较并导致哈希表过度扩容。此问题已在 PR #126 中通过使用改进的 64 位凸包哈希得到修复。请将 Box3D 更新到包含该 PR 的版本。在所报告的包含 3,000 个凸包的复现案例中,该修复将耗时从约 159.9 ms 降至 3.9 ms,桶数量从 2,097,152 降至 4,096。一种临时解决方法是向凸包偏移量添加一个微小的唯一抖动,例如 1.0e-4f,但这会改变碰撞体的几何形状;如果需要精确的体素对齐,则应避免使用此方法。

来源 Issue #120
故障排除
如何修复在步进 Box3D 世界时 b3FreeElement 中出现的 UBSan 未对齐地址 panic?

崩溃发生的原因是 b3Manifold 的大小为 268 字节。当奇数个 manifold 紧密排列在一起时,下一个元素的起始位置可能偏离 8 字节边界 4 个字节,但 b3FreeElement 会在该位置存储一个 void*,而这需要 8 字节对齐。

修复方法是在 b3CreateBlockAllocator(block_allocator.c)中将每个分配器元素的大小向上取整到指针对齐:

elementSize = (elementSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1);

在元素大小被用于初始化块/空闲列表之前应用此修改。在受影响的 64 位平台上,使用 sizeof(void *) 就足够了;取整到 64 字节的缓存行大小也可以,但会浪费更多空间。

对于 Box3D v0.1.0,可以应用此对齐补丁,或者作为临时变通方案,仅针对 Box3D 目标禁用对齐检查:

-fno-sanitize=alignment

禁用所有 sanitization 也可以避免 panic,但在应用补丁之前,更可取的做法是保持 ASan/UBSan 启用,仅禁用对齐检查。

来源 Issue #78
故障排除
如何修复两个 Box3D 刚体在创建关节并将 collideConnected 设置为 false 后仍然发生碰撞的问题?

出现这种情况是因为创建关节会改变后续的碰撞过滤,但不会销毁两个物体之间已存在的 b3Contact 对象。该问题已在 Box3D PR #157 中正式修复,因此请更新到包含该 PR 的 Box3D 版本。对于旧版本,可采用的变通方法是:在创建关节之后、下一次模拟步之前,立即显式销毁相连物体之间的接触,例如当 jointDef.collideConnected == false 时调用 b3DestroyContactsBetweenBodies(world, bodyA, bodyB)。

来源 Issue #117
故障排除
如何修复 Box3D 中 b3World_Step 将深度重叠的动态刚体推穿薄静态墙的问题?

这是预期的求解器行为,并非 Box3D 的 bug。"将速度设为零、调用 b3World_Step、重复执行"这一模式并不是受支持的准静态去穿透方法。一旦一个大型动力学刚体的中心越过薄墙的另一侧,接触求解器就无法推断你所指的"房间内部"是哪一侧。它会沿当前接触法线进行解算,而该法线可能指向远侧,因此反复的校正会不断累积,把物体推得更远。

请使用以下方法之一:

1. **在步进之前防止深度重叠。**在生成物体或接受拖拽位姿之前,针对墙体碰撞体运行重叠/形状投射(shape-cast)查询。在调用 b3World_Step 之前,拒绝候选位姿或将其钳制到正确的墙面。
2. **显式跟踪进入的一侧。**如果物体原本位于内侧,将其投影回 interiorWallFace - objectHalfExtent;在中心越过墙体之后,不要依赖求解器来选择那一侧。
3. **使用马达关节(motor joint)驱动拖拽。**为该动力学物体创建一个马达关节,并朝指针目标更新其目标变换/线性偏移。配置足够的 maxForce 和 maxTorque,然后让接触约束在墙面处将其挡停。不要使用 b3Body_SetLinearVelocity 之后再执行零速度步进的方式作为位置松弛器。
4. **手动修复已失效的状态。**如果刚体已经深度穿透或越过墙体中心线,在步进之前将其移回一个已知的无穿透变换。

启用连续碰撞(continuous collision)有助于防止高速隧穿,但无法修复初始即无效、深度重叠的放置状态。该行为已在提交 3fc20f5b45 和 30c67b5e6d 上得到确认;维护者建议进行重叠验证并使用马达关节。

来源 Issue #135
故障排除
为什么我的 mover 在以接近垂直或浅角度移动时会卡在网格三角形边缘上?

这是由 mover 形状投射(shape cast)期间的背面三角形碰撞引起的。该问题已在 PR #130 中修复:请更新到包含该 PR 的物理引擎构建版本并重新构建。形状投射现在会忽略网格(mesh)和高度场(height-field)三角形的背面碰撞,与射线投射(ray-cast)的行为保持一致,并且 mover 碰撞现在包含了实现更平滑接触所需的三角形信息。如果您定义了自定义网格,请验证其三角形环绕方向(winding),并正确设置新的 b3MeshDef clockwise 选项(以及 stride)。

来源 Issue #141