/// <summary> /// This function filters out keyframes that can be approximated well with /// linear interpolation. /// </summary> /// <param name="keyframes"></param> static void LinearKeyframeReduction(LinkedList <MyAnimationClip.Keyframe> keyframes, float translationThreshold, float rotationThreshold) { if (keyframes.Count < 3) { return; } for (LinkedListNode <MyAnimationClip.Keyframe> node = keyframes.First.Next; ;) { LinkedListNode <MyAnimationClip.Keyframe> next = node.Next; if (next == null) { break; } // Determine nodes before and after the current node. MyAnimationClip.Keyframe a = node.Previous.Value; MyAnimationClip.Keyframe b = node.Value; MyAnimationClip.Keyframe c = next.Value; float t = (float)((node.Value.Time - node.Previous.Value.Time) / (next.Value.Time - node.Previous.Value.Time)); Vector3 translation = Vector3.Lerp(a.Translation, c.Translation, t); var rotation = VRageMath.Quaternion.Slerp(a.Rotation, c.Rotation, t); if ((translation - b.Translation).LengthSquared() < translationThreshold && VRageMath.Quaternion.Dot(rotation, b.Rotation) > rotationThreshold) { keyframes.Remove(node); } node = next; } }
/// <summary> /// Set the keyframes to a valid value relative to /// the current keyframe /// </summary> void SetKeyframes() { if (ClipBone == null) { return; } if (ClipBone.Keyframes.Count > 0) { Keyframe1 = ClipBone.Keyframes[m_currentKeyframe]; if (m_currentKeyframe == ClipBone.Keyframes.Count - 1) { Keyframe2 = Keyframe1; } else { Keyframe2 = ClipBone.Keyframes[m_currentKeyframe + 1]; } } else { // If there are no keyframes, set both to null Keyframe1 = null; Keyframe2 = null; } }
public void Clear() { m_currentKeyframe = 0; m_isConst = false; m_assignedBone = null; Rotation = default(Quaternion); Translation = Vector3.Zero; Player = null; Keyframe1 = null; Keyframe2 = null; m_clipBone = null; }
private static MyAnimationClip ReadClip(BinaryReader reader) { var myAnimationClip = new MyAnimationClip(); myAnimationClip.Name = reader.BaseStream.ReadString(Encoding.ASCII); myAnimationClip.Duration = reader.ReadDouble(); var num1 = reader.ReadInt32(); while (num1-- > 0) { var bone = new MyAnimationClip.Bone(); bone.Name = reader.BaseStream.ReadString(Encoding.ASCII); var num2 = reader.ReadInt32(); while (num2-- > 0) { var keyframe = new MyAnimationClip.Keyframe(); keyframe.Time = reader.ReadDouble(); keyframe.Rotation = ImportQuaternion(reader); if (NORMALIZE_QUATERNIONS) { keyframe.Rotation.Normalize(); } keyframe.Translation = ImportVector3(reader); bone.Keyframes.Add(keyframe); } myAnimationClip.Bones.Add(bone); var count = bone.Keyframes.Count; var num3 = 0; if (count > 3) { if (USE_LINEAR_KEYFRAME_REDUCTION) { var linkedList = new LinkedList <MyAnimationClip.Keyframe>(); foreach (var keyframe in bone.Keyframes) { linkedList.AddLast(keyframe); } LinearKeyframeReduction(linkedList, 1E-08f, 0.9999999f); bone.Keyframes.Clear(); bone.Keyframes.AddCollection <MyAnimationClip.Keyframe>( linkedList.ToArray <MyAnimationClip.Keyframe>()); num3 = bone.Keyframes.Count; } } CalculateKeyframeDeltas(bone.Keyframes); } return(myAnimationClip); }
static MyAnimationClip ReadClip(BinaryReader reader) { MyAnimationClip clip = new MyAnimationClip(); clip.Name = reader.ReadString(); clip.Duration = reader.ReadDouble(); int bonesCount = reader.ReadInt32(); while (bonesCount-- > 0) { MyAnimationClip.Bone bone = new MyAnimationClip.Bone(); bone.Name = reader.ReadString(); int keyframesCount = reader.ReadInt32(); while (keyframesCount-- > 0) { MyAnimationClip.Keyframe keyframe = new MyAnimationClip.Keyframe(); keyframe.Time = reader.ReadDouble(); keyframe.Rotation = ImportQuaternion(reader); keyframe.Translation = ImportVector3(reader); bone.Keyframes.Add(keyframe); } clip.Bones.Add(bone); int originalCount = bone.Keyframes.Count; int newCount = 0; if (originalCount > 3) { if (USE_LINEAR_KEYFRAME_REDUCTION) { LinkedList <MyAnimationClip.Keyframe> linkedList = new LinkedList <MyAnimationClip.Keyframe>(); foreach (var kf in bone.Keyframes) { linkedList.AddLast(kf); } //LinearKeyframeReduction(linkedList, 0.000001f, 0.985f); //PercentageKeyframeReduction(linkedList, 0.9f); LinearKeyframeReduction(linkedList, TinyLength, TinyCosAngle); bone.Keyframes.Clear(); bone.Keyframes.AddArray(linkedList.ToArray()); newCount = bone.Keyframes.Count; } if (LINEAR_KEYFRAME_REDUCTION_STATS) { ReductionInfo ri = new ReductionInfo() { BoneName = bone.Name, OriginalKeys = originalCount, OptimizedKeys = newCount }; List <ReductionInfo> riList; if (!ReductionStats.TryGetValue(m_debugAssetName, out riList)) { riList = new List <ReductionInfo>(); ReductionStats.Add(m_debugAssetName, riList); } riList.Add(ri); } } CalculateKeyframeDeltas(bone.Keyframes); } return(clip); }