Box3D: The Physics Engine That Treats Determinism Like a Feature
A 3D successor to Box2D that swaps raw pointers for IDs, rewrites math for repeatability, and uses soft stepping to keep stacks, joints, and large worlds from falling apart.
- Box3D treats physics as a repeatability problem first, which is why its API, math, and stepping model all bias toward stable behavior instead of raw convenience.
- The engine replaces pointer-heavy ownership with IDs and transient events, which makes integration safer and reduces the chance of stale state leaking into game code.
- Soft stepping is the core design move, because dividing a frame into controlled substeps is more effective than simply cranking up iteration counts.
- Box3D is deliberately narrower than broader engines like Bullet or PhysX, and that restraint is part of its appeal for teams that want clarity and predictability.
Box3D is easy to misread if you start from the usual physics-engine checklist. It is not trying to impress you with a giant feature surface first. It is trying to keep a simulation honest when the world gets noisy, the frame budget gets tight, and tiny numeric differences start showing up as bugs.
That matters because physics failures are rarely dramatic at the root. They show up as a stack that slowly jitters, a joint that behaves differently on another machine, or a ray cast that costs too much once the world gets crowded. Box3D is built to narrow those failure modes before they metastasize.
I started Box3D to provide a 3D physics engine that is efficient and accurate, suitable for games and other interactive applications.
Why physics engines fail in the same boring ways
Most physics bugs are not about exotic math. They are about drift, stale references, and broadphase work that scales badly when the scene gets busy. The problem is not that the engine cannot simulate a box. The problem is that it cannot keep simulating the same box the same way everywhere.
Box3D’s appeal starts there. It is a response to the unglamorous reality that games need physics to be repeatable, cheap to query, and predictable under stress. Stability is not a side effect. It is the product.
The API is built around trust, not pointers
Box3D does something quietly radical for a physics engine: it centers the public API on IDs instead of raw pointers. That sounds like a small implementation detail, but it changes the contract between the engine and your game. You ask the world to step. You get back events. You do not keep dangling ownership in your own code.
b3WorldId world = b3CreateWorld(&def);
b3World_Step(world, timeStep, subStepCount);
b3ContactEvents events = b3World_GetContactEvents(world);
for (int i = 0; i < events.count; ++i) {
// Consume transient contact data here.
}
This is where Box3D starts to feel like a system designed for integration, not just simulation. IDs are easier to serialize, easier to invalidate, and easier to move through a host engine's job system. Transient events also keep the API honest. If a contact only exists for the current step, the API should not pretend otherwise.
Soft stepping is the engine’s real personality
If there is one idea that explains Box3D, it is soft stepping. The engine exposes a `subStepCount` because it is willing to spend a frame in smaller pieces rather than demand that one aggressive solve do everything at once. That is a stability trade. It lowers the chance that contact impulses spike, joints explode, or stacks collapse from one bad update.
This is not the same as blindly turning up iterations. More iterations can help, but they do not change the shape of the contract. Soft stepping changes the shape. It slices time, narrows the error introduced per slice, and gives the solver a calmer problem to solve.
That distinction matters in 3D, where rotational coupling and large piles of bodies make instability show up faster. Box3D is less interested in pretending the solver is perfect than in making each step easier for the solver to survive.
Box3D fights floating-point chaos at the math layer
Determinism is not just a networked-multiplayer concern. It is also a debugging concern. If the same scene behaves differently on different hardware, the engine becomes harder to trust. Box3D responds with custom trigonometric functions, precision switches such as `BOX3D_DOUBLE_PRECISION`, and a math layer designed to stay repeatable across platforms.
#ifdef BOX3D_DOUBLE_PRECISION
typedef double b3Pos;
#else
typedef float b3Pos;
#endif
b3Vec2 p = b3MakeVec2(100000.0, 3.0);
auto angle = b3Atan2(p.y, p.x);
auto cs = b3ComputeCosSin(angle);
That combination is what makes large worlds possible without inviting the usual edge-of-the-map wobble. Doubling precision helps, but the real discipline is that the math is chosen to behave like a system, not a collection of library calls with platform-specific quirks.
The dynamic tree keeps the world searchable
A physics engine lives or dies on broadphase performance. Box3D uses a dynamic AABB tree with proxies so it can answer queries without dragging the whole world into every check. Ray casts, overlap queries, and box casts stay local, even when the simulation itself is large.
The proxy model matters because it separates moving things from the data structure that indexes them. That is the difference between a world that stays responsive and one that starts feeling expensive as soon as the scene gets busy.
Box3D is modular on purpose
The repository layout matches the philosophy. Public headers live in `include/box3d/`, the core implementation sits in `src/`, samples are isolated in `samples/`, and docs stay in `docs/`. The core is written in portable C17. The samples can use C++20, graphics helpers, and UI tools without contaminating the engine itself.
That separation is more than housekeeping. It signals what Box3D wants to be: a compact engine core with a host-controlled runtime around it. Multithreading is handled by callbacks into the application, which keeps the engine portable without pretending every game uses the same scheduler.
Where Box3D sits among Bullet, PhysX, and Newton
| Engine | Positioning | Strength | Trade-off |
|---|---|---|---|
| Box3D | Disciplined 3D successor to Box2D | Determinism, soft stepping, clean API | Smaller ecosystem and narrower scope |
| Bullet | Broad open-source physics toolkit | Feature breadth and community | More surface area to tune and integrate |
| PhysX | Industrial-scale commercial engine | Performance and platform reach | Licensing and heavier integration gravity |
| Newton | Open-source stability-focused engine | Solid realism and simplicity | Smaller community and less momentum |
Box3D is not trying to win by being everything. It is trying to win by being legible. The design choices line up around one promise: if you understand the contract, the engine will stay out of your way more often than it surprises you.
Box3D seems promising, but I'm curious about its performance compared to other established engines like Bullet.