private ModelContent SkinnedData(ModelContent model, NodeContent input, ContentProcessorContext context, MeshMetaData metadata) { // Find the skeleton BoneContent skeleton = MeshHelper.FindSkeleton(input); if (skeleton != null) { // Read the bind pose and skeleton hierarchy data. IList<BoneContent> bones = MeshHelper.FlattenSkeleton(skeleton); // Set up the bone matrices and index lists List<Matrix> bindPose = new List<Matrix>(); List<Matrix> inverseBindPose = new List<Matrix>(); List<int> skeletonHierarchy = new List<int>(); Dictionary<String, int> boneIndices = new Dictionary<String, int>(); Dictionary<String, AnimationClip> animationClips = new Dictionary<String, AnimationClip>(); // Extract the bind pose transforms, inverse bind pose transforms, // and parent bone index of each bone in order foreach (BoneContent bone in bones) { bindPose.Add(bone.Transform); inverseBindPose.Add(Matrix.Invert(bone.AbsoluteTransform)); skeletonHierarchy.Add(bones.IndexOf(bone.Parent as BoneContent)); boneIndices.Add(bone.Name, boneIndices.Count); } // Convert animation data to our runtime format. animationClips = ProcessAnimations(skeleton.Animations, bones); // Save skinndd data metadata.SkinningData = new SkinningData(animationClips, bindPose, inverseBindPose, skeletonHierarchy, boneIndices); } // Save meta data model.Tag = metadata; // Return the model with the custom animation data return model; }
private BoundingBox ComputeBoundingBox(NodeContent input, ref BoundingBox aabb, MeshMetaData metadata) { BoundingBox boundingBox; if (input is MeshContent) { MeshContent mc = (MeshContent)input; MeshHelper.TransformScene(mc, mc.Transform); mc.Transform = Matrix.Identity; // Create bounding box boundingBox = BoundingBox.CreateFromPoints(mc.Positions); //create sub mesh information MeshMetaData.SubMeshMetadata subMeshMetadata = new MeshMetaData.SubMeshMetadata(); subMeshMetadata.BoundingBox = boundingBox; subMeshMetadata.RenderQueue = m_RenderQueue; subMeshMetadata.ShadowCullMode = m_ShadowCullMode; subMeshMetadata.EnableLighting = m_EnableLighting; subMeshMetadata.UseNormalMap = m_EnableNormalMap; subMeshMetadata.CastShadows = m_CastShadows; // Add sub mesh meta data metadata.AddSubMeshMetadata(subMeshMetadata); // merge bounding boxes of sub parts if (metadata.SubMeshesMetadata.Count > 1) boundingBox = BoundingBox.CreateMerged(boundingBox, aabb); } else { boundingBox = aabb; } // Run through children of node and merge children foreach (NodeContent c in input.Children) { boundingBox = BoundingBox.CreateMerged(boundingBox, ComputeBoundingBox(c, ref boundingBox, metadata)); } return boundingBox; }
public override ModelContent Process(NodeContent input, ContentProcessorContext context) { if (input == null) { throw new ArgumentNullException("input"); } // Get directory m_Directory = Path.GetDirectoryName(input.Identity.SourceFilename); // Look up textures LookUpTextures(input); // merge transforms MeshHelper.TransformScene(input, input.Transform); input.Transform = Matrix.Identity; // Before anything rotate the entire model and animations // I use separate animation files so I have to remember to // rotated the animations the same way as the // recipient of those animations. RotateAll(input, DegreesX, DegreesY, DegreesZ); if (!string.IsNullOrEmpty(MergeAnimations)) { foreach (string mergeFile in MergeAnimations.Split(';').Select(s => s.Trim()).Where(s => !string.IsNullOrEmpty(s))) { MergeAnimation(input, context, mergeFile); } } if (!m_IsSkinned) { // Not a skinned model so merge transforms for optimisations MergeTransforms(input); } // Chain to the base ModelProcessor class so it can convert the model data. ModelContent model = base.Process(input, context); // Create model mesh data tag MeshMetaData metadata = new MeshMetaData(); // Normal skinning data model = SkinnedData(model, input, context, metadata); //gather some information that will be useful in run time BoundingBox aabb = new BoundingBox(); metadata.BoundingBox = ComputeBoundingBox(input, ref aabb, metadata); // Return model data return model; }