Editor/SmplModel.cs
using System;
using System.IO;
using System.IO.Compression;
using System.Threading;
using HumanoidMocapX.Inference;
namespace HumanoidMocapX.EditorTools;
/// <summary>Reads only numeric SMPL-H arrays with the shared NPY reader; never
/// evaluates pickle objects. Run off the editor thread after verifying the asset.</summary>
internal static class SmplModel
{
internal static SmplJoints Load(string path, CancellationToken cancellation = default)
{
cancellation.ThrowIfCancellationRequested();
using var archive = ZipFile.OpenRead(path);
var hierarchy = Read("kintree_table", 2, SmplJoints.Joints);
for (var joint = 0; joint < SmplJoints.Joints; joint++)
{
// Upstream replaces the unsigned root sentinel with -1.
if (joint > 0 && hierarchy[joint] != FlowMotion.JointParents[joint]
|| hierarchy[SmplJoints.Joints + joint] != joint)
throw new InvalidDataException("SMPL-H kintree_table is not the supported 52-joint hierarchy.");
}
return SmplJoints.Regress(Read("J_regressor", SmplJoints.Joints, SmplJoints.Vertices),
Read("v_template", SmplJoints.Vertices, 3), Read("shapedirs", SmplJoints.Vertices, 3, SmplJoints.Shapes), cancellation);
float[] Read(string name, params int[] shape)
{
var array = NumpyArray.Read(archive, name + ".npy", cancellation);
if (!array.Shape.AsSpan().SequenceEqual(shape))
throw new InvalidDataException("Incorrect SMPL-H array shape: " + name);
return array.Values;
}
}
}