Browser-side body model evaluation for viser
Project description
body-models-viser
body-models-viser is a browser-oriented implementation of selected
body-models models. The goal is to evaluate body models directly in a web
viewer, without being limited by viser skinning constraints such as a fixed
maximum number of bones per vertex.
The package currently supports unbatched/default SMPL, SMPLH, SMPLX, MHR, ANNY,
and SOMA models. The Rust implementation is checked against Python body-models output
using JSON fixtures, and the Python wheel ships the JavaScript bundle that can
be injected into a viser frontend.
Layout
src/contains the Rust model implementation and JSON CLI.fixtures/contains small input cases for each model.scripts/generate_reference.pyexports model weights and Python reference outputs intogenerated/.tests/parity.rscompares Rust output against the generated Python outputs.client/contains the small browser-side skinning helper.
generated/, target/, client/dist/, and client/node_modules/ are local
build artifacts and are ignored.
How It Works
Reference data is generated from a local body-models checkout. The script
saves two kinds of JSON:
generated/model_data/<model>.json: model weights needed by Rust.generated/reference/<model>/<case>.json: expectedskeletonandmeshoutputs for each fixture.
Rust loads the same fixture JSON as Python, evaluates the model, and emits:
{
"model": "smpl",
"case": "rest",
"skeleton": [],
"mesh": []
}
The Python package exposes the viser-facing API and injects the bundled browser runtime into viser. Python sends custom body-model messages with unskinned vertices, sparse weights, joint indices, and bone transforms. The browser runtime intercepts those messages, applies skinning with every supplied weight, and forwards a regular viser mesh message to the viewer.
User Usage
Install the Python package:
uv add body-models-viser
Get the bundled browser module from Python:
from body_models_viser import client_path
print(client_path())
Add a model to a viser scene:
import body_models_viser as bmv
from body_models.smpl.numpy import SMPL
handle = bmv.add_body_model(scene, "/body", SMPL(gender="neutral"))
handle.body_pose = next_body_pose
add_body_model() injects the browser runtime automatically. It does not call
scene.add_mesh_simple() or scene.add_mesh_skinned(); the mesh sent to viser
is produced by the runtime after browser-side skinning.
client_path() returns the packaged body-models-viser.js bundle. Advanced
browser integrations can import the same low-level skinning API directly:
import { skinVertices } from "./body-models-viser.js";
const vertices = skinVertices({
vertices: bindVertices,
skinWeights,
skinJoints,
boneTransforms,
});
For development against the TypeScript source, import from client/src/index.ts
and run npm test from client/. Do not commit client/dist/; CI builds the
JavaScript bundle for releases.
Commands
Generate Python references:
uv run --project ../body-models --no-sync scripts/generate_reference.py
Run Rust parity tests:
cargo test --release
Run the forward benchmark:
cargo run --release --bin bench_forward
Run one fixture through the Rust CLI:
cargo run --release -- \
--model-data generated/model_data \
--input fixtures/smpl/rest.json
Build and test the TypeScript package:
cd client
npm test
CI And Releases
GitHub Actions runs three checks:
- Rust formatting, clippy, and crate/bin tests.
- TypeScript build and tests from
client/src. - Python package build after generating the JavaScript bundle in CI.
The JavaScript bundle in client/dist/ is not tracked by git. Releases build it
in GitHub Actions, package it into the Python wheel under
body_models_viser/client/body-models-viser.js, and publish with uv publish.
Configure PYPI_USERNAME and PYPI_PASSWORD repository secrets before creating
a GitHub release or running the publish workflow manually.
Notes
The Rust implementation keeps the JSON format simple and builds sparse runtime caches for large sparse model matrices on first use. SOMA identity preparation is intentionally done in Python during reference/model-data export; Rust consumes the prepared identity state and handles pose evaluation, correctives, skinning, and global translation. This keeps the generated data easy to inspect while making repeated forwards fast enough for interactive viewer work.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file body_models_viser-0.0.1.tar.gz.
File metadata
- Download URL: body_models_viser-0.0.1.tar.gz
- Upload date:
- Size: 15.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9669a8137f2107d33c0a80fe72ba10971614a7d54cf78445d36a964ef350696c
|
|
| MD5 |
6376dcab23451f6037c9f2ab2547e3d0
|
|
| BLAKE2b-256 |
788c46b9fe0055520b902a4b5a2b269eac693f55337bb0eefc4337cf3d05c6e5
|
File details
Details for the file body_models_viser-0.0.1-py3-none-any.whl.
File metadata
- Download URL: body_models_viser-0.0.1-py3-none-any.whl
- Upload date:
- Size: 10.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6a29a14c14364846ed6259b47c33ed63657dc4be628043b1c400e7d2404d098
|
|
| MD5 |
a398456cc0648e5cd045f9b875b98469
|
|
| BLAKE2b-256 |
a0d25aa0d864816f596ed1ce8e519c9bb791e8c94fc8a4156d18837fc75600b8
|