Wang, Dionne, De Ruyter, Rempe, Peng, Zhu, Yuen et al. (NVIDIA), 2026 · ACM TOG / SIGGRAPH

MotionBricks:
Real-Time Motion from a Modular Latent Brain

Generative models can dream up gorgeous human motion — but they take seconds per clip and offer only a text box for control. Games and robots need thousands of skills, at 60 FPS, controlled to the centimeter. MotionBricks closes that gap: one frozen neural backbone that models 350,000 motion clips, driven by "smart primitives" you assemble like LEGO — 15,000 FPS, 2 ms latency, zero fine-tuning, and it runs the same on a virtual character and a real Unitree G1 robot.

Prerequisites: VQ-VAE / discrete latents + transformers & self-attention + a little physics (springs)
11
Chapters
10
Simulations

Chapter 0: The Problem

Open any modern video game and watch a character walk, sprint, vault a fence, draw a sword, climb a ledge, and sit on a bench. Every one of those motions is real animation, playing back in real time, reacting to your thumbstick within milliseconds. Now ask the uncomfortable question: how is that built?

The answer, for nearly thirty years, has been the animation graph (also called a behavior graph or state machine). Artists record or author motion clips — "idle", "walk", "run", "jump" — and wire them into a graph. Nodes are states; edges are transitions that fire on game events. To go from walking to running you blend along an edge; to turn while running you blend between directional variants. It works, and it gives artists granular control. But it has a fatal flaw: it does not scale.

The number that should scare you: a modern AAA animation state machine — the paper cites Assassin's Creed — can require managing over 15,000 animations, 5,000 states, and nested graphs 12 levels deep. Every new skill multiplies the transitions you must hand-author and debug. The graph becomes nearly impossible to maintain or extend. High-quality runtime behavior has effectively become the exclusive domain of giant, well-funded studios.

Why transitions, not clips, are the curse

The trap is combinatorial. If you have N motion states and any state might need to transition into any other, you are on the hook for up to transitions, each potentially needing its own blend logic, its own foot-phase alignment, its own hand-tuned timing to avoid foot sliding or a jarring pop. Double the skills and you roughly quadruple the authoring burden. The clips are cheap; the connective tissue between them is what kills you.

Drag the slider below and watch the explosion. As the number of skills grows, the count of states stays linear but the transition graph — the thing humans must actually author and maintain — fills in like a dense web. This quadratic wall is the entire reason the next chapters exist.

The animation-graph explosion: skills are cheap, transitions are not

The other half of the problem: control

Suppose you throw the animation graph away and reach for a modern generative model instead — the kind of network that produces stunning motion from a text prompt. Now you hit two new walls. (1) Speed. Diffusion-based motion models typically take seconds to minutes to generate a clip. That is a non-starter for a 60 FPS game loop or a robot that must react now. (2) Control. A text box ("a person walks happily, then jumps") is a wonderful demo and a terrible production tool. Animators and game designers need fine-grained control: this exact velocity, this heading, this hand position on this ledge, this precise keyframe at this frame. Text cannot express that, and tag-based models need a predefined one-hot vocabulary that does not scale across thousands of dissimilar skills.

The core tension MotionBricks resolves: runtime motion control bridges low-level synthesis (make the motion look real and smooth) and high-level behavior design (let a human author what should happen, precisely, in real time). Traditional graphs nail control but not scale. Generative models nail quality but not speed or precise control. A winning system has to excel at both ends at once — and that is exactly what this paper sets out to do.

What is the fundamental scalability problem with traditional animation graphs?

Chapter 1: The Key Insight

Here is the move that makes everything else possible. Instead of asking the model to "generate a walk" or "generate a vault," MotionBricks asks it a much more humble, much more general question: given where the character is now (context) and where it needs to be soon (target), fill in the motion in between. That is the classic animation problem of in-betweening.

Why is this the right abstraction? Because every form of control collapses into the same currency: a keyframe. Want the character to walk north at 1.5 m/s? That is a target root keyframe. Want its hand to land on a ledge? That is a target pose keyframe. Want a specific stylized strut? Drop a style keyframe. Navigation and object interaction, locomotion and acrobatics — they all reduce to "here are some context frames, here are some target frames, generate the bridge." One interface, infinitely many behaviors.

The unification: MotionBricks trains a single backbone that is agnostic to the downstream task. No velocity labels, no one-hot tags, no task descriptors during training. All task specifications are supplied at runtime as keyframe constraints. The backbone never learns "walking" vs "vaulting" as named categories — it only ever learns "connect these constraints with natural motion." This is why it generalizes to new tasks zero-shot, with the backbone frozen.

Manufacturing the need: why naive in-betweening fails

You might think: if I have a start pose and an end pose, can't I just interpolate? Linearly blend joint angles from A to B? Try it in the widget below. Drag the scrubber and watch a naive linear interpolation between two real poses. The character's feet skate across the floor, limbs pass through impossible configurations, and the timing is robotic — there is no sense of weight, no push-off, no gait. Linear interpolation has no idea how bodies actually move.

Naive interpolation vs. what we actually want

The "learned in-between" toggle shows the goal: a model that has seen hundreds of thousands of real motions and therefore knows that to get from a left-foot-forward stance to a right-foot-forward stance, the body must shift weight, the back leg must push off, the arms must counter-swing. It fills the gap with plausible physics it absorbed from data, not a straight line through joint space.

Concept → realization: the in-betweening formulation also solves a sneaky deployment problem. Offline in-betweening tools assume you already have the target keyframe. At runtime in a game, you don't — the player just pushed the stick. MotionBricks's trick is that the high-level "smart primitives" (Chapters 6–7) manufacture target keyframes on the fly from user input, so the low-level in-betweener always has a goal to aim at. Keyframes are the API between the two halves of the system.

Why does MotionBricks frame everything as motion in-betweening rather than task-conditioned generation?

Chapter 2: Background — the landscape MotionBricks fights in

To appreciate the design choices ahead, you need a map of what came before. There are three broad camps, and each one is strong on one axis and weak on another. The whole art is winning on every axis at once.

Camp 1: Traditional methods (graphs & motion matching)

Animation graphs replay clips inside states and blend during transitions. Motion matching (Clavet 2016, used widely in AAA games) is the clever successor: instead of pre-wiring transitions, it keeps a big database of motion frames and, every few frames, searches for the database frame whose pose and trajectory best match the current state and the user's command, then plays forward from there. This frees you from rigid node-based graphs and feels wonderfully responsive. But it is still fundamentally retrieval: it can only ever produce motion that already exists in the database, it needs careful feature engineering, and it still does not overcome the underlying scalability wall as skill counts grow.

Camp 2: Deterministic neural models

Phase-Functioned Neural Networks (PFNN, Holden 2017) and its descendants predict the next pose autoregressively from controls and a phase variable. They are fast and were a genuine breakthrough. But deterministic regression to a single "average" next pose causes well-known artifacts — over-smoothing (the model averages plausible futures into mush), foot sliding, and object penetration — and they tend to be specialized for a narrow task set.

Camp 3: Generative models (diffusion & tokens)

Motion Diffusion Models (MDMs) brought genuinely diverse, high-quality, text-controllable motion. Their curse is inference speed: iterative denoising takes many network passes — seconds to minutes per clip. Tricks like DDIM, flow matching, and autoregressive diffusion claw back speed but still trade quality for it and barely reach real time. Token-based models (the camp MotionBricks belongs to) discretize motion into tokens — like words — with a VQ-VAE, then predict tokens with a transformer, often via iteratively masked prediction (MaskGIT-style). This is fast, but prior token methods used a single codebook without root–pose separation, and had not yet reached industry-grade quality, scale, and interactivity simultaneously.

The widget plots every camp on the two axes that matter for production — throughput (how many frames per second you can generate) and quality (how real the motion looks, inversely tracking FID). Toggle the methods. Notice the empty top-right corner: fast and high-quality. That corner is the prize.

The speed–quality frontier: everyone is missing a corner
Read the frontier carefully. Non-generative methods (traditional, deterministic) get reasonable keyframe precision but poor distribution quality (bad FID) — they don't look real. Diffusion gets good distribution quality but struggles to satisfy spatial constraints precisely and is slow. MotionBricks's claim is that a structured token approach can land in the empty corner: diffusion-grade realism, motion-matching-grade speed, and better keyframe precision than either. The rest of the lesson is how.

What is the characteristic weakness of diffusion-based motion models for real-time use?

Chapter 3: The Four-Stage Pipeline

Before diving into any single component, let's get the data flow exact. MotionBricks's runtime is a four-stage pipeline. Each stage produces something concrete that the next consumes. Getting these shapes and roles straight now makes every later chapter click into place.

Click each stage in the diagram to trace what flows through it — the actual inputs, outputs, and tensor shapes.

The MotionBricks inference pipeline — click a stage

The four stages in words

Coarse-to-fine, by design. Notice the order: timing first (how long?), then the coarse root path (where?), then the detailed body pose (how exactly?), then the polished continuous motion. Each stage commits to a coarser decision before the finer one depends on it. This is not arbitrary — it mirrors how an animator blocks out a shot (timing → staging → poses → polish), and it gives a transparent pipeline where you can inspect or override any intermediate result.

The runtime loop & the masking trick

The system runs autoregressively: it generates a buffer of future motion, pops one frame per tick to drive the character, and replans only when the control signal changes or the buffer is running low. Replanning lazily (not every frame) is what keeps it cheap — and on robots, it avoids fighting the low-level controller for compute.

One more crucial detail that recurs everywhere: flexible constraints via masking. Different tasks need different keyframe density. Navigation might supply just 1–2 keyframes (don't over-constrain a walk!); precise object interaction might supply dense hand positions. So every module accepts an arbitrary subset of constraints. When a constraint is absent, MotionBricks substitutes a learnable mask embedding — a trained "this is missing" token — so the network degrades gracefully instead of crashing. The same masking mechanism is shared across the root module, pose module, and decoder.

Concept → realization: in-between segments range from 12 to 64 frames at 30 FPS (≈ 0.4 s to ≈ 2.1 s). Because the tokenizer downsamples by 4, a 64-frame segment becomes 16 pose tokens. The root module reasons over a maximum of 16 frame-slots (64÷4). Hold these numbers — they explain the "16 learnable frame-slot embeddings" you'll meet in Chapter 5.
In what order does the pipeline commit to decisions, and why?

Chapter 4: The Structured Multi-Head Tokenizer (showcase)

This is the cornerstone of MotionBricks, and the single most important idea to absorb. The job: turn continuous motion into a compact sequence of discrete tokens (so a transformer can model it like language), and do it in a way that scales to a 350,000-clip dataset and degrades gracefully when a token is wrong. The two design decisions that make it work are root–pose disentanglement and multi-head quantization.

First idea: encode pose separately from root

The motion state at each frame is a tuple (rg, rl, p, q, v, c): global root values (pelvis position + heading), local root values (pelvis linear/angular velocity), joint positions p, joint rotations q, joint velocities v, and contact labels c. Crucially, the encoder ignores the root and encodes only the local pose:

ze = enc( {pt, qt}t=1..T )  →  T/4 tokens

Why throw away the root? Because pose intent and root intent are largely separable. A person can walk the same gait at slightly different speeds, or follow the same footstep pattern along a curved vs. straight path. The shape of the motion (the gait) is one thing; where it travels (the root) is another. By tokenizing only the pose, the same pose tokens can be reused across many different root trajectories — which, as you'll see in the widget, lets you warp a motion to a new path without re-generating the body. The encoder progressively downsamples (rates 2 then 4) via a 1D conv U-Net (or a transformer), so T frames become T/4 latent vectors.

Second idea: quantize with K codebooks, not one

Now the continuous latent ze must become discrete. The naive approach (VQ-VAE) uses one big codebook: snap the whole latent vector to its nearest entry. MotionBricks instead splits the feature dimension into K parts and quantizes each part against its own codebook {e1, …, eK}:

zq,k = argmine ∈ Ek ∥ ze,k − e ∥2    for k = 1 … K

Each frame is now described by K token indices instead of 1. This is the difference between describing a person with one giant word from a vocabulary of millions, versus describing them with K independent attributes ("head-tilt = 3, left-arm = 71, stance = 12, …"). The authors deliberately do not hand-partition by body part — they let the network learn its own decomposition, fully data-driven. Two payoffs follow, and they are the heart of the paper:

A worked example you can do by hand

Take K = 2 heads. Say the encoder outputs a 4-dim latent ze = [0.9, 0.2, −0.6, 0.1], split into head-1 = [0.9, 0.2] and head-2 = [−0.6, 0.1]. Each head has a tiny 3-entry codebook:

Head-1: distances² to [0.9,0.2] are  to e₁₀: (0.1)²+(0.2)²=0.05;  to e₁₁: (0.9)²+(0.8)²=1.45;  to e₁₂: (1.9)²+(0.2)²=3.65. Nearest = e₁₀ → index 0. Head-2: distances² to [−0.6,0.1] are  to e₂₀: (0.1)²+(0.1)²=0.02;  to e₂₁: (0.6)²+(0.6)²=0.72;  to e₂₂: (1.1)²+(0.4)²=1.37. Nearest = e₂₀ → index 0. So this frame's tokens are (0, 0), and the reconstructed latent is the concatenation [1.0, 0.0, −0.5, 0.0]. Now imagine the pose module mispredicts head-1 to index 2 ([−1.0,0.0]) — head-2 is still correct, so half the latent survives. That's the safety net, made concrete.

See it, break it

The showcase has three views. Encode animates a motion through downsampling into K codebook heads. Disentangle shows the killer feature: fix the pose tokens, change the root trajectory, and watch the same body motion warp onto a new path (this is Figure 4 of the paper, made live). Perturb corrupts a fraction of tokens and contrasts multi-head vs. single-head degradation — drag the corruption slider and watch which one falls off a cliff.

The structured multi-head tokenizer

Training the tokenizer

The tokenizer is trained with the standard VQ-VAE objective: a codebook loss that pulls each codebook entry toward the encoder output, and a commitment loss (weighted by β) that pulls the encoder output toward its chosen entry, using the stop-gradient operator sg(·) to route gradients correctly past the non-differentiable argmin:

L = ∑t,k ∥ sg(zq,kt) − ek2 + β ∥ zq,kt − sg(ek) ∥2

In practice they use a running-mean codebook update (more stable than gradient updates) and note that an FSQ tokenizer (finite scalar quantization — no learned codebook at all, just rounding to a fixed grid) gives similar performance. During training the decoder is fed a random 0–10 keyframe constraints at arbitrary positions, forcing it to learn robust, generalizable features rather than memorizing a fixed constraint pattern.

Concept → realization (the decoder's skip-connection plumbing): the decoder mirrors the encoder, upsampling tokens at rates 2 then 4. Since pose tokens live at T/4 resolution but the root trajectory lives at full T resolution, root features are temporally stacked by the downsampling factor (4→2→1) before being concatenated at each upsampling layer via skip connections. Sparse keyframe constraints are zero-padded to length T and injected the same way, with a boolean availability mask choosing whether to read the skip feature or the hidden state. This is exactly how the decoder can refine the root for cleaner footsteps while honoring hard keyframes.
Why does multi-head quantization (K codebooks) beat a single large codebook?

Chapter 5: The Neural Backbone — root & pose modules

The tokenizer gives us a vocabulary. The backbone is the language model that generates tokens from constraints. It is split into two transformers that run coarse-to-fine: the root module (50M parameters) decides timing and the coarse path, then the pose module (150M parameters, the largest network) fills in the full-body tokens.

The root module: a two-step transformer

Step 1 — how many frames? Before you can draw a trajectory you need to know its length. Going from a start pose to a target two meters away takes more frames at a stroll than at a sprint. So step 1 predicts a distribution over in-between frame counts (at 4-frame resolution). Its inputs are three kinds of embedding:

From the output distribution we sample (or argmax) to get the predicted frame count T2. A neat control hook: you can apply bit-wise masking over the valid frame counts to constrain timing at inference (e.g. "make this take exactly 20–24 frames").

Step 2 — where does the root go? The intermediate frame-slot embeddings from step 1 are passed to step 2, with slots beyond the predicted count T2 masked out. A second temporal transformer then predicts the initial global root trajectory. Formally:

{h2}, T2 = ℱ1( {h1}; g(T1); f(𝐓1,𝐓2,𝐓3) )
{rg} = ℱ2( {h2}; g(T2); f(𝐓1,𝐓2,𝐓3) )

Because of 4× downsampling, each output embedding decodes into 4 consecutive frames of root trajectory.

The pose module: masked token modeling

Now the big one. The pose module models the distribution of pose tokens, conditioned on the root trajectory (from the root module) and keyframes. It uses masked token modeling, the same idea behind MaskGIT and modern masked image generators: start with all tokens masked, predict them all in parallel, keep the most confident predictions, re-mask the rest, and repeat. Each step "freezes" the tokens the model is surest about and lets later steps fill the harder ones with that context.

{hp} = 𝐏( φ( {rl}; {rg}; {zq} ) )
p(zq,kt) = σ( fk( htp,k ) ),   k = 1 … K

Here φ embeds and combines the three input types (local root, global root, current pose tokens) via an MLP; 𝐏 is the transformer; the final hidden state is partitioned along the feature dimension into K slices, and each slice htp,k is projected by a linear head fk and softmaxed to give that head's token distribution. (See the multi-head structure paying off again — one transformer, K parallel classification heads.)

The detail that makes it real-time: although masked token modeling is iterative in principle, the authors report that in practice a single forward pass at inference usually produces high-quality motion. The cosine masking schedule is used as a curriculum during training (gradually mixing ground-truth and masked tokens), not as a many-step inference loop. One pass through the tokenizer-decoder and one through each backbone module is why latency is 2 ms — not the dozens of denoising steps a diffusion model needs.

Step through both modules in the widget. The root view shows the timing distribution forming and then the root path being drawn; the pose view animates MaskGIT-style iterative token reveal — watch confident tokens lock in first and the rest fill around them.

Inside the backbone: timing + root, then masked pose tokens
Concept → realization (frozen vs trained): the tokenizer (encoder + decoder + codebooks) is trained first and then frozen. The root and pose modules are trained on top of the frozen token space. At deployment, all three are frozen — no fine-tuning, ever, for any downstream task. What the backbone "knows" (how bodies move) is fixed; what changes per task is only the keyframe constraints the smart primitives feed in. This separation is precisely why one model serves both a UE5 game character and a physical robot.
How does the pose module generate tokens fast enough for real time?

Chapter 6: Smart Locomotion & the spring model (showcase)

We have a frozen backbone that turns keyframes into motion. Now: where do the keyframes come from? A player pushes a thumbstick — that is a velocity and a heading, not a keyframe. Smart locomotion is the primitive that bridges raw navigation commands into target keyframes the backbone can consume, while solving two nasty problems: making natural motion from arbitrary velocity/heading commands (including impossible ones — the "control dead zone"), and supporting many styles with smooth transitions.

Step 1: a critically damped spring for the initial path

You can't feed a raw thumbstick command straight to the backbone — it's jittery and may point somewhere infeasible. First you need a smooth, physically reasonable guess at where the root should go. The classic tool from motion matching (Clavet 2016) is the critically damped spring: imagine the character's pelvis attached by a spring to a moving target; tune the spring so it converges to the target as fast as possible without overshooting or oscillating. That "fastest without overshoot" condition is exactly critical damping.

MotionBricks first computes a naive target rg,1 by linearly extrapolating the current state with the commanded velocity and heading over a 1.0 s horizon. Then it smooths the path from the current root r0 toward that target with the critically damped spring solution:

r(t) = e−γt [ (r0 − rg,1) + (v0 + γ(r0 − rg,1)) t ] + rg,1

where γ is the damping coefficient and r0, v0 are the current position and velocity. Evaluating at t = 1.0 s yields the spring-smoothed target rg,2. The whole transient lives under the exponential envelope e−γt — that's what guarantees no overshoot.

Worked example: plug in real numbers

Say the character starts at r0 = 0 with velocity v0 = 0.5 m/s, the extrapolated target is rg,1 = 2.0 m, and damping γ = 4.0. Then:

The spring has carried the root smoothly from 0 to ≈1.83 m, closing in on the 2.0 m target without overshooting it. Crank γ up and it converges faster (snappier, more responsive); drop it and the approach is lazy and soft. Play with exactly this in the widget.

Steps 2–4: progressive neural refinement

The spring path is smooth but mechanistic — it doesn't know about footsteps, style, or the body. So MotionBricks refines it in stages. This is the progressive root refinement, summarized as four named stages:

StageSymbolWhat produces it
Naiverg,1Direct linear extrapolation of the command
Springrg,2Critically damped spring smoothing
Root modulerg,3Neural refinement with style & timing (handles dead zones)
Decoderrg,4Final refinement coordinated with full-body motion (footsteps)

The neural root refinement (stage 3) is where the magic is. Feeding the spring path plus keyframes into the root module produces trajectories with realistic detail instead of mechanical smoothness, and its timing prediction safeguards against control dead zones — if a user commands an infeasible velocity, the network produces a natural motion anyway rather than teleporting or stuttering. Remarkably, identical commands produce different root paths depending on the chosen style (a "happy" walk curves differently than a "stealth" crouch), because the style keyframe shapes the refinement.

Style by keyframe, not by tag. To set a locomotion style, you simply place keyframes sampled from short reference clips (or human-authored poses) of that style onto the spring-smoothed trajectory. No style label, no retraining. And because the system replans on a fixed interval, the output is never rigidly locked to an arbitrarily placed keyframe — even a single keyframe plus a made-up velocity yields natural, coherent motion. That robustness is what makes the "assemble like bricks" workflow feasible for non-experts.

Critically damped spring + progressive root refinement
Why is a critically damped spring used to produce the initial root trajectory?

Chapter 7: Smart Object — interaction without animation graphs

Smart locomotion handles getting around. Smart object handles interacting with the world — climbing ledges, vaulting fences, sitting, picking up swords, opening doors. Traditionally each interaction needs its own pre-canned clip tied to a specific object position, plus careful entry/exit blends. That is the animation-graph curse all over again. Smart object dissolves it with two lightweight ingredients: intent keyframes and an interaction binding.

Intent keyframes & the drop-frame dial

An interaction is defined by a few essential poses. A ledge climb, for instance, needs a contact pose (hands reach the wall edge) and an exit pose (standing on the ledge). You author these with standard translate/rotate/IK gizmos, or pull them from a motion library. The key control is the drop-frame attribute τ on each keyframe set, which decides how strictly the pose must be hit:

Why a dial and not a switch? Real interactions mix hard and soft requirements. A vault has a hard contact moment (hand on the obstacle) bracketed by soft preparation and recovery poses. Exposing τ per keyframe lets an author say "be exact here, be loose there" — giving precise contact where physics demands it and natural freedom everywhere else. One number per keyframe replaces hand-tuned blend logic.

Interaction binding: detection, sockets, anchoring

The binding glues interaction logic to the object and manages three things: (1) Detection — an interaction mesh derived from the object's geometry acts as a trigger volume; a box-collision trace decides if the character is in range. (2) Object sockets & placement — for portable objects, sockets define where the object attaches (e.g. the hand) and placement logic snaps it to a valid surface when released. (3) Keyframe anchoring — for scene/static objects, the mesh's world transform is a pivot: keyframes flagged with a boolean ω = 1 are rotated around that pivot at runtime.

That anchoring flag is what delivers the headline benefit: the same keyframe definition works from any approach angle or object placement. Author a ledge-climb once; the pivot rotation lets the character climb that ledge approaching from the north, the east, or a diagonal — and lets identical "sit" keyframes adapt to chairs at different positions and orientations. Combined with the backbone's generative adaptation, one smart object yields automatic motion variations (falling adapts to height, pickups adapt to angle) without any extra authoring.

In the widget: place an object, set τ to feel hard vs. soft constraint enforcement, and rotate the approach angle to watch pivot anchoring re-target the same keyframes. The character's reach either snaps exactly to contact (low τ) or transitions early and loosely (high τ).

Smart object: drop-frame τ and pivot anchoring
Concept → realization (it plugs into UE5): detection uses UE5 box traces, sockets use UE5's socket system, anchoring uses the mesh world transform. The authors deliberately built on the game engine's existing infrastructure rather than reinventing it — which is why authoring a smart navigation or smart object takes a non-expert under 10 minutes. The generative backbone supplies the motion; the engine supplies the world plumbing.
What does the drop-frame attribute τ control, and why is it useful?

Chapter 8: Experiments & Results

A production claim demands production-scale evidence. MotionBricks is evaluated on four datasets of very different scales, against six recent baselines, across seven categories of metric. The headline: it wins on essentially everything that matters, including the things that usually trade off against each other.

The datasets

DatasetHoursTrain clipsJointsRole
350k (proprietary)700315,16227Primary — 9,300 skills, 36 categories, 163 performers
70k / Bones-70k14062,13227Scaling-study subset
HumanML3D28.623,20622Public benchmark
LaFAN1-G14.62,36234Robotics — retargeted to Unitree G1

How motion quality is even measured

You can't just eyeball 350k clips. The seven metric families each capture a different failure mode:

The 350k scoreboard

Explore the comparison below. Pick a metric and see every method's bar; MotionBricks ("Ours") is highlighted. The story repeats across metrics: deterministic methods (Cond. In-betweening, Two-stage, Delta-interp) get okay precision but terrible FID and human scores; diffusion methods (CondMDI, Closd-DiP) get good FID but weaker constraint satisfaction and slower speed; the prior token method (MMM) is decent but not dominant. Ours sits at or near the top of all of them, simultaneously.

350k dataset: method comparison — pick a metric
The standout numbers (350k): 15,000 FPS and 2 ms latency (the fastest generative method by a wide margin), FID 1.054 (best — closest to the real-motion distribution), 86.5% human win rate with a 4.06/5 quality score (next best ≈20%), foot-contact accuracy 92.6%, and 99.6% reaching success — near-perfect keyframe adherence. It is, at once, the fastest, the most realistic, and the most precise.

The same pattern holds across LaFAN1-G1 (robotics), HumanML3D (public), and Bones-70k: MotionBricks leads on distribution quality, smoothness, and precision. On the two small datasets, baselines occasionally match or edge ahead on raw diversity — unsurprising, since a high-capacity model's advantage shows most when there's enough data to learn from. There is no significant trade-off between diversity and precision or speed.

What makes MotionBricks's results notable beyond just "better numbers"?

Chapter 9: Scaling Laws & Ablations

The most important experiments aren't the leaderboard — they're the ablations that prove why the design works. Three results matter most: tokenizer scaling, the head/codebook trade-off, and dataset scaling.

Scaling: multi-head keeps climbing, single-head plateaus

This is the paper's central scientific claim. Take the structured multi-head tokenizer and a standard single-head VQ-VAE baseline, and grow the codebook capacity. The multi-head tokenizer's reconstruction loss keeps improving as you scale the effective vocabulary all the way up to ~10⁹ tokens. The single-head baseline plateaus almost immediately — throwing more codebook entries at it does nothing. Drag the slider and watch the two curves diverge.

Tokenizer scalability: ours vs. single-head baseline
Why does single-head plateau? A single codebook must place every possible full-body pose as one point in one vocabulary. Doubling the codebook barely helps because the model can't use the extra entries — the optimization can't carve a million-way decision cleanly. Splitting into K heads turns one impossible million-way choice into K easy hundred-way choices whose combinations cover the space exponentially. The structure is what unlocks the capacity. There's a sweet spot, though: the right-side trade-off plot in the paper shows FID improves with more tokens but keyframe error creeps up at extreme scales, suggesting an optimal operating point around 10⁶–10⁷ effective tokens.

Heads vs. tokens-per-head: a coherence trade-off

Fix the total capacity (~10⁶) and vary the split — many heads with small codebooks (e.g. 20 heads × 2 entries) vs. few heads with big ones (2 heads × 1000 entries). Under token perturbation (simulating prediction errors), a clear trade-off appears: too many tokens per head hurts NPSS (temporal coherence — the motion gets jittery), while too few tokens per head hurts FID and keyframe precision. The paper's recommendation: 128–256 tokens per head, with total capacity around 10⁹.

Dataset scaling & a counterintuitive FID

Train on 10% → 100% of the 350k data. MotionBricks's keyframe precision consistently improves with more data while the baseline's degrades (its limited capacity gets overwhelmed). One honest surprise the authors flag: FID sometimes worsens with more data for both methods. Their hypothesis — and this is a great lesson in reading metrics critically — is that models trained on smaller data overfit and produce less diverse output that happens to hug the training distribution, yielding artificially low FID. More data → more diverse, genuinely better motion → slightly higher FID. The metric that matters (precision, and human eval) keeps improving.

Concept → realization (root interpolation robustness): a separate ablation overrides the predicted root with an interpolated trajectory while keeping pose tokens fixed (compress or stretch the path). FID and reaching success stay stable and foot-skate stays low even under significant root manipulation — direct proof that the root–pose disentanglement from Chapter 4 actually holds in practice. The decoder is genuinely agnostic to where the root came from, which is exactly what makes runtime root constraints (precise keyframe matching without foot sliding) possible.

The engineering that ships it

Training: 32 GPUs (4 nodes × 8), 2M updates, batch 256/GPU, AdamW at lr 5×10⁻⁵ with cosine decay. Tokenizer is a 23.5M-param U-Net (1024 channels); pose module 150M (16 layers, 16 heads, dim 1024); root module 50M. Roughly 7 days (tokenizer) + 3 days (root) + 7 days (pose) on H100s. Inference: RTX 5090, 2 ms / 15,000 FPS, exported via ONNX + TensorRT into a native C++ UE5 plugin. On the Unitree G1 robot it runs on a Jetson Orin (5 ms latency), feeding kinematic targets to a physical tracking controller, replanning lazily at 10 Hz to avoid starving the low-level control loop.

What is the central scaling finding that justifies the multi-head tokenizer?

Chapter 10: Connections & cheat sheet

MotionBricks is a beautiful synthesis of ideas you've met elsewhere. Seeing the lineage makes the whole thing feel inevitable rather than magical.

Where each idea comes from

The cheat sheet — every key equation & symbol

ObjectMeaning
(rg, rl, p, q, v, c)Per-frame state: global root, local root, joint positions, rotations, velocities, contact labels
𝐓 = {𝐓1,𝐓2,𝐓3}Keyframe constraint sets for local root, global root, pose
ze = enc(p,q)Encode pose only (no root) → T/4 continuous latents
zq,k = argmine∈Ek∥ze,k−e∥²Multi-head quantization: K codebooks, one token index per head
L = ∑∥sg(zq)−e∥² + β∥zq−sg(e)∥²VQ-VAE codebook + commitment loss; sg = stop-gradient
1,ℱ2Root module: step 1 predicts frame count T2, step 2 predicts root trajectory
p(zq,k)=σ(fk(hp,k))Pose module: K softmax heads over the partitioned hidden state
r(t)=e−γt[…]+rg,1Critically damped spring for initial root path (smart locomotion)
rg,1 → rg,2 → rg,3 → rg,4Progressive root refinement: naive → spring → root module → decoder
τ (drop-frame), ω (pivot flag)Smart object: τ=0 hard / τ>0 soft constraint; ω=1 rotate keyframe around object pivot

Limitations the authors name honestly

The mastery test. You should now be able to: redraw the four-stage pipeline with tensor shapes; explain why pose is tokenized without root and what disentanglement buys; do the multi-head quantization argmin by hand and say why K heads degrade gracefully; explain masked-token generation and why one pass suffices; compute the critically damped spring at t=1s; describe the four progressive root-refinement stages; and explain the drop-frame τ dial. If a colleague asked "why not just use diffusion?", you could answer with numbers. That's the bar.

Which single design choice most directly enables MotionBricks to scale to 350k clips with one model?