The pure-Rust physics engine just grew a real Python skin — PyO3 bindings you can import, kept strictly optional behind a feature flag.
Today we released OxiPhysics 0.1.1 — a consolidation release for the unified, pure-Rust physics engine that targets Bullet (rigid body), OpenFOAM (CFD), LAMMPS (molecular dynamics), and CalculiX (FEM). The headline: the Python bindings are now real, not a JSON bridge — and they are feature-gated, so the heavy PyO3 dependency is opt-in.
No C. No C++. No Fortran. The core stays 100% C/Fortran-free, default features remain pure Rust, and OxiPhysics still compiles to a single static binary or to wasm32 for the browser. The difference in 0.1.1 is reach: the same engine is now callable from Python and from JavaScript, without dragging native toolchains into your default build.
Why 0.1.1 matters
In 0.1.0, the oxiphysics-python and oxiphysics-wasm crates shipped a JSON/serde bridge — useful, but not the ergonomic, typed bindings real users expect. The pain is familiar to anyone who has shipped a Rust library to Python: the moment you add PyO3, you have made everyone who only wanted the Rust crate pay for a Python toolchain at build time. The fix is to make the FFI layer optional. That is exactly what 0.1.1 does.
- Real PyO3 0.28 bindings.
oxiphysics-pythonnow exposes 210#[pyclass]types across 14 domain modules — a genuine, importable Python surface over the physics engine, validated by its own pytest suite. - Optional and feature-gated. The PyO3 dependency is gated behind a feature, so the default
oxiphysicsbuild links zero Python symbols. You opt into bindings only when you build the extension module. - Real wasm-bindgen 0.2 bindings.
oxiphysics-wasmnow carries 929#[wasm_bindgen]entry points across 27+ bridge files — the engine, callable from JavaScript and TypeScript in the browser. - Crates graduate to Stable. Most domain crates — core, geometry, collision, materials, FEM, I/O, LBM, MD, SPH, rigid, soft body, constraints, vehicle, and viz — move from Alpha to Stable in this release, reflecting a settled public API.
- Still honest, still complete. Zero
todo!()/unimplemented!()stubs across the workspace, ~60,087 tests passing undercargo nextest, strict Rustdoc, andcargo publish --dry-rungreen for the top-level crate.
Technical Deep Dive: how the bindings stay optional
The architecture that makes 0.1.1 possible is the same layered workspace from 0.1.0 — a pure-Rust numeric core, domain solvers above it, and bindings strictly on top — but the binding crates are now wired so that the FFI dependency is a switch, not a tax.
-
Pure-Rust core, untouched (
oxiphysics-coreand the domain crates) The solver crates have no knowledge of Python or WASM. They are the sameVec3/Quat/Transformmath, the same GJK/EPA collision, the same SPH/LBM/FEM/MD solvers — promoted to Stable status because their public APIs have settled. Nothing here links PyO3. -
oxiphysics-python— PyO3 0.28, behind a feature (#[pyclass]× 210) The Python crate wraps the domain types in#[pyclass]declarations across 14 modules, but the PyO3 dependency is feature-gated: a consumer who only wants the Rust engine never compiles it. When you do build the extension module (e.g. withmaturin), you get typed Python classes that call straight into the Rust solvers — no JSON marshalling, no serde round-trip. -
oxiphysics-wasm— wasm-bindgen 0.2 (#[wasm_bindgen]× 929) The browser bridge exposes the engine to JS/TS across 27+ files, so the same simulation that runs as a native static binary can run inside a web page. As with Python, the binding layer sits above the pure-Rust core and pulls inwasm-bindgenonly on the wasm path.
The principle throughout: default features are 100% Rust. Bindings are a deliberate opt-in, so library consumers get the engine with no FFI surprises and binding consumers get an ergonomic, typed surface — without either one paying for the other.
Getting Started
cargo add oxiphysics
For Rust consumers nothing changes — the default build is pure Rust and links no PyO3. The full physics surface is still one import away:
use oxiphysics::core::math::Vec3;
use oxiphysics::core::Transform;
// Build a transform at a given position
let origin = Transform::default();
let offset = Vec3::new(1.0, 2.0, 3.0);
// Transform a point from local space into world space
let world_pt = origin.transform_point(&offset);
println!("world: {:?}", world_pt);
To build the Python extension module, opt into the bindings crate with PyO3 enabled (typically via maturin develop), and the 210 #[pyclass] types become importable from Python — backed end to end by the same pure-Rust solvers.
What’s New in 0.1.1
- Feature-gated Python bindings.
oxiphysics-pythonmakes its PyO3 dependency optional behind a feature flag, so the default build stays free of Python toolchain requirements while real PyO3 0.28 bindings (210#[pyclass]across 14 domain modules) are available on demand. - Real WASM bindings.
oxiphysics-wasmships wasm-bindgen 0.2 entry points (929#[wasm_bindgen]across 27+ bridge files) for browser-side simulation. - Workspace version consistency. A coordinated version bump keeps the internal crate graph aligned across the workspace.
- Continued Pure Rust implementation. The engine remains 100% C/Fortran-free; default features are entirely Rust.
Tips
- Don’t pay for Python if you only want Rust. The default
oxiphysicsbuild links zero PyO3 symbols. You only pull the Python toolchain in when you explicitly enable the bindings feature and build the extension module — keep your service builds lean by leaving it off. - Build wheels with maturin. Because the FFI layer is feature-gated, the clean way to ship the Python package is to enable the bindings feature and run
maturin(develop or build) — that is what produces the importable#[pyclass]surface. - Take the engine to the browser. The wasm-bindgen 0.2 layer means an OxiPhysics simulation can run client-side in a web page — something the C/C++/Fortran incumbents can’t do without an Emscripten/WASM porting ordeal.
- Treat “Stable” as a contract signal. Most domain crates moved from Alpha to Stable in 0.1.1, so their public APIs are settled — a good cue that it’s safe to build on
oxiphysics-fem,oxiphysics-sph,oxiphysics-md, and friends for real work. - Upgrade in place from 0.1.0. This is a consolidation release with no breaking changes to the pure-Rust API — bump the version and your existing code keeps compiling; the new capability is purely additive (optional bindings).
This is the foundation
OxiPhysics is the simulation layer of the broader COOLJAPAN pure-Rust ecosystem, and 0.1.1 builds directly on its siblings — its solver paths lean on SciRS2 (scientific-computing primitives, via scirs2-integrate), OxiFFT (pure-Rust spectral transforms), and OxiARC (pure-Rust compression, via oxiarc-zstd) instead of any C/C++ stack. The result is an engine that is sovereign top to bottom: pure Rust by default, with real Python and WASM bindings available the moment you ask for them.
Repository: https://github.com/cool-japan/oxiphysics
Star the repo if you want a physics engine you can call from Rust, Python, and the browser — without a C toolchain anywhere in the default build.
Pure Rust physics is here — fast, safe, and sovereign.
— KitaSan at COOLJAPAN OÜ May 17, 2026