Announcing Box3D

Announcing Box3D

I’m happy to announce the release of Box3D, an open source 3D physics engine. It is now available on GitHub. 我很高兴地宣布 Box3D 的发布,这是一个开源的 3D 物理引擎。它现已在 GitHub 上开源。

You can think of Box3D as a fork of Box2D, extended with many features needed for 3D games. Some additions: 你可以将 Box3D 看作是 Box2D 的一个分支,并针对 3D 游戏所需的许多功能进行了扩展。新增功能包括:

  • Triangle mesh collision
  • 三角网格碰撞
  • Height-field collision
  • 高度图碰撞
  • Baked compound collision
  • 预烘焙复合碰撞

The core architecture of Box3D remains almost identical to Box2D. Box3D 的核心架构与 Box2D 几乎完全一致。

  • C API
  • C API
  • All library source is C17
  • 所有库源码均为 C17 标准
  • Sub-stepping solver
  • 子步求解器
  • Continuous collision
  • 连续碰撞检测 (CCD)
  • Graph coloring for large islands
  • 用于大型岛屿的图着色算法
  • Wide SIMD contact solver
  • 宽 SIMD 接触求解器
  • Multi-threading hooks
  • 多线程钩子
  • Optional internal scheduler
  • 可选的内部调度器
  • Large world support with doubles for position
  • 支持使用双精度浮点数进行定位的大世界支持
  • Cross platform determinism
  • 跨平台确定性
  • Recording and replay
  • 录制与回放

If you want to see Box3D in action, watch this video: 如果你想看看 Box3D 的实际运行效果,请观看此视频:

There are two main reasons Box3D exists. But there is a lot to unpack. So stay awhile, and listen. Box3D 的诞生主要有两个原因。但内容较多,请稍作停留,听我细细道来。

Reason 1: The Legend of California

原因 1:《加州传奇》(The Legend of California)

The first reason I developed Box3D is that the game I’ve been working on needs it. Let me explain. 我开发 Box3D 的第一个原因是,我正在开发的游戏需要它。让我解释一下。

Problems with native Unreal physics

原生虚幻引擎物理的问题

I’ve been working on The Legend of California at Kintsugiyama since 2022. This game is built using the Unreal engine. We started with version 5.0. Our experiments with the native physics engine (called Chaos) had some problems. 自 2022 年以来,我一直在 Kintsugiyama 开发《加州传奇》。这款游戏是使用虚幻引擎构建的,我们从 5.0 版本开始。我们在使用原生物理引擎(Chaos)时遇到了一些问题。

There was no support for simulating gyroscopic torques. This means slender shapes could spin for a long time, conserving angular velocity. For example, see this video of a spinning rifle. In 2015 I developed a ~10 line drop-in algorithm for adding gyroscopic torques to any physics engine and presented it at the Game Developer Conference: presentation. So I could have easily added this feature to the Chaos solver. Epic added this feature in late 2024. However, that was not my biggest problem. 它不支持模拟陀螺力矩。这意味着细长物体在旋转时会长时间保持角速度。例如,请看这个步枪旋转的视频。2015 年,我开发了一个约 10 行代码的插件算法,用于为任何物理引擎添加陀螺力矩,并在游戏开发者大会 (GDC) 上进行了演示。所以我本可以轻松地将此功能添加到 Chaos 求解器中。Epic 在 2024 年底才添加了此功能。然而,这并不是我面临的最大问题。

Being a survival game, one of the first things I worked on was chopping down trees. The falling trees moved erratically, teleporting around the screen. My best guess is that Chaos was using some sort of continuous collision fallback. This simulation was a large capsule falling on a smooth triangle mesh. This scenario should have been easy to simulate. 作为一款生存游戏,我最先着手的工作之一就是砍树。倒下的树木移动异常,在屏幕上瞬移。我猜测 Chaos 可能使用了某种连续碰撞回退机制。该模拟场景是一个大型胶囊体落在平滑的三角网格上,这本应是一个很容易模拟的场景。

Another factor is that The Legend of California needs to manage a lot of entities. Hundreds of thousands of entities exist on the server. We need a fast broad-phase for this. This is so central to our game that it seemed risky to hand this off to middleware. I have a lot of experience working on broad-phase data structures. I even did a GDC presentation on the topic. So we reached a pivot point with our physics tech. 另一个因素是《加州传奇》需要管理大量实体。服务器上存在数十万个实体,我们需要一个快速的粗略阶段 (broad-phase) 算法。这对我们的游戏至关重要,将其交给中间件处理风险太大。我在粗略阶段数据结构方面拥有丰富的经验,甚至为此做过 GDC 演讲。因此,我们的物理技术到了一个转折点。

All these factors were adding up and I needed to make a decision: try to fix the native solution or replace it with an outside physics engine. I was considering using an existing open source physics engine, such as Jolt. Being a physics programmer, I was pretty confident that I could at least fork Jolt and get the outcomes we need for our game. However, a good friend suggested another course of action. 所有这些因素加在一起,我必须做出决定:是尝试修复原生方案,还是用外部物理引擎替换它。我曾考虑使用现有的开源物理引擎,例如 Jolt。作为一名物理程序员,我有信心至少可以 fork Jolt 并获得我们游戏所需的结果。然而,一位好友建议了另一种方案。

Valve to the rescue

Valve 的援手

My friend Dirk Gregorius is an accomplished physics programmer, having shipped a custom physics engine in Half-Life: Alyx called Rubikon. Dirk maintains a hobby/home version of Rubikon. Let’s call this “Rubikon-Lite”. He suggested that I could fork Rubikon-Lite and modify it to my needs. So that’s what I did. 我的朋友 Dirk Gregorius 是一位成就卓著的物理程序员,他曾在《半衰期:爱莉克斯》中发布过名为 Rubikon 的自定义物理引擎。Dirk 维护着一个 Rubikon 的业余/个人版本,我们称之为“Rubikon-Lite”。他建议我 fork Rubikon-Lite 并根据我的需求进行修改。于是我照做了。

I hooked Rubikon-Lite directly into Unreal. It worked great! We got gyroscopic torques and trees fell nicely. Everything just worked. 我将 Rubikon-Lite 直接接入了虚幻引擎。效果非常好!我们实现了陀螺力矩,树木倒下的效果也很自然。一切都运行顺畅。

The topic of replacing the physics engine in Unreal is likely a whole blog post (or more) on its own. I was able to make a few shortcuts because: 替换虚幻引擎中的物理引擎这个话题本身可能就需要一篇(甚至更多)博客文章来详述。我之所以能走一些捷径,是因为:

  • we use our own scripting system (not Blueprint)
  • 我们使用自己的脚本系统(而非蓝图)
  • we use the Esoterica animation system ported to Unreal
  • 我们使用了移植到虚幻引擎的 Esoterica 动画系统
  • we have a custom ECS that hooks to Box3D directly
  • 我们拥有一个直接接入 Box3D 的自定义 ECS(实体组件系统)

Box2D v3.0 had many optimizations I wanted to bring into my Rubikon-Lite fork. At some point I realized I needed to keep my 2D and 3D efforts as similar as possible, for efficiency and sanity. So I replaced almost all the APIs, data structures, and algorithms in Rubikon-Lite with Box2D code. Fortunately, the data structures for 2D and 3D are largely indifferent to spatial dimensions. Eventually my Rubikon-Lite fork transformed into Box3D. Box2D v3.0 拥有许多我想要引入到 Rubikon-Lite 分支中的优化。在某个阶段,我意识到为了效率和保持清醒,我需要尽可能保持 2D 和 3D 开发的一致性。因此,我用 Box2D 的代码替换了 Rubikon-Lite 中几乎所有的 API、数据结构和算法。幸运的是,2D 和 3D 的数据结构在很大程度上与空间维度无关。最终,我的 Rubikon-Lite 分支演变成了 Box3D。

Today Box3D still has some Rubikon-Lite code in the convex hull generation and some collision algorithms. The rest is code from Box2D and new code I wrote for Box3D. On the Valve side, Rubikon continues to evolve and Dirk has developed optimizations (similar to those in Box3D) in a new engine called Ragnarok. Look for that in future Valve games. 如今,Box3D 在凸包生成和部分碰撞算法中仍保留了一些 Rubikon-Lite 的代码。其余部分则来自 Box2D 以及我为 Box3D 编写的新代码。在 Valve 方面,Rubikon 仍在不断演进,Dirk 已经在名为 Ragnarok 的新引擎中开发了(类似于 Box3D 中的)优化。敬请期待它在未来 Valve 游戏中的表现。

Custom is better

自定义更好

The Legend of California is an ambitious project with a large open world and server authority. Falling trees, ragdolls, voxels, saloon doors, and tumbleweeds are all simulated on the server. Having a custom physics engine means I can tailor the feature set and performance to the needs of our game. 《加州传奇》是一个雄心勃勃的项目,拥有广阔的开放世界和服务器权威架构。倒下的树木、布娃娃系统、体素、酒吧门和风滚草都在服务器上进行模拟。拥有一个自定义物理引擎意味着我可以根据我们游戏的需求来定制功能集和性能。

For performance, I’ve done a lot of work to optimize for falling trees. We have huge redwood trees that fall fast onto a voxel terrain. Getting the mesh collision and CCD working well is a big effort. I’ve also worked on building collision meshes fast for our voxel system, since they need to be built at runtime. They build well with median split because voxels are grid-like. 在性能方面,我为优化倒下的树木做了大量工作。我们有巨大的红杉树,它们会快速倒在体素地形上。让网格碰撞和 CCD 良好运行是一项艰巨的任务。我还致力于为我们的体素系统快速构建碰撞网格,因为它们需要在运行时构建。由于体素是网格状的,使用中值分割法构建效果很好。

Streaming is another critical feature. Our strongholds are built using kitbashing. A large stronghold can easily have around 50,000 separate collision meshes. Loading these into the physics engine one-by-one is inefficient and uses a lot of memory. So I built a compound collision system where the separate collision shapes are cooked into an optimized data structure that can be loaded as a single uber shape. This removes the overhead of creating thousands of bodies and shapes. 流式传输是另一个关键功能。我们的据点是使用组件拼装 (kitbashing) 构建的。一个大型据点很容易拥有约 50,000 个独立的碰撞网格。将它们逐一加载到物理引擎中效率低下且占用大量内存。因此,我构建了一个复合碰撞系统,将独立的碰撞形状烘焙成一个优化的数据结构,可以作为一个单一的“超级形状”加载。这消除了创建数千个刚体和形状的开销。

Reason 2: Sustaining knowledge (and sanity)

原因 2:传承知识(与保持清醒)

On the personal side, I have been making physics engines for games since 2004. Every time I change jobs, I need to leave that work behind. This is partly the reason I developed Box2D. It is an open source project that captures my knowledge and efforts so I can use it as the basis for future work. However, on the 3D side I keep re-i 在个人层面,我自 2004 年以来一直致力于为游戏开发物理引擎。每次换工作,我都不得不将之前的工作抛在脑后。这也是我开发 Box2D 的部分原因。它是一个开源项目,记录了我的知识和心血,使我可以将其作为未来工作的基础。然而,在 3D 领域,我一直在重复……