Data¶
A landmark pass is worth more than the scene it was made in. Save it as a file and it can come back onto the same asset, a renamed one, or a mesh that has since been rebuilt.
-
Saving
What goes in the file, and the samples that decide what it can be loaded onto later.
-
Loading
Four ways to find the faces again, and how to re-target a file at a differently named asset.
-
File format
The schema, field by field, for anyone who wants to write or read one from somewhere else.
What a file is for¶
| Situation | How the file helps |
|---|---|
| The next shot needs the same markup | Load it and every landmark is back, colours, groups and all. |
| The model was rebuilt | Load it by UV or by position and the pass lands on the new topology. |
| Two people mark up different halves | Each saves; both load the other's file. |
| The asset was renamed for a show | Rename meshes on load re-targets the whole file in one field. |
| The geometry went to another package and came back | Bake first, then load by colour set. |
| A landmark pass needs review | The file is plain JSON — readable, diffable, storable next to the asset. |
What is in one¶
Per landmark: its name, node type, colour, group, notes and stable id; its shading-group name; a curated set of shader attributes; and the faces it is assigned to, packed into inclusive ranges.
Optionally, per assigned face: a UV and a position sample. These are what make the file survive the topology changing, and they are the only part of the format that scales with face count.
{
"format": "am_landmark",
"version": 3,
"landmarks": [
{
"name": "jaw_line",
"type": "surfaceShader",
"color": [0.9, 0.35, 0.2],
"group": "head",
"assignments": { "|head|headShape": [[0, 128], [204, 211]] }
}
]
}
Every version of the format this tool has written loads unchanged.
Why ranges and not component strings
The obvious thing to write is what Maya hands you: the raw cmds.sets
member strings, headShape.f[0], headShape.f[1], … For a 40 000-face
assignment that is a megabyte of text which has to be re-parsed on load, and
which cannot be re-targeted at a mesh whose name differs by more than a
substring. Ranges are a handful of integer pairs and the mesh name is stored
once.
