Bodies without a skin load as BodyRig::Static through load_body_file:
OBJ+MTL and skinless FBX via the rigid equipment readers (normalized once),
glTF without skins with node world transforms baked once (mirror flips
winding). No skeleton or clips are invented: live view and production draw
the stored pose, the batch renders clip000-bind x 36 views with the same
four maps, the pivot falls back to center Y (manual pivot still wins).
Clip picker/Play, bone tree and equipment render are disabled with an
explanation; production refuses equipment jobs on a static body.
Fixtures from scripts/generate_static_bodies.py, tests/static_body.rs and
GPU proof examples/static_body_fixture.rs.
FBX bodies load through preview::load_body_file (fbx_scene, normalized
once) in the shared-depth live viewport and the production four-map batch
with the same camera, neck pivot and fixed per-body zoom. FBX UVs are
converted once to the PreviewCharacter convention.
equipment::import_fbx imports rigid FBX parts from in-memory bytes with
the same axis/unit normalization, embeds the original FBX and embedded or
relative PNG textures in the .ppe, and rejects skinned meshes, blend
shapes and non-PNG textures. The equipment picker accepts OBJ and FBX.
Adds Blender-generated CC0 FBX sword fixtures, integration tests against
the GLB body, and the fbx_live_fixture GPU proof example.
Build an in-process FBX scene (fbx_scene) with unit/axis normalization,
materials/textures, skin inverse-binds, and baked sampleable clips.
Fixture tests compare bind-equivalent and animated joints against the
matching GLB. Live viewport and production remain glTF/GLB-only.
- run.lock + append-only progress.jsonl (path/SHA-256 per published PNG)
- resume only when stored render.json equals the current job contract
- verify every planned PNG; keep good files untouched, regenerate missing,
quarantine corrupt/foreign files (.corrupt-aNNN-K), compare unjournaled
- archive previous cancelled/failed markers as attempt-NNN-*.json,
resume.jsonl per attempt, cancel again, complete.json as uninterrupted
- unique per-write temp names; editor 'Onderbroken renders' list + Hervat
- crash/cancel/mismatch/lock tests and real GPU resume_fixture
Add preview2d state machine over schema-3 export_set + compositor:
sex/equipment/clip selection via CompatKey, looping FPS/speed playback,
yaw wrap and pitch clamp preserving time, continuous held light controls
with dt, missing-frame diagnostics, and an editor 2D-preview tab with
aspect-preserving nearest-neighbor letterboxing. Mark Preview2d present.
Consume schema-3 export_set maps for body + compatible equipment. Nearest
valid depth wins with DEPTH_EPSILON_U16=1 and lower-index tie-break; diffuse,
normal and specular stay bound to that same layer. Documented single-depth
alpha-edge policy. Linear ambient/diffuse/Blinn-Phong relighting uses a
view-space light matching exported normals. Pixel fixtures cover occlusion,
ties, transparency and lighting. Preview2d GUI remains not built.
Bump production render.json/complete.json to schema 3 with project
identity, body/equipment SHA-256 fingerprints, resolved camera/pivot
contract, clip inventory and per-PNG checksums. Add export_set reader
that opens only completed runs with matching identity, rejects
traversal/symlinks/stale schemas/corrupt maps, and decodes real RGBA8
and gray-alpha16 depth under production caps. Keep atomic no-clobber
hardlink publication; incomplete runs never get complete.json.