A generative model that recovers full 3D shape, texture, and layout for any object in a cluttered, occluded photo — by treating 3D reconstruction like an LLM: synthetic pretraining, then a human-and-model-in-the-loop data flywheel that breaks the "3D data barrier".
You take one photo of your living room. A chair is half-hidden behind a table, a mug sits on a cluttered desk, a plant leans in the corner. Now ask: what is the full 3D shape of each of those objects — not just the front you can see, but the back, the bottom, the parts buried behind other things?
Your brain does this instantly. You know the chair has four legs even though two are occluded. You know the mug is a hollow cylinder even though you only see one curved face. This is single-image 3D perception, and humans are astonishingly good at it.
Photography is a lossy projection: it maps a rich 3D object down to a flat grid of pixels. Depth is collapsed. Occluded surfaces vanish. We are trying to invert a function that threw away most of its input. There is no unique answer — many different 3D objects produce the exact same photo.
SAM 3D's response is to refuse to predict one answer. It models the problem as a conditional distribution p(S, T, R, t, s | I, M): given image I and mask M, there is a whole distribution of plausible 3D objects, and we train a generative model q to approximate it. The "one number" mindset (regress the depth) is replaced by a "generate a plausible sample" mindset (like an image diffusion model, but for shape).
Why hadn't this been cracked? Data. Text models train on trillions of tokens scraped from the web. Image models train on billions of captioned photos. But "a natural photo paired with the ground-truth 3D mesh of an object inside it" is a data type that essentially does not exist at scale.
Modeling a single mesh from a reference image takes a skilled 3D artist hours. You cannot crowd-source it the way SAM crowd-sourced segmentation masks (anyone can trace an outline; almost nobody can sculpt a mesh). So prior 3D generators trained on clean synthetic objects (Objaverse) — and promptly fell apart on real, occluded, cluttered photos.
| Domain | Web-scale paired data? | Consequence |
|---|---|---|
| Text | Yes — trillions of tokens | Strong LLMs |
| Images | Yes — billions of (image, caption) | Strong image generators |
| 3D from natural images | No — meshes take artists hours each | Models stuck on synthetic objects |
SAM 3D's breakthrough is not a clever new network layer. It is a recipe borrowed from LLMs: stop trying to find scarce real 3D data, and instead build a multi-stage training pipeline plus a self-improving data engine that manufactures it.
| LLM stage | SAM 3D equivalent | Data |
|---|---|---|
| Pretraining | Shape vocabulary from isolated synthetic objects | Iso-3DO (2.7M meshes, 2.5T tokens) |
| Mid-training | Occlusion, mask-following, layout — skills | RP-3DO (61M render-paste samples) |
| SFT | Adapt synthetic → real on vetted meshes | MITL-3DO + Art-3DO |
| Preference alignment | DPO on human-preferred vs rejected shapes | MITL preference pairs |
| Distillation | Cut inference from 25 steps to 4 | Shortcut-model distillation |
The payoff: a 5:1 human-preference win rate on real-world objects and 6:1 on full scenes over the previous best methods. Reframing 3D as an LLM-style data problem is the entire contribution.
Before the architecture, we need the engine that generates shapes. SAM 3D is a rectified flow matching model. If you've met diffusion, flow matching is its straighter, faster cousin — and you need it to understand how a voxel grid gets conjured from noise.
We said reconstruction is sampling from a distribution. But how do you sample a complex object like "a 64³ voxel grid of a chair"? You can't just pick from a list. The trick of all modern generative models: learn to transport a simple distribution (Gaussian noise) into the complex one (real shapes).
Imagine noise at time t=0 and a real shape at t=1. Draw a straight line between a noise sample x₀ and a data sample x₁. A point on that line at time t is:
Here x₀ is pure Gaussian noise (the easy distribution), x₁ is a real shape latent (the hard distribution we want), and t ∈ [0,1] is a "how far along" knob — 0 means all noise, 1 means finished shape. Differentiate that line with respect to t and the velocity is gorgeously simple:
That constant x₁ − x₀ is the target velocity — the direction and speed you'd move to get from noise to data along the straight path. The network's only job is to predict that velocity at any (xt, t), conditioned on the image. Call the network vθ. The training loss is just regression:
Every symbol: E = average over random t and random noise/data pairs; vθ = the network's predicted velocity; the squared term = how wrong that prediction is. Minimize it and the network learns the velocity field that flows noise to shapes.
At inference you start from noise x₀ and walk forward in N steps of size Δt = 1/N, each step nudging x by the predicted velocity:
This is one function evaluation (NFE) per step. SAM 3D's base model uses 25 NFE; the distilled one uses 4. Play with the simulation below to see noise flow into a shape, and watch what too-few steps does to the result.
A 1D toy: each dot is a noise sample being transported toward the target shape distribution (two clusters = a multimodal "shape"). Drag the step count to see why few steps still works for straight flows — but overshoots if too few.
SAM 3D is a two-stage cascade. A Geometry model first predicts a coarse shape and the object's layout. Its output is then handed to a Texture & Refinement model that adds high-resolution detail and color. Think: rough clay form first, then sculpt and paint.
Let's trace exactly what tensors move through the system — this is where "concept" becomes "realization".
| Stage | Input → Output (shapes) | What it does |
|---|---|---|
| DINOv2 encoder | 4 image+mask pairs → 4 sets of conditioning tokens | Extracts visual features (frozen) |
| Geometry model (1.2B) | tokens → O ∈ R64³, R ∈ R6, t ∈ R3, s ∈ R3 | Coarse voxel shape + 6D pose + layout |
| Texture & Refine (600M) | active voxels of O → refined latent S, T | Sparse latent flow over occupied voxels only |
| VAE decoders Dm, Dg | latent → mesh OR 3D Gaussian splats | Two decoders, one shared latent space |
SAM 3D feeds DINOv2 two pairs of (image, mask), giving four token sets. This is a deliberate engineering choice:
SAM 3D can optionally take a coarse scene point map P (from an iPhone LiDAR or a monocular depth estimator). Here's the key failure-mode lesson: if no pointmap is provided, the model still predicts shape and texture fine — only metric layout (translation/scale) becomes less accurate, because absolute scale is genuinely unknowable from RGB alone. The model degrades gracefully rather than crashing.
The Geometry model is the heart of the system. It is a 1.2B-parameter flow transformer that models p(O, R, t, s | I, M): coarse shape O (a 64³ voxel occupancy field), 6D rotation R, translation t, and scale s. It must generate two very different things — a big spatial voxel grid AND a tiny 12-number layout vector — in one model. How?
SAM 3D uses a Mixture-of-Transformers. Picture two parallel transformer "streams" — one specialized for geometry tokens, one for layout tokens. Each stream has its own weights (feed-forward, norms). But they share a single multi-modal self-attention layer where the two streams can read each other.
This reconstructs the Geometry model's core loop: a 2D occupancy slice of a voxel object is generated by flowing noise → shape via the velocity field, while a separate stream predicts the pose. Pick a target object, set the recognition strength (how much the image conditions the flow), and the NFE step budget. Watch shape AND pose emerge together.
Notice two things in the sim. Low recognition strength (image barely conditions the flow) gives a blobby, generic shape — the model falls back to a prior, ignoring the photo. This is exactly what under-trained or no-context models do. Too few NFE leaves the shape noisy and the pose jittery — the integration hasn't converged. Both are real failure modes SAM 3D had to engineer around.
R is a 6D rotation representation (Zhou et al., 2019), not 3 Euler angles. Euler angles have discontinuities (gimbal lock) and the wraparound at 360° makes them a nightmare to regress — a network predicting 359° vs 1° gets a huge loss for a 2° error. The 6D form (two 3-vectors, then Gram-Schmidt orthogonalized into a rotation matrix) is continuous, so the loss surface is smooth and learnable. A small ablation in the paper confirms 6D beats alternatives for pose.
The Geometry model gives a coarse 64³ voxel blob. That's the silhouette in 3D, but it's low-res and colorless. The Texture & Refinement model — a 600M-parameter sparse latent flow transformer — fixes both.
A 64³ grid has 262,144 voxels. But most of them are empty — an object only occupies a thin shell of that cube. Running a dense transformer over all 262K positions would be enormously wasteful.
Left: the dense 64³ cube — most cells empty. Right: only active voxels survive. Toggle to see how many computations are saved.
The refined latent can be decoded two ways by a pair of VAE decoders that share the same encoder and latent space:
Texture quality depends on visible surface. The back of an occluded object is hallucinated from the learned prior — plausible, but not "true". The paper notes common failure modes the post-training stage specifically hunts down: floaters (stray disconnected voxels), bottomless meshes (no base), and broken symmetry. These are exactly the artifacts flow-matching's per-voxel objective doesn't penalize — which motivates the next two chapters.
Architecture aside, the paper's genuine innovation is the model-in-the-loop (MITL) data engine — the flywheel that manufactures real-world 3D training data. This is the part you'd present in an interview as "what's actually new here".
On iteration zero, the model is synthetic-only and produces few good real-world meshes. So how do you bootstrap? An ensemble. Early on, candidate meshes come mostly from a suite of existing learned + retrieval-based models. As the model improves, it dominates — eventually producing ~80% of the annotated data. The crutch is kicked away once the model can walk.
Why ask for N=8 candidates instead of 1? Suppose any single model sample is "good enough" (r > α) with probability p. The probability that the best of N is good enough is:
Worked example: say p = 0.30 (a lone sample is good 30% of the time). With N=1 you get 30%. With N=8: P = 1 − (0.70)⁸ = 1 − 0.0576 = 94.2%. By spending 8 samples and one cheap human pick, the success rate jumps from 30% to 94%. SAM 3D further boosts effective N by pre-filtering candidates with a model, then having the human filter — a two-stage funnel.
Drag the per-sample quality p and the candidate count N. The curve shows P(success)=1−(1−p)ⁿ. See why N=8 is the chosen sweet spot.
The base model has only ever seen (semi-)synthetic data. The domain gap to real photos is large. Post-training closes it, in a careful order.
Supervised fine-tuning starts with the larger, noisier non-expert labels (MITL-3DO) to broadly adapt the model to real images, then finishes on the small, high-quality artist set (Art-3DO). Order matters: the artist data is precious, so you use it last to polish — it aligns outputs with artists' aesthetic sense and specifically suppresses floaters, bottomless meshes, and broken symmetry.
Flow matching's objective is a per-voxel reconstruction loss. It has no notion of "humans find symmetric, closed shapes more pleasing". You can have low flow-matching loss and still output an ugly, asymmetric, hole-riddled mesh. The objective and human preference are misaligned.
So after SFT comes Direct Preference Optimization (DPO), borrowed straight from LLM alignment. Recall the D⁺/D⁻ pairs the data engine produced for free: D⁺ is the human-chosen shape, D⁻ is a rejected candidate. DPO nudges the model to raise the likelihood of preferred outputs and lower the rejected ones — without needing an explicit reward model.
Symbols: qθ = model being trained; qref = frozen reference (the SFT model); σ = sigmoid; β = a temperature controlling how hard we push. The bracket is "how much more does our model prefer the chosen over the rejected, relative to the reference". Maximizing it = learning human aesthetic preferences. The paper finds this off-policy preference data is effective at eliminating undesirable outputs even after Art-3DO SFT.
Table 4 of the paper shows near-monotonic improvement as each stage is stacked. Watch the metric climb:
The aligned Geometry model is great but slow: 25 function evaluations per reconstruction. For an interactive demo ("convert image to 3D" in a browser) you want sub-second. The final stage cuts NFE from 25 → 4.
SAM 3D adapts the shortcut model idea (Frans et al., 2024). A normal flow model only knows how to take an infinitesimal step — that's why you need many. A shortcut model is additionally conditioned on the step size d, and trained so that one big step of size d lands in the same place as two small steps of size d/2 would. This self-consistency property lets it leap.
Where x' is where the first half-step lands. Read it as: "your big-step velocity should equal the average of two consistent half-steps." Train this and the model can take 4 giant strides instead of 25 baby ones — because the straight rectified-flow path makes large steps accurate in the first place (recall Chapter 2).
Both walk the same trajectory from noise to shape. The distilled model takes 4 large self-consistent steps; the base takes 25. On a straight path, the endpoints nearly coincide — that's why distillation barely hurts quality.
The headline: on the new SA-3DAO benchmark (1,000 artist-made meshes from real images), SAM 3D dominates. It's not mainly about clean synthetic objects — it's about messy real ones.
| Metric | Best prior | SAM 3D | Meaning |
|---|---|---|---|
| F1@0.01 (↑) | ~0.163 (Hi3DGen) | 0.234 | Surface point match within 1% — +44% relative |
| vIoU (↑) | ~0.153 | 0.231 | Volumetric overlap with GT |
| Chamfer (↓) | ~0.084 | 0.040 | Avg point-to-surface distance — halved |
| Human pref. (objects) | 1 | 5 | 5:1 win rate on real images |
| Human pref. (scenes) | 1 | 6 | 6:1 win rate on full-scene reconstruction |
| Layout ADD-S@0.1 (ADT, ↑) | 0.02 (joint MIDI) | 0.77 | A new real-world capability, not a small gain |
Note the honest detail in the paper: on the isolated synthetic ISO3D set, SAM 3D merely matches prior work on perceptual metrics. The win is entirely on hard, real, occluded inputs — which is exactly what the data engine was built for. The method does what it was designed to do, and not more — a credibility signal.
Strip away the 1.2B params and the engineering. The beating heart is: train a velocity field that flows image-conditioned noise into shape latents, and sample by integrating it. Here is that core, runnable:
import torch, torch.nn as nn
class VelocityField(nn.Module):
"""Predicts dx/dt = x1 - x0, conditioned on image features + time."""
def __init__(self, latent_dim, cond_dim):
super().__init__()
self.net = nn.Sequential(
nn.Linear(latent_dim + cond_dim + 1, 512), nn.SiLU(),
nn.Linear(512, 512), nn.SiLU(),
nn.Linear(512, latent_dim), # outputs a velocity, same shape as latent
)
def forward(self, x_t, t, cond): # cond = DINOv2 image+mask tokens
t = t.view(-1, 1)
return self.net(torch.cat([x_t, cond, t], dim=-1))
def flow_matching_loss(model, x1, cond):
"""Rectified flow: regress the straight-line velocity x1 - x0."""
x0 = torch.randn_like(x1) # noise (easy distribution)
t = torch.rand(x1.size(0), 1) # random point along the path
x_t = (1 - t) * x0 + t * x1 # point on the straight line
target_v = x1 - x0 # constant target velocity
pred_v = model(x_t, t, cond)
return ((pred_v - target_v) ** 2).mean()
@torch.no_grad()
def sample(model, cond, latent_dim, nfe=25):
"""Integrate noise -> shape latent. nfe=25 base, nfe=4 distilled."""
x = torch.randn(cond.size(0), latent_dim) # start at noise (t=0)
dt = 1.0 / nfe
for i in range(nfe):
t = torch.full((cond.size(0), 1), i * dt)
x = x + dt * model(x, t, cond) # Euler step along velocity
return x # -> decode with VAE to mesh/splats
That's the whole idea in 30 lines. SAM 3D scales the network to 1.2B params, makes cond the four DINOv2 token sets, splits the latent into geometry+layout via MoT, and wraps it all in the data-engine flywheel. But this is the engine.
SAM 3D sits at the crossroads of generative modeling, the Segment Anything lineage, and the LLM training playbook.
| Symbol | Meaning |
|---|---|
| I, M | Input image and object mask (the conditioning) |
| S, T | Shape and texture to recover |
| R, t, s | 6D rotation, translation, scale (the layout in camera frame) |
| O ∈ R64³ | Coarse voxel occupancy from the Geometry model |
| xt=(1−t)x₀+t·x₁ | Point on the straight flow path; x₀ noise, x₁ data |
| vθ | Learned velocity field; target = x₁−x₀ |
| NFE | Function evals per sample: 25 (base) → 4 (distilled) |
| 1−(1−p)N | Best-of-N annotation success probability |
| D⁺ / D⁻ | Engine's chosen / rejected meshes → DPO pairs |
| α | Quality threshold; rises across data-engine iterations |