erincatto/box3d · 上手攻略
- 仓库:erincatto/box3d
- 链接:https://github.com/erincatto/box3d
- 分类:engineering
- 作者:Tom
- 更新:2026-07-05
这是什么
Box3D 是著名 2D 物理引擎 Box2D 作者 Erin Catto 推出的3D 物理引擎,专为游戏设计。
Box2D 是游戏行业公认的 2D 物理标杆(愤怒的小鸟、植物大战僵尸等无数游戏都在用),Box3D 则将其设计理念扩展到三维空间,定位与 Bullet、Havok、PhysX 同台竞技。
核心定位:高性能、数据导向(data-oriented)、跨平台确定性(deterministic)的 3D 物理求解器,专注于刚体碰撞和约束求解。
当前版本:v0.1.0(MIT 许可),C17 编写,核心库无外部依赖。
解决什么问题
游戏开发者需要物理模拟,但现有 3D 物理引擎往往存在以下问题:
- 依赖繁重:Bullet、Havok 附带大量 SDK 和运行时,集成成本高
- 闭源限制:PhysX(NVIDIA)需要接受特定许可条款
- 跨平台确定性不足:很多引擎在多平台间无法复现同一条物理轨迹(影响联机游戏)
- 性能不透明:大型物理场景(如成百上千个刚体)性能不可预期
Box3D 的核心价值主张:
- 零依赖核心库:只有 C runtime 和 libm(Unix),单头文件 + 单源文件就可以集成
- 数据导向设计:内存布局按数据访问模式优化,减少 cache miss
- 确定性模拟:同样输入在所有平台产生完全相同的物理结果——这对联机游戏和回放系统至关重要
- 大规模场景优化:专为"大量物体堆积"(large piles of bodies)场景调优
- SIMD 加速:SSE2(x86)和 NEON(ARM)内置支持
快速安装
编译核心库(推荐)
Box3D 使用 CMake 构建系统,需要:
- CMake 3.16+
- C17 编译器(GCC 10+、Clang 11+、MSVC 2019+)
- Git
使用 CMake Presets(各平台最简方式)
# Linux
cmake --preset linux-release
cmake --build --preset linux-release
# macOS(使用 Metal)
cmake --preset macos-release
cmake --build --preset macos-release
# Windows(使用 Visual Studio)
cmake --preset windows-release
cmake --build --preset windows-release
# 构建产物默认在 build/bin/ 目录
通用 CMake(无条件偏好)
git clone https://github.com/erincatto/box3d.git
cd box3d
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build . --config Release
# 安装到系统(可选,需要 sudo)
sudo cmake --install .
版本不确定性说明:当前版本标注为 v0.1.0,但代码仓库的 git tag 和 GitHub Releases 可能已更新。首次使用前建议运行
git tag或查看 Releases 页面确认实际可用版本号。
编译示例 App(附带图形界面)
构建示例程序需要额外依赖:
- C++20 编译器(示例代码用 C++ 编写)
- sokol(跨平台图形 API 封装,D3D11/Metal/OpenGL 4.5)
- Dear ImGui(UI 界面)
# CMakePresets 已包含示例构建
cmake --preset linux-release # Linux + OpenGL
cmake --build --preset linux-release
# 运行示例
./build/bin/samples # Linux
.\build\bin\Release\samples.exe # Windows
./build/bin/Release/samples # macOS
编译 Web 版本(WebAssembly)
# 安装 Emscripten SDK
emcmake cmake -B build -DBOX3D_SAMPLES=OFF
cmake --build build
核心用法
集成到你的项目
Box3D 核心库有两种集成方式:
方式一:FetchContent(CMake,推荐)
include(FetchContent)
FetchContent_Declare(box3d
GIT_REPOSITORY https://github.com/erincatto/box3d.git
GIT_TAG v0.1.0) # 确认实际可用版本号
FetchContent_MakeAvailable(box3d)
target_link_libraries(my_app PRIVATE box3d::box3d)
方式二:Git Submodule / 手动复制
git submodule add https://github.com/erincatto/box3d.git extern/box3d
add_subdirectory(extern/box3d)
target_link_libraries(my_app PRIVATE box3d::box3d)
第一个程序(Hello World,纯 C)
参考 docs/hello.md 的最小示例:
#include <box3d/box3d.h>
int main(void) {
// 1. 创建世界,设定重力
b3WorldDef worldDef = b3DefaultWorldDef();
worldDef.gravity = (b3Vec3){ 0.0f, -10.0f, 0.0f };
b3WorldId worldId = b3CreateWorld(&worldDef);
// 2. 创建地面(静态刚体)
b3BodyDef groundBodyDef = b3DefaultBodyDef();
groundBodyDef.position = (b3Vec3){ 0.0f, -10.0f, 0.0f };
b3BodyId groundId = b3CreateBody(worldId, &groundBodyDef);
b3BoxHull groundBox = b3MakeBoxHull(50.0f, 10.0f, 50.0f);
b3ShapeDef groundShapeDef = b3DefaultShapeDef();
b3CreateHullShape(groundId, &groundShapeDef, &groundBox.base);
// 3. 创建动态刚体(从 y=4 落下)
b3BodyDef bodyDef = b3DefaultBodyDef();
bodyDef.type = b3_dynamicBody; // ← 必须设为 dynamic
bodyDef.position = (b3Vec3){ 0.0f, 4.0f, 0.0f };
b3BodyId bodyId = b3CreateBody(worldId, &bodyDef);
b3BoxHull dynamicBox = b3MakeCubeHull(1.0f); // 单位立方体
b3ShapeDef shapeDef = b3DefaultShapeDef();
shapeDef.density = 1.0f;
shapeDef.baseMaterial.friction = 0.3f;
b3CreateHullShape(bodyId, &shapeDef, &dynamicBox.base);
// 4. 模拟 90 帧(1.5 秒 @ 60Hz)
float timeStep = 1.0f / 60.0f;
int subStepCount = 4;
for (int i = 0; i < 90; ++i) {
b3World_Step(worldId, timeStep, subStepCount);
b3Vec3 pos = b3Body_GetPosition(bodyId);
b3Quat rot = b3Body_GetRotation(bodyId);
printf("%.2f %.2f %.2f\n", pos.x, pos.y, pos.z);
}
// 5. 清理
b3World_Destroy(worldId);
return 0;
}
编译(假设 Box3D 已安装):
gcc -std=c17 -I/path/to/box3d/include hello_box3d.c -lbox3d -lm -o hello_box3d
关键 API 速查
| 功能 | 函数 |
|---|---|
| 创建世界 | b3CreateWorld(&worldDef) |
| 创建刚体 | b3CreateBody(worldId, &bodyDef) |
| 创建盒形碰撞体 | b3CreateHullShape(bodyId, &shapeDef, &hullData) |
| 创建球形碰撞体 | b3CreateSphereShape(...) |
| 创建胶囊碰撞体 | b3CreateCapsuleShape(...) |
| 创建铰链约束 | b3CreateRevoluteJoint(...) |
| 创建距离约束 | b3CreateDistanceJoint(...) |
| 射线投射 | b3World_RayCast(worldId, &ray, &callback) |
| 步进模拟 | b3World_Step(worldId, timeStep, subSteps) |
| 获取刚体位置 | b3Body_GetPosition(bodyId) |
| 获取刚体旋转 | b3Body_GetRotation(bodyId)(返回四元数) |
碰撞形状类型
Box3D 支持以下碰撞几何体:
- Convex Hull(凸包):通用凸多面体
- Box(盒):
b3MakeBoxHull(hx, hy, hz)半Extent - Sphere(球):
b3MakeSphereHull(radius) - Capsule(胶囊):两个半球 + 圆柱
- Triangle Mesh(三角形网格):静态地形
- Height Field(高度场):大规模地形,内存友好
约束(关节)类型
- Revolute Joint:铰链关节(类似门轴)—— 1 个旋转自由度
- Prismatic Joint:滑动关节——1 个平移自由度
- Distance Joint:固定两点距离
- Weld Joint:焊接,完全约束相对位置和旋转
- Wheel Joint:轮轴,驱动轮子的悬挂系统
典型适用场景
| 场景 | 推荐配置 |
|---|---|
| 大型物理模拟(如落塔、碰撞) | 4-8 substeps,启用 SIMD,多线程 |
| 确定性联机游戏 | 固定 1/60 timestep,关闭多线程,保证所有客户端同步 |
| 刚体下落/堆积 | 启用 Island Sleep,大型刚体堆会自动进入休眠节省算力 |
| 角色控制器 | 使用内置 Character Mover 系统,配合 Capsule 碰撞体 |
| 地形物理 | Height Field + 静态三角网格,避免全动态刚体 |
坑与注意
-
v0.1.0 = 早期版本:虽然 Box2D 非常成熟,但 Box3D 是全新项目。API 设计、文档和示例都在快速迭代中,生产使用前务必锁定具体版本 tag,不要直接用 main 分支。
-
物理单位约定:Box3D 以米/千克/秒(mks)为单位。1 单位 = 1 米。建议让场景物体尺寸接近真实世界(成年人约 1.7 米高),否则单精度浮点精度会出问题。模拟冰川或尘埃粒子尺寸会有精度问题。
-
C API 内存管理需小心:Box3D 是纯 C API,所有
b3Create*函数返回的是 opaque handle。销毁对象用b3World_Destroy(一次性销毁整个世界),不要手动 free。 -
Character Mover 不等于角色控制器:Box3D 提供的是物理层面的 Character Mover(处理地面碰撞、爬坡等),但行走逻辑、动画、输入处理需要自己实现——这是和 Unity/UE 内置 Character Controller 的本质区别。
-
多线程需提供 Task System:Box3D 的多线程求解需要你自己实现
enqueueTask/finishTask回调并传入userTaskContext。如果你用 Ogre、EnTT 等有自带 task 系统的引擎,需要做适配层。 -
SIMD 版本需 CPU 支持:x86 必须支持 SSE2(2000 年后绝大多数 CPU 都支持),ARM 必须支持 NEON。旧设备需要定义
BOX3D_DISABLE_SIMD禁用。 -
回放和录制:Box3D 支持确定性回放(
Recording and Replay),这对调试和外挂检测很有用,但需要参考文档手动实现记录格式。 -
文档质量有限:目前文档以 Doxygen 生成,且仍在完善中。遇到问题可以看示例代码(
samples/目录)或参考 Box2D 文档——很多概念是 2D→3D 的自然扩展。
与同类对比
| 引擎 | 许可 | 语言 | 确定性 | 依赖 | 适合场景 |
|---|---|---|---|---|---|
| Box3D | MIT | C17 | ✅ 跨平台 | 零依赖 | 游戏、轻量级、需要确定性的场景 |
| Bullet | Zlib | C++ | ❌ 不保证 | 可选 | 通用 3D 物理,影视/游戏均可用 |
| PhysX | NVIDIA EULA | C++ | 部分 | SDK 安装 | AAA 游戏,NVIDIA 生态 |
| Havok | 商业 | C++ | ❌ | 闭源 DLL | AAA 商业游戏,授权费用高 |
| Jolt | Zlib | C++ / WASM | ✅ | 可选 | 游戏,WebAssembly 支持好 |
| ODE | LGPL | C | ✅ | 零依赖 | 老项目、教学 |
Box3D 核心差异:Box3D 是唯一同时做到"零外部依赖 + 跨平台确定性 + SIMD 优化 + 数据导向设计"的纯 C 开源方案,定位非常清晰——面向现代游戏而非通用物理仿真。
一句话推荐结论
Box3D 是 Box2D 作者 Erin Catto 推出的 3D 续作,如果你已经在用 Box2D 或需要一个零依赖、跨平台确定性、高性能的 3D 物理库,Box3D 值得关注——但目前尚处 v0.1.0,生产项目建议锁定版本并充分测试。
参考来源
- GitHub README:https://github.com/erincatto/box3d
- 最小示例文档:docs/hello.md
- 构建指南:README.md → Building all platforms / Building with CMake presets
- 安装指南:README.md → Building and installing
- YouTube 介绍视频(官方):https://www.youtube.com/watch?v=jr_Fzl2XwKU
- 许可:MIT(来源:README)
- 构建 badge:GitHub Actions CI