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
        }
Exemple #3
0
        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();
 }
Exemple #5
0
        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;
        }
Exemple #7
0
        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
            }
        }