internal SkinnedModelContent(ModelContent model, SkinnedModelBoneContentCollection skeleton, AnimationClipContentDictionary animationClips) { this.model = model; this.skeleton = skeleton; this.animationClips = animationClips; }
internal SkinnedModelContent(SkinnedModelMeshContentCollection meshes, SkinnedModelBoneContentCollection skeleton, AnimationClipContentDictionary animationClips) { this.meshes = meshes; this.skeleton = skeleton; this.animationClips = animationClips; }
private bool ValidateAnimationChannel( KeyValuePair <string, AnimationChannel> animationChannelPair, AnimationContent parentAnimation, SkinnedModelBoneContentCollection boneCollection, ContentProcessorContext context) { // Check if this channel has any keyframe if (animationChannelPair.Value.Count == 0) { context.Logger.LogWarning(null, parentAnimation.Identity, String.Format( "Channel {0} in animation {1} does not contain any keyframe and will be skipped.", animationChannelPair.Key, parentAnimation.Name)); return(false); } // Check if the animation channel exists in the skeleton bool boneFound = false; foreach (SkinnedModelBoneContent boneContent in boneCollection) { if (boneContent.Name.Equals(animationChannelPair.Key)) { boneFound = true; break; } } if (!boneFound) { context.Logger.LogWarning(null, parentAnimation.Identity, String.Format( "Channel {0} in animation {1} affects a bone that does not exists in the " + "model's skeleton and will be skipped.", animationChannelPair.Key, parentAnimation.Name)); return(false); } return(true); }
public override SkinnedModelContent Process(NodeContent input, ContentProcessorContext context) { if (input == null) { throw new ArgumentNullException("input"); } BoneContent rootBone = MeshHelper.FindSkeleton(input); ValidateModel(input, rootBone, context); // Transform scene according to user defined rotation and scale TransformScene(input); // Processes model's meshes ProcessMeshes(input, context); // Processes model's skeleton SkinnedModelBoneContentCollection skinnedModelBoneCollection = ProcessBones(rootBone, context); // Processes model's animations AnimationClipContentDictionary animationClipDictionary = ProcessAnimations(input, rootBone.Animations, skinnedModelBoneCollection, context); OpaqueDataDictionary processorParameters = new OpaqueDataDictionary(); processorParameters["DefaultEffect"] = MaterialProcessorDefaultEffect.SkinnedEffect; // Uses the default model processor ModelContent modelContent = context.Convert <NodeContent, ModelContent>(input, "ModelProcessor", processorParameters); // Return a new skinned model return(new SkinnedModelContent(modelContent, skinnedModelBoneCollection, animationClipDictionary)); }
private AnimationClipContentDictionary ProcessAnimations(NodeContent input, AnimationContentDictionary animationDictionary, SkinnedModelBoneContentCollection boneCollection, ContentProcessorContext context) { // Create a collection here (Does not need a dictionary here) Dictionary <string, AnimationClipContent> animationClipDictionary = new Dictionary <string, AnimationClipContent>(); foreach (AnimationContent animation in animationDictionary.Values) { // Validate animation if (!ValidateAnimation(animation, context)) { continue; } Dictionary <string, AnimationChannelContent> animationChannelDictionary = new Dictionary <string, AnimationChannelContent>(); // Process each animation channel (One channel per bone) foreach (KeyValuePair <string, AnimationChannel> animationChannelPair in animation.Channels) { // Validate animation channel if (!ValidateAnimationChannel(animationChannelPair, animation, boneCollection, context)) { continue; } List <AnimationKeyframeContent> keyframeList = new List <AnimationKeyframeContent>(animationChannelPair.Value.Count); // Process all the keyframes of that channel foreach (AnimationKeyframe channelKeyframe in animationChannelPair.Value) { // Extract the keyframe pose from its transform matrix Pose keyframePose; channelKeyframe.Transform.Decompose(out keyframePose.Scale, out keyframePose.Orientation, out keyframePose.Translation); keyframeList.Add( new AnimationKeyframeContent(channelKeyframe.Time, keyframePose)); } // Sort the keyframes by time keyframeList.Sort(); animationChannelDictionary.Add(animationChannelPair.Key, new AnimationChannelContent(keyframeList)); } AnimationClipContent animationClip = new AnimationClipContent( animation.Name, new AnimationChannelContentDictionary(animationChannelDictionary), animation.Duration); animationClipDictionary.Add(animation.Name, animationClip); } // Split animations if (!string.IsNullOrEmpty(splitAnimationFilename)) { SplitAnimations(input, animationClipDictionary, context); } return(new AnimationClipContentDictionary(animationClipDictionary)); }