public override void Read(BinaryReader b) { base.Read(b); NumIntVertices = (int)((this.Size - 32) / 64); IntSkinVertices = new IntSkinVertex[NumIntVertices]; this.SkipBytes(b, 32); // Padding between the chunk header and the first IntVertex. // Size of the IntSkinVertex is 64 bytes for (int i = 0; i < NumIntVertices; i++) { IntSkinVertices[i].Obsolete0.ReadVector3(b); IntSkinVertices[i].Position.ReadVector3(b); IntSkinVertices[i].Obsolete2.ReadVector3(b); // Read 4 bone IDs IntSkinVertices[i].BoneIDs = new ushort[4]; for (int j = 0; j < 4; j++) { IntSkinVertices[i].BoneIDs[j] = b.ReadUInt16(); } // Read the weights for those bone IDs IntSkinVertices[i].Weights = new float[4]; for (int j = 0; j < 4; j++) { IntSkinVertices[i].Weights[j] = b.ReadSingle(); } // Read the color IntSkinVertices[i].Color.Read(b); } SkinningInfo skin = GetSkinningInfo(); skin.IntVertices = IntSkinVertices.ToList(); }
public override void Read(BinaryReader b) { base.Read(b); this.SkipBytes(b, 32); // Padding between the chunk header and the first bone. this.NumBones = (int)((this.Size - 32) / 152); for (uint i = 0; i < NumBones; i++) { // Start reading at the root bone. First bone found is root, then read until no more bones. CompiledPhysicalBone tmpBone = new CompiledPhysicalBone(); tmpBone.ReadCompiledPhysicalBone(b); // Set root bone if not already set if (RootPhysicalBone != null) { RootPhysicalBone = tmpBone; } PhysicalBoneList.Add(tmpBone); PhysicalBoneDictionary[i] = tmpBone; } // Add the ChildID to the parent bone. This will help with navigation. Also set up the TransformSoFar foreach (CompiledPhysicalBone bone in PhysicalBoneList) { AddChildIDToParent(bone); } SkinningInfo skin = GetSkinningInfo(); //skin.PhysicalBoneMeshes }
public override void Read(BinaryReader b) { base.Read(b); this.SkipBytes(b, 32); // Padding between the chunk header and the first bone. Vector3 localTranslation; Matrix33 localRotation; // Read the first bone with ReadCompiledBone, then recursively grab all the children for each bone you find. // Each bone structure is 584 bytes, so will need to seek childOffset * 584 each time, and go back. NumBones = (int)((this.Size - 32) / 584); for (int i = 0; i < NumBones; i++) { CompiledBone tempBone = new CompiledBone(); tempBone.ReadCompiledBone(b); if (RootBone == null) // First bone read is root bone { this.RootBone = tempBone; } tempBone.LocalTranslation = tempBone.boneToWorld.GetBoneToWorldTranslationVector(); // World positions of the bone tempBone.LocalRotation = tempBone.boneToWorld.GetBoneToWorldRotationMatrix(); // World rotation of the bone. //tempBone.ParentBone = BoneMap[i + tempBone.offsetParent]; tempBone.ParentBone = GetParentBone(tempBone, i); if (tempBone.ParentBone != null) { tempBone.parentID = tempBone.ParentBone.ControllerID; } else { tempBone.parentID = 0; } if (tempBone.parentID != 0) { localRotation = GetParentBone(tempBone, i).boneToWorld.GetBoneToWorldRotationMatrix().ConjugateTransposeThisAndMultiply(tempBone.boneToWorld.GetBoneToWorldRotationMatrix()); localTranslation = GetParentBone(tempBone, i).LocalRotation *(tempBone.LocalTranslation - GetParentBone(tempBone, i).boneToWorld.GetBoneToWorldTranslationVector()); } else { localTranslation = tempBone.boneToWorld.GetBoneToWorldTranslationVector(); localRotation = tempBone.boneToWorld.GetBoneToWorldRotationMatrix(); } tempBone.LocalTransform = GetTransformFromParts(localTranslation, localRotation); BoneList.Add(tempBone); BoneDictionary[i] = tempBone; } // Add the ChildID to the parent bone. This will help with navigation. Also set up the TransformSoFar foreach (CompiledBone bone in BoneList) { AddChildIDToParent(bone); } SkinningInfo skin = GetSkinningInfo(); skin.CompiledBones = new List <CompiledBone>(); skin.HasSkinningInfo = true; skin.CompiledBones = BoneList; }
// TODO: Implement this. public override void Read(BinaryReader b) { base.Read(b); NumberOfMorphTargets = b.ReadUInt32(); if (NumberOfMorphTargets > 0) { MorphTargetVertices = new MeshMorphTargetVertex[NumberOfMorphTargets]; for (int i = 0; i < NumberOfMorphTargets; i++) { MorphTargetVertices[i] = MeshMorphTargetVertex.Read(b); } } SkinningInfo skin = GetSkinningInfo(); //skin.MorphTargets = MorphTargetVertices.ToList(); }
public override void Read(BinaryReader b) { base.Read(b); NumIntFaces = this.DataSize / 6; // This is an array of TFaces, which are 3 uint16. Faces = new TFace[NumIntFaces]; for (int i = 0; i < NumIntFaces; i++) { Faces[i].i0 = b.ReadUInt16(); Faces[i].i1 = b.ReadUInt16(); Faces[i].i2 = b.ReadUInt16(); } SkinningInfo skin = GetSkinningInfo(); skin.IntFaces = Faces.ToList(); }
public override void Read(BinaryReader b) { base.Read(b); NumExtVertices = this.DataSize / sizeof(UInt16); Source = new UInt16[NumExtVertices]; for (int i = 0; i < NumExtVertices; i++) { Source[i] = b.ReadUInt16(); } // Add to SkinningInfo SkinningInfo skin = GetSkinningInfo(); skin.Ext2IntMap = Source.ToList(); skin.HasIntToExtMapping = true; }
public override void Read(BinaryReader b) { base.Read(b); SkinningInfo skin = GetSkinningInfo(); this.NumPhysicalProxies = b.ReadUInt32(); // number of Bones in this chunk. //Utils.Log(LogLevelEnum.Debug, "Number of bones (physical proxies): {0}", NumPhysicalProxies); this.PhysicalProxies = new PhysicalProxy[NumPhysicalProxies]; // now have an array of physical proxies for (Int32 i = 0; i < NumPhysicalProxies; i++) { // Start populating the physical proxy array. This is the Header. this.PhysicalProxies[i].ID = b.ReadUInt32(); this.PhysicalProxies[i].NumVertices = b.ReadUInt32(); this.PhysicalProxies[i].NumIndices = b.ReadUInt32(); this.PhysicalProxies[i].Material = b.ReadUInt32(); // Probably a fill of some sort? this.PhysicalProxies[i].Vertices = new Vector3[PhysicalProxies[i].NumVertices]; this.PhysicalProxies[i].Indices = new UInt16[PhysicalProxies[i].NumIndices]; for (Int32 j = 0; j < PhysicalProxies[i].NumVertices; j++) { PhysicalProxies[i].Vertices[j].x = b.ReadSingle(); PhysicalProxies[i].Vertices[j].y = b.ReadSingle(); PhysicalProxies[i].Vertices[j].z = b.ReadSingle(); } // Read the indices for (Int32 j = 0; j < PhysicalProxies[i].NumIndices; j++) { PhysicalProxies[i].Indices[j] = b.ReadUInt16(); //Utils.Log(LogLevelEnum.Debug, "Indices: {0}", HitBoxes[i].Indices[j]); } // Utils.Log(LogLevelEnum.Debug, "Index 0 is {0}, Index 9 is {1}", HitBoxes[i].Indices[0],HitBoxes[i].Indices[9]); // read the crap at the end so we can move on. for (Int32 j = 0; j < PhysicalProxies[i].Material; j++) { b.ReadByte(); } } skin.PhysicalBoneMeshes = PhysicalProxies.ToList(); }
// Spriggan models, not sure which game. SC, MWO uses 0800 public override void Read(BinaryReader b) { base.Read(b); this.Flags2 = b.ReadUInt32(); // another filler uint tmpdataStreamType = b.ReadUInt32(); this.DataStreamType = (DataStreamTypeEnum)Enum.ToObject(typeof(DataStreamTypeEnum), tmpdataStreamType); this.SkipBytes(b, 4); this.NumElements = b.ReadUInt32(); // number of elements in this chunk this.BytesPerElement = b.ReadUInt32(); // bytes per element //if (this.NumElements == 0) // For vertices, number of elements is frequently 0. //{ //} this.SkipBytes(b, 8); // Now do loops to read for each of the different Data Stream Types. If vertices, need to populate Vector3s for example. switch (this.DataStreamType) { #region case DataStreamTypeEnum.VERTICES: case DataStreamTypeEnum.VERTICES: // Ref is 0x00000000 this.Vertices = new Vector3[this.NumElements]; for (Int32 i = 0; i < this.NumElements; i++) { this.Vertices[i].x = b.ReadSingle(); this.Vertices[i].y = b.ReadSingle(); this.Vertices[i].z = b.ReadSingle(); } break; #endregion #region case DataStreamTypeEnum.INDICES: case DataStreamTypeEnum.INDICES: // Ref is this.Indices = new UInt32[NumElements]; if (this.BytesPerElement == 2) { for (Int32 i = 0; i < this.NumElements; i++) { this.Indices[i] = (UInt32)b.ReadUInt16(); //Console.WriteLine("Indices {0}: {1}", i, this.Indices[i]); } } if (this.BytesPerElement == 4) { for (Int32 i = 0; i < this.NumElements; i++) { this.Indices[i] = b.ReadUInt32(); } } //Utils.Log(LogLevelEnum.Debug, "Offset is {0:X}", b.BaseStream.Position); break; #endregion #region case DataStreamTypeEnum.NORMALS: case DataStreamTypeEnum.NORMALS: this.Normals = new Vector3[this.NumElements]; for (Int32 i = 0; i < NumElements; i++) { this.Normals[i].x = b.ReadSingle(); this.Normals[i].y = b.ReadSingle(); this.Normals[i].z = b.ReadSingle(); } //Utils.Log(LogLevelEnum.Debug, "Offset is {0:X}", b.BaseStream.Position); break; #endregion #region case DataStreamTypeEnum.UVS: case DataStreamTypeEnum.UVS: this.UVs = new UV[this.NumElements]; for (Int32 i = 0; i < this.NumElements; i++) { this.UVs[i].U = b.ReadSingle(); this.UVs[i].V = b.ReadSingle(); } //Utils.Log(LogLevelEnum.Debug, "Offset is {0:X}", b.BaseStream.Position); break; #endregion #region case DataStreamTypeEnum.TANGENTS: case DataStreamTypeEnum.TANGENTS: this.Tangents = new Tangent[this.NumElements, 2]; this.Normals = new Vector3[this.NumElements]; for (Int32 i = 0; i < this.NumElements; i++) { switch (this.BytesPerElement) { case 0x10: // These have to be divided by 32767 to be used properly (value between 0 and 1) this.Tangents[i, 0].x = b.ReadInt16(); this.Tangents[i, 0].y = b.ReadInt16(); this.Tangents[i, 0].z = b.ReadInt16(); this.Tangents[i, 0].w = b.ReadInt16(); this.Tangents[i, 1].x = b.ReadInt16(); this.Tangents[i, 1].y = b.ReadInt16(); this.Tangents[i, 1].z = b.ReadInt16(); this.Tangents[i, 1].w = b.ReadInt16(); break; case 0x08: // These have to be divided by 127 to be used properly (value between 0 and 1) // Tangent this.Tangents[i, 0].w = b.ReadSByte() / 127.0; this.Tangents[i, 0].x = b.ReadSByte() / 127.0; this.Tangents[i, 0].y = b.ReadSByte() / 127.0; this.Tangents[i, 0].z = b.ReadSByte() / 127.0; // Binormal this.Tangents[i, 1].w = b.ReadSByte() / 127.0; this.Tangents[i, 1].x = b.ReadSByte() / 127.0; this.Tangents[i, 1].y = b.ReadSByte() / 127.0; this.Tangents[i, 1].z = b.ReadSByte() / 127.0; // Calculate the normal based on the cross product of the tangents. //this.Normals[i].x = (Tangents[i,0].y * Tangents[i,1].z - Tangents[i,0].z * Tangents[i,1].y); //this.Normals[i].y = 0 - (Tangents[i,0].x * Tangents[i,1].z - Tangents[i,0].z * Tangents[i,1].x); //this.Normals[i].z = (Tangents[i,0].x * Tangents[i,1].y - Tangents[i,0].y * Tangents[i,1].x); //Console.WriteLine("Tangent: {0:F6} {1:F6} {2:F6}", Tangents[i,0].x, Tangents[i, 0].y, Tangents[i, 0].z); //Console.WriteLine("Binormal: {0:F6} {1:F6} {2:F6}", Tangents[i, 1].x, Tangents[i, 1].y, Tangents[i, 1].z); //Console.WriteLine("Normal: {0:F6} {1:F6} {2:F6}", Normals[i].x, Normals[i].y, Normals[i].z); break; default: throw new Exception("Need to add new Tangent Size"); } } // Utils.Log(LogLevelEnum.Debug, "Offset is {0:X}", b.BaseStream.Position); break; #endregion #region case DataStreamTypeEnum.COLORS: case DataStreamTypeEnum.COLORS: switch (this.BytesPerElement) { case 3: this.RGBColors = new IRGB[this.NumElements]; for (Int32 i = 0; i < NumElements; i++) { this.RGBColors[i].r = b.ReadByte(); this.RGBColors[i].g = b.ReadByte(); this.RGBColors[i].b = b.ReadByte(); } break; case 4: this.RGBAColors = new IRGBA[this.NumElements]; for (Int32 i = 0; i < this.NumElements; i++) { this.RGBAColors[i].r = b.ReadByte(); this.RGBAColors[i].g = b.ReadByte(); this.RGBAColors[i].b = b.ReadByte(); this.RGBAColors[i].a = b.ReadByte(); } break; default: Utils.Log("Unknown Color Depth"); for (Int32 i = 0; i < this.NumElements; i++) { this.SkipBytes(b, this.BytesPerElement); } break; } break; #endregion #region case DataStreamTypeEnum.VERTSUVS: case DataStreamTypeEnum.VERTSUVS: // 3 half floats for verts, 3 half floats for normals, 2 half floats for UVs // Utils.Log(LogLevelEnum.Debug, "In VertsUVs..."); this.Vertices = new Vector3[this.NumElements]; this.Normals = new Vector3[this.NumElements]; this.RGBColors = new IRGB[this.NumElements]; this.UVs = new UV[this.NumElements]; switch (this.BytesPerElement) // new Star Citizen files { case 20: // Dymek wrote this. Used in 2.6 skin files. 3 floats for vertex position, 4 bytes for normals, 2 halfs for UVs. Normals are calculated from Tangents for (Int32 i = 0; i < this.NumElements; i++) { this.Vertices[i].x = b.ReadSingle(); this.Vertices[i].y = b.ReadSingle(); this.Vertices[i].z = b.ReadSingle(); // For some reason, skins are an extra 1 meter in the z direction. // Normals are stored in a signed byte, prob div by 127. this.Normals[i].x = (float)b.ReadSByte() / 127; this.Normals[i].y = (float)b.ReadSByte() / 127; this.Normals[i].z = (float)b.ReadSByte() / 127; b.ReadSByte(); // Should be FF. Half uvu = new Half(); uvu.bits = b.ReadUInt16(); this.UVs[i].U = uvu.ToSingle(); Half uvv = new Half(); uvv.bits = b.ReadUInt16(); this.UVs[i].V = uvv.ToSingle(); //bver = b.ReadUInt16(); //ver = Byte4HexToFloat(bver.ToString("X8")); //this.UVs[i].U = ver; //bver = b.ReadUInt16(); //ver = Byte4HexToFloat(bver.ToString("X8")); //this.UVs[i].V = ver; } break; case 16: // Dymek updated this. //Console.WriteLine("method: (5), 3 half floats for verts, 3 colors, 2 half floats for UVs"); for (Int32 i = 0; i < this.NumElements; i++) { ushort bver = 0; float ver = 0; bver = b.ReadUInt16(); ver = Byte2HexIntFracToFloat2(bver.ToString("X4")) / 127; this.Vertices[i].x = ver; bver = b.ReadUInt16(); ver = Byte2HexIntFracToFloat2(bver.ToString("X4")) / 127; this.Vertices[i].y = ver; bver = b.ReadUInt16(); ver = Byte2HexIntFracToFloat2(bver.ToString("X4")) / 127; this.Vertices[i].z = ver; bver = b.ReadUInt16(); ver = Byte2HexIntFracToFloat2(bver.ToString("X4")) / 127; this.Vertices[i].w = ver; // Almost always 1 // Next structure is Colors, not normals. For 16 byte elements, normals are calculated from Tangent data. //this.RGBColors[i].r = b.ReadByte(); //this.RGBColors[i].g = b.ReadByte(); //this.RGBColors[i].b = b.ReadByte(); //b.ReadByte(); // additional byte. //this.Normals[i].x = (b.ReadByte() - 128.0f) / 127.5f; //this.Normals[i].y = (b.ReadByte() - 128.0f) / 127.5f; //this.Normals[i].z = (b.ReadByte() - 128.0f) / 127.5f; //b.ReadByte(); // additional byte. // Read a Quat, convert it to vector3 Vector4 quat = new Vector4(); quat.x = (b.ReadByte() - 128.0f) / 127.5f; quat.y = (b.ReadByte() - 128.0f) / 127.5f; quat.z = (b.ReadByte() - 128.0f) / 127.5f; quat.w = (b.ReadByte() - 128.0f) / 127.5f; this.Normals[i].x = (2 * (quat.x * quat.z + quat.y * quat.w)); this.Normals[i].y = (2 * (quat.y * quat.z - quat.x * quat.w)); this.Normals[i].z = (2 * (quat.z * quat.z + quat.w * quat.w)) - 1; // UVs ABSOLUTELY should use the Half structures. Half uvu = new Half(); uvu.bits = b.ReadUInt16(); this.UVs[i].U = uvu.ToSingle(); Half uvv = new Half(); uvv.bits = b.ReadUInt16(); this.UVs[i].V = uvv.ToSingle(); #region Legacy version using Halfs //Half xshort = new Half(); //xshort.bits = b.ReadUInt16(); //this.Vertices[i].x = xshort.ToSingle(); //Half yshort = new Half(); //yshort.bits = b.ReadUInt16(); //this.Vertices[i].y = yshort.ToSingle(); //Half zshort = new Half(); //zshort.bits = b.ReadUInt16(); //this.Vertices[i].z = zshort.ToSingle(); //Half xnorm = new Half(); //xnorm.bits = b.ReadUInt16(); //this.Normals[i].x = xnorm.ToSingle(); //Half ynorm = new Half(); //ynorm.bits = b.ReadUInt16(); //this.Normals[i].y = ynorm.ToSingle(); //Half znorm = new Half(); //znorm.bits = b.ReadUInt16(); //this.Normals[i].z = znorm.ToSingle(); //Half uvu = new Half(); //uvu.bits = b.ReadUInt16(); //this.UVs[i].U = uvu.ToSingle(); //Half uvv = new Half(); //uvv.bits = b.ReadUInt16(); //this.UVs[i].V = uvv.ToSingle(); #endregion } break; default: Utils.Log("Unknown VertUV structure"); for (Int32 i = 0; i < this.NumElements; i++) { this.SkipBytes(b, this.BytesPerElement); } break; } break; #endregion #region case DataStreamTypeEnum.BONEMAP: case DataStreamTypeEnum.BONEMAP: SkinningInfo skin = GetSkinningInfo(); skin.HasBoneMapDatastream = true; skin.BoneMapping = new List <MeshBoneMapping>(); // Bones should have 4 bone IDs (index) and 4 weights. for (int i = 0; i < NumElements; i++) { MeshBoneMapping tmpMap = new MeshBoneMapping(); switch (this.BytesPerElement) { case 8: tmpMap.BoneIndex = new int[4]; tmpMap.Weight = new int[4]; for (int j = 0; j < 4; j++) // read the 4 bone indexes first { tmpMap.BoneIndex[j] = b.ReadByte(); } for (int j = 0; j < 4; j++) // read the weights. { tmpMap.Weight[j] = b.ReadByte(); } skin.BoneMapping.Add(tmpMap); break; case 12: tmpMap.BoneIndex = new int[4]; tmpMap.Weight = new int[4]; for (int j = 0; j < 4; j++) // read the 4 bone indexes first { tmpMap.BoneIndex[j] = b.ReadUInt16(); } for (int j = 0; j < 4; j++) // read the weights. { tmpMap.Weight[j] = b.ReadByte(); } skin.BoneMapping.Add(tmpMap); break; default: Utils.Log("Unknown BoneMapping structure"); break; } } break; #endregion #region DataStreamTypeEnum.Unknown1 case DataStreamTypeEnum.UNKNOWN1: this.Tangents = new Tangent[this.NumElements, 2]; this.Normals = new Vector3[this.NumElements]; for (Int32 i = 0; i < NumElements; i++) { this.Tangents[i, 0].w = b.ReadSByte() / 127.0; this.Tangents[i, 0].x = b.ReadSByte() / 127.0; this.Tangents[i, 0].y = b.ReadSByte() / 127.0; this.Tangents[i, 0].z = b.ReadSByte() / 127.0; // Binormal this.Tangents[i, 1].w = b.ReadSByte() / 127.0; this.Tangents[i, 1].x = b.ReadSByte() / 127.0; this.Tangents[i, 1].y = b.ReadSByte() / 127.0; this.Tangents[i, 1].z = b.ReadSByte() / 127.0; // Calculate the normal based on the cross product of the tangents. this.Normals[i].x = (Tangents[i, 0].y * Tangents[i, 1].z - Tangents[i, 0].z * Tangents[i, 1].y); this.Normals[i].y = 0 - (Tangents[i, 0].x * Tangents[i, 1].z - Tangents[i, 0].z * Tangents[i, 1].x); this.Normals[i].z = (Tangents[i, 0].x * Tangents[i, 1].y - Tangents[i, 0].y * Tangents[i, 1].x); } break; #endregion // Prey normals? #region default: default: Utils.Log(LogLevelEnum.Debug, "***** Unknown DataStream Type *****"); break; #endregion } }
public override void Read(BinaryReader b) { base.Read(b); this.Flags2 = Utils.SwapUIntEndian(b.ReadUInt32()); // another filler uint tmpdataStreamType = Utils.SwapUIntEndian(b.ReadUInt32()); this.DataStreamType = (DataStreamTypeEnum)Enum.ToObject(typeof(DataStreamTypeEnum), tmpdataStreamType); this.NumElements = Utils.SwapUIntEndian(b.ReadUInt32()); // number of elements in this chunk this.BytesPerElement = Utils.SwapUIntEndian(b.ReadUInt32()); this.SkipBytes(b, 8); // Now do loops to read for each of the different Data Stream Types. If vertices, need to populate Vector3s for example. switch (this.DataStreamType) { #region case DataStreamTypeEnum.VERTICES: case DataStreamTypeEnum.VERTICES: // Ref is 0x00000000 this.Vertices = new Vector3[this.NumElements]; switch (BytesPerElement) { case 12: for (Int32 i = 0; i < this.NumElements; i++) { this.Vertices[i].x = Utils.SwapSingleEndian(b.ReadSingle()); this.Vertices[i].y = Utils.SwapSingleEndian(b.ReadSingle()); this.Vertices[i].z = Utils.SwapSingleEndian(b.ReadSingle()); } break; } break; #endregion #region case DataStreamTypeEnum.INDICES: case DataStreamTypeEnum.INDICES: // Ref is this.Indices = new UInt32[NumElements]; if (this.BytesPerElement == 2) { for (Int32 i = 0; i < this.NumElements; i++) { this.Indices[i] = (UInt32)Utils.SwapUInt16Endian(b.ReadUInt16()); } } if (this.BytesPerElement == 4) { for (Int32 i = 0; i < this.NumElements; i++) { this.Indices[i] = Utils.SwapUIntEndian(b.ReadUInt32()); } } break; #endregion #region case DataStreamTypeEnum.NORMALS: case DataStreamTypeEnum.NORMALS: this.Normals = new Vector3[this.NumElements]; for (Int32 i = 0; i < NumElements; i++) { this.Normals[i].x = Utils.SwapSingleEndian(b.ReadSingle()); this.Normals[i].y = Utils.SwapSingleEndian(b.ReadSingle()); this.Normals[i].z = Utils.SwapSingleEndian(b.ReadSingle()); } //Utils.Log(LogLevelEnum.Debug, "Offset is {0:X}", b.BaseStream.Position); break; #endregion #region case DataStreamTypeEnum.UVS: case DataStreamTypeEnum.UVS: this.UVs = new UV[this.NumElements]; for (Int32 i = 0; i < this.NumElements; i++) { this.UVs[i].U = Utils.SwapSingleEndian(b.ReadSingle()); this.UVs[i].V = Utils.SwapSingleEndian(b.ReadSingle()); } break; #endregion #region case DataStreamTypeEnum.TANGENTS: case DataStreamTypeEnum.TANGENTS: this.Tangents = new Tangent[this.NumElements, 2]; this.Normals = new Vector3[this.NumElements]; for (Int32 i = 0; i < this.NumElements; i++) { switch (this.BytesPerElement) { case 0x10: // These have to be divided by 32767 to be used properly (value between 0 and 1) this.Tangents[i, 0].x = Utils.SwapIntEndian(b.ReadInt16()); this.Tangents[i, 0].y = Utils.SwapIntEndian(b.ReadInt16()); this.Tangents[i, 0].z = Utils.SwapIntEndian(b.ReadInt16()); this.Tangents[i, 0].w = Utils.SwapIntEndian(b.ReadInt16()); this.Tangents[i, 1].x = Utils.SwapIntEndian(b.ReadInt16()); this.Tangents[i, 1].y = Utils.SwapIntEndian(b.ReadInt16()); this.Tangents[i, 1].z = Utils.SwapIntEndian(b.ReadInt16()); this.Tangents[i, 1].w = Utils.SwapIntEndian(b.ReadInt16()); break; case 0x08: // These have to be divided by 127 to be used properly (value between 0 and 1) // Tangent this.Tangents[i, 0].w = b.ReadSByte() / 127.0; this.Tangents[i, 0].x = b.ReadSByte() / 127.0; this.Tangents[i, 0].y = b.ReadSByte() / 127.0; this.Tangents[i, 0].z = b.ReadSByte() / 127.0; // Binormal this.Tangents[i, 1].w = b.ReadSByte() / 127.0; this.Tangents[i, 1].x = b.ReadSByte() / 127.0; this.Tangents[i, 1].y = b.ReadSByte() / 127.0; this.Tangents[i, 1].z = b.ReadSByte() / 127.0; break; default: throw new Exception("Need to add new Tangent Size"); } } break; #endregion #region case DataStreamTypeEnum.COLORS: case DataStreamTypeEnum.COLORS: switch (this.BytesPerElement) { case 3: this.RGBColors = new IRGB[this.NumElements]; for (Int32 i = 0; i < NumElements; i++) { this.RGBColors[i].r = b.ReadByte(); this.RGBColors[i].g = b.ReadByte(); this.RGBColors[i].b = b.ReadByte(); } break; case 4: this.RGBAColors = new IRGBA[this.NumElements]; for (Int32 i = 0; i < this.NumElements; i++) { this.RGBAColors[i].r = b.ReadByte(); this.RGBAColors[i].g = b.ReadByte(); this.RGBAColors[i].b = b.ReadByte(); this.RGBAColors[i].a = b.ReadByte(); } break; default: Utils.Log("Unknown Color Depth"); for (Int32 i = 0; i < this.NumElements; i++) { this.SkipBytes(b, this.BytesPerElement); } break; } break; #endregion #region case DataStreamTypeEnum.BONEMAP: case DataStreamTypeEnum.BONEMAP: SkinningInfo skin = GetSkinningInfo(); skin.HasBoneMapDatastream = true; skin.BoneMapping = new List <MeshBoneMapping>(); // Bones should have 4 bone IDs (index) and 4 weights. for (int i = 0; i < NumElements; i++) { MeshBoneMapping tmpMap = new MeshBoneMapping(); switch (this.BytesPerElement) { case 8: tmpMap.BoneIndex = new int[4]; tmpMap.Weight = new int[4]; for (int j = 0; j < 4; j++) // read the 4 bone indexes first { tmpMap.BoneIndex[j] = b.ReadByte(); } for (int j = 0; j < 4; j++) // read the weights. { tmpMap.Weight[j] = b.ReadByte(); } skin.BoneMapping.Add(tmpMap); break; case 12: tmpMap.BoneIndex = new int[4]; tmpMap.Weight = new int[4]; for (int j = 0; j < 4; j++) // read the 4 bone indexes first { tmpMap.BoneIndex[j] = Utils.SwapUInt16Endian(b.ReadUInt16()); } for (int j = 0; j < 4; j++) // read the weights. { tmpMap.Weight[j] = b.ReadByte(); } skin.BoneMapping.Add(tmpMap); break; default: Utils.Log("Unknown BoneMapping structure"); break; } } break; #endregion #region DataStreamTypeEnum.Unknown1 case DataStreamTypeEnum.UNKNOWN1: this.Tangents = new Tangent[this.NumElements, 2]; this.Normals = new Vector3[this.NumElements]; for (Int32 i = 0; i < NumElements; i++) { this.Tangents[i, 0].w = b.ReadSByte() / 127.0; this.Tangents[i, 0].x = b.ReadSByte() / 127.0; this.Tangents[i, 0].y = b.ReadSByte() / 127.0; this.Tangents[i, 0].z = b.ReadSByte() / 127.0; // Binormal this.Tangents[i, 1].w = b.ReadSByte() / 127.0; this.Tangents[i, 1].x = b.ReadSByte() / 127.0; this.Tangents[i, 1].y = b.ReadSByte() / 127.0; this.Tangents[i, 1].z = b.ReadSByte() / 127.0; // Calculate the normal based on the cross product of the tangents. this.Normals[i].x = (Tangents[i, 0].y * Tangents[i, 1].z - Tangents[i, 0].z * Tangents[i, 1].y); this.Normals[i].y = 0 - (Tangents[i, 0].x * Tangents[i, 1].z - Tangents[i, 0].z * Tangents[i, 1].x); this.Normals[i].z = (Tangents[i, 0].x * Tangents[i, 1].y - Tangents[i, 0].y * Tangents[i, 1].x); } break; #endregion // Prey normals? #region default: default: Utils.Log(LogLevelEnum.Debug, "***** Unknown DataStream Type *****"); break; #endregion } }