} // ProcessVertexChannel #endregion #region Process Animations /// <summary> /// Converts an intermediate format content pipeline AnimationContentDictionary /// object to our runtime AnimationClip format. /// </summary> static Dictionary <string, ModelAnimationClip> ProcessAnimations(AnimationContentDictionary animations, IList <BoneContent> bones, ContentProcessorContext context) { // Build up a table mapping bone names to indices. Dictionary <string, int> boneMap = new Dictionary <string, int>(); for (int i = 0; i < bones.Count; i++) { string boneName = bones[i].Name; if (!string.IsNullOrEmpty(boneName)) { boneMap.Add(boneName, i); } } // Convert each animation in turn. Dictionary <string, ModelAnimationClip> animationClips; animationClips = new Dictionary <string, ModelAnimationClip>(); foreach (KeyValuePair <string, AnimationContent> animation in animations) { ModelAnimationClip processed = ProcessAnimation(animation.Value, boneMap); animationClips.Add(animation.Key, processed); } if (animationClips.Count == 0) { context.Logger.LogWarning(null, null, "Input file does not contain any animations."); //throw new InvalidContentException("Input file does not contain any animations."); } return(animationClips); } // ProcessAnimations
/// <summary> /// Load all graphical content. /// </summary> protected override void LoadContent() { // Load the rigid model rigidModel = Content.Load <Model>("AnimatedCube"); rigidWorld = Matrix.CreateScale(.05f, .05f, .05f); // Create animation players/clips for the rigid model ModelData modelData = rigidModel.Tag as ModelData; if (modelData != null) { if (modelData.RootAnimationClips != null && modelData.RootAnimationClips.ContainsKey("Take 001")) { rigidRootClip = modelData.RootAnimationClips["Take 001"]; rigidRootPlayer = new RootAnimationPlayer(); rigidRootPlayer.Completed += new EventHandler(rigidPlayer_Completed); rigidRootPlayer.StartClip(rigidRootClip, 1, TimeSpan.Zero); } if (modelData.ModelAnimationClips != null && modelData.ModelAnimationClips.ContainsKey("Take 001")) { rigidClip = modelData.ModelAnimationClips["Take 001"]; rigidPlayer = new RigidAnimationPlayer(rigidModel.Bones.Count); rigidPlayer.Completed += new EventHandler(rigidPlayer_Completed); rigidPlayer.StartClip(rigidClip, 1, TimeSpan.Zero); } } // Load the skinned model skinnedModel = Content.Load <Model>("DudeWalk"); skinnedWorld = Matrix.CreateScale(.025f, .025f, .025f) * Matrix.CreateRotationY((float)(-Math.PI / 2)); // Create animation players for the skinned model modelData = skinnedModel.Tag as ModelData; if (modelData != null) { if (modelData.RootAnimationClips != null && modelData.RootAnimationClips.ContainsKey("Take 001")) { skinnedRootClip = modelData.RootAnimationClips["Take 001"]; skinnedRootPlayer = new RootAnimationPlayer(); skinnedRootPlayer.Completed += new EventHandler(skinnedPlayer_Completed); } if (modelData.ModelAnimationClips != null && modelData.ModelAnimationClips.ContainsKey("Take 001")) { skinnedClip = modelData.ModelAnimationClips["Take 001"]; skinnedPlayer = new SkinnedAnimationPlayer(modelData.BindPose, modelData.InverseBindPose, modelData.SkeletonHierarchy); skinnedPlayer.Completed += new EventHandler(skinnedPlayer_Completed); } } // Create the projection/view matrix we'll use for rendering projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), GraphicsDevice.Viewport.AspectRatio, .01f, 200.0f); view = Matrix.CreateLookAt(new Vector3(0, 1, 4), new Vector3(0, 1, 0), Vector3.Up); spriteBatch = new SpriteBatch(GraphicsDevice); font = Content.Load <SpriteFont>("font"); }
} // ProcessVertexChannel #endregion #region Process Animations /// <summary> /// Converts an intermediate format content pipeline AnimationContentDictionary object to our runtime AnimationClip format. /// </summary> static void ProcessAnimations(NodeContent input, ModelContent model, Dictionary<string, ModelAnimationClip> modelAnimationClips, Dictionary<string, RootAnimationClip> rootAnimationClips) { // Build up a table mapping bone names to indices. Dictionary<string, int> boneMap = new Dictionary<string, int>(); for (int i = 0; i < model.Bones.Count; i++) { string boneName = model.Bones[i].Name; if (!string.IsNullOrEmpty(boneName)) boneMap.Add(boneName, i); } // Convert each animation in the root of the object foreach (KeyValuePair<string, AnimationContent> animation in input.Animations) { RootAnimationClip processed = ProcessRootAnimation(animation.Value, model.Bones[0].Name); rootAnimationClips.Add(animation.Key, processed); } // Get the unique names of the animations on the mesh children List<string> animationNames = new List<string>(); AddAnimationNodes(animationNames, input); // Now create those animations foreach (string key in animationNames) { ModelAnimationClip processed = ProcessRigidAnimation(key, boneMap, input, model); modelAnimationClips.Add(key, processed); } } // ProcessAnimations
} // WrapMode #endregion #region Constructor /// <summary> /// Internal Constructor for File Model assets. /// </summary> internal ModelAnimation(string name, ModelAnimationClip resource) { Name = name; Resource = resource; ContentManager = null; // This is controled by the own file model. } // ModelAnimation
protected override void Write(ContentWriter output, AnimationData animData) { BinaryDataWriter data = new BinaryDataWriter(); ContentBinaryWriter bw; #region BindPoseTag List <Matrix> bindPose = animData.BindPose; if (bindPose != null) { data.AddEntry(BindPoseCountTag, bindPose.Count); bw = data.AddEntry(BindPoseTag); for (int i = 0; i < bindPose.Count; i++) { bw.Write(bindPose[i]); } bw.Close(); } #endregion #region InvBindPoseTag List <Matrix> invBindPose = animData.InverseBindPose; if (invBindPose != null) { data.AddEntry(InvBindPoseCountTag, invBindPose.Count); bw = data.AddEntry(InvBindPoseTag); for (int i = 0; i < invBindPose.Count; i++) { bw.Write(invBindPose[i]); } bw.Close(); } #endregion #region AnimationClipTag var aclip = animData.ModelAnimationClips; if (aclip != null) { data.AddEntry(ModelAnimationClipCountTag, aclip.Count); bw = data.AddEntry(ModelAnimationClipTag); foreach (var e in aclip) { bw.WriteStringUnicode(e.Key); ModelAnimationClip clip = e.Value; bw.Write(clip.Duration.TotalSeconds); bw.Write(clip.Keyframes.Count); for (int i = 0; i < clip.Keyframes.Count; i++) { bw.Write(clip.Keyframes[i].Bone); bw.Write(clip.Keyframes[i].Time.TotalSeconds); bw.Write(clip.Keyframes[i].Transform); } } bw.Close(); } #endregion #region RootAnimationClipTag aclip = animData.RootAnimationClips; if (aclip != null) { data.AddEntry(RootAnimationClipCountTag, aclip.Count); bw = data.AddEntry(RootAnimationClipTag); foreach (var e in aclip) { bw.WriteStringUnicode(e.Key); ModelAnimationClip clip = e.Value; bw.Write(clip.Duration.TotalSeconds); bw.Write(clip.Keyframes.Count); for (int i = 0; i < clip.Keyframes.Count; i++) { bw.Write(clip.Keyframes[i].Bone); bw.Write(clip.Keyframes[i].Time.TotalSeconds); bw.Write(clip.Keyframes[i].Transform); } } bw.Close(); } #endregion #region BoneHierarchyTag List <int> bh = animData.SkeletonHierarchy; if (bh != null) { data.AddEntry(BoneHierarchyCountTag, bh.Count); bw = data.AddEntry(BoneHierarchyTag); for (int i = 0; i < bh.Count; i++) { bw.Write(bh[i]); } bw.Close(); } #endregion output.Write(0); //Õ¼¸öλÖà output.Flush(); long start = output.BaseStream.Position; data.Save(new VirtualStream(output.BaseStream, output.BaseStream.Position)); long end = output.BaseStream.Position; int size = (int)(end - start); output.BaseStream.Position = start - 4; output.Write(size); output.BaseStream.Position = end; }
/// <summary> /// The main Process method converts an intermediate format content pipeline /// NodeContent tree to a ModelContent object with embedded animation data. /// </summary> public override ModelContent Process(NodeContent input, ContentProcessorContext context) { ValidateMesh(input, context, null); // Find the skeleton. BoneContent skeleton = MeshHelper.FindSkeleton(input); if (skeleton == null) { throw new InvalidContentException("Input skeleton not found."); } // We don't want to have to worry about different parts of the model being // in different local coordinate systems, so let's just bake everything. FlattenTransforms(input, skeleton); // Read the bind pose and skeleton hierarchy data. IList <BoneContent> bones = MeshHelper.FlattenSkeleton(skeleton); if (bones.Count > MaxBones) { throw new InvalidContentException(string.Format( "Skeleton has {0} bones, but the maximum supported is {1}.", bones.Count, MaxBones)); } List <Matrix> bindPose = new List <Matrix>(); List <Matrix> inverseBindPose = new List <Matrix>(); List <int> skeletonHierarchy = new List <int>(); foreach (BoneContent bone in bones) { bindPose.Add(bone.Transform); inverseBindPose.Add(Matrix.Invert(bone.AbsoluteTransform)); skeletonHierarchy.Add(bones.IndexOf(bone.Parent as BoneContent)); } // Convert animation data to our runtime format. Dictionary <string, ModelAnimationClip> animationClips = ProcessAnimations(skeleton.Animations, bones); Dictionary <string, ModelAnimationClip> rootClips = new Dictionary <string, ModelAnimationClip>(); // Chain to the base ModelProcessor class so it can convert the model data. ModelContent model = base.Process(input, context); // Convert each animation in the root of the object foreach (KeyValuePair <string, AnimationContent> animation in input.Animations) { ModelAnimationClip processed = AnimatedModelProcessor.ProcessRootAnimation(animation.Value, model.Bones[0].Name); rootClips.Add(animation.Key, processed); } // Store our custom animation data in the Tag property of the model. model.Tag = new ModelData(animationClips, null, bindPose, inverseBindPose, skeletonHierarchy); return(model); }
public Cyclist() { //string test = typeof(AnimationDataReader).AssemblyQualifiedName; TimeScale = 1; skinnedModel = BaseGame.Content.Load <XnaModel>("Content\\Models\\bike_boy"); objectMatrix = Matrix.CreateScale(0.5f);// Matrix.Identity; // Create animation players for the skinned model animData = skinnedModel.Tag as AnimationData; if (animData != null) { if (animData.RootAnimationClips != null && animData.RootAnimationClips.ContainsKey("Take 001")) { skinnedRootClip = animData.RootAnimationClips["Take 001"]; skinnedRootPlayer = new RootAnimationPlayer(); skinnedRootPlayer.Completed += new EventHandler(skinnedPlayer_Completed); } if (animData.ModelAnimationClips != null && animData.ModelAnimationClips.ContainsKey("Take 001")) { skinnedClip = animData.ModelAnimationClips["Take 001"]; skinnedPlayer = new SkinnedAnimationPlayer(animData.BindPose, animData.InverseBindPose, animData.SkeletonHierarchy); skinnedPlayer.StartClip(skinnedClip, 1, TimeSpan.Zero); skinnedPlayer.CurrentTimeValue = skinnedClip.Duration; skinnedPlayer.CurrentTimeValue = TimeSpan.Zero; skinnedPlayer.Completed += new EventHandler(skinnedPlayer_Completed); } } rigidModel = BaseGame.Content.Load <XnaModel>("Content\\Models\\bike"); // Create animation players/clips for the rigid model animData2 = rigidModel.Tag as AnimationData; if (animData2 != null) { if (animData2.RootAnimationClips != null && animData2.RootAnimationClips.ContainsKey("Take 001")) { rigidRootClip = animData2.RootAnimationClips["Take 001"]; rigidRootPlayer = new RootAnimationPlayer(); rigidRootPlayer.Completed += new EventHandler(skinnedPlayer_Completed); rigidRootPlayer.StartClip(rigidRootClip, 1, TimeSpan.Zero); } if (animData2.ModelAnimationClips != null && animData2.ModelAnimationClips.ContainsKey("Take 001")) { rigidClip = animData2.ModelAnimationClips["Take 001"]; rigidPlayer = new RigidAnimationPlayer(rigidModel.Bones.Count); rigidPlayer.StartClip(rigidClip, 1, TimeSpan.Zero); rigidPlayer.CurrentTimeValue = rigidClip.Duration; rigidPlayer.CurrentTimeValue = TimeSpan.Zero; rigidPlayer.Completed += new EventHandler(skinnedPlayer_Completed); } } skinned = BaseGame.Content.Load <Effect>("Content\\Shaders\\skinned"); skinned.CurrentTechnique = skinned.Techniques[0]; Update(null); }