Ready Player Me shut down its avatar service on 2026-01-31. OxiHuman 0.2.1 ships the answer: a human body generator with no server left to shut down — and, for the first time, a body asset pack you are actually allowed to redistribute.
Today we released OxiHuman 0.2.1 — the BodyLab production release: a fully client-side, browser-ready human body generator that ships its first real CC0 asset pack (OHPK v1), in-memory browser exports, a live three.js demo, a measurement-fit solver, and the legal / safety cleanroom that makes the whole thing shippable.
No cloud. No Python. No avatar account. No server ever receives your body measurements. No C, no C++, no Fortran — OxiHuman compiles to WebAssembly and the whole pipeline runs inside the browser sandbox. No upload step, no rate limit that isn’t yours to set, no vendor that can quietly go dark on you. Just a WASM module, a CC0-licensed asset pack you can actually redistribute, and a three.js viewer carrying parameter sliders through to a validated GLB / VRM / STL / OBJ export — entirely on the device in front of you, with 0 bytes uploaded and the whole footprint measured at runtime, not asserted.
Why OxiHuman 0.2.1 is a game changer
Hosted avatar generators keep proving the same point the hard way:
- Ready Player Me shut down its avatar service on 2026-01-31 — every product that had wired in a hosted, cross-platform avatar generator woke up needing a replacement overnight. Union Avatars followed not long after.
- Every remaining hosted alternative shares the same single point of failure. Your users’ body measurements live on someone else’s server, their rate limits become your rate limits, and their next outage or shutdown notice becomes yours too — because the mesh math never ran on hardware you controlled.
- Until this release, OxiHuman couldn’t fully close that gap either. The engine was already client-side and open, but there was no real, license-clean asset pack to ship, the in-browser export path panicked on first use, and there was no public demo proving any of it actually worked end to end.
0.2.1 answers all three:
- A real, license-clean asset pack.
oxihuman-core-v1.ohpk(OHPK v1) is OxiHuman’s first shipped CC0 pack — 2,093,260 bytes, 38 CC0-licensed morph targets (30 macrodetail corners + 8measure/girth targets) over a 21,833-vertex base mesh, backed by a machine-checkable provenance chain (PROVENANCE.md,scripts/check_provenance.sh) and a clean-room audit record (docs/CLEANROOM_AUDIT.md). Worst-case per-vertex reconstruction error from the pack’s sparsei16-quantised deltas: 0.011 mm. - Three P0 bugs, caught before anyone shipped on top of them. Every WASM exporter used to reach
std::fs/std::env::temp_dir()— which panics on wasm32, and the trap poisoned the engine object’s wasm-bindgenWasmRefCellborrow flag, so the first export call broke every call after it with “recursive use of an object detected.” The ~30 macrodetail corner targets were being summed instead of composed as a partition of unity, so a neutral-slider body ballooned instead of staying neutral. And packed morph deltas were indexed against the wrong vertex order — 19,158 raw MakeHuman v-lines versus 21,833 seam-split packed vertices — so every target silently deformed the wrong vertices. - A measurement-fit solver that shows its work.
fit_to_measurementssolves height directly by bisection on the monotone stature response,weight/muscle/ gender by Nelder–Mead, then refines themeasure/girth weights by lever-gated coordinate descent. Thebrief-172probe (172 / 96 / 82 / 98 cm) fits to |Δ| ≤ 0.66 cm in ~0.9 s, with every delta re-measured from the output mesh, never echoed back from the input. - A live demo, not a promise. BodyLab is hosted at cooljapan.tech/bodylab and verified end-to-end in headless Chrome.
- 33,569 tests, 0 clippy warnings, 0
unwrap/expectin production code — up from 33,410 tests in 0.2.0.
Technical Deep Dive
OxiHuman’s ten-crate workspace keeps its shape in 0.2.1, but this release is where four of those layers had to agree on the same facts simultaneously — pack format, parser, measurer, and browser bindings all touch the same 21,833 vertices, and a single ordering mismatch anywhere in that chain silently corrupts every morph target downstream.
-
Parsing (
oxihuman-core,parser/obj.rs/units.rs) The OBJ loader packs vertices in face-first-occurrence order after splitting UV seams — 21,833 vertices for the base mesh, versus 19,158 rawvlines in the source MakeHuman OBJ. The gap itself isn’t a bug: every duplicated seam vertex is needed so one vertex position can carry two different UV coordinates across a texture seam. The bug was everywhere else still treating the two orderings as interchangeable. -
Measurement & calibration (
oxihuman-morph,measurements/cross_section.rs,body_measurement.rs,calibration.rs) The new cross-section measurer reads real tape circumferences — the convex hull of the isolated torso’s cross-section at a given height band, not a bounding-box or landmark-distance approximation — and feeds them back as theresults[]in a fit report. That’s what makesfit_to_measurements’s output an honest re-measurement instead of an echoed target. -
Export & pack format (
oxihuman-export’score_pack.rs,oxihuman-cli’spack-corecommand)pack-corebuildsoxihuman-core-v1.ohpkfrom the upstream CC0 MakeHuman data: 38 targets, sparsei16max-abs-quantised deltas against the 21,833-vertex packed mesh. 0.2.1 is also wherepack-corestarts re-indexing every target delta through the parser’s raw→packed mapping before quantising it — duplicating each delta across its seam copies — which is what actually fixed the index-remap P0 above. With the fix in place, the lever-gated girth refinement engages end-to-end and every girth residual comes in sub-1.5 cm. -
Browser bindings & the BodyLab demo (
oxihuman-wasm,demo/)WasmEnginegainedfrom_core_pack_bytes(bytes)to load an OHPK pack directly, four in-memory exporters (export_glb/export_vrm/export_stl/export_obj) that never touch a filesystem, andfit_to_measurements(engine_fit.rs) for the solver above. Zero-copy geometry hand-off (wasm_memory(),refresh_geometry(),positions_ptr()/positions_len()) lets the BodyLab three.js viewer read the vertex buffer as aFloat32Arrayview with no JS-side copy — measured at p50 ≈ 0.52 ms/frame for the full 21,833-vertex morph. The demo itself (demo/src/viewer.js,controls.js,badges.js) vendors three.js r160 directly underdemo/vendor/and is verified end-to-end in headless Chrome byscripts/demo_serve_check.sh.
Getting Started
Build the browser package:
wasm-pack build --release --target web crates/oxihuman-wasm --no-default-features --features bindgen
Then, entirely in the browser:
import init, { OxiHumanEngine } from "oxihuman-wasm";
await init();
const bytes = new Uint8Array(await (await fetch("./pack/oxihuman-core-v1.ohpk")).arrayBuffer());
const engine = OxiHumanEngine.from_core_pack_bytes(bytes);
engine.set_param("height", 0.7);
// in-memory export — no filesystem, safe to call repeatedly on wasm32
const glb = engine.export_glb();
// solve sliders from real centimetres; every delta is re-measured, not echoed
const report = JSON.parse(engine.fit_to_measurements(JSON.stringify({
height_cm: 172.0,
chest_cm: 96.0,
waist_cm: 82.0,
hip_cm: 98.0,
})));
console.log(report.results); // [{ name, target_cm, measured_cm, delta_cm }, ...]
What’s New in 0.2.1
- Legal & safety cleanroom.
docs/CLEANROOM_AUDIT.md,PROVENANCE.mdwith machine-checkablescripts/check_provenance.sh,CONTRIBUTING.md’s forbidden-sources policy, andNOTICE. A named regression testinvariant_no_nude_mesh_stage, an export gate enforced on every export entry point (GLB / VRM / OBJ / STL / COLLADA / USD / 3MF / X3D), and a client-side 18-year age-floor clamp — all documented inSAFETY.md. - OHPK v1 asset pack format. A new
core_packcontainer inoxihuman-exportplus theoxihuman-cli pack-corecommand that builds the shippedoxihuman-core-v1.ohpk(2,093,260 B, 38 CC0 targets, 21,833 base vertices, 0.011 mm worst-case quantisation error), and a precise convex-hull cross-section body measurer. - Browser exports + measurement fit.
WasmEnginegains filesystem-freeexport_glb/export_vrm/export_stl/export_obj,from_core_pack_bytes(bytes), andfit_to_measurements(bisection + Nelder–Mead + coordinate descent); hand-written TypeScriptinterfacedefinitions now ship in the generated.d.ts. - The BodyLab demo. A fully static
demo/app — sliders, live preview, browser GLB/OBJ/STL export — rendered with three.js r160, plusscripts/build_demo.shandscripts/demo_serve_check.sh; verified end-to-end in headless Chrome. - Zero-copy geometry, benchmarks, CI.
wasm_memory()/refresh_geometry()/positions_ptr()/positions_len()for zero-JS-copy three.js/WebGL upload; a reproducible bench harness (web/bench/fps_bench.mjs,scripts/wasm_node_check.mjs’s 60 checks,scripts/validate_exports.mjs’s 25 checks); annpm-publish.ymlgzip size gate reading its budget fromwasm-opt.toml. - Changed. Branding reworded from “pure Rust MakeHuman port” to “MakeHuman-compatible independent implementation (reads
.target/.mhcloformats)”; routine dependency bumps (oxiarc-deflate0.3.5,anyhow1.0.103,wasm-bindgen0.2.126); the unusedjs-sysdependency dropped fromoxihuman-wasm. - Fixed. The three P0s above, plus CLI de-stubs for real
pc2/mdd/anim-bakeanimation export. - Removed. SMPL / SMPL-X export modules deleted per the forbidden-sources policy, and six dead/phantom export modules that duplicated or were unreachable from the public API.
- Testing. 33,569 tests (up from 33,410), 0 clippy warnings, 0
unwrap/expectin production code,cargo fmtclean.
Tips
- Load the pack once, drive it entirely through
set_param.OxiHumanEngine.from_core_pack_bytes(bytes)wires all 38 OHPK targets into the partition-of-unity blend in a single call; from there,set_param("height"|"weight"|"muscle"|"age", v)is the whole surface you need — no per-target weight bookkeeping. - Reach for
fit_to_measurementsinstead of hand-tuning sliders. Pass any subset ofheight_cm/chest_cm/waist_cm/hip_cm(at least one is required) and readresults[]back —measured_cmis re-measured from the fitted geometry, not your input echoed to you. The pack’s girth envelope is finite, though: at the extremes (anadult-XLbuild, for instance) a residual can sit near the envelope edge rather than closing all the way. - Check
age_floor_years()before trusting a low age slider. The shipped core pack declares an 18-year floor;engine.age_floor_years()returns it, andageis clamped client-side before any mesh is built — don’t reimplement the clamp yourself. - Use the zero-copy pointers for anything per-frame.
refresh_geometry()pluspositions_ptr()/positions_len()(and thenormals_/indices_equivalents) hand youFloat32Array/Uint32Arrayviews straight over WASM memory — only re-create the views whenmesh_generation()changes orpositions.buffer !== memory.buffer, not on every frame. - You don’t need to check the bodysuit gate yourself — every export path already does.
export_glb/export_vrm/export_obj/export_stl, and the native GLB/VRM/OBJ/STL/COLLADA/USD/3MF/X3D paths, all run through the same gate theinvariant_no_nude_mesh_stageregression test enforces; there’s no lower-level call that bypasses it. - Re-run provenance verification after rebuilding your own pack. If you regenerate the pack from
scripts/fetch_upstream_assets.sh+pack-core, runscripts/check_provenance.shafterward — it checks the pack’s SHA-256, the sidecar.provenance.json, and all 38 targets plus the base mesh against the upstream CC0 manifest.
This is the foundation
OxiHuman is the privacy-first, client-side human modeling layer for the COOLJAPAN ecosystem, sitting alongside 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. 0.2.1 is the release where the client-side principle stops being an architectural claim and becomes a shipped, downloadable pack: engine, assets, and viewer all now run to completion inside the browser sandbox, C-, C++-, and Fortran-free, with no body data ever leaving the machine it runs on.
Repository: https://github.com/cool-japan/oxihuman
Star the repo if you want proof that a hosted avatar service was never actually the only option.
The era of hoping your avatar vendor stays funded is over. Pure Rust client-side human modeling is here — fast, private, and sovereign.
— KitaSan at COOLJAPAN OÜ July 13, 2026