Forge — Simulation
Project memory: if
FORGE.mdexists at the project root, read it first — it carries the frame range, output paths, coordinate system, and prior bake state for this project. ReadATELIER.mdtoo if present (for aesthetic cues that affect simulation look: e.g. slow-motion physics, exaggerated cloth flutter for an award-grade direction).
Forge suite — simulation sits in the rigtech pipeline, between rigging/animation and render/export:
forge (router) → forge-brief (FORGE.md) → forge-standards (units/axes) → forge-model (mesh) → forge-rig (armature/skin) → forge-animate (keyframes) →
forge-sim(YOU — cloth/RB/particles/hair/fluid bake) → forge-export (format matrix) → forge-optimize (Draco/Meshopt/KTX2) → forge-validate (gate) → atelier-webgl (web handoff)
- forge-rig — armatures and skinning that cloth wraps over
- forge-animate — keyframe/F-curve animation; baked RB keyframes land here
- forge-topology — mesh resolution prep before cloth (edge length target 1–2 cm)
- forge-material — Principled Hair BSDF, Principled Volume for smoke/fire
- forge-render — headless Cycles render after bake; QA PNG loop
- forge-export — format matrix; FBX/glTF/USD handoff; particle→mesh conversion
- forge-optimize — Draco/Meshopt/KTX2 compression for web-bound baked meshes
- forge-validate — mandatory gate after export; runs manifold + render QA
Cross-suite: web-bound sims go forge-export → forge-optimize →
Skill(atelier-webgl); the web-runtime perf/a11y gate is atelier-perf-a11y. Atelier-side motion budget: atelier-motion.
Run = call the Skill tool with the exact skill name (e.g. Skill("forge-export")). Saying "next, run forge-render" in prose runs nothing.
Decide first: which sim type, which bake strategy?
Before writing any script, pick the simulation type and confirm Blender is available:
1. Identify the type: cloth | rigid body | particles | hair/GN curves | fluid/smoke
2. Verify Blender (same preflight the other rigtech/lookdev skills use):
python "$CLAUDE_CONFIG_DIR/skills/forge-render/scripts/preflight.py" --tools blender,python --json
If `all_found` is false (or `blender` is in `missing`), stop and instruct installation;
`blender_path` gives the resolved blender.exe for the bake invocation below.
3. Confirm .blend file is SAVED to disk (point cache requires a saved anchor)
4. Check cache type for fluid: must be ALL or MODULAR — never REPLAY for headless bakes
5. Confirm FORGE.md frame range and output paths
Each sim type has its own bake operator and gotchas. Deep references below — read only what you need.
The flow
Read project state — read
FORGE.md; if absent, ask for frame range, output dir, and target engine.Preflight gate — verify
blenderis on PATH. If missing, stop and report.Identify sim type — cloth / rigid body / particles / hair-fur / fluid-smoke. Multiple types in one scene: bake all via
ptcache.bake_all(bake=True)first, then per-type operators if needed (Mantaflow needsfluid.bake_allseparately — it is NOT covered by ptcache).Write the bake script — use the patterns from
references/for the chosen type. Save to.forge-build/scripts/<slug>_bake.py. Configuration at the top of the script as named constants, not inline magic numbers.Save the .blend first — before any bake:
bpy.ops.wm.save_mainfile(). Disk cache writes toblendcache_<filename>/beside the .blend; an unsaved file has no anchor path.Run the bake — PowerShell, absolute paths, forward slashes in Blender filepath args:
$blender = "C:\Program Files\Blender Foundation\Blender 4.5\blender.exe" & $blender -b "C:/Projects/scene.blend" -t 0 --python "C:/Projects/bake.py" -- --forgeThe
--separator before custom args is mandatory.-t 0uses all CPU cores (fast, but non-deterministic — switch to-t 1for byte-reproducible / idempotent rebuilds; see Operating principles).Verify the cache — run the type-specific programmatic check (see
references/<type>-bake.md). For cloth:pc.is_baked. For rigid body:rbw.point_cache.is_baked. For fluid:ds.has_cache_baked_data+ VDB file count.QA render — render a mid-sim frame headlessly (Cycles, 32–64 samples). Read the PNG with the Read tool and inspect visually. If the render is blank, static, or exploded — diagnose via the gotcha tables in
references/.Export cache — Alembic for cloth/rigid body/hair; OpenVDB folder for smoke/fire. See
references/export-cache.mdfor operator flags. Alwaysas_background_job=False.Hand off (Run = call the Skill tool, not prose):
- Game engine (Unreal/Unity/Godot):
Skill("forge-export"). - Web / Three.js / R3F:
Skill("forge-export")→Skill("forge-optimize")→Skill("atelier-webgl")— the export→compress→web chain; the baked cache ships as a Meshopt-compressed GLB, never stopping at forge-export. - Full-quality final render over the baked cache:
Skill("forge-render"). - Always gate the result with
Skill("forge-validate").
- Game engine (Unreal/Unity/Godot):
Sim-type quick reference
| Type | Bake operator | Cache format | Export |
|---|---|---|---|
| Cloth | ptcache.bake_all or ptcache.bake + temp_override |
.bphys |
Alembic (.abc) |
| Rigid body | ptcache.bake_all |
.bphys |
Keyframes (headless manual) or Alembic |
| Particles | ptcache.bake_all or per-system temp_override |
.bphys |
Instances→real objects → FBX/glTF |
| Hair (GN Curves) | No bake needed (static); use cloth dynamics if physics needed | — | Alembic (particle hair) or GroomExporter (UE5) |
| Fluid/smoke/fire | fluid.bake_all + temp_override |
OpenVDB .vdb |
Copy cache/data/ folder |
Critical split: ptcache.bake_all does NOT bake Mantaflow fluid. Fluid needs fluid.bake_all.
Deep references (read on demand)
references/cloth-bake.md— cloth modifier setup, pinning, presets (cotton/silk/denim/rubber), impulse clamping, Alembic export, explosion detection, gotcha tablereferences/rigid-particles-bake.md— rigid body world config, active/passive bodies, manual keyframe bake (headless-safe), particle emitter setup, force fields, particles-to-real-mesh for export, gotcha tablereferences/hair-fluid-bake.md— GN Curves creation, Principled Hair BSDF, Mantaflow ALL/MODULAR bake, VDB export structure, REPLAY gotcha, Windows path pitfalls, decision matrixreferences/export-cache.md— Alembic export operator flags, MeshSequenceCache re-import, VDB import, UE5 Groom scale (100×), game-engine conversion notes
Operating principles
- Bake before render, always. In headless mode Blender cannot evaluate physics on-the-fly. A render of an unbaked sim returns the reset pose. Check
is_bakedorhas_cache_baked_databefore launching forge-render. - Save the .blend before baking. Point cache and VDB files anchor to the .blend path. An unsaved file silently loses all cache data on exit.
- Use
ptcache.bake_allfor cloth/RB/particles; usefluid.bake_allfor Mantaflow. These are separate operators; one does not call the other. - Always set
as_background_job=Falsein any export operator (Alembic, USD, FBX). The background-job thread exits before Blender's main loop can collect it — the file will not be written. - Forward slashes in all Blender file paths. Use
pathlib.Path(p).as_posix()or raw forward-slash strings. Backslashes can be silently misinterpreted in Blender's internal path handling on Windows. - Determinism: sims are FP-order-sensitive.
-t 0(all cores) is fast but NOT reproducible — two bakes give different results. Use-t 1(single-thread) whenever a bake must be byte-reproducible: CI, regression, or an idempotent rebuild. Always set an explicit force-fieldseed(e.g.seed=1) so wind/turbulence is repeatable, and seed the particle system (ps.seed) as well. See thereferences/*.mdgotcha tables ("two bakes produce different results → -t 1").