Exemplo n.º 1
0
        /// <summary>
        /// Converts an intermediate format content pipeline AnimationContent
        /// object to our runtime AnimationClip format.
        /// </summary>
        static Clip ProcessAnimation(
            AnimationContent animation,
            Dictionary <string, int> boneMap,
            ClipData clipData)
        {
            List <Keyframe> keyframes = new List <Keyframe>();
            Dictionary <TimeSpan, AnimationControlEvents> controlEvents = new Dictionary <TimeSpan, AnimationControlEvents>();

            bool frameTimesFilled = false;

            TimeSpan[] frameTimes = new TimeSpan[clipData.LastFrame - clipData.FirstFrame + 1];
            TimeSpan   syncTime   = TimeSpan.Zero;

            // For each input animation channel.
            foreach (KeyValuePair <string, AnimationChannel> channel in animation.Channels)
            {
                // Look up what bone this channel is controlling.
                int boneIndex;

                if (!boneMap.TryGetValue(channel.Key, out boneIndex))
                {
                    // string.Format("Found animation for bone '{0}', which is not part of the skeleton.", channel.Key));

                    // We can just ignore these channels.
                    continue;
                }

                if (!frameTimesFilled)
                {
                    // I guess the frames in the ClipData are specified with a 0-based index?
                    TimeSpan startTime = channel.Value[clipData.FirstFrame].Time;

                    for (int i = clipData.FirstFrame; i <= clipData.LastFrame; i++)
                    {
                        frameTimes[i - clipData.FirstFrame] = channel.Value[i].Time - startTime;
                        // Also, let's get the times for the events:
                        foreach (KeyValuePair <int, AnimationControlEvents> ace in clipData.Events)
                        {
                            if (ace.Key == i)
                            {
                                controlEvents.Add(frameTimes[i - clipData.FirstFrame], ace.Value);
                            }
                        }

                        // Don't forget to convert the sync frame offset into a time:
                        if (clipData.SyncFrameOffset == i - clipData.FirstFrame)
                        {
                            syncTime = frameTimes[i - clipData.FirstFrame];
                        }
                    }

                    if (controlEvents.Count != clipData.Events.Count)
                    {
                        throw new InvalidContentException("The time index of some control events could not be determined.");
                    }

                    frameTimesFilled = true;
                }

                // Convert the keyframe data.
                for (int i = clipData.FirstFrame; i <= clipData.LastFrame; i++)
                {
                    Matrix boneTransform;
                    if (channel.Value.Count <= i)
                    {
                        boneTransform = channel.Value[channel.Value.Count - 1].Transform;
                    }
                    else
                    {
                        boneTransform = channel.Value[i].Transform;
                    }

                    keyframes.Add(new Keyframe(boneIndex, frameTimes[i - clipData.FirstFrame], boneTransform));
                }
            }

            if (keyframes.Count == 0)
            {
                throw new InvalidContentException("Animation has no keyframes.");
            }

            TimeSpan framePeriod = TimeSpan.Zero;

            if (keyframes.Count > 1)
            {
                framePeriod = keyframes[1].Time - keyframes[0].Time;
            }

            // Sort the merged keyframes by time.
            keyframes.Sort(CompareKeyframeTimes);

            TimeSpan duration = keyframes[keyframes.Count - 1].Time + framePeriod;

            if (duration <= TimeSpan.Zero)
            {
                throw new InvalidContentException("Animation has a zero duration.");
            }

            return(new Clip(duration, keyframes, clipData.Loopable, controlEvents, syncTime));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Converts an intermediate format content pipeline AnimationContent
        /// object to our runtime AnimationClip format.
        /// </summary>
        static Clip ProcessAnimation(
            AnimationContent animation,
            Dictionary<string, int> boneMap,
            ClipData clipData)
        {
            List<Keyframe> keyframes = new List<Keyframe>();
            Dictionary<TimeSpan, AnimationControlEvents> controlEvents = new Dictionary<TimeSpan,AnimationControlEvents>();

            bool frameTimesFilled = false;
            TimeSpan[] frameTimes = new TimeSpan[clipData.LastFrame - clipData.FirstFrame + 1];
            TimeSpan syncTime = TimeSpan.Zero;

            // For each input animation channel.
            foreach (KeyValuePair<string, AnimationChannel> channel in animation.Channels)
            {
                // Look up what bone this channel is controlling.
                int boneIndex;

                if (!boneMap.TryGetValue(channel.Key, out boneIndex))
                {
                    // string.Format("Found animation for bone '{0}', which is not part of the skeleton.", channel.Key));

                    // We can just ignore these channels.
                    continue;
                }

                if (!frameTimesFilled)
                {
                    // I guess the frames in the ClipData are specified with a 0-based index?
                    TimeSpan startTime = channel.Value[clipData.FirstFrame].Time;

                    for (int i = clipData.FirstFrame; i <= clipData.LastFrame; i++)
                    {
                        frameTimes[i - clipData.FirstFrame] = channel.Value[i].Time - startTime;
                        // Also, let's get the times for the events:
                        foreach (KeyValuePair<int, AnimationControlEvents> ace in clipData.Events)
                        {
                            if (ace.Key == i)
                            {
                                controlEvents.Add(frameTimes[i - clipData.FirstFrame], ace.Value);
                            }
                        }

                        // Don't forget to convert the sync frame offset into a time:
                        if (clipData.SyncFrameOffset == i - clipData.FirstFrame)
                            syncTime = frameTimes[i - clipData.FirstFrame];
                    }

                    if (controlEvents.Count != clipData.Events.Count)
                        throw new InvalidContentException("The time index of some control events could not be determined.");

                    frameTimesFilled = true;
                }

                // Convert the keyframe data.
                for (int i = clipData.FirstFrame; i <= clipData.LastFrame; i++)
                {
                    Matrix boneTransform;
                    if (channel.Value.Count <= i)
                    {
                        boneTransform = channel.Value[channel.Value.Count - 1].Transform;
                    }
                    else
                    {
                        boneTransform = channel.Value[i].Transform;
                    }

                    keyframes.Add(new Keyframe(boneIndex, frameTimes[i - clipData.FirstFrame], boneTransform));
                }

            }

            if (keyframes.Count == 0)
                throw new InvalidContentException("Animation has no keyframes.");

            TimeSpan framePeriod = TimeSpan.Zero;
            if (keyframes.Count > 1)
                 framePeriod = keyframes[1].Time - keyframes[0].Time;

            // Sort the merged keyframes by time.
            keyframes.Sort(CompareKeyframeTimes);

            TimeSpan duration = keyframes[keyframes.Count - 1].Time + framePeriod;

            if (duration <= TimeSpan.Zero)
                throw new InvalidContentException("Animation has a zero duration.");

            return new Clip(duration, keyframes, clipData.Loopable, controlEvents, syncTime);
        }