Documentation
Docs/en/reference/model-format/validation.md
Model Format Validation
Generated reference. Do not edit directly. Update
BuildTools/ModelFormatInterface.json, then runpython BuildTools/docs_model_format.py --write.
| Index | Syntax | Tokens | Composition | Assets | Animation | Validation | Canonical JSON | Guide |
Contract rules
| Stable ID | Rule | Requirement | Why | Source |
|---|---|---|---|---|
model-format.rule.lexical-syntax |
Whitespace tokenization | Directives and arguments are whitespace-separated; # and ; start comments; there is no quoting or escaping for paths containing spaces. | The parser strips comments and feeds each line through istringstream token extraction. | Source/Tools/ModelInfoBaker.cpp |
model-format.rule.multiple-directives |
Sequential line parsing | A line may contain multiple directives; each directive consumes its exact argument count and parsing continues with the next token. | Compact layer entries are legal, but ordering changes which current link or mesh selector receives later modifiers. | Source/Tools/ModelInfoBaker.cpp |
model-format.rule.selector-order |
Selector ordering | After Layer or Value, author Root, Attach, or AttachParticles before link modifiers such as transforms, materials, disables, or cuts. | Layer and Value point at a dummy link and clear Mesh; modifiers written before a real link is created are discarded. | Source/Tools/ModelInfoBaker.cpp |
model-format.rule.template-files |
Template naming | Name include-only files with a basename beginning TEMPLATE_; concrete files must not use that prefix. | Template files participate in include timestamps and parsing but ModelInfoBaker does not emit them as independent resources or animation-metadata sections. | Source/Tools/ModelInfoBaker.cpp |
model-format.rule.include-replacements |
Include replacement scope | Include arguments are name/value pairs replacing every literal %name% occurrence in the included text before tokenization. | Replacement is plain text and does not understand token boundaries; choose placeholder names that cannot collide accidentally. | Source/Tools/ModelInfoBaker.cpp |
model-format.rule.relative-paths |
Path ownership | Model, Include, Attach, and Cut paths resolve relative to their declaring .fo3d file; animation files resolve relative to the concrete description unless ModelFile is used; particle and effect paths are global baked-resource paths. | Moving a template or concrete description can change the asset paths contributed by directives inside that file. | Source/Tools/ModelInfoBaker.cpp |
model-format.rule.zero-identity |
Zero is transform identity | Treat zero transform and Speed fields as no contribution. The + and * variants initialize a zero field from their operand before applying later operations. | Runtime SetAnimData skips zero fields, while parser accumulation deliberately makes template-only Scale* and Speed* useful. | Source/Tools/ModelInfoBaker.cpp, Source/Client/ModelInstance.cpp |
model-format.rule.layer-zero |
Layer zero value is inactive | A runtime layer value of zero selects no link; authored Root and Attach entries require a non-zero Value. | The composition loop skips zero layer values and the baker rejects links created with zero. | Source/Tools/ModelInfoBaker.cpp, Source/Client/ModelInstance.cpp |
model-format.rule.parent-materials |
Parent material inheritance | Use Parent or Parent_<mesh> only inside an attached child model; the parent mesh must already expose the requested texture slot or effect. | The child copies the parent’s current material state, not the imported default, and root descriptions have no parent context. | Source/Tools/ModelInfoBaker.cpp, Source/Client/ModelInstance.cpp |
model-format.rule.mesh-before-info |
Baker order | Run ModelMeshBaker before ModelInfoBaker so every mesh, hierarchy, material, animation, and cut reference can be validated from baked data. | Built-in baker orders are 4 for ModelMesh and 6 for ModelInfo. | Source/Tools/ModelMeshBaker.h, Source/Tools/ModelInfoBaker.h |
model-format.rule.first-animation-wins |
First animation mapping wins | Do not declare the same state/action Anim pair more than once; only the first mapping is validated and registered. | Duplicates are skipped by both model-info validation and client registration. | Source/Tools/ModelInfoBaker.cpp, Source/Client/ModelInformation.cpp |
model-format.rule.runtime-composition |
Layer changes rebuild composition | Treat model-layer arrays as composition state: changing a value may create or remove children and particles, change materials/effects, disable geometry, apply cuts, and regenerate combined meshes. | A layer change is not a cosmetic integer update; it changes the render graph and batching state. | Source/Client/ModelInstance.cpp |
model-format.rule.baked-link-bounds |
Baked geometry-link bounds | Every non-particle child link carries a validated aggregate root-space AABB plus per-animation AABBs for its parent’s mapped clips; default and particle links carry no geometry payload. | Runtime framing selects direct-child bounds for active parent clips and falls back to the aggregate link envelope instead of walking and skinning combined-mesh vertices. | Source/Tools/ModelInfoBaker.cpp, Source/Client/ModelInformation.cpp, Source/Client/ModelInstance.cpp |
model-format.rule.source-units-and-mirroring |
Positive scale and Engine world units | Freeze mirrored mesh nodes to a positive transform before export, and author direct FBX/OBJ attachments within Baking.ModelAttachmentMinExtent and Baking.ModelAttachmentMaxExtent. Use a child .fo3d when an explicit description-level scale is required. | Negative transforms invert winding and normals; foreign unit scales produce impossible model-sprite frames. Failing the bake keeps both defects at their authored source. | Source/Tools/ModelMeshBaker.cpp, Source/Tools/ModelInfoBaker.cpp |
model-format.rule.validation-boundary |
Bake plus visible validation | Require a clean resource bake for syntax and asset closure, then exercise the model in a visible client scene for scale, pose, layer composition, attachments, materials, cuts, and interaction bounds. | Baking proves references and serialized structure; only the client renderer proves the composed visual result. | Source/Tests/Test_ModelBaker.cpp |
Removed legacy spellings
| Removed token | Replacement | Current contract |
|---|---|---|
AnimEqual |
StateAnimEqual or ActionAnimEqual |
The current parser requires the enum domain to be explicit. |
CalculateTangentSpace |
none |
Mesh import configures ufbx to generate and normalize missing normals and tangents; there is no .fo3d directive. |
RenderFrame |
none |
Current model descriptions do not generate 2D render frames. |
RenderFrames |
none |
Current model descriptions do not generate 2D render-frame sequences. |
DrawSize |
automatic model-sprite layout from baked animation bounds |
ModelInfo baking records aggregate and per-animation bounds; the client derives the offscreen frame for the active composition and pose. |
ViewSize |
automatic view/name layout from baked idle-priority bounds |
The client projects baked model bounds and active child layers instead of accepting an authored interaction rectangle. |
The accepted compatibility spelling Subset is listed separately in Tokens as deprecated because it consumes an argument but does not select a mesh.
Validation commands
python BuildTools\docs_model_format.py --check
python -m unittest BuildTools.tests.test_docs_model_format
.\Binaries\Tests-Windows-win64\LF_UnitTests.exe "ModelBaker*"
cmake --build Build\Auto --config RelWithDebInfo --target BakeResources
Finish with a visible client scene that exercises every authored layer combination, attachment, material override, cut, animation, draw size, and interaction bound used by the project.