예제 #1
0
        /// <summary>
        /// Transforms the verticies making up this mesh into
        /// the designated bone positions.
        /// </summary>
        /// <param name="bone">The bone to start with. Should always be the ROOT bone.</param>
        public void TransformVertices(Bone bone)
        {
            var binding = this.BoneBindings.FirstOrDefault(x => x.BoneName == bone.Name);
            if (binding != null)
            {
                for (var i = 0; i < binding.RealVertexCount; i++)
                {
                    var vertexIndex = binding.FirstRealVertex + i;
                    var blendVertexIndex = vertexIndex;//binding.FirstBlendVertex + i;

                    var realVertex = this.RealVertexBuffer[vertexIndex];
                    var matrix = Matrix.CreateTranslation(realVertex.Position) * bone.AbsoluteMatrix;

                    //Position
                    var newPosition = Vector3.Transform(Vector3.Zero, matrix);
                    this.BlendVertexBuffer[blendVertexIndex].Position = newPosition;

                    //Normals
                    matrix = Matrix.CreateTranslation(
                        new Vector3(realVertex.Normal.X,
                                    realVertex.Normal.Y,
                                    realVertex.Normal.Z)) * bone.AbsoluteMatrix;
                }
            }

            foreach (var child in bone.Children)
            {
                TransformVertices(child);
            }

            if (bone.Name == "ROOT")
            {
                this.InvalidateMesh();
            }
        }
예제 #2
0
        /// <summary>
        /// Computes the absolute position for all the bones in this skeleton.
        /// </summary>
        /// <param name="bone">The bone to start with, should always be the ROOT bone.</param>
        /// <param name="world">A world matrix to use in the calculation.</param>
        public void ComputeBonePositions(Bone bone, Matrix world)
        {
            var translateMatrix = Matrix.CreateTranslation(bone.Translation);
            var rotationMatrix = FindQuaternionMatrix(bone.Rotation);

            var myWorld = (rotationMatrix * translateMatrix) * world;
            bone.AbsolutePosition = Vector3.Transform(Vector3.Zero, myWorld);
            bone.AbsoluteMatrix = myWorld;

            foreach (var child in bone.Children)
            {
                ComputeBonePositions(child, myWorld);
            }
        }
예제 #3
0
 public Bone Clone()
 {
     var result = new Bone
     {
         Unknown = this.Unknown,
         Name = this.Name,
         ParentName = this.ParentName,
         HasProps = this.HasProps,
         Properties = this.Properties,
         Translation = this.Translation,
         Rotation = this.Rotation,
         CanTranslate = this.CanTranslate,
         CanRotate = this.CanRotate,
         CanBlend = this.CanBlend,
         WiggleValue = this.WiggleValue,
         WigglePower = this.WigglePower
     };
     return result;
 }
예제 #4
0
        public void Read(Stream stream)
        {
            using (var io = IoBuffer.FromStream(stream))
            {
                var version = io.ReadUInt32();
                Name = io.ReadPascalString();

                var boneCount = io.ReadInt16();

                Bones = new Bone[boneCount];
                for (var i = 0; i < boneCount; i++)
                {
                    Bones[i] = ReadBone(io);
                }

                /** Construct tree **/
                foreach (var bone in Bones)
                {
                    bone.Children = Bones.Where(x => x.ParentName == bone.Name).ToArray();
                }
                RootBone = Bones.FirstOrDefault(x => x.ParentName == "NULL");
                ComputeBonePositions(RootBone, Matrix.Identity);
            }
        }
예제 #5
0
        /// <summary>
        /// Transforms the vertices in a mesh to their location in 3D-space based on 
        /// the location of a bone.
        /// </summary>
        /// <param name="Bne">The bone to start with (should be a skeleton's ROOT bone).</param>
        /// <param name="Effect">The BasicEffect instance used for rendering.</param>
        public void TransformVertices2(Bone Bne, ref BasicEffect Effect)
        {
            int BoneIndex = 0;
            Matrix WorldMat = Effect.World * Bne.AbsoluteTransform;

            for (BoneIndex = 0; BoneIndex < m_BndCount; BoneIndex++)
            {
                if (Bne.BoneName == m_BoneNames[m_BoneBindings[BoneIndex].BoneIndex])
                    break;
            }

            if (BoneIndex < m_BndCount)
            {
                for (int i = 0; i < m_BoneBindings[BoneIndex].VertexCount; i++)
                {
                    int VertexIndex = m_BoneBindings[BoneIndex].FirstVertex + i;
                    Vector3 RelativeVertex = new Vector3(m_VertexData[VertexIndex, 0],
                        m_VertexData[VertexIndex, 1], m_VertexData[VertexIndex, 2]);
                    Vector3 RelativeNormal = new Vector3(m_VertexData[VertexIndex, 3],
                        m_VertexData[VertexIndex, 4], m_VertexData[VertexIndex, 5]);

                    WorldMat *= Matrix.CreateTranslation(RelativeVertex);

                    Vector3.Transform(RelativeVertex, WorldMat);
                    m_TransformedVertices[VertexIndex].Coord.X = WorldMat.M41;
                    m_TransformedVertices[VertexIndex].Coord.Y = WorldMat.M42;
                    m_TransformedVertices[VertexIndex].Coord.Z = WorldMat.M43;

                    WorldMat *= Matrix.CreateTranslation(new Vector3(-RelativeVertex.X,
                        -RelativeVertex.Y, -RelativeVertex.Z));

                    WorldMat *= Matrix.CreateTranslation(RelativeNormal);

                    Vector3.TransformNormal(RelativeNormal, WorldMat);
                    m_TransformedVertices[VertexIndex].Normal.X = WorldMat.M41;
                    m_TransformedVertices[VertexIndex].Normal.Y = WorldMat.M42;
                    m_TransformedVertices[VertexIndex].Normal.Z = WorldMat.M43;

                    WorldMat *= Matrix.CreateTranslation(new Vector3(-RelativeNormal.X,
                        -RelativeNormal.Y, -RelativeNormal.Z));
                }

                for (int i = 0; i < m_BoneBindings[BoneIndex].BlendedVertexCount; i++)
                {
                    int VertexIndex = m_RealVertexCount + m_BoneBindings[BoneIndex].FirstBlendedVert + i;
                    Vector3 RelativeVertex = new Vector3(m_VertexData[VertexIndex, 0],
                        m_VertexData[VertexIndex, 1], m_VertexData[VertexIndex, 2]);
                    Vector3 RelativeNormal = new Vector3(m_VertexData[VertexIndex, 3],
                        m_VertexData[VertexIndex, 4], m_VertexData[VertexIndex, 5]);

                    WorldMat *= Matrix.CreateTranslation(RelativeVertex);

                    Vector3.Transform(RelativeVertex, WorldMat);
                    m_TransformedVertices[VertexIndex].Coord.X = WorldMat.M41;
                    m_TransformedVertices[VertexIndex].Coord.Y = WorldMat.M42;
                    m_TransformedVertices[VertexIndex].Coord.Z = WorldMat.M43;

                    WorldMat *= Matrix.CreateTranslation(new Vector3(-RelativeVertex.X,
                        -RelativeVertex.Y, -RelativeVertex.Z));

                    WorldMat *= Matrix.CreateTranslation(RelativeNormal);

                    Vector3.TransformNormal(RelativeNormal, WorldMat);
                    m_TransformedVertices[VertexIndex].Normal.X = WorldMat.M41;
                    m_TransformedVertices[VertexIndex].Normal.Y = WorldMat.M42;
                    m_TransformedVertices[VertexIndex].Normal.Z = WorldMat.M43;

                    WorldMat *= Matrix.CreateTranslation(new Vector3(-RelativeNormal.X,
                        -RelativeNormal.Y, -RelativeNormal.Z));
                }
            }

            if (Bne.NumChildren == 1)
                TransformVertices2(Bne.Children[0], ref Effect);
            else if (Bne.NumChildren > 1)
            {
                for (int i = 0; i < Bne.NumChildren; i++)
                    TransformVertices2(Bne.Children[i], ref Effect);
            }
        }
예제 #6
0
        private Bone ReadBone(IoBuffer reader)
        {
            var bone = new Bone();
            bone.Unknown = reader.ReadInt32();
            bone.Name = reader.ReadPascalString();
            bone.ParentName = reader.ReadPascalString();
            bone.HasProps = reader.ReadByte();
            if (bone.HasProps != 0)
            {
                var propertyCount = reader.ReadInt32();
                var property = new PropertyListItem();

                for (var i = 0; i < propertyCount; i++)
                {
                    var pairCount = reader.ReadInt32();
                    for (var x = 0; x < pairCount; x++)
                    {
                        property.KeyPairs.Add(new KeyValuePair<string, string>(
                            reader.ReadPascalString(),
                            reader.ReadPascalString()
                        ));
                    }
                }
                bone.Properties.Add(property);
            }

            var xx = -reader.ReadFloat();
            bone.Translation = new Vector3(
                xx,
                reader.ReadFloat(),
                reader.ReadFloat()
            );
            bone.Rotation = new Vector4(
                reader.ReadFloat(),
                -reader.ReadFloat(),
                -reader.ReadFloat(),
                reader.ReadFloat()
            );
            bone.CanTranslate = reader.ReadInt32();
            bone.CanRotate = reader.ReadInt32();
            bone.CanBlend = reader.ReadInt32();
            bone.WiggleValue = reader.ReadFloat();
            bone.WigglePower = reader.ReadFloat();
            return bone;
        }
예제 #7
0
        /// <summary>
        /// Transforms the verticies making up this mesh into
        /// the designated bone positions.
        /// </summary>
        /// <param name="bone">The bone to start with. Should always be the ROOT bone.</param>
        public void TransformVertices(Bone bone)
        {
            var boneBinding = BoneBindings.FirstOrDefault(x => BoneNames[x.BoneIndex] == bone.Name);

            if (boneBinding != null)
            {
                for (var i = 0; i < boneBinding.RealVertexCount; i++)
                {
                    int vertexIndex = boneBinding.FirstRealVertex + i;
                    MeshVertexData transformedVertex = TransformedVertices[vertexIndex];
                    MeshVertexData relativeVertex = Vertex[vertexIndex];

                    var translatedMatrix = Matrix.CreateTranslation(new Vector3(relativeVertex.Vertex.Coord.X, relativeVertex.Vertex.Coord.Y, relativeVertex.Vertex.Coord.Z)) * bone.AbsoluteMatrix;
                    transformedVertex.Vertex.Coord = Vector3.Transform(Vector3.Zero, translatedMatrix);

                    //Normals...
                    translatedMatrix = Matrix.CreateTranslation(new Vector3(relativeVertex.Vertex.NormalCoord.X, relativeVertex.Vertex.NormalCoord.Y, relativeVertex.Vertex.NormalCoord.Z)) * bone.AbsoluteMatrix;
                    transformedVertex.Vertex.NormalCoord = Vector3.Transform(Vector3.Zero, translatedMatrix);
                }
            }

            foreach (var child in bone.Children)
            {
                TransformVertices(child);
            }
        }
예제 #8
0
        private Bone ReadBone(VBReader reader)
        {
            var bone = new Bone();
            bone.Unknown = reader.ReadInt32();
            bone.Name = reader.ReadPascalString();
            bone.ParentName = reader.ReadPascalString();

            System.Diagnostics.Debug.WriteLine("Name: " + bone.Name);
            System.Diagnostics.Debug.WriteLine("ParentName: " + bone.ParentName);

            bone.HasProps = reader.ReadByte();
            if (bone.HasProps != 0)
            {
                var propertyCount = reader.ReadInt32();
                var property = new PropertyListItem();

                for (var i = 0; i < propertyCount; i++){
                    var pairCount = reader.ReadInt32();
                    for (var x = 0; x < pairCount; x++){
                        property.KeyPairs.Add(new KeyValuePair<string, string>(
                            reader.ReadPascalString(),
                            reader.ReadPascalString()
                        ));
                    }
                }
                bone.Properties.Add(property);
            }

            /*if (bone.Name == "ROOT")
            {
                var y = true;
            }*/
            var xx = -reader.ReadFloat();
            bone.Translation = new Vector3(
                xx,
                reader.ReadFloat(),
                reader.ReadFloat()
            );

            bone.Rotation = new Vector4(
                reader.ReadFloat(),
                -reader.ReadFloat(),
                -reader.ReadFloat(),
                reader.ReadFloat()
            );

            bone.CanTranslate = reader.ReadInt32();
            bone.CanRotate = reader.ReadInt32();
            bone.CanBlend = reader.ReadInt32();

            bone.WiggleValue = reader.ReadFloat();
            bone.WigglePower = reader.ReadFloat();

            return bone;
        }
예제 #9
0
        /// <summary>
        /// Reads a skeleton.
        /// </summary>
        /// <param name="data">The data from which to read this skeleton.</param>
        public void Read(byte[] data)
        {
            using(var reader = new VBReader(new MemoryStream(data))){
                Version = reader.ReadInt32();
                Name = reader.ReadPascalString();
                BoneCount = reader.ReadInt16();

                System.Diagnostics.Debug.WriteLine("========== Skeleton ==========");
                System.Diagnostics.Debug.WriteLine("Version: " + Version);
                System.Diagnostics.Debug.WriteLine("Name: " + Name);
                System.Diagnostics.Debug.WriteLine("BoneCount: " + BoneCount);

                Bones = new Bone[BoneCount];
                for (var i = 0; i < BoneCount; i++){
                    System.Diagnostics.Debug.WriteLine("\n [Bone " + i + "]");
                    Bones[i] = ReadBone(reader);
                }

                /** Construct tree **/
                foreach (var bone in Bones){
                    bone.Children = Bones.Where(x => x.ParentName == bone.Name).ToArray();
                }

                RootBone = Bones.FirstOrDefault(x => x.ParentName == "NULL");
            }
        }
예제 #10
0
 /// <summary>
 /// Replaces a bone in this skeleton's list of bones with a specific bone.
 /// </summary>
 /// <param name="Index">The index of the bone to replace/update.</param>
 /// <param name="Bne">The bone with which to replace the bone at the specified index.</param>
 public void UpdateBone(int Index, Bone Bne)
 {
     m_Bones[Index] = Bne;
 }
예제 #11
0
        public Skeleton(GraphicsDevice Device, byte[] Filedata)
        {
            MemoryStream MemStream = new MemoryStream(Filedata);
            BinaryReader Reader = new BinaryReader(MemStream);

            m_Version = Endian.SwapUInt32(Reader.ReadUInt32());
            m_Name = Encoding.ASCII.GetString(Reader.ReadBytes(Reader.ReadByte()));

            m_BoneCount = Endian.SwapUInt16(Reader.ReadUInt16());
            m_Bones = new Bone[m_BoneCount];

            for (int i = 0; i < m_BoneCount; i++)
            {
                Endian.SwapUInt32(Reader.ReadUInt32()); //1 in hexadecimal... typical useless Maxis value...

                Bone Bne = new Bone();

                Bne.ID = i;

                Bne.BoneName = Encoding.ASCII.GetString(Reader.ReadBytes(Reader.ReadByte()));
                Bne.ParentName = Encoding.ASCII.GetString(Reader.ReadBytes(Reader.ReadByte()));

                Bne.HasPropertyList = Reader.ReadByte();

                if (Bne.HasPropertyList == 1)
                    Bne.PList = ReadPropList(Reader);

                //Little Endian
                Bne.Translations = new float[3];
                Bne.Translations[0] = Reader.ReadSingle();
                Bne.Translations[1] = Reader.ReadSingle();
                Bne.Translations[2] = Reader.ReadSingle();

                Bne.Quaternions = new float[4];
                Bne.Quaternions[0] = Reader.ReadSingle();
                Bne.Quaternions[1] = Reader.ReadSingle();
                Bne.Quaternions[2] = Reader.ReadSingle();
                Bne.Quaternions[3] = Reader.ReadSingle();

                Bne.CanTranslate = Endian.SwapInt32(Reader.ReadInt32());
                Bne.CanRotate = Endian.SwapInt32(Reader.ReadInt32());
                Bne.CanUseBlending = Endian.SwapInt32(Reader.ReadInt32());
                //Little endian.
                Bne.CanWiggle = Reader.ReadSingle();
                Bne.WiggleAmount = Reader.ReadSingle();

                Bne.BoneEffect = new BasicEffect(Device, null);

                Bne.Children = new Bone[m_BoneCount - i - 1];

                m_Bones[i] = Bne;
            }

            for(int i = 0; i < m_Bones.Length; i++)
            {
                for(int j = 0; j < m_Bones.Length; j++)
                {
                    if (m_Bones[i].ParentName == m_Bones[j].BoneName)
                        m_Bones[i].Parent = m_Bones[j];
                }
            }

            foreach (Bone Bne in m_Bones)
            {
                Bne.ComputeAbsoluteTransform();
            }

            Reader.Close();
        }