This fork exists to answer two questions:
- What would Box3D look like if it was entirely fixed point?
- Exactly how much slower would it be?
The answer: 2× slower (geometric mean over the full benchmark suite, measured on Apple silicon and on AMD Zen 4).
What you get in exchange is one thing: a truly huge world with uniform precision everywhere.
That trade is narrower than it sounds, and you should probably keep using vanilla Box3D — see Should I use this? for the honest comparison.
Box3D with every float torn out of the simulation and replaced with Q48.16
fixed point in an int64_t. All of it: the solver, GJK, the trig, the ray
casts, the mass properties, the recording format. The float SIMD is gone (it
grew back on AVX-512 and NEON — same bits, just faster). In
exchange, resolution is a uniform 1/65536 everywhere in a ±1.4×10¹⁴ meter
world, every step is still bit-exact on every platform (vanilla Box3D already
was — see below), and all 22 unit test suites still pass.
benchmark -t=4 -w=4 -r=2 (4 workers, min of 2 runs, continuous collision on),
Apple M3 Ultra, macOS 26.5.1, Apple clang 21, RelWithDebInfo, Ninja.
Measured 2026-07-13 at the current build defaults; all three columns were
re-run in the same session, float included.
- float = vanilla Box3D at
e961bfb(single precision, NEON SIMD) - fixed = this tree, scalar int64 lanes
- fixed+NEON = this tree with
-DBOX3D_NEON=ON(narrow phase only)
| Benchmark | float (ms) | fixed (ms) | fixed+NEON (ms) | fixed/float | NEON/float | NEON speedup |
|---|---|---|---|---|---|---|
| convex_pile | 13,725.4 | 21,391.2 | 10,316.8 | 1.6× | 0.75× | 2.07× |
| joint_grid | 276.7 | 789.1 | 785.3 | 2.9× | 2.8× | 1.00× |
| junkyard | 4,875.1 | 9,859.1 | 8,750.3 | 2.0× | 1.8× | 1.13× |
| large_pyramid | 547.8 | 1,676.9 | 1,625.0 | 3.1× | 3.0× | 1.03× |
| large_world | 13.4 | 23.5 | 23.9 | 1.8× | 1.8× | 0.98× |
| many_pyramids | 518.0 | 1,681.5 | 1,651.8 | 3.2× | 3.2× | 1.02× |
| rain | 610.5 | 1,289.0 | 1,286.1 | 2.1× | 2.1× | 1.00× |
| trees25 | 234.5 | 358.7 | 348.4 | 1.5× | 1.5× | 1.03× |
| trees50 | 117.5 | 196.5 | 195.0 | 1.7× | 1.7× | 1.01× |
| trees100 | 84.2 | 154.1 | 149.0 | 1.8× | 1.8× | 1.03× |
| washer | 6,896.4 | 13,599.9 | 13,606.9 | 2.0× | 2.0× | 1.00× |
Geometric mean: 2.07× slower scalar, 1.90× with NEON. I expect this to worsen to around 2.5× as any worthwhile optimizations found during this exercise are backported to the real Box3D.
Probably not. Check what you actually need against what vanilla Box3D already does:
-
Determinism? Vanilla Box3D is already deterministic in floating point across platforms. The only argument that can be made against Box3D determinism is that floating point determinism across different platforms like x64 vs. ARM is an unstable equilibrium maintained by constant effort, while fixed point determinism is in stable equilibrium and always works.
-
A big world? Vanilla Box3D already handles a 20,000 km cubed world with just ~1M of broadphase padding at 10,000km from origin, and its double position support costs just 3% over standard float positions.
-
Uniform resolution over a truly enormous range? The same 1/65536 everywhere in a ±1.4×10¹⁴ m world, with zero precision falloff away from the origin — this is the one thing this tree does that vanilla Box3D does not.
If your world genuinely outruns what large positions plus broadphase padding cover, this library is the answer to your problem. Be sure that is your problem before paying 2× for it.
For everything else, vanilla Box3D almost certainly does what you need: https://github.com/erincatto/box3d
MIT, same as Box3D.