using System; using MathNet.Numerics.LinearAlgebra; using MathNet.Numerics.LinearAlgebra.Double; using SMPLModel; using ThirdParty.SimpleJSON; using UnityEngine; namespace FileLoaders { /// /// Reads the regressor JSON file and loads it into Unity-Compatible formats. /// File should contain a Joint template and Joint regressor to fit formula /// JointLocations = JointTemplate + JointRegressor * Betas /// I wrote a python script included in the github repository to extract the necessary matrices /// from the model.npz files provided by MPI /// public class SMPLHRegressorFromJSON { const string JointRegressorJSONKey = "joint_regressor"; const string JointTemplateJSONKey = "joint_template"; const int SMPLHJointCount = 52; const int SMPLHBetaCount = 16; const int ThreeDimensions = 3; const int XDimension = 0; const int YDimension = 1; const int ZDimension = 2; Matrix jointRegressorMatrixX; Matrix jointRegressorMatrixY; Matrix jointRegressorMatrixZ; Matrix jointTemplate; /// /// Static builder to create a Regressor from a JSON file. /// public static JointRegressor LoadRegressorFromJSON(TextAsset jsonFile) { if (jsonFile == null) throw new NullReferenceException("No JointRegressor file defined"); JSONNode jsonNode = JSON.Parse(jsonFile.text); SMPLHRegressorFromJSON fromJSON = new SMPLHRegressorFromJSON(); fromJSON.LoadJointTemplate(jsonNode); fromJSON.LoadJointRegressor(jsonNode); JointRegressor jointRegressor = new JointRegressor(fromJSON.jointTemplate, fromJSON.jointRegressorMatrixX, fromJSON.jointRegressorMatrixY, fromJSON.jointRegressorMatrixZ); return jointRegressor; } /// /// Loads the Joint template from a JSON node /// void LoadJointTemplate(JSONNode templateJSONNode) { JSONNode jointTemplateNode = templateJSONNode[JointTemplateJSONKey]; double[,] jointTemplateArray = new double[SMPLHJointCount, ThreeDimensions]; for (int jointIndex = 0; jointIndex < SMPLHJointCount; jointIndex++) { for (int dimensionIndex = 0; dimensionIndex < ThreeDimensions; dimensionIndex++) { jointTemplateArray[jointIndex, dimensionIndex] = jointTemplateNode[jointIndex][dimensionIndex]; } } jointTemplate = DenseMatrix.OfArray(jointTemplateArray); } /// /// Loads the joint regressor into Unity-compatible matrix format (3 separate matrices, one for each dimension) /// void LoadJointRegressor(JSONNode regressorJSONNode) { JSONNode regressorNode = regressorJSONNode[JointRegressorJSONKey]; //joint jointRegressor stored as 52x3x16 jointTemplate, need to decompose into 3 separate 52x16 matrices. double[,] jointRegressorX = new double[SMPLHJointCount, SMPLHBetaCount]; double[,] jointRegressorY = new double[SMPLHJointCount, SMPLHBetaCount]; double[,] jointRegressorZ = new double[SMPLHJointCount, SMPLHBetaCount]; for (int jointIndex = 0; jointIndex < SMPLHJointCount; jointIndex++) { for (int betaIndex = 0; betaIndex < SMPLHBetaCount; betaIndex++) { jointRegressorX[jointIndex, betaIndex] = regressorNode[jointIndex][XDimension][betaIndex]; jointRegressorY[jointIndex, betaIndex] = regressorNode[jointIndex][YDimension][betaIndex]; jointRegressorZ[jointIndex, betaIndex] = regressorNode[jointIndex][ZDimension][betaIndex]; } } jointRegressorMatrixX = DenseMatrix.OfArray(jointRegressorX); jointRegressorMatrixY = DenseMatrix.OfArray(jointRegressorY); jointRegressorMatrixZ = DenseMatrix.OfArray(jointRegressorZ); } } }