OxiHuman’s physics and export layers just stopped faking it — eight placeholder kernels are now real, from multibody dynamics to skinned glTF.
Today we released OxiHuman 0.2.0 — the privacy-first, pure Rust parametric human body generator that runs entirely client-side, with a wave of genuine algorithm implementations replacing the last of its scaffolding stubs.
No cloud. No Python. No server ever receives your body parameters. No data leakage. No network calls by default. Just clean, memory-safe, deterministic 3D human mesh synthesis that runs in the browser via WASM + WebGPU or natively anywhere — now backed by real rigid-body dynamics, real skinned export, and a real procedural environment.
Why OxiHuman 0.2.0 is a game changer
For a generator that prides itself on determinism and correctness, “returns 0 for now” is not good enough. 0.2.0 is the release where eight of those compromises get retired and replaced with textbook-correct, test-verified math. This is the minor-version bump that turns several “it compiles” paths into “it’s actually right.”
The headline wins, all grounded in real algorithms and analytic test checks:
- Articulated-body forward dynamics.
forward_dynamics_stepinrigid_body_tree.rsreplaces a scalarτ/mass·dtintegrator with real multibody dynamics: it assembles the joint-space inertia matrixH(q)via the Composite-Rigid-Body Algorithm (propagating each link’s spatial inertia through the tree with world-frame geometric Jacobians), computes the Coriolis/centrifugal biasC(q,q̇)with the Recursive Newton–Euler Algorithm, solvesH q̈ = τ − Cby Gauss–Jordan with partial pivoting, and integrates semi-implicitly.total_kinetic_energynow returns the correct½ q̇ᵀH q̇. Verified against the single-link parallel-axis identity (H = Izz + m·d²), kinetic-energy match, and base-torque sign. - Real skinned GLB export.
export_glb_with_skeletoninglb.rsnow emits properJOINTS_0(u16×4) andWEIGHTS_0(f32×4) vertex attributes plus per-jointinverseBindMatrices. Joint world-bind transforms come from memoised forward kinematics under any parent ordering; inverse-bind matrices use a general 4×4 inverse; per-vertex weights use the top-4 nearest joints, inverse-distance weighted and normalised. Read back from the binary chunk, every vertex’s weights sum to 1. Previously the skeleton was used for the node hierarchy only — now your exported glTF is genuinely skinned. - Real procedural sky. The old
CubemapStubbecomes a realCubemapinbackground_renderer.rs: equirectangularuv → direction, OpenGL cube-face selection, a smoothstep elevation gradient from nadir to zenith, horizon haze, and a directional sun highlight — a genuine direction-dependent environment instead of a flat colour. - Exact CRC-32 combine.
CrcTable::combinenow implements the zlib GF(2) matrix algorithm — advancingcrc1overlen2zero bytes via repeated GF(2) matrix squaring, then folding incrc2.combine(crc(A), crc(B), B.len())now equalscrc(A‖B)exactly; it used to return 0. - Divergence-theorem fracture volumes.
cell_volume_approxinfracture.rscomputes the star-shaped solid volume from the seed apex viaV = (1/6)|Σ (a−s)·((b−s)×(c−s))|over a fan triangulation — exact for closed, consistently wound cells — replacing the oldarea × 0.1thickness heuristic. - Stokes-theorem discrete curl.
edge_flow_field_curl_magnitudenow computes curl as circulation divided by enclosed area (area via Newell’s method, circulation via the trapezoidal rule) instead of returning 0. A rotational fieldF = (−y, x, 0)correctly yields curl 2.0. - Real expression weights parsing.
expression_from_jsonnow parses the full"weights":[…]array instead of discarding it as a single0.0— and the module is finally wired into the crate (it was an orphan file that never compiled). - Geometric Laplacian AO.
smooth_aois now a real geometric Laplacian over an adaptive proximity graph, with a new topological 1-ring umbrella variant (smooth_ao_laplacian) over a triangle index buffer.
All of this lands with 33,410 passing tests (up from 33,364), 0 clippy warnings across the workspace, and 0 unwrap in production code.
Technical Deep Dive: real math in the physics and export layers
OxiHuman’s layered workspace is unchanged in shape, but several layers got substantially more honest in 0.2.0:
-
Physics & Biomechanics (
oxihuman-physics) The big story.rigid_body_tree.rsnow does true articulated-body forward dynamics (CRBA forH(q), RNEA for the bias term, a linear solve forq̈).fracture.rscomputes exact cell volumes by the divergence theorem. To support this,ArtBodygainscom_offset: [f32; 3]andlink_length: f32so links carry real geometry into the dynamics. -
Mesh Pipeline (
oxihuman-mesh) Discrete differential operators got real:edge_flow_field_curl_magnitudenow implements Stokes’ theorem (its ring argument changed to&[(usize, [f32; 3])]so each ring vertex maps to its flow vector), and ambient occlusion smoothing became a genuine Laplacian diffusion.AoMeshgains anindices: Vec<u32>field to carry triangle topology for the 1-ring operator. -
Export Pipeline (
oxihuman-export)glb.rsnow produces fully skinned glTF binaries withJOINTS_0/WEIGHTS_0and inverse-bind matrices, andCrcTable::combineis bit-exact.expression_io.rsparses real expression weights. -
Viewer (
oxihuman-viewer)background_renderer.rsrenders a procedural cubemap sky with a real elevation gradient, horizon haze, and a sun highlight —BackgroundType::CubemapStubis renamedBackgroundType::Cubemap.
0.2.0 also removes thirteen dead-code scaffolding modules that were never part of the public API — unreachable files carrying #![allow(dead_code)] across core, mesh, physics, and viewer — trimming the codebase of code that compiled but did nothing.
Getting Started
cargo add oxihuman
Generate a mesh from a few slider parameters and export it to a binary glTF:
use oxihuman_morph::engine::MorphEngine;
use oxihuman_export::gltf::GltfExporter;
fn main() -> anyhow::Result<()> {
let mut engine = MorphEngine::default();
engine.set_param("height", 0.6);
engine.set_param("weight", 0.4);
engine.set_param("age", 0.35);
let mesh = engine.build_mesh();
let exporter = GltfExporter::new();
let glb_bytes = exporter.export_glb(&mesh)?;
std::fs::write("human.glb", glb_bytes)?;
Ok(())
}
In the browser, the same engine runs entirely client-side via WebAssembly:
import init, { WasmEngine } from "./oxihuman_wasm.js";
await init();
const engine = new WasmEngine();
engine.set_param("height", 0.6);
engine.set_param("weight", 0.4);
const mesh_bytes = engine.export_mesh_bytes();
What’s New in 0.2.0
- Articulated-body forward dynamics in
rigid_body_tree.rs: CRBA-assembledH(q), RNEA Coriolis/centrifugal bias,H q̈ = τ − Csolve, semi-implicit integration; correct½ q̇ᵀH q̇kinetic energy. - Skinned GLB export:
JOINTS_0(u16×4),WEIGHTS_0(f32×4), and per-joint inverse-bind matrices, with per-vertex weights summing to 1. - Procedural cubemap environment: direction-dependent sky with elevation gradient, horizon haze, and a sun highlight (
CubemapStub→Cubemap). - Exact CRC-32 combine via the zlib GF(2) matrix algorithm —
combinenow equals the CRC of the concatenation. - Divergence-theorem fracture cell volumes replacing the old thickness heuristic.
- Stokes-theorem discrete curl (
edge_flow_field_curl_magnitude), exact on a rotational test field. - Real expression weights parser (
expression_from_json), and the previously-orphaned module is now compiled into the crate. - Geometric Laplacian ambient-occlusion smoothing, plus a topological 1-ring
smooth_ao_laplacianvariant;AoMeshgains anindicesfield. - API tweaks:
ArtBodygainscom_offsetandlink_length;AoMeshgainsindices;edge_flow_field_curl_magnitude’s ring parameter is now&[(usize, [f32; 3])]. - Cleanup: thirteen dead-code scaffolding modules removed; 33,410 tests, 0 clippy warnings, 0 production
unwrap.
Tips
- Set link geometry before stepping dynamics.
ArtBodynow carriescom_offsetandlink_length, and the forward-dynamics step uses them to buildH(q). Populate them with your real link geometry — leaving them at defaults gives correct math for a degenerate body, not the one you intended. - Pass flow vectors, not just positions, to the curl operator.
edge_flow_field_curl_magnitudenow takes&[(usize, [f32; 3])]— each ring vertex paired with its flow vector. If you were calling the old positions-only signature, update the call site; the new signature is what makes Stokes’ theorem exact. - Your exported glTF is now genuinely skinned.
export_glb_with_skeletonemitsJOINTS_0/WEIGHTS_0and inverse-bind matrices, so importers (Blender, three.js, Babylon.js) will animate the mesh by the skeleton — not just parent it under a node hierarchy. - Give AO smoothing a triangle index buffer. For the topological umbrella operator, populate
AoMesh::indicesand callsmooth_ao_laplacian; without indices you fall back to the adaptive proximity-graph Laplacian. - Rename
CubemapStub→Cubemap. The enum variant changed names along with becoming real. If you referencedBackgroundType::CubemapStub, switch toBackgroundType::Cubemap. combineis now safe to rely on. If you were avoidingCrcTable::combinebecause it returned 0, you can now compose CRCs of independently-hashed chunks and get the exact CRC of their concatenation.
This is the foundation
OxiHuman is the privacy-first, client-side human modeling layer for the COOLJAPAN ecosystem. As of this release it sits among a broad set of Pure Rust siblings — SciRS2 and NumRS2 for scientific and numerical computing, ToRSh and TenfloweRS for deep learning, OxiMedia for media and video pipelines, OxiPhysics for general physics, OxiBLAS and Oxicode for the low-level building blocks, and OxiGAF for Gaussian-avatar reconstruction. Everything stays C-, C++-, and Fortran-free, compiling to a single static binary or to WASM, with no body data ever leaving the machine.
Repository: https://github.com/cool-japan/oxihuman
Star the repo if you want a human generator whose physics and export paths are real, verified, and sovereign.
Pure Rust client-side human modeling is here — fast, private, and sovereign.
— KitaSan at COOLJAPAN OÜ June 19, 2026