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 + 静态三角网格,避免全动态刚体

坑与注意

  1. v0.1.0 = 早期版本:虽然 Box2D 非常成熟,但 Box3D 是全新项目。API 设计、文档和示例都在快速迭代中,生产使用前务必锁定具体版本 tag,不要直接用 main 分支。

  2. 物理单位约定:Box3D 以米/千克/秒(mks)为单位。1 单位 = 1 米。建议让场景物体尺寸接近真实世界(成年人约 1.7 米高),否则单精度浮点精度会出问题。模拟冰川或尘埃粒子尺寸会有精度问题。

  3. C API 内存管理需小心:Box3D 是纯 C API,所有 b3Create* 函数返回的是 opaque handle。销毁对象用 b3World_Destroy(一次性销毁整个世界),不要手动 free。

  4. Character Mover 不等于角色控制器:Box3D 提供的是物理层面的 Character Mover(处理地面碰撞、爬坡等),但行走逻辑、动画、输入处理需要自己实现——这是和 Unity/UE 内置 Character Controller 的本质区别。

  5. 多线程需提供 Task System:Box3D 的多线程求解需要你自己实现 enqueueTask / finishTask 回调并传入 userTaskContext。如果你用 Ogre、EnTT 等有自带 task 系统的引擎,需要做适配层。

  6. SIMD 版本需 CPU 支持:x86 必须支持 SSE2(2000 年后绝大多数 CPU 都支持),ARM 必须支持 NEON。旧设备需要定义 BOX3D_DISABLE_SIMD 禁用。

  7. 回放和录制:Box3D 支持确定性回放(Recording and Replay),这对调试和外挂检测很有用,但需要参考文档手动实现记录格式。

  8. 文档质量有限:目前文档以 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