Skip to content

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.

The Data page

  • Saving


    What goes in the file, and the samples that decide what it can be loaded onto later.

    Saving

  • Loading


    Four ways to find the faces again, and how to re-target a file at a differently named asset.

    Loading

  • File format


    The schema, field by field, for anyone who wants to write or read one from somewhere else.

    File format

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.