// Go through the modelmeshes and replace all basic effects for skinned models // with BasicPaletteEffect. private void ReplaceBasicEffects(ModelMeshContent input) { foreach (ModelMeshPartContent part in input.MeshParts) { SkinningType skinType = ContentUtil.GetSkinningType(part.GetVertexDeclaration()); if (skinType != SkinningType.None) { ReplaceBasicEffect(skinType, part); } } }
/// <summary> /// Interpolates an AnimationContent object to 60 fps. /// </summary> /// <param name="input">The AnimationContent to interpolate.</param> /// <returns>The interpolated AnimationContent.</returns> public virtual AnimationContent Interpolate(AnimationContent input) { AnimationContent output = new AnimationContent(); long time = 0; long animationDuration = input.Duration.Ticks; // default XNA importers, due to floating point errors or TimeSpan // estimation, sometimes have channels with a duration slightly longer than // the animation duration. So, set the animation duration to its true // value foreach (KeyValuePair <string, AnimationChannel> c in input.Channels) { if (c.Value[c.Value.Count - 1].Time.Ticks > animationDuration) { animationDuration = c.Value[c.Value.Count - 1].Time.Ticks; } } foreach (KeyValuePair <string, AnimationChannel> c in input.Channels) { time = 0; string channelName = c.Key; AnimationChannel channel = c.Value; AnimationChannel outChannel = new AnimationChannel(); int currentFrame = 0; // 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) { 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) { 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; } // Compensate for the time error,(animation duration % TICKS_PER_60FPS), // caused by the interpolation by setting the last keyframe in the // channel to the animation duration. if (outChannel[outChannel.Count - 1].Time.Ticks < animationDuration) { outChannel.Add(new AnimationKeyframe( TimeSpan.FromTicks(animationDuration), channel[channel.Count - 1].Transform)); } outChannel.Add(new AnimationKeyframe(input.Duration, channel[channel.Count - 1].Transform)); // Add the interpolated channel to the animation output.Channels.Add(channelName, outChannel); } // Set the interpolated duration to equal the inputs duration for consistency output.Duration = TimeSpan.FromTicks(animationDuration); return(output); }