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); } }
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"); } }
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); } }
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; }
/// <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(ref Skeleton Skel, Bone Bne, ref Matrix World) { int BoneIndex = 0; Matrix WorldMat = 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); 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); 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); 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); 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(ref Skel, Skel.Bones[Bne.Children[0]], ref World); else if (Bne.NumChildren > 1) { for (int i = 0; i < Bne.NumChildren; i++) TransformVertices2(ref Skel, Skel.Bones[Bne.Children[i]], ref World); } }
public Skeleton(GraphicsDevice Device, byte[] Filedata, Matrix WorldMatrix) { MemoryStream MemStream = new MemoryStream(Filedata); BinaryReader Reader = new BinaryReader(MemStream); m_WorldMatrix = WorldMatrix; 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(this); Bne.ID = i; Bne.BoneName = Encoding.ASCII.GetString(Reader.ReadBytes(Reader.ReadByte())); Log.LogThis("BoneName: " + Bne.BoneName, eloglevel.info); 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.Versor = new float[4]; //These values are given in degrees... Bne.Versor[0] = MathHelper.ToRadians(Reader.ReadSingle()); Bne.Versor[1] = MathHelper.ToRadians(Reader.ReadSingle()); Bne.Versor[2] = MathHelper.ToRadians(Reader.ReadSingle()); Bne.Versor[3] = MathHelper.ToRadians(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 int[m_BoneCount - i - 1]; int Parent = FindBone(Bne.ParentName, i); if (Parent != -1) { m_Bones[Parent].Children[m_Bones[Parent].NumChildren] = Bne.ID; m_Bones[Parent].NumChildren += 1; Bne.Parent = m_Bones[Parent]; Bne.ComputeAbsoluteTransform(m_WorldMatrix); } m_Bones[i] = Bne; /*Log.LogThis("Bone: " + Bne.BoneName, eloglevel.info); if (Parent != -1) { Log.LogThis("Parent: " + Bne.Parent.BoneName, eloglevel.info); for (int j = 0; j < Bne.Parent.NumChildren; j++) Log.LogThis("Child: " + Bne.Parent.Children[j].BoneName, eloglevel.info); } else Log.LogThis("Parent: NULL", eloglevel.info);*/ } Reader.Close(); }
public Skeleton(GraphicsDevice Device, string Filepath, ref Matrix WorldMatrix) { BinaryReader Reader = new BinaryReader(File.Open(Filepath, FileMode.Open)); m_WorldMatrix = WorldMatrix; 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(this); 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.Versor = new float[4]; //These values are given in degrees... Bne.Versor[0] = MathHelper.ToRadians(Reader.ReadSingle()); Bne.Versor[1] = MathHelper.ToRadians(Reader.ReadSingle()); Bne.Versor[2] = MathHelper.ToRadians(Reader.ReadSingle()); Bne.Versor[3] = MathHelper.ToRadians(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 int[m_BoneCount - i - 1]; int Parent = FindBone(Bne.ParentName, i); if (Parent != -1) { m_Bones[Parent].Children[m_Bones[Parent].NumChildren] = Bne.ID; m_Bones[Parent].NumChildren += 1; Bne.Parent = m_Bones[Parent]; Bne.ComputeAbsoluteTransform(m_WorldMatrix); } m_Bones[i] = Bne; } Reader.Close(); }
/// <summary> /// Populates a list of vertices (points) that are rendered at the location /// of each bone in the skeleton. /// </summary> private void PopulateSkeletonPoints(ref VertexPositionNormalTexture[] SkelPoints, ref Bone Bne) { /*if (m_Skeleton != null) { m_SkelPoints = new VertexPositionNormalTexture[m_Skeleton.Bones.Length]; for (int i = 0; i < m_Skeleton.Bones.Length; i++) { m_WorldMatrixStack.Push(m_WorldMatrixStack.Peek()); if (m_SkelPoints[i] == null) { m_SkelPoints[i] = new VertexPositionNormalTexture(m_Skeleton.Bones[i].GlobalTranslation, Vector3.Forward, Vector2.One); m_SkelPoints[i].Position = Vector3.Transform(m_Skeleton.Bones[i].GlobalTranslation, m_Skeleton.Bones[i].AbsoluteTransform); } if (m_Skeleton.Bones[i].NumChildren == 1) { int ChildIndex = m_Skeleton.Bones[i].Children[0].ID; m_SkelPoints[ChildIndex] = new VertexPositionNormalTexture(m_Skeleton.Bones[i].GlobalTranslation * m_Skeleton.Bones[ChildIndex].GlobalTranslation, Vector3.Forward, Vector2.One); m_SkelPoints[ChildIndex].Position = Vector3.Transform(m_Skeleton.Bones[ChildIndex].GlobalTranslation, m_Skeleton.Bones[ChildIndex].AbsoluteTransform); } else if (m_Skeleton.Bones[i].NumChildren > 1) { for (int j = 0; j < m_Skeleton.Bones[i].NumChildren; j++) { int ChildIndex = m_Skeleton.Bones[i].Children[j].ID; m_SkelPoints[ChildIndex] = new VertexPositionNormalTexture(m_Skeleton.Bones[i].GlobalTranslation * m_Skeleton.Bones[ChildIndex].GlobalTranslation, Vector3.Forward, Vector2.One); m_SkelPoints[ChildIndex].Position = Vector3.Transform(m_Skeleton.Bones[ChildIndex].GlobalTranslation, m_Skeleton.Bones[ChildIndex].AbsoluteTransform); } } mWorldMat = m_WorldMatrixStack.Pop(); } }*/ mProjectionMat *= Matrix.CreateFromQuaternion(Bne.GlobalRotation); mProjectionMat *= Matrix.CreateTranslation(Bne.GlobalTranslation); VertexPositionNormalTexture SkelPoint = new VertexPositionNormalTexture(Bne.GlobalTranslation, Vector3.Forward, Vector2.One); SkelPoint.Position = Vector3.Transform(Bne.GlobalTranslation, mProjectionMat); /*SkelPoint.Position *= Vector3.Transform(Bne.GlobalTranslation, Matrix.CreateFromQuaternion(Bne.GlobalRotation));*/ SkelPoints[Bne.ID] = SkelPoint; if (Bne.NumChildren == 1) { PopulateSkeletonPoints(ref SkelPoints, ref m_Skeleton.Bones[Bne.Children[0]]); } else if (Bne.NumChildren > 1) { for (int i = 0; i < Bne.NumChildren; i++) { m_WorldMatrixStack.Push(mProjectionMat); PopulateSkeletonPoints(ref SkelPoints, ref m_Skeleton.Bones[Bne.Children[i]]); m_WorldMatrixStack.Pop(); mProjectionMat = m_WorldMatrixStack.Peek(); } } }