Vixen
dd8b0a81
csharp
public record class MorphTargetData

One blend shape: what a named expression does to the vertices it touches.

Read the guide page for this →

Remarks

Doc 33 § D4, which is where the shape of this was decided and why it is sparse: a brow-raise moves a few hundred vertices of a forty-thousand-vertex face, and the dense form would store thirty-nine thousand seven hundred zero deltas per target. Twenty targets stored densely is more bytes than the mesh.

An entry is a vertex index and two deltas, and the deltas are quantised against a range this target carries. Sixteen-bit signed normals against PositionScale/NormalScale rather than floats: a delta's magnitude is bounded by the shape's own extent, so the quantum is a ten-thousandth of the largest movement in this target — which for a face is a few micrometres — and the entry is sixteen bytes instead of twenty-eight.

⚠ A per-target scale, and not a per-mesh one. A model with a jaw-open worth ten centimetres and an eyelid worth two millimetres shares one range only by giving the eyelid fifty times the quantisation error it needs. The scale costs four bytes a target; sharing one costs precision on every small shape, which is every shape that matters on a face.

⚠ The normal delta is stored as a delta and is not renormalised anywhere. A morphed normal is n + Σ wᵢ Δnᵢ, whose length is not one and is not meant to be — see MorphKernel for why nothing in the pre-pass normalises it, and why that is the safe choice rather than the lazy one.

Sorted by index, ascending. The scatter writes in index order, so a sorted entry list is a coalesced write; and two targets sorted the same way are two runs a merge could walk in step, which is what the union optimisation named in MorphKernel's remarks would need.

Fields and properties (10)

  • public const int Quantum

    The largest magnitude a quantised component can carry.

  • public string Name

    What the shape is called — browRaise, jawOpen, an ARKit name.

  • public int[] Indices

    Which vertices this target moves, ascending.

  • public float PositionScale

    The largest position-delta component in this target, in the mesh's units.

  • public short[] Positions

    Three quantised components per entry, against PositionScale.

  • public float NormalScale

    The largest normal-delta component in this target.

  • public short[] Normals

    Three quantised components per entry against NormalScale, or empty.

  • public int Count

    How many vertices this target moves.

  • public bool HasNormals

    Whether it carries normal deltas as well as position deltas.

  • public long SizeInBytes

    What this target costs, resident, not counting its name.

Methods (4)

  • public Vector3 PositionDelta(int entry)

    The position delta of one entry, dequantised.

  • public Vector3 NormalDelta(int entry)

    The normal delta of one entry, dequantised. Zero where there are none.

  • public static MorphTargetData Encode(string name, ReadOnlySpan<int> indices, ReadOnlySpan<Vector3> positions, ReadOnlySpan<Vector3> normals)

    Builds a target from deltas that are already sparse.

  • public static MorphTargetData Sparsify(string name, ReadOnlySpan<Vector3> positions, ReadOnlySpan<Vector3> normals, float threshold)

    Builds a target from one delta per vertex, dropping the ones that do not move.

Used by (18)

  • CompositorImageTestsVixen.Graphics.Golden.Tests
  • MeshDataVixen.Rendering
  • ModelDataTestsVixen.Rendering.Tests
  • MorphIndexVixen.Rendering
  • MorphIndexTestsVixen.Rendering.Tests
  • MorphKernelVixen.Rendering
  • MorphRenderFeatureVixen.Rendering
  • MorphRenderFeatureTestsVixen.Rendering.Tests
  • MorphScatterDeviceTestsVixen.Graphics.Golden.Tests
  • MorphTargetTestsVixen.Rendering.Tests
  • MorphedClusterTestsVixen.Rendering.Tests
  • ShapesVixen.Rendering
  • TypeRegistrationVixen.Rendering
  • VirtualGeometryGoldenTestsVixen.Graphics.Golden.Tests
  • Vixen_Rendering_MeshDataSerializerVixen.Rendering
  • Vixen_Rendering_MorphTargetDataSerializerVixen.Rendering
  • ModelReaderVixen.Editor.Assets
  • ModelReaderTestsVixen.Editor.Assets.Tests