public Skeleton(Stream Data) { m_Reader = new FileReader(Data, true); m_Reader.ReadUInt32(); //Version Name = m_Reader.ReadPascalString(); BoneCount = m_Reader.ReadUShort(); for(int i = 0; i < BoneCount; i++) { Bones.Add(new Bone(m_Reader, i)); } /** Construct tree **/ foreach (Bone bone in Bones) bone.Children = Bones.Where(x => x.ParentName == bone.Name).ToArray(); RootBone = Bones.FirstOrDefault(x => x.ParentName == "NULL"); m_Reader.Close(); }
/// <summary> /// Transforms all vertices in a given mesh to their correct positions. /// </summary> /// <param name="Msh">The mesh to transform.</param> /// <param name="bone">The bone to transform to.</param> private void TransformVertices(Mesh Msh, Bone bone, MeshType MshType) { switch (MshType) { case MeshType.Head: for (int i = 0; i < Msh.TotalVertexCount; i++) { //Transform the head vertices' position by the absolute transform //for the headbone (which is always bone 17) to render the head in place. Msh.TransformedVertices[i].Position = Vector3.Transform(Msh.RealVertices[i].Position, Skel.Bones[16].AbsoluteMatrix); Msh.TransformedVertices[i].TextureCoordinate = Msh.RealVertices[i].TextureCoordinate; //Transform the head normals' position by the absolute transform //for the headbone (which is always bone 17) to render the head in place. Msh.TransformedVertices[i].Normal = Vector3.Transform(Msh.RealVertices[i].Normal, Skel.Bones[16].AbsoluteMatrix); } return; case MeshType.Body: BoneBinding boneBinding = Msh.BoneBindings.FirstOrDefault(x => Msh.Bones[(int)x.BoneIndex] == bone.Name); if (boneBinding != null) { for (int i = 0; i < boneBinding.RealVertexCount; i++) { int vertexIndex = (int)boneBinding.FirstRealVertexIndex + i; VertexPositionNormalTexture relativeVertex = Msh.RealVertices[vertexIndex]; Matrix translatedMatrix = Matrix.CreateTranslation(new Vector3(relativeVertex.Position.X, relativeVertex.Position.Y, relativeVertex.Position.Z)) * bone.AbsoluteMatrix; Msh.TransformedVertices[vertexIndex].Position = Vector3.Transform(Vector3.Zero, translatedMatrix); Msh.TransformedVertices[vertexIndex].TextureCoordinate = relativeVertex.TextureCoordinate; //Normals... translatedMatrix = Matrix.CreateTranslation(new Vector3(relativeVertex.Normal.X, relativeVertex.Normal.Y, relativeVertex.Normal.Z)) * bone.AbsoluteMatrix; Msh.TransformedVertices[vertexIndex].Normal = Vector3.Transform(Vector3.Zero, translatedMatrix); } } foreach (var child in bone.Children) TransformVertices(Msh, child, MshType); break; case MeshType.LHand: for (int i = 0; i < Msh.TotalVertexCount; i++) { //Transform the left hand vertices' position by the absolute transform //for the left handbone (which is always bone 10) to render the left hand in place. Msh.TransformedVertices[i].Position = Vector3.Transform(Msh.RealVertices[i].Position, Skel.Bones[9].AbsoluteMatrix); //Transform the left hand normals' position by the absolute transform //for the left handbone (which is always bone 10) to render the left hand in place. Msh.TransformedVertices[i].Normal = Vector3.Transform(Msh.RealVertices[i].Normal, Skel.Bones[9].AbsoluteMatrix); } return; case MeshType.RHand: for (int i = 0; i < Msh.TotalVertexCount; i++) { //Transform the right hand vertices' position by the absolute transform //for the right handbone (which is always bone 15) to render the right hand in place. Msh.TransformedVertices[i].Position = Vector3.Transform(Msh.RealVertices[i].Position, Skel.Bones[14].AbsoluteMatrix); //Transform the right hand normals' position by the absolute transform //for the right handbone (which is always bone 15) to render the right hand in place. Msh.TransformedVertices[i].Normal = Vector3.Transform(Msh.RealVertices[i].Normal, Skel.Bones[14].AbsoluteMatrix); } return; } }
/// <summary> /// Computes the absolute positions for all bones in a Skeleton. /// </summary> /// <param name="bone">The first bone in the skeleton.</param> /// <param name="world">World matrix.</param> public void ComputeBonePositions(Bone bone, Matrix world) { var translateMatrix = Matrix.CreateTranslation(bone.Translation); var rotationMatrix = Helpers.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); } }