diff --git a/TombLib/TombLib/LevelData/Compilers/TombEngine/Structs.cs b/TombLib/TombLib/LevelData/Compilers/TombEngine/Structs.cs index a00161107..916f4ec1b 100644 --- a/TombLib/TombLib/LevelData/Compilers/TombEngine/Structs.cs +++ b/TombLib/TombLib/LevelData/Compilers/TombEngine/Structs.cs @@ -631,7 +631,6 @@ public void Write(BinaryWriterEx writer) foreach (var animation in Animations) { writer.Write(animation.StateID); - writer.Write(animation.Interpolation); writer.Write(animation.FrameEnd); writer.Write(animation.NextAnimation); writer.Write(animation.NextFrame); @@ -665,6 +664,7 @@ public void Write(BinaryWriterEx writer) writer.Write(fixedMotionCurveZ.StartHandle); writer.Write(fixedMotionCurveZ.EndHandle); + // Write dummy frame if no key frames exist. if (animation.KeyFrames.Count == 0) { var defaultKeyFrame = new TombEngineKeyFrame(); @@ -673,12 +673,49 @@ public void Write(BinaryWriterEx writer) writer.Write(1); defaultKeyFrame.Write(writer); } + // Write baked frames. else { - writer.Write(animation.KeyFrames.Count); - foreach (var keyFrame in animation.KeyFrames) + // Write key frame. + writer.Write(animation.KeyFrames.Count * animation.Interpolation); + + float alphaStep = 1.0f / (float)animation.Interpolation; + for (int i = 0; i < animation.KeyFrames.Count; i++) { - keyFrame.Write(writer); + var currentKeyframe = animation.KeyFrames[i]; + currentKeyframe.Write(writer); + + if (i == (animation.KeyFrames.Count - 1)) + break; + + var nextKeyframe = animation.KeyFrames[i + 1]; + + // Write interpolated frames. + for (int j = 1; j < animation.Interpolation; j++) + { + float alpha = alphaStep * j; + + var center = Vector3.Lerp(currentKeyframe.BoundingBox.Center, nextKeyframe.BoundingBox.Center, alpha); + var extents = Vector3.Lerp(currentKeyframe.BoundingBox.Extents, nextKeyframe.BoundingBox.Extents, alpha); + + var rootPos = Vector3.Lerp(currentKeyframe.RootOffset, nextKeyframe.RootOffset, alpha); + + var boneOrients = new List(currentKeyframe.BoneOrientations.Count); + for (int k = 0; k < boneOrients.Count; k++) + boneOrients[k] = Quaternion.Slerp(currentKeyframe.BoneOrientations[k], nextKeyframe.BoneOrientations[k], alpha); + + var frame = new TombEngineKeyFrame(); + frame.BoundingBox = new TombEngineBoundingBox(); + frame.BoundingBox.X1 = (short)(center.X - extents.X); + frame.BoundingBox.X2 = (short)(center.X + extents.X); + frame.BoundingBox.Y1 = (short)(center.Y - extents.Y); + frame.BoundingBox.Y2 = (short)(center.Y + extents.Y); + frame.BoundingBox.Z1 = (short)(center.Z + extents.Z); + frame.BoundingBox.Z2 = (short)(center.Z - extents.Z); + frame.RootOffset = rootPos; + frame.BoneOrientations = boneOrients; + frame.Write(writer); + } } } @@ -757,17 +794,8 @@ public class TombEngineKeyFrame public void Write(BinaryWriterEx writer) { - var center = new Vector3( - BoundingBox.X1 + BoundingBox.X2, - BoundingBox.Y1 + BoundingBox.Y2, - BoundingBox.Z1 + BoundingBox.Z2) / 2; - var extents = new Vector3( - BoundingBox.X2 - BoundingBox.X1, - BoundingBox.Y2 - BoundingBox.Y1, - BoundingBox.Z2 - BoundingBox.Z1) / 2; - - writer.Write(center); - writer.Write(extents); + writer.Write(BoundingBox.Center); + writer.Write(BoundingBox.Extents); writer.Write(RootOffset); writer.Write(BoneOrientations.Count); @@ -784,6 +812,28 @@ public struct TombEngineBoundingBox public short Y2; public short Z1; public short Z2; + + public Vector3 Center + { + get + { + return new Vector3( + X1 + X2, + Y1 + Y2, + Z1 + Z2) / 2; + } + } + + public Vector3 Extents + { + get + { + return new Vector3( + X1 - X2, + Y1 - Y2, + Z1 - Z2) / 2; + } + } } [StructLayout(LayoutKind.Sequential, Pack = 1)]