/// <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)); }
/// <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); }