| --- |
| license: mit |
| tags: |
| - onnx |
| - auto-rigging |
| - skeleton-prediction |
| - rigging |
| - 3d |
| - qtmesheditor |
| library_name: onnx |
| pipeline_tag: other |
| --- |
| |
| # UniRig (skeleton stage) β ONNX export |
|
|
| **ONNX re-export of the skeleton-prediction stage of |
| [VAST-AI/UniRig](https://huggingface.co/VAST-AI/UniRig)** (*"One Model to Rig |
| Them All"*, SIGGRAPH 2025 β MIT code + MIT weights, trained on |
| Articulation-XL2.0 / CC-BY-4.0): an autoregressive transformer that predicts a |
| full skeleton (joints + hierarchy) from raw mesh geometry β no template or |
| markers needed. All credit for the original weights goes to VAST-AI-Research. |
|
|
| Exported for **[QtMeshEditor](https://github.com/fernandotonon/QtMeshEditor)** |
| (issue #408), powering `qtmesh rig --algo unirig`, the Inspector's |
| **Generate Rig (AI)** button, and the `auto_rig` MCP tool β local inference |
| via ONNX Runtime with a template-rig fallback. |
|
|
| > The files QtMeshEditor downloads at runtime live in the shared |
| > [`fernandotonon/QtMeshEditor-models`](https://huggingface.co/fernandotonon/QtMeshEditor-models) |
| > repo under `unirig/`. This repo is the standalone model card + mirror. |
|
|
| Note: UniRig's **skin-weight head is not included** β it depends on |
| spconv/PTv3, which has no ONNX lowering. For ML skin weights see |
| [`QtMeshEditor-skintokens-onnx`](https://huggingface.co/fernandotonon/QtMeshEditor-skintokens-onnx). |
|
|
| ## Files |
|
|
| | file | role | |
| |---|---| |
| | `encoder.onnx` | Michelangelo point-cloud encoder: `pc [1,N,3]` + `feats [1,N,3]` (normals), N β€ 65536 β latent prefix | |
| | `decoder.onnx` | ~350M-param causal-LM **KV-cache step** | |
| | `embed.onnx` | token id β embedding | |
|
|
| ## Inference contract |
|
|
| 1. Surface-sample up to 65536 points + normals, normalise into a centred unit |
| box (+Y up). |
| 2. Run the encoder β latent prefix for the LM. |
| 3. Greedy **constrained** autoregressive decode with a manual KV cache, |
| masking each step to the tokenizer FSM's valid next tokens (a documented |
| simplification of upstream's beam+sampling β deterministic, still yields a |
| valid tree). Safety cap 2048 tokens; generation ends at EOS (typically |
| ~180 tokens). |
| 4. Detokenize: 256 coordinate bins over `[-1,1]`, |
| `undiscretize(t) = (t+0.5)/256*2-1`; vocab 267 (`branch=256`, `bos=257`, |
| `eos=258`); per-bone records `[branch?, parent xyz, joint xyz]` β joints + |
| parent indices. Match branch parents to the nearest earlier joint rather |
| than requiring exact bin equality β real decodes frequently miss the exact |
| bin. |
|
|
| ## Reproducing |
|
|
| `scripts/export-unirig-onnx.py` in the QtMeshEditor repo (one-time, offline; |
| via `optimum` with a hand-rolled KV-cache fallback). |
|
|
| ## License |
|
|
| MIT (same as the upstream code and weights). Training data: Articulation-XL2.0 |
| (CC-BY-4.0) β credit VAST-AI-Research. |
|
|