private void ExportAnimation()
{
int numBones = Maxscript.QueryInteger("grnBones.count");
this.File.Animation.Duration = 0f;
GrnBoneTrack rootBoneTrack = new GrnBoneTrack();
HashSet<float> rootTrackKeys = new HashSet<float>();
rootBoneTrack.DataExtensionIndex = this.File.Bones[0].DataExtensionIndex;
this.File.Animation.BoneTracks.Add(rootBoneTrack);
Maxscript.Command("grnBoneAnimKeys = #()");
for (int i = 1; i <= numBones; ++i)
{
GrnBoneTrack bone = new GrnBoneTrack();
bone.DataExtensionIndex = this.File.Bones[i].DataExtensionIndex;
Maxscript.Command("GetBoneAnimKeys grnBones[{0}]", i);
Maxscript.Command("append grnBoneAnimKeys keys");
if (this.File.Bones[i].ParentIndex > 0 &&
(Maxscript.QueryBoolean("classof grnBones[{0}] == Biped_Object", i) ||
Maxscript.QueryBoolean("classof grnBones[{0}][3].controller == BipSlave_Control", i) ||
Maxscript.QueryBoolean("classof grnBones[{0}][3].controller == Vertical_Horizontal_Turn", i)))
{
Maxscript.Command("join keys grnBoneAnimKeys[grnBoneParents[{0}]]", i);
Maxscript.Command("keys = makeUniqueArray keys");
Maxscript.Command("sort keys");
Maxscript.Command("grnBoneAnimKeys[{0}] = keys", i);
}
int numKeys = Maxscript.QueryInteger("keys.count");
float startTime = Maxscript.QueryFloat("animationRange.start.ticks / 4800.0");
float time = Maxscript.QueryFloat("keys[1]");
Vector3D pos = new Vector3D();
Quaternion rot = new Quaternion();
Matrix3x3 scale = Matrix3x3.Identity;
if (numKeys > 0)
{
if (Maxscript.QueryBoolean("classof grnBones[{0}] == Dummy", i))
{
Maxscript.SetVarAtTime(time + startTime, "boneTransMat", "grnBones[{0}][3].controller.value", i);
}
else if (this.File.Bones[i].ParentIndex > 0)
{
Maxscript.SetVarAtTime(time + startTime, "boneTransMat", "grnBones[{0}].transform", i);
Maxscript.SetVarAtTime(time + startTime, "bonePTransMat", "grnBones[{0}].parent.transform", i);
Maxscript.Command("boneTransMat = boneTransMat * inverse(bonePTransMat)");
}
else
{
Maxscript.SetVarAtTime(time + startTime, "boneTransMat", "grnBones[{0}].transform", i);
}
this.GetTransformPRS("boneTransMat", out pos, out rot, out scale);
bone.PositionKeys.Add(time);
bone.Positions.Add(pos);
bone.RotationKeys.Add(time);
bone.Rotations.Add(rot);
bone.ScaleKeys.Add(time);
bone.Scales.Add(scale);
}
Vector3D posCurrent = new Vector3D();
Quaternion rotCurrent = new Quaternion();
Matrix3x3 scaleCurrent = Matrix3x3.Identity;
for (int j = 1; j < numKeys; ++j)
{
time = Maxscript.QueryFloat("keys[{0}]", j + 1);
if (Maxscript.QueryBoolean("classof grnBones[{0}] == Dummy", i))
{
Maxscript.SetVarAtTime(time + startTime, "boneTransMat", "grnBones[{0}][3].controller.value", i);
}
else if (this.File.Bones[i].ParentIndex > 0)
{
Maxscript.SetVarAtTime(time + startTime, "boneTransMat", "grnBones[{0}].transform", i);
Maxscript.SetVarAtTime(time + startTime, "bonePTransMat", "grnBones[{0}].parent.transform", i);
Maxscript.Command("boneTransMat = boneTransMat * inverse(bonePTransMat)");
}
else
{
Maxscript.SetVarAtTime(time + startTime, "boneTransMat", "grnBones[{0}].transform", i);
}
this.GetTransformPRS("boneTransMat", out posCurrent, out rotCurrent, out scaleCurrent);
if (pos != posCurrent || j + 1 == numKeys)
{
bone.PositionKeys.Add(time);
bone.Positions.Add(posCurrent);
pos = posCurrent;
}
if (rot != rotCurrent || j + 1 == numKeys)
{
bone.RotationKeys.Add(time);
bone.Rotations.Add(rotCurrent);
rot = rotCurrent;
}
if (!this.AreEqual(scale, scaleCurrent) || j + 1 == numKeys) //if (scale != scaleCurrent)
{
bone.ScaleKeys.Add(time);
bone.Scales.Add(scaleCurrent);
scale = scaleCurrent;
}
}
this.File.Animation.BoneTracks.Add(bone);
this.File.Animation.Duration = Math.Max(this.File.Animation.Duration, bone.PositionKeys.Last());
this.File.Animation.Duration = Math.Max(this.File.Animation.Duration, bone.RotationKeys.Last());
this.File.Animation.Duration = Math.Max(this.File.Animation.Duration, bone.ScaleKeys.Last());
}
// Add keys for the root node at 0, middle, end
rootTrackKeys.Add(0);
rootTrackKeys.Add(this.File.Animation.Duration / 2f);
rootTrackKeys.Add(this.File.Animation.Duration);
rootBoneTrack.PositionKeys.AddRange(rootTrackKeys);
rootBoneTrack.RotationKeys.AddRange(rootTrackKeys);
rootBoneTrack.ScaleKeys.AddRange(rootTrackKeys);
for (int i = 0; i < rootTrackKeys.Count; ++i)
{
rootBoneTrack.Positions.Add(new Vector3D(0, 0, 0));
rootBoneTrack.Rotations.Add(new Quaternion(1, 0, 0, 0));
rootBoneTrack.Scales.Add(Matrix3x3.Identity);
}
}