private BoneContent createSkel(aiNode root)
        {
            BoneContent BoneContent = null;

            if (ainodetocontent.ContainsKey(root.mName.Data))
            {
                aiBone b = bones.Find((a) => a.mName.Data == root.mName.Data);
                if (b != null)
                {
                    BoneContent           = new BoneContent();
                    BoneContent.Name      = b.mName.Data;
                    BoneContent.Transform = tomatrix(b.mOffsetMatrix);

                    foreach (var item in root.mChildren)
                    {
                        BoneContent bon = createSkel(item);
                        if (bon != null)
                        {
                            BoneContent.Children.Add(bon);
                        }
                    }
                    return(BoneContent);
                }
            }
            return(null);
        }
        private static void FlattenTransforms(NodeContent node, BoneContent skeleton)
        {
            bool flag;
            IEnumerator <NodeContent> enumerator = node.Children.GetEnumerator();

            try {
                while (true)
                {
                    flag = enumerator.MoveNext();
                    if (!flag)
                    {
                        break;
                    }
                    NodeContent current = enumerator.Current;
                    flag = current != skeleton;
                    if (flag)
                    {
                        MeshHelper.TransformScene(current, current.Transform);
                        current.Transform = Matrix.Identity;
                        SkinnedModelProcessor.FlattenTransforms(current, skeleton);
                    }
                }
            } finally {
                flag = enumerator == null;
                if (!flag)
                {
                    enumerator.Dispose();
                }
            }
        }
Example #3
0
        MeshData ProcessMesh(MeshContent mesh, ContentProcessorContext context, string rootPath, Dictionary <string, object> processedContent, SkeletonData skeletonData, AnimationData[] animations, ref int geometryCount)
        {
            MeshHelper.TransformScene(mesh, mesh.AbsoluteTransform);

            string[] normalMapNames = new string[] { "Bump0", "Bump", "NormalMap", "Normalmap", "Normals", "BumpMap" };
            MeshHelper.OptimizeForCache(mesh);

            List <GeometryData> geometry = new List <GeometryData>();

            BoneContent skeleton = MeshHelper.FindSkeleton(mesh);
            Dictionary <string, int> boneIndices = null;

            if (skeleton != null)
            {
                boneIndices = FlattenSkeleton(skeleton);
            }

            foreach (GeometryContent geom in mesh.Geometry)
            {
                this.ProcessVertexChannels(geom, context, rootPath, boneIndices, null);
                MeshHelper.MergeDuplicateVertices(geom);

                VertexBufferContent vb;
                VertexElement[]     ve;
                geom.Vertices.CreateVertexBuffer(out vb, out ve, context.TargetPlatform);

                int[] indices = new int[geom.Indices.Count];
                geom.Indices.CopyTo(indices, 0);

                geometry.Add(new GeometryData(geometryCount++, geom.Name, ve, vb.VertexData, indices, new MaterialData(), skeletonData, animations, context.TargetPlatform == TargetPlatform.Xbox360));
            }

            return(new MeshData(mesh.Name, geometry.ToArray(), animations));
        }
Example #4
0
        /// <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.");
            }

            _isSkinned = true;
            // 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 > SkinnedEffect.MaxBones)
            {
                throw new InvalidContentException(string.Format(
                                                      "Skeleton has {0} bones, but the maximum supported is {1}.",
                                                      bones.Count, SkinnedEffect.MaxBones));
            }

            List <Matrix> bindPose          = new List <Matrix>();
            List <Matrix> inverseBindPose   = new List <Matrix>();
            List <int>    skeletonHierarchy = new List <int>();

            foreach (BoneContent bone in bones)
            {
                Matrix m = bone.Transform;
                //scale all translations
                m.Translation  = m.Translation * Scale;
                bone.Transform = m;

                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, AnimationClip> animationClips;

            animationClips = ProcessAnimations(skeleton.Animations, bones);

            // Chain to the base ModelProcessor class so it can convert the model data.
            ModelContent model = base.Process(input, context);

            // Store our custom animation data in the Tag property of the model.
            MeshMetadata metadata = model.Tag as MeshMetadata;

            metadata.SkinningData = new SkinningData(animationClips, bindPose,
                                                     inverseBindPose, skeletonHierarchy);

            return(model);
        }
        public override ModelContent Process(NodeContent input, ContentProcessorContext context)
        {
            // Znajduje szkielet w modelu.
            BoneContent skeleton = MeshHelper.FindSkeleton(input);

            // Wczytuje domyœlne ustawienia koœci i hierarchiê.
            IList <BoneContent> bones = MeshHelper.FlattenSkeleton(skeleton);

            // Deklaracja list
            List <Matrix> bindPose          = new List <Matrix>();
            List <Matrix> inverseBindPose   = new List <Matrix>();
            List <int>    skeletonHierarchy = new List <int>();

            // ZaÂładowanie powyÂższych list
            foreach (BoneContent bone in bones)
            {
                bindPose.Add(bone.Transform);
                inverseBindPose.Add(Matrix.Invert(bone.AbsoluteTransform));
                skeletonHierarchy.Add(bones.IndexOf(bone.Parent as BoneContent));
            }

            // Konwersja animacji do formatu dictionary
            Dictionary <string, AnimationClip> animationClips;

            animationClips = ProcessAnimations(skeleton.Animations, bones);

            ModelContent modelContent = base.Process(input, context);

            modelContent.Tag = new SkinningData(animationClips, bindPose, inverseBindPose, skeletonHierarchy);
            return(modelContent);
        }
Example #6
0
        private static Dictionary <string, int> FlattenSkeleton(BoneContent skeleton)
        {
            //avatars require their bones to be sorted in a slighty strange order.
            //the order is not setup in the file

            //they must be sorted first by depth (so root first, then it's children, then all their children)
            //and within those groups, sorted by name.

            //this is done in a method ripped from the XNA samples... (XnaFlattenSkeleton)

            Dictionary <string, int> dictionary = new Dictionary <string, int>();

            IList <BoneContent> list = XnaFlattenSkeleton(skeleton);

            int index = 0;

            for (int i = 0; i < list.Count; i++)
            {
                BoneContent content = list[i];
                if (!string.IsNullOrEmpty(content.Name))
                {
                    if (dictionary.ContainsKey(content.Name))
                    {
                        throw new InvalidContentException("Duplicate bone found: " + content.Name);
                    }
                    dictionary.Add(content.Name, index++);
                }
            }
            return(dictionary);
        }
Example #7
0
        public override ModelContent Process(NodeContent input, ContentProcessorContext context)
        {
            // Find the skeleton.
            BoneContent skeleton = MeshHelper.FindSkeleton(input);
            // Read the bind pose and skeleton hierarchy data.
            IList <BoneContent> bones = MeshHelper.FlattenSkeleton(skeleton);

            List <Matrix> bindPose          = new List <Matrix>();
            List <Matrix> inverseBindPose   = new List <Matrix>();
            List <int>    skeletonHierarchy = new List <int>();

            // Extract the bind pose transform, inverse bind pose transform,
            // 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));
            }

            // Convert animation data to our runtime format.
            Dictionary <string, AnimationClip> animationClips; animationClips = ProcessAnimations(skeleton.Animations, bones);

            // Chain to the base ModelProcessor class so it can convert the model data.
            ModelContent model = base.Process(input, context);

            // Store our custom animation data in the Tag property of the model.
            model.Tag = new SkinningData(animationClips, bindPose, inverseBindPose, skeletonHierarchy);

            return(model);
        }
        private bool ValidateModel(NodeContent input, BoneContent rootBone,
                                   ContentProcessorContext context)
        {
            // Finds the root bone
            if (rootBone == null)
            {
                throw new InvalidContentException("Input model does not contain a skeleton.");
            }

            // Validate maximum supported bones
            IList <BoneContent> boneList = MeshHelper.FlattenSkeleton(rootBone);

            if (boneList.Count > MaxBones)
            {
                throw new InvalidContentException(string.Format(
                                                      "Model's skeleton has {0} bones, but the maximum supported is {1}.",
                                                      boneList.Count, MaxBones));
            }

            // Find animations
            AnimationContentDictionary animationDictionary = rootBone.Animations;

            if (animationDictionary.Count == 0)
            {
                context.Logger.LogWarning(null, rootBone.Identity,
                                          "Input model does not contain any animation.");
            }

            return(true);
        }
Example #9
0
        /// <summary>
        /// Converts incoming graphics data into our custom model format.
        /// </summary>
        public override MyreModelContent Process(NodeContent input,
                                                 ContentProcessorContext context)
        {
            this.context = context;

            directory = Path.GetDirectoryName(input.Identity.SourceFilename);

            // Find the skeleton.
            BoneContent skeleton = MeshHelper.FindSkeleton(input);

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

            outputModel = new MyreModelContent();

            //if (skeleton != null)
            //    outputModel.Skeleton = MeshHelper.FlattenSkeleton(skeleton).ToArray();
            //else
            //    outputModel.Skeleton = new BoneContent[0];

            ProcessNode(input);

            return(outputModel);
        }
Example #10
0
        void BuildBoneHirachy(BoneContent bone, int boneIndex, List <BoneData> structure, Dictionary <string, int> indices, BoneData[] allBones, Matrix[] transforms)
        {
            if (bone.Name != null && indices.ContainsKey(bone.Name))
            {
                List <BoneData> children = new List <BoneData>();

                foreach (NodeContent child in bone.Children)
                {
                    if (child is BoneContent)
                    {
                        BuildBoneHirachy((BoneContent)child, indices[bone.Name], children, indices, allBones, transforms);
                    }
                }

                int[] childIndices = new int[children.Count];
                for (int i = 0; i < children.Count; i++)
                {
                    childIndices[i] = indices[children[i].Name];
                }

                int      index = indices[bone.Name];
                BoneData data  = new BoneData(bone.Name, index, boneIndex, childIndices);
                if (structure != null)
                {
                    structure.Add(data);
                }
                allBones[index]   = data;
                transforms[index] = bone.Transform;
            }
        }
Example #11
0
        // Import the skeleton for Skeleton-Animation
        private BoneContent ImportSkeleton(NodeContent input)
        {
            BoneContent skeleton = MeshHelper.FindSkeleton(input);

            if (skeleton == null)
            {
                return(null);
            }

            FlattenTransforms(input, skeleton);
            List <NodeContent>  nodes = FlattenHeirarchy(input);
            IList <BoneContent> bones = MeshHelper.FlattenSkeleton(skeleton);

            // Create a dictionary to convert a node to an index into the array of nodes
            Dictionary <NodeContent, int> nodeToIndex = new Dictionary <NodeContent, int>();

            for (int i = 0; i < nodes.Count; i++)
            {
                nodeToIndex[nodes[i]] = i;
            }

            foreach (BoneContent bone in bones)
            {
                animationData.Skeleton.Add(nodeToIndex[bone]);
            }

            return(skeleton);
        }
Example #12
0
        static void ProcessWeightsChannel(GeometryContent geometry, int vertexChannelIndex)
        {
            // create a map of Name->Index of the bones
            BoneContent skeleton = MeshHelper.FindSkeleton(geometry.Parent);
            Dictionary <string, int> boneIndices    = new Dictionary <string, int>();
            IList <BoneContent>      flattenedBones = MeshHelper.FlattenSkeleton(skeleton);

            for (int i = 0; i < flattenedBones.Count; i++)
            {
                boneIndices.Add(flattenedBones[i].Name, i);
            }

            // convert all of our bone weights into the correct indices and weight values
            VertexChannel <BoneWeightCollection> inputWeights = geometry.Vertices.Channels[vertexChannelIndex] as VertexChannel <BoneWeightCollection>;

            Vector4[] outputIndices = new Vector4[inputWeights.Count];
            Vector4[] outputWeights = new Vector4[inputWeights.Count];
            for (int i = 0; i < inputWeights.Count; i++)
            {
                ConvertWeights(inputWeights[i], boneIndices, outputIndices, outputWeights, i, geometry);
            }

            // create our new channel names
            int    usageIndex  = VertexChannelNames.DecodeUsageIndex(inputWeights.Name);
            string indicesName = VertexChannelNames.EncodeName(VertexElementUsage.BlendIndices, usageIndex);
            string weightsName = VertexChannelNames.EncodeName(VertexElementUsage.BlendWeight, usageIndex);

            // add in the index and weight channels
            geometry.Vertices.Channels.Insert(vertexChannelIndex + 1, indicesName, outputIndices);
            geometry.Vertices.Channels.Insert(vertexChannelIndex + 2, weightsName, outputWeights);

            // remove the original weights channel
            geometry.Vertices.Channels.RemoveAt(vertexChannelIndex);
        }
Example #13
0
        private BoneContent BuildSkeleton(Node node, BoneContent parent)
        {
            BoneContent bone = new BoneContent(node.Name, (uint)_bones.Count, ConvertMatrix(node.Transform), parent);

            _bones.Add(bone);
            _namesToBones[bone.Name] = bone;

            bone.InverseAbsoluteTransform = OpenTK.Matrix4.Invert(bone.Transform);
            BoneContent p = bone.Parent;

            while (p != null)
            {
                bone.InverseAbsoluteTransform *= p.Transform;
                p = p.Parent;
            }

            if (node.HasChildren)
            {
                foreach (Node n in node.Children)
                {
                    BoneContent child = BuildSkeleton(n, bone);
                    bone.Children.Add(child);
                }
            }

            return(bone);
        }
Example #14
0
        public override ModelContent Process(NodeContent input, ContentProcessorContext context)
        {
            CompileRegularExpressions();
            context.Logger.LogMessage("Output Platform: {0}", context.TargetPlatform);

            maxScale_  = 0;
            maxOffset_ = 0;
            BoneContent skeleton = MeshHelper.FindSkeleton(input);

            FlattenTransforms(input, skeleton, context);
            SkinnedBone[] inverseBindPose = GetInverseBindPose(input, context, skeleton);
            context.Logger.LogMessage("Found {0} skinned bones in skeleton.", (inverseBindPose == null) ? 0 : inverseBindPose.Length);

            ModelContent output = base.Process(input, context);

            if (output.Tag == null)
            {
                output.Tag = new Dictionary <string, object>();
            }

            if (FoundSkinning)
            {
#if DEBUG
                StringBuilder strb = new StringBuilder();
#endif
                if (inverseBindPose == null)
                {
                    throw new System.Exception("Could not find skeleton although there is skinned data.");
                }
                for (int i = 0; i != inverseBindPose.Length; ++i)
                {
                    SkinnedBone sb = inverseBindPose[i];
                    int         q  = 0;
                    sb.Index = -1;
                    foreach (ModelBoneContent mbc in output.Bones)
                    {
                        if (mbc.Name == sb.Name)
                        {
                            sb.Index = mbc.Index;
                            break;
                        }
                        ++q;
                    }
                    if (sb.Index == -1)
                    {
                        throw new System.ArgumentException(
                                  String.Format("Can't find the index for animated bone named {0}.", sb.Name));
                    }
                    inverseBindPose[i] = sb;
                }
                ((Dictionary <string, object>)output.Tag).Add("InverseBindPose", inverseBindPose);
            }

            ((Dictionary <string, object>)output.Tag).Add("AnimationSet",
                                                          BuildAnimationSet(input, ref output, context));

            ((Dictionary <string, object>)output.Tag).Add("BoundsInfo",
                                                          new BoundsInfo(maxScale_, maxOffset_));
            return(output);
        }
Example #15
0
        /// <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)
        {
            if (string.IsNullOrEmpty(this.EffectFileName))
            {
                this.EffectFileName = "Effects\\Animation.fx";
            }

            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 > this.maxBones)
            {
                throw new InvalidContentException(string.Format("Skeleton has {0} bones, but the maximum supported is {1}.", bones.Count, this.maxBones));
            }

            Dictionary <string, int> boneMap         = new Dictionary <string, int>();
            List <Matrix>            bindPose        = new List <Matrix>();
            List <Matrix>            inverseBindPose = new List <Matrix>();
            List <int> skeletonHierarchy             = new List <int>();

            int i = 0;

            foreach (BoneContent bone in bones)
            {
                boneMap.Add(bone.Name, i);
                bindPose.Add(bone.Transform);
                inverseBindPose.Add(Matrix.Invert(bone.AbsoluteTransform));
                skeletonHierarchy.Add(bones.IndexOf(bone.Parent as BoneContent));
                i++;
            }

            // Convert animation data to our runtime format.
            Dictionary <string, Clip> animationClips;

            animationClips = ProcessAnimations(skeleton.Animations, bones);

            // Chain to the base ModelProcessor class so it can convert the model data.
            ModelContent model = base.Process(input, context);

            // Store our custom animation data in the Tag property of the model.
            model.Tag = new SkinningData(boneMap, animationClips, bindPose, inverseBindPose, skeletonHierarchy);

            return(model);
        }
Example #16
0
        /// <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 > ModelAnimationClip.MaxBones)
            {
                throw new InvalidContentException(string.Format("Skeleton has {0} bones, but the maximum supported is {1}.", bones.Count, ModelAnimationClip.MaxBones));
            }

            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>();

            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.
            Dictionary <string, ModelAnimationClip> modelAnimationClips = ProcessAnimations(skeleton.Animations, bones, context);

            Dictionary <string, RootAnimationClip> rootAnimationClips = new Dictionary <string, RootAnimationClip>();

            // 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)
            {
                RootAnimationClip processed = RigidModelProcessor.ProcessRootAnimation(animation.Value, model.Bones[0].Name);

                rootAnimationClips.Add(animation.Key, processed);
            }

            // Store our custom animation data in the Tag property of the model.
            model.Tag = new ModelAnimationData(modelAnimationClips, rootAnimationClips, bindPose, inverseBindPose, skeletonHierarchy, boneIndices);

            return(model);
        } // Process
        /// <summary>
        /// Extract and processes all the bones (BoneContent) of the model generating a
        /// SkinnedModelBoneCollection.
        /// </summary>
        private SkinnedModelBoneContentCollection ProcessBones(BoneContent rootBone,
                                                               ContentProcessorContext context)
        {
            List <SkinnedModelBoneContent> skinnedBoneList = new
                                                             List <SkinnedModelBoneContent>(MaxBones);

            ProcessBones(rootBone, null, skinnedBoneList, context);

            return(new SkinnedModelBoneContentCollection(skinnedBoneList));
        }
        public override Dictionary <string, BoneAnimationClip> Process(NodeContent input, ContentProcessorContext context)
        {
            ModelSkeletonProcessor skeletonProcessor = new ModelSkeletonProcessor();

            skeletonProcessor.RotationX = RotationX;
            skeletonProcessor.RotationY = RotationY;
            skeletonProcessor.RotationZ = RotationZ;
            skeletonProcessor.Scale     = Scale;

            Skeleton = skeletonProcessor.Process(input, context);

            this.context = context;

            if (FramesPerSecond <= 0)
            {
                throw new ArgumentOutOfRangeException("FramesPerSecond");
            }

            BoneContent skeleton = MeshHelper.FindSkeleton(input);

            // Flattern input node content
            List <NodeContent> nodes = new List <NodeContent>();

            FlattenNodeContent(input, nodes);

            // Process animations
            Dictionary <string, AnimationClip> animations = new Dictionary <string, AnimationClip>();

            ProcessAnimation(input, animations, nodes);

            if (animations.Count <= 0)
            {
                return(null);
            }


            // Sort keyframes
            foreach (AnimationClip clip in animations.Values)
            {
                clip.Keyframes.Sort(CompareKeyframeTimes);
            }


            // Convert to BoneAnimationClip format
            Dictionary <string, BoneAnimationClip> boneAnimations = new Dictionary <string, BoneAnimationClip>();

            foreach (string key in animations.Keys)
            {
                boneAnimations.Add(key, ConvertAnimationClip(animations[key]));
            }

            ClampAnimationsAndApplyTransform(boneAnimations);

            return(boneAnimations);
        }
        public override ModelContent Process(NodeContent input, ContentProcessorContext context)
        {
            SkinnedModelProcessor.ValidateMesh(input, context, null);
            BoneContent boneContent = MeshHelper.FindSkeleton(input);
            bool        count       = boneContent != null;

            if (count)
            {
                SkinnedModelProcessor.FlattenTransforms(input, boneContent);
                IList <BoneContent> boneContents = MeshHelper.FlattenSkeleton(boneContent);
                count = boneContents.Count <= 59;
                if (count)
                {
                    List <Matrix>             matrices   = new List <Matrix>();
                    List <Matrix>             matrices1  = new List <Matrix>();
                    List <int>                nums       = new List <int>();
                    IEnumerator <BoneContent> enumerator = boneContents.GetEnumerator();
                    try {
                        while (true)
                        {
                            count = enumerator.MoveNext();
                            if (!count)
                            {
                                break;
                            }
                            BoneContent current = enumerator.Current;
                            matrices.Add(current.Transform);
                            matrices1.Add(Matrix.Invert(current.AbsoluteTransform));
                            nums.Add(boneContents.IndexOf(current.Parent as BoneContent));
                        }
                    } finally {
                        count = enumerator == null;
                        if (!count)
                        {
                            enumerator.Dispose();
                        }
                    }
                    Dictionary <string, AnimationClip> strs = SkinnedModelProcessor.ProcessAnimations(boneContent.Animations, boneContents);
                    ModelContent modelContent = base.Process(input, context);
                    modelContent.Tag = new SkinningData(strs, matrices, matrices1, nums);
                    ModelContent modelContent1 = modelContent;
                    return(modelContent1);
                }
                else
                {
                    throw new InvalidContentException(string.Format("Skeleton has {0} bones, but the maximum supported is {1}.", boneContents.Count, 59));
                }
            }
            else
            {
                throw new InvalidContentException("Input skeleton not found.");
            }
        }
Example #20
0
        // A frame can store any data, but is constrained such that each frame must haveB
        // a transform matrix for .X meshes.
        // template Frame
        // {
        //    [...]
        // }
        /// <summary>
        /// Imports a data Node in a directx file, usually a Frame node.
        /// </summary>
        /// <returns>The imported node</returns>
        private NodeContent ImportNode()
        {
            NodeContent c;

            if (meshes.Count == 0)
            {
                c = new NodeContent();
            }
            else
            {
                c = new BoneContent();
            }
            c.Name = tokens.ReadName();
            if (c.Name == null)
            {
                c.Name = "Node" + c.GetHashCode();
            }
            // process all of this frame's children
            for (string next = tokens.NextToken(); next != "}"; next = tokens.NextToken())
            {
                if (next == "Frame")
                {
                    c.Children.Add(ImportNode());
                }
                else if (next == "FrameTransformMatrix")
                {
                    c.Transform = ImportFrameTransformMatrix();
                }
                else if (next == "Mesh")
                {
                    XMeshImporter meshImporter = new XMeshImporter(this);
                    c.Children.Add(meshImporter.ImportMesh());
                }
                // Ignore templates, which define new structure that store data
                // for now, we only will work with the standard directx templates
                else if (next == "template")
                {
                    tokens.SkipName().SkipNode();
                }
                // Skin weight nodes can exist either inside meshes or inside frames.
                // When they exist in a frame, they will refer to a universal mesh
                else if (next == "SkinWeights")
                {
                    meshes[0].ImportSkinWeights();
                }
                // an data node that we are uninterested in
                else if (next == "{")
                {
                    tokens.SkipNode();
                }
            }
            return(c);
        }
Example #21
0
        static void CreateChildBones(BoneContent xnaParentBone, SerializableBone parentBone, SerializableSkeleton skeleton)
        {
            foreach (BoneContent xnaChildBone in xnaParentBone.Children)
            {
                SerializableBone childBone = new SerializableBone();
                childBone.name = xnaChildBone.Name;
                childBone.matrixLocalTransform = xnaChildBone.Transform;
                parentBone.children.Add(childBone);
                skeleton.AddBone(childBone);

                CreateChildBones(xnaChildBone, childBone, skeleton);
            }
        }
Example #22
0
        private NodeContent WalkHierarchy(Node aiNode, NodeContent xnaParent, Matrix4x4 parentXform)
        {
            var  transform = Matrix4x4.Identity;
            Node walk      = aiNode;

            while (walk != null && walk.Name != xnaParent.Name)
            {
                transform *= walk.Transform;
                walk       = walk.Parent;
            }

            NodeContent node = null;

            if (!aiNode.Name.Contains("_$AssimpFbx$"))      // Ignore pivot nodes
            {
                const string mangling = "_$AssimpFbxNull$"; // Null leaf nodes are helpers

                if (_skeletonNodes.Contains(aiNode.Name))
                {
                    node = new BoneContent {
                        Name = aiNode.Name
                    }
                }
                ;
                else if (aiNode.Name.Contains(mangling))
                {
                    node = new NodeContent {
                        Name = aiNode.Name.Replace(mangling, string.Empty)
                    }
                }
                ;

                // Only emit XNA nodes for concrete nodes
                if (node != null)
                {
                    node.Transform = ToXna(transform);
                    xnaParent.Children.Add(node);

                    // For the children, this is the new parent.
                    xnaParent = node;
                }
            }

            // Children
            foreach (var child in aiNode.Children)
            {
                WalkHierarchy(child, xnaParent, transform);
            }

            return(node);
        }
Example #23
0
        // Function to process a model from normal content to a model with animation data
        public override ModelContent Process(NodeContent input, ContentProcessorContext context)
        {
            SetSkinnedEffect(input);

            BoneContent skeleton = ImportSkeleton(input);

            model = base.Process(input, context);

            AnimationDataImport(model, input, context);

            model.Tag = animationData;

            return(model);
        }
Example #24
0
        public override AnimationsContent Process(NodeContent input, ContentProcessorContext context)
        {
            if (_fixRealBoneRoot)
            {
                MGFixRealBoneRoot(input, 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> invBindPose       = new List <Matrix>();
            List <int>    skeletonHierarchy = new List <int>();
            List <string> boneNames         = new List <string>();

            foreach (var bone in bones)
            {
                bindPose.Add(bone.Transform);
                invBindPose.Add(Matrix.Invert(bone.AbsoluteTransform));
                skeletonHierarchy.Add(bones.IndexOf(bone.Parent as BoneContent));
                boneNames.Add(bone.Name);
            }

            // Convert animation data to our runtime format.
            Dictionary <string, ClipContent> clips;

            clips = ProcessAnimations(input, context, skeleton.Animations, bones, GenerateKeyframesFrequency);

            return(new AnimationsContent(bindPose, invBindPose, skeletonHierarchy, boneNames, clips));
        }
        private bool ValidateBone(NodeContent nodeContent, ContentProcessorContext context)
        {
            BoneContent boneContent = nodeContent as BoneContent;

            if (boneContent == null)
            {
                context.Logger.LogWarning(null, nodeContent.Identity, string.Format(
                                              "Node {0} is invalid inside the model's skeleton and will be skipped.",
                                              nodeContent.Name));

                return(false);
            }

            return(true);
        }
        /// <summary>
        /// The function to process a model from original content into model content for export
        /// </summary>
        /// <param name="input"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public override ModelContent Process(NodeContent input, ContentProcessorContext context)
        {
            // Process the skeleton for skinned character animation
            BoneContent skeleton = ProcessSkeleton(input);

            SwapSkinnedMaterial(input);

            model = base.Process(input, context);

            ProcessAnimations(model, input, context);

            // Add the extra content to the model
            model.Tag = modelExtra;

            return(model);
        }
        /// <summary>
        /// The main Process method converts an intermediate format content pipeline
        /// NodeContent tree to a ModelContent object with embedded animation data.
        /// </summary>
        public SkinningData Process(NodeContent input,
                                    ContentProcessorContext context)
        {
            SkinnedModelHelper.ValidateMesh(input, context, null);

            // Find the skeleton.
            BoneContent skeleton = MeshHelper.FindSkeleton(input);

            if (skeleton == null)
            {
                return(null);
            }

            // 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.
            SkinnedModelHelper.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, AnimationClip> animationClips;

            animationClips = SkinnedModelHelper.ProcessAnimations(skeleton.Animations, bones);

            // Store our custom animation data in the Tag property of the model.
            return(new SkinningData(animationClips, bindPose,
                                    inverseBindPose, skeletonHierarchy));
        }
Example #28
0
        public override SerializableModel Process(NodeContent xnaInputNode, ContentProcessorContext context)
        {
            //System.Diagnostics.Debugger.Launch();

            this.context = context;

            outputModel      = new SerializableModel();
            outputModel.name = RemoveFileExtension(GetFileName(context));

            ValidateMesh(xnaInputNode, context, null);

            // Find the root.
            BoneContent xnaRootBone = MeshHelper.FindSkeleton(xnaInputNode);

            if (xnaRootBone == 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(xnaInputNode, xnaRootBone);

            // Read the bind pose and skeleton hierarchy data.
            IList <BoneContent> xnaBoneList = MeshHelper.FlattenSkeleton(xnaRootBone);

            if (xnaBoneList.Count > MAX_BONES)
            {
                throw new InvalidContentException(string.Format("Skeleton has {0} bones, but the maximum supported is {1}.", xnaBoneList.Count, MAX_BONES));
            }

            SerializableSkeleton skeleton = new SerializableSkeleton();
            SerializableBone     root     = new SerializableBone();

            root.name = xnaRootBone.Name;
            root.matrixLocalTransform = xnaRootBone.Transform;
            skeleton.rootBone         = root;
            skeleton.AddBone(root);
            outputModel.skeleton = skeleton;

            CreateChildBones(xnaRootBone, root, skeleton);

            ProcessNode(xnaInputNode);
            ProcessAnimations(xnaRootBone.Animations, outputModel);

            return(outputModel);
        }
        /// <summary>
        /// Recursively process each BoneContent of the model generating a new SkinnedModelBone
        /// </summary>
        private SkinnedModelBoneContent ProcessBones(BoneContent boneContent,
                                                     SkinnedModelBoneContent skinnedModelParentBone,
                                                     List <SkinnedModelBoneContent> skinnedBoneList, ContentProcessorContext context)
        {
            // Add the current boneContent to the skinned boneContent list
            ushort boneIndex = (ushort)skinnedBoneList.Count;

            // Decompose boneContent bind pose from the transform matrix
            Pose bindPose;

            boneContent.Transform.Decompose(out bindPose.Scale, out bindPose.Orientation,
                                            out bindPose.Translation);

            // Calculates boneContent inverse bind pose
            Matrix inverseBindPose = Matrix.Invert(boneContent.AbsoluteTransform);

            // Create the skinned model's boneContent and add it to the skinned model's boneContent list
            SkinnedModelBoneContent skinnedModelBone =
                new SkinnedModelBoneContent(boneIndex, boneContent.Name, bindPose, inverseBindPose);

            skinnedBoneList.Add(skinnedModelBone);

            // Process all children
            List <SkinnedModelBoneContent> skinnedBoneChildrenList = new List <SkinnedModelBoneContent>();

            foreach (NodeContent nodeContent in boneContent.Children)
            {
                // Validate the bone
                if (!ValidateBone(nodeContent, context))
                {
                    continue;
                }

                BoneContent             childBoneContent = nodeContent as BoneContent;
                SkinnedModelBoneContent skinnedBoneChild =
                    ProcessBones(childBoneContent, skinnedModelBone, skinnedBoneList, context);

                skinnedBoneChildrenList.Add(skinnedBoneChild);
            }

            // Sets boneContent parent and children
            skinnedModelBone.Parent   = skinnedModelParentBone;
            skinnedModelBone.Children = new SkinnedModelBoneContentCollection(skinnedBoneChildrenList);

            return(skinnedModelBone);
        }
        BoneContent CreateSkeleton(Joint joint)
        {
            var bone = new BoneContent();

            bone.Name      = GetJointKey(joint);
            bone.Transform = joint.Transform;

            if (joint.Children != null && joint.Children.Count > 0)
            {
                foreach (var childJoint in joint.Children)
                {
                    bone.Children.Add(CreateSkeleton(childJoint));
                }
            }

            return(bone);
        }