public override void Optimise()
{
// Eliminate duplicate keyframes from 2nd to penultimate keyframe
// NB only eliminate middle keys from sequences of 5+ identical keyframes
// since we need to preserve the boundary keys in place, and we need
// 2 at each end to preserve tangents for spline interpolation
Vector3 lasttrans = Vector3.Zero;
Vector3 lastscale = Vector3.Zero;
Quaternion lastorientation = Quaternion.Zero;
float tolerance = 1e-3f;
float quatTolerance = 1e-3f;
ushort k = 0;
ushort dupKfCount = 0;
List<short> removeList = new List<short>();
for ( int i = 0; i < keyFrameList.Count; i++ )
{
KeyFrame keyFrame = keyFrameList[ i ];
TransformKeyFrame kf = (TransformKeyFrame)keyFrame;
Vector3 newtrans = kf.Translate;
Vector3 newscale = kf.Scale;
Quaternion neworientation = kf.Rotation;
// Ignore first keyframe; now include the last keyframe as we eliminate
// only k-2 in a group of 5 to ensure we only eliminate middle keys
if ( i != 0 &&
newtrans.DifferenceLessThan( lasttrans, tolerance ) &&
newscale.DifferenceLessThan( lastscale, tolerance ) &&
neworientation.Equals( lastorientation, quatTolerance ) )
{
++dupKfCount;
// 4 indicates this is the 5th duplicate keyframe
if ( dupKfCount == 4 )
{
// remove the 'middle' keyframe
removeList.Add( (short)( k - 2 ) );
--dupKfCount;
}
}
else
{
// reset
dupKfCount = 0;
lasttrans = newtrans;
lastscale = newscale;
lastorientation = neworientation;
}
}
// Now remove keyframes, in reverse order to avoid index revocation
for ( int i = removeList.Count - 1; i >= 0; i-- )
RemoveKeyFrame( removeList[ i ] );
}