-
Notifications
You must be signed in to change notification settings - Fork 51
Description
We have a 400mb pose set, and it takes about 11 seconds to load. Iterating has become slower because of it. I did make an effort to use memory mapped files, but in Unity that requires permissions that could trip up developers unduly. I made a small change to load the whole file into memory then construct classes from it in ram. This brought us down to 7.8 seconds, with minimal code change. Note that because AnimationClip is a struct and it's being fed into the poseSet one at a time, whenever the clip list resizes, it has to re-copy all of that data over and over again... a slightly more invasive change would dramatically help by simply setting the list capacity once nClips has been read.
` public bool Deserialize(string path, string fileName, MotionMatchingData mmData, out PoseSet poseSet)
{
poseSet = new PoseSet(mmData);
// --------------------
// Read Skeleton File
// --------------------
string skeletonPath = Path.Combine(path, fileName + ".mmskeleton");
if (!File.Exists(skeletonPath))
return false;
Skeleton skeleton = new Skeleton();
PROFILE.BEGIN_SAMPLE_PROFILING("Skeleton File Read");
byte[] skeletonData = File.ReadAllBytes(skeletonPath);
PROFILE.END_AND_PRINT_SAMPLE_PROFILING("Skeleton File Read");
using (var ms = new MemoryStream(skeletonData))
{
using (var reader = new BinaryReader(ms, Encoding.UTF8))
{
uint nJoints = reader.ReadUInt32();
for (int i = 0; i < nJoints; i++)
{
string jointName = reader.ReadString();
uint jointIndex = reader.ReadUInt32();
uint jointParentIndex = reader.ReadUInt32();
float3 jointLocalOffset = ReadFloat3(reader);
HumanBodyBones jointType = (HumanBodyBones)reader.ReadUInt32();
skeleton.AddJoint(new Skeleton.Joint(jointName, (int)jointIndex, (int)jointParentIndex, jointLocalOffset, jointType));
}
}
}
poseSet.SetSkeletonFromFile(skeleton);
// --------------------
// Read Pose File
// --------------------
string posePath = Path.Combine(path, fileName + ".mmpose");
if (!File.Exists(posePath))
return false;
PROFILE.BEGIN_SAMPLE_PROFILING("Pose File Read");
byte[] poseData = File.ReadAllBytes(posePath);
PROFILE.END_AND_PRINT_SAMPLE_PROFILING("Pose File Read");
using (var ms = new MemoryStream(poseData))
{
using (var reader = new BinaryReader(ms, Encoding.UTF8))
{
uint nClips = reader.ReadUInt32();
for (int i = 0; i < nClips; i++)
{
uint start = reader.ReadUInt32();
uint end = reader.ReadUInt32();
float frameTime = reader.ReadSingle();
poseSet.AddAnimationClipDeserialized(new PoseSet.AnimationClip((int)start, (int)end, frameTime));
}
uint nPoses = reader.ReadUInt32();
uint nJoints = reader.ReadUInt32();
uint nTags = reader.ReadUInt32();
Debug.Assert(nJoints == skeleton.Joints.Count, "Number of joints in skeleton and pose do not match");
PoseVector[] poses = new PoseVector[nPoses];
for (int i = 0; i < nPoses; i++)
{
PoseVector pose = new PoseVector();
pose.JointLocalPositions = ReadFloat3Array(reader, nJoints);
pose.JointLocalRotations = ReadQuaternionArray(reader, nJoints);
pose.JointLocalVelocities = ReadFloat3Array(reader, nJoints);
pose.JointLocalAngularVelocities = ReadFloat3Array(reader, nJoints);
pose.LeftFootContact = reader.ReadUInt32() == 1u;
pose.RightFootContact = reader.ReadUInt32() == 1u;
poses[i] = pose;
}
poseSet.AddClipDeserialized(poses);
for (int i = 0; i < nTags; i++)
{
string name = reader.ReadString();
int nRanges = (int)reader.ReadUInt32();
List<int> tagStarts = new List<int>(nRanges);
List<int> tagEnds = new List<int>(nRanges);
for (int r = 0; r < nRanges; r++)
{
tagStarts.Add((int)reader.ReadUInt32());
tagEnds.Add((int)reader.ReadUInt32());
}
poseSet.AddTagDeserialized(name, tagStarts, tagEnds);
}
poseSet.ConvertTagsToNativeArrays();
}
}
return true;
}
`