// Writing compressed & decompressing keyframes private RwCompressedKeyFrameData ReadCompressedKeyFrames(BinaryReader reader) { var compressedKeyFrames = new List <RwCompressedKeyFrame>(); for (int i = 0; i < KeyFrames.Capacity; i++) { var compressedKeyFrame = new RwCompressedKeyFrame { Time = reader.ReadSingle(), RotationX = reader.ReadUInt16(), RotationY = reader.ReadUInt16(), RotationZ = reader.ReadUInt16(), RotationW = reader.ReadUInt16(), TranslationX = reader.ReadUInt16(), TranslationY = reader.ReadUInt16(), TranslationZ = reader.ReadUInt16(), PreviousFrameOffset = reader.ReadInt32() }; compressedKeyFrames.Add(compressedKeyFrame); } var customData = new RwCompressedKeyFrameCustomData { Offset = reader.ReadVector3(), Scalar = reader.ReadVector3() }; return(new RwCompressedKeyFrameData(compressedKeyFrames, customData)); }
// Compress keyframes private void CompressKeyFrames(out List <RwCompressedKeyFrame> compressedKeyFrames, out RwCompressedKeyFrameCustomData customData) { var keyFrameToOffsetMap = new Dictionary <RwKeyFrame, int>(); // Move translations >= 0 customData = new RwCompressedKeyFrameCustomData { Offset = new Vector3 ( KeyFrames.Min(x => x.Translation.X), KeyFrames.Min(x => x.Translation.Y), KeyFrames.Min(x => x.Translation.Z) ) }; compressedKeyFrames = new List <RwCompressedKeyFrame>(); var offsetTranslations = new List <Vector3>(); for (var i = 0; i < KeyFrames.Count; i++) { var keyFrame = KeyFrames[i]; // add key frame to offset map for mapping the previous keyframe keyFrameToOffsetMap[keyFrame] = i * COMPRESSED_KEYFRAME_SIZE; // create the compressed key frame var compressedKeyFrame = new RwCompressedKeyFrame { // time will remain the same Time = keyFrame.Time, // compress rotation quaternion RotationX = CompressFloat(keyFrame.Rotation.X), RotationY = CompressFloat(keyFrame.Rotation.Y), RotationZ = CompressFloat(keyFrame.Rotation.Z), RotationW = CompressFloat(keyFrame.Rotation.W), }; // set to previous frame offset using the map if (keyFrame.Previous != null) { compressedKeyFrame.PreviousFrameOffset = keyFrameToOffsetMap[keyFrame.Previous]; } else { compressedKeyFrame.PreviousFrameOffset = -1; } // add the newly created compressed key frame to the list // it's not yet fully initialized as the translations still // have to be processed compressedKeyFrames.Add(compressedKeyFrame); // offset the translation by the distance overall closest to zero var translation = keyFrame.Translation; translation.X -= customData.Offset.X; translation.Y -= customData.Offset.Y; translation.Z -= customData.Offset.Z; // add the offset translation to a seperate list offsetTranslations.Add(translation); } // calculate the translation scalar by taking the largest value of each // axis customData.Scalar = new Vector3( offsetTranslations.Max(x => x.X), offsetTranslations.Max(x => x.Y), offsetTranslations.Max(x => x.Z)); // compress the translation using the offset translation and calculated scalar for (int i = 0; i < offsetTranslations.Count; i++) { compressedKeyFrames[i].TranslationX = CompressFloat(offsetTranslations[i].X / customData.Scalar.X); compressedKeyFrames[i].TranslationY = CompressFloat(offsetTranslations[i].Y / customData.Scalar.Y); compressedKeyFrames[i].TranslationZ = CompressFloat(offsetTranslations[i].Z / customData.Scalar.Z); } }