示例#1
0
 // 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);
         }
     }
 }
示例#2
0
        /// <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);
        }