Case study · Film previs 3D

One shot list → an Unreal-ready previs pack in 15 minutes

A mixed shot list goes in — some reference photos, some one-line text briefs. An Unreal-ready pre-visualization pack comes out: a prop per line, FBX and GLB each, one batch import script, Nanite on the heroes. Fifteen minutes, not three days.

6 real props, one run 4 reference photos + 2 text briefs measured on one RTX 5090 refusals shown, not hidden


The problem

To block a sequence a director needs the set standing in the engine — the hero the camera lingers on, the mid-ground it dresses past, the crowd it never focuses on. Dozens of props, and their only jobs are to import clean and read at a glance. They are throwaway by design; they will be replaced before the shot is final.

The usual options are both bad. Asset libraries never have your props — the specific field cannon, the specific brick facade, the crowd that fits this world — so you end up kitbashing approximations. Outsourcing each prop is per-asset and takes days, which is absurd for geometry you're going to throw away. And a raw text‑to‑3D tool hands you a mesh with no guarantee it will even open in Unreal — a broken UV, a non-manifold shell, an invalid glTF that the importer silently mangles.

For a blocking asset, the render isn't the deliverable. It importing clean, every time, on the first try — that's the deliverable. A pack you have to hand-repair before you can block is worse than no pack.

The run: one shot list → a set you can block in

Here is a real run end-to-end — a six-prop shot list, deliberately mixed the way a real one is: four reference photos and two one-line text briefs, spread across three quality tiers. Nothing was hand-modelled; every number below is from this run.

Contact sheet of the previs pack: field cannon hero, a parked brick-facade tile marked with an X, a glass bottle, a street lamp, a wild-boar dressing prop, and a white draft-clay crowd figure
The contact sheet — the whole set at a glance, the director's index. Five props textured and turntabled; the sixth shown with the reason it was refused, not quietly dropped.

1 — The shot list

Six lines. Each line names a prop, its source (a photo or a one-line brief), how many copies the set needs, and the tier — how much camera time it earns.

PropSourceCopiesTier
Field cannonreference photo1hero
Brick building facadetext brief1dressing
Glass bottlereference photo12dressing
Street lamptext brief8dressing
Wild boarreference photo4dressing
Crowd figurereference photo40draft

2 — The delivered props

Each line drives a generation model, then an automated mesh chain sized to its tier: retopology to the tier's face budget, UV, a texture pass, and export to both FBX and GLB. Below are renders of the actual delivered assets — color-true, under a neutral view transform (not the grey-clay preview an early pipeline would show).

Textured render of the field cannon hero prop: dark weathered metal with a teal barrel accent on a heavy base
Hero — field cannon
Textured render of a teal glass bottle with a tan cork
Dressing — glass bottle ×12
Textured render of a tall rust-and-black street lamp
Dressing — street lamp ×8
White draft-clay render of a crowd figure — rough untextured blocking geometry
Draft — crowd figure ×40, shipped as fast blocking clay. It never faces the camera; it doesn't earn a texture pass, and it doesn't wait for one.

3 — The measured numbers

This is the whole point — the wall-clock cost, per prop, from this run. Time follows the tier: a crowd body in seconds, dressing props in a couple of minutes, the hero in six. The pack total is what a director actually waits.

PropTierWallResult
Crowd figuredraft15 s✓ delivered
Street lampdressing1m58s✓ delivered
Wild boardressing2m09s✓ delivered
Glass bottledressing2m41s✓ delivered
Field cannonhero5m53s✓ delivered
Brick facadedressing1m37srefused — see below
Whole pack15m12s5 of 6 delivered

15m12s is a warm run — the stack already resident. From a cold start the same pack lands in roughly 22 minutes; the extra time is the model weights loading once, not per-prop. Either way it's a shot list in under half an hour.

4 — The Unreal import

The pack ships with one script. You run it in Unreal's Python console and the whole set imports under /Game/Previs/<pack>/ in one pass — the right file per prop, materials attached, and Nanite switched on only for the heroes (previs wants dense heroes and light dressing the DP can instance freely). It reads the pack's own manifest, so it skips anything that was refused and never half-imports a broken prop:

for asset in PACK["assets"]:
    if asset.get("status") != "delivered":
        print("skip (not delivered):", asset["prop_id"])
        continue                       # refused props are never imported
    ...
    opts.static_mesh_import_data.build_nanite = bool(asset.get("nanite"))
    opts.static_mesh_import_data.import_uniform_scale = 0.001   # land at true size
    if asset.get("import_rotation"):   # stand up props the generator laid down
        opts.static_mesh_import_data.import_rotation = ...
    tools.import_asset_tasks([task])   # Nanite auto-on for heroes only

It's idempotent — re-export the pack, re-run, and it replaces in place. No per-prop clicking, no picking through a folder deciding which files are safe to import.

Scale and orientation are handled for you — and tested in Unreal Engine 5.8, not assumed. When we ran this pack's own import script inside UE 5.8.0 for the first time (2026‑07‑10), the engine caught what file inspection alone had mis-measured: the exported FBX declared the wrong unit, so every prop landed a thousand times too large, and one prop imported lying on its side. The import contract above is the corrected, engine-verified version — the automated pass now imports the pack into a headless UE 5.8 project, measures every prop's bounds against the shot list's real-world dimensions, checks the Nanite build, and screenshots the result. The screenshot below is that pass's actual output: a 4.2 m field cannon, a 3.2 m street lamp, a 60 cm bottle and a 1.8 m crowd figure, at true relative scale on the engine's own grid.

Unreal Engine 5.8 viewport render: the delivered previs props at true relative scale — field cannon, glass bottle, street lamp and crowd figure standing on a grid floor.
Rendered in Unreal Engine 5.8.0 by the automated validation pass (2026‑07‑10): the spec-correct props at true relative scale — cannon 4.2 m, lamp 3.2 m, crowd figure 1.8 m (standing), bottle 60 cm. One dressing stand-in (the boar) ships with a known generator-scale outlier, recorded in the validation report — its edge is the dark shape entering frame right. Honest N-of-M, as always.
Unreal Engine 5.8 close-up render of the dense Nanite hero mesh, a knight-helmet-class prop, untextured geometry lane.
The dense Nanite hero lane, in-engine: Nanite enabled and built on import (57k source triangles), untextured geometry as this lane ships it.

What you do with it

The pack isn't the product — the afternoon is. Here are the five delivered props dropped into one set and shot with a director's dolly-in — a blocking preview rendered from the delivered meshes. No modelling, no sourcing, no waiting on a vendor: a shot list at breakfast, a blockable set to point a camera at by lunch.

Five delivered props, blocked as a set and shot with a director's dolly — a neutral blocking preview of the afternoon the pack replaces (rendered offline from the same delivered meshes, not an in-engine capture). Draft-tier clay stays clay; the camera never focuses on the crowd, so it never waits on their textures.

The honest differentiator: the gate refuses the broken import

Anyone can show you the props that worked. The reason this pack is worth paying for is the prop it stopped — and the calibration decision that let the other five through fast without letting a broken one slip.

Exhibit A — refused to ship

The brick facade the gates refused

A photoreal concept image of a red-brick building facade with arched windows — the front-end concept that looked perfect before 3D reconstruction failed

The brick facade came from a one-line text brief, and the front-end concept looked perfect — the image on the left is what the pipeline generated before it touched geometry. Then the 3D reconstruction collapsed: the UV layout came out degenerate, texture utilization 0.00 against a 0.40 floor. On a flat, planar facade the unwrap folded to nothing — a mesh that would import into Unreal as an untextured, un-materialisable shell.

The gate caught it at the UV stage and marked the prop refused. You never receive this file. It shows on the contact sheet with the exact reason — a re-brief or a hero-tier retry, not a broken prop you discover only when it imports blank in front of the director.

Verdict on record: parked at S6 — UV utilization 0.00 below the 0.40 floor. A perfect concept is not a valid mesh; the gate checks the mesh.

Exhibit B — the tuning decision

Fit-for-purpose gates: import-ability stays non-negotiable, production precision doesn't block a blocking asset

Here's the part that took real calibration. Run this same six-prop pack under the gate profile built for finished production props, and it parks four of six — not because the props were unusable, but because production gates measure a different thing:

PropUnder production gatesWhy it parked
Street lampparked6,758 faces vs a 7,200 floor — 6% under budget
Brick facadeparked41,677 faces vs an 8,000 target
Wild boarparkedbasecolor luma 29 vs a 30 dielectric floor
Field cannonparkedglTF-Validator: 4 tangent errors

A street lamp 6% under a face budget and a boar one luminance point below a material floor are real production findings — on props a DP looks at for composition, never for a close-up. A gate wall calibrated for marketplace-grade finish was parking product that, for blocking, was done.

So previs gets its own gate profile. The precision gates widen or drop to advisory for draft and dressing tiers — but the gates that decide whether the prop imports at all stay hard everywhere. A pack that won't open is worthless at any speed; that line does not move.

GateChecksProductionPrevis (draft/dressing)
manifold / glTF-Validatorwill it import cleanHARDHARD — never relaxed
face budgetexact poly count±10%±50%
material luma bandtexture precisionblockingadvisory — recorded, ships

Advisory doesn't mean ignored. The boar's luma-29 finding is written into the pack's gate summary verbatim — a paying client can still ask for it. It just doesn't park a blocking asset over one luminance point. And the two fixes those parks surfaced — a face-budget escape hatch that used to stall far above target, and invalid tangents on degenerate-UV geometry — were root-caused and closed, so the delivered run above hits neither.

Exhibit C — tier routing

Money follows camera time

The reason 15 minutes is possible at all is that not every prop earns the same work. Each line is routed by how much the camera lingers on it, and the budget — time, polygons, texture effort — follows:

Spend the render budget where the lens is. A flat rate per prop would either bankrupt the crowd or under-build the hero; tier routing is what lets one run serve all three.

The point

Five props delivered, import-ready. One was refused with the exact reason on the sheet. That refusal isn't a hole in the demo — it's the service. A raw text-to-3D tool would have handed you all six, including the facade that imports as a blank shell, with equal confidence and no warning. The gate that says "this one won't import — here's why" is worth more on a blocking day than one more mediocre mesh.

What a delivery contains

Public-safe summary of the delivery profile. Exact scope is quoted per job.

ItemWhat ships
Per propFBX + GLB, tier-appropriate topology & textures
Importone Unreal batch import script (Nanite auto-on for heroes, idempotent)
Indexcontact sheet — textured turntables, the director's index of the set
Provenanceper-prop verdicts — delivered / refused, with the gate reason for anything that didn't ship
Tiersdraft (blocking) · dressing (mid-ground) · hero (Nanite, strict gates)
Honestythe pack ships N-of-M — a refused prop is shown with its reason, never silently dropped
One number that stays hard, everywhere

Whatever the tier, the import-ability gates — manifold geometry and a clean glTF-Validator pass — are never relaxed. A previs pack's entire value is that it drops into your scene on the first try. Speed is negotiable prop by prop; opening in the engine is not.

Have a sequence to block?

Send a shot list — reference photos, one-line briefs, or a mix — with a tier per prop. You get back one Unreal-ready pack and a contact sheet of the whole set, or an honest "this one won't import cleanly, here's why" before it wastes a review. Batch-priced; every job scoped and quoted.

Contact for a quote → See the full 3D catalogue The e-commerce case study The engineering & honest benchmarks

There is no pricing on this page on purpose — scope drives the estimate, and every job is quoted. The stack, the honest benchmarks (refusals included), and the open-source licence chain live in the documentation repo.