I am looking at the code that pre-compiles the animation data coming from the exporter.
It looks like it is storing 60 keys per second, regardless of what it receives from the exporter.
Here is the code:
// Step through time until the time passes the animation duration
while (time <= animationDuration)
{
AnimationKeyframe keyframe;
// Clamp the time to the duration of the animation and make this
// keyframe equal to the last animation frame.
if (time >= animationDuration)
{
time = animationDuration;
keyframe = new AnimationKeyframe(new TimeSpan(time),
channel[channel.Count - 1].Transform);
}
else
{
// If the channel only has one keyframe, set the transform for the current time
// to that keyframes transform
if (channel.Count == 1 || time < channel[0].Time.Ticks)
{
keyframe = new AnimationKeyframe(new TimeSpan(time), channel[0].Transform);
}
// If the current track duration is less than the animation duration,
// use the last transform in the track once the time surpasses the duration
else if (channel[channel.Count - 1].Time.Ticks <= time)
{
keyframe = new AnimationKeyframe(new TimeSpan(time), channel[channel.Count - 1].Transform);
}
else // proceed as normal
{
// Go to the next frame that is less than the current time
while (channel[currentFrame + 1].Time.Ticks < time)
{
currentFrame++;
}
// Numerator of the interpolation factor
double interpNumerator = (double)(time - channel[currentFrame].Time.Ticks);
// Denominator of the interpolation factor
double interpDenom = (double)(channel[currentFrame + 1].Time.Ticks - channel[currentFrame].Time.Ticks);
// The interpolation factor, or amount to interpolate between the current
// and next frame
double interpAmount = interpNumerator / interpDenom;
// If the frames are roughly 60 frames per second apart, use linear interpolation
if (channel[currentFrame + 1].Time.Ticks - channel[currentFrame].Time.Ticks
<= ContentUtil.TICKS_PER_60FPS * 1.05)
{
// context.Logger.LogImportantMessage("Lerp between frames {0} and {1}, interpAmount: {2}", currentFrame.ToString(), (currentFrame + 1).ToString(), interpAmount.ToString()); // input.Duration.Ticks.ToString(), ((long)(durationFactor * input.Duration.Ticks)).ToString());
keyframe = new AnimationKeyframe(new TimeSpan(time),
Matrix.Lerp(
channel[currentFrame].Transform,
channel[currentFrame + 1].Transform,
(float)interpAmount));
}
else // else if the transforms between the current frame and the next aren't identical
// decompose the matrix and interpolate the rotation separately
if (channel[currentFrame].Transform != channel[currentFrame + 1].Transform)
{
// context.Logger.LogImportantMessage("Slerp between frames {0} and {1}, interpAmount: {2}", currentFrame.ToString(), (currentFrame + 1).ToString(), interpAmount.ToString()); // input.Duration.Ticks.ToString(), ((long)(durationFactor * input.Duration.Ticks)).ToString());
keyframe = new AnimationKeyframe(new TimeSpan(time),
ContentUtil.SlerpMatrix(
channel[currentFrame].Transform,
channel[currentFrame + 1].Transform,
(float)interpAmount));
}
else // Else the adjacent frames have identical transforms and we can use
// the current frames transform for the current keyframe.
{
keyframe = new AnimationKeyframe(new TimeSpan(time),
channel[currentFrame].Transform);
}
}
}
// Add the interpolated keyframe to the new channel.
outChannel.Add(keyframe);
// Step the time forward by 1/60th of a second
time += ContentUtil.TICKS_PER_60FPS;
}
But at runtime, interpolation is performed again. So as some of you mentioned, I may be able to reduce this data and still get smooth playback.