Пример #1
0
        protected bool looping = true;               // When true, ms3d file should loop the animation
        #endregion

        #region LoadData
        /// Loads the MS3D file
        public virtual void LoadModelData(string filename)
        {
            model_data = new Model();
            looping    = true;
            System.IO.FileInfo fInfo = new System.IO.FileInfo(filename);
            if (!fInfo.Exists)
            {
                // Display an error message and don't load anything if no file was found
                MessageBox.Show("Unable to find the file: " + filename, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            fileFolder = fInfo.DirectoryName;

            System.IO.Stream fs = new System.IO.FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);

            long totalLength = fs.Length;

            // Read the header data and store it in our m_Header member variable
            byte[] b = new byte[Marshal.SizeOf(typeof(MS3DHeader))];

            fs.Read(b, 0, b.Length);
            MS3DHeader m_Header = (MS3DHeader)RawDeserializeEx(b, typeof(MS3DHeader));
            string     id       = new string(m_Header.ID);

            // Only Milkshape3D Version 1.3 and 1.4 is supported.

            #region Vertices
            b = new byte[Marshal.SizeOf(typeof(short))];
            fs.Read(b, 0, Marshal.SizeOf(typeof(short)));
            short nVertices = (short)RawDeserializeEx(b, typeof(short));
            model_data.Vertices    = new Vertex[nVertices];
            model_data.numVertices = nVertices;

            for (int i = 0; i < nVertices; i++)
            {
                b = new byte[Marshal.SizeOf(typeof(MS3DVertex))];
                fs.Read(b, 0, b.Length);
                MS3DVertex Vertex = (MS3DVertex)RawDeserializeEx(b, typeof(MS3DVertex));
                model_data.Vertices[i]          = new Vertex();
                model_data.Vertices[i].boneID   = Vertex.boneID;
                model_data.Vertices[i].location = Vertex.vertex;
            }
            #endregion

            #region Triangles
            b = new byte[Marshal.SizeOf(typeof(short))];
            fs.Read(b, 0, Marshal.SizeOf(typeof(short)));
            short nTriangles = (short)RawDeserializeEx(b, typeof(short));
            model_data.Triangles    = new Triangle[nTriangles];
            model_data.numTriangles = nTriangles;

            for (int i = 0; i < nTriangles; i++)
            {
                int[] vertexIndices = new int[3] {
                    0, 0, 0
                };
                float[] t = new float[3] {
                    0, 0, 0
                };

                b = new byte[Marshal.SizeOf(typeof(MS3DTriangle))];
                fs.Read(b, 0, b.Length);
                MS3DTriangle pTriangle = (MS3DTriangle)RawDeserializeEx(b, typeof(MS3DTriangle));

                model_data.Triangles[i] = new Triangle();

                vertexIndices[0] = (int)pTriangle.vertexIndices[0];
                vertexIndices[1] = (int)pTriangle.vertexIndices[1];
                vertexIndices[2] = (int)pTriangle.vertexIndices[2];
                t[0]             = 1.0f - pTriangle.t[0];
                t[1]             = 1.0f - pTriangle.t[1];
                t[2]             = 1.0f - pTriangle.t[2];
                model_data.Triangles[i].vertexNormals = pTriangle.vertexNormals;
                model_data.Triangles[i].s             = pTriangle.s;
                model_data.Triangles[i].t             = t;
                model_data.Triangles[i].vertexIndices = vertexIndices;
            }
            #endregion

            #region Groups
            b = new byte[Marshal.SizeOf(typeof(short))];
            fs.Read(b, 0, Marshal.SizeOf(typeof(short)));
            short nGroups = (short)RawDeserializeEx(b, typeof(short));
            model_data.Meshes    = new Mesh[nGroups];
            model_data.numMeshes = nGroups;

            for (int i = 0; i < nGroups; i++)
            {
                b = new byte[Marshal.SizeOf(typeof(byte))];
                fs.Read(b, 0, b.Length); // Flags

                b = new byte[32];
                fs.Read(b, 0, b.Length); // name
                string name = System.Text.Encoding.UTF8.GetString(b);

                b = new byte[Marshal.SizeOf(typeof(short))];
                fs.Read(b, 0, b.Length); // number of Triangle Indices
                nTriangles = (short)RawDeserializeEx(b, typeof(short));
                int[] pTriangleIndices = new int[nTriangles];

                for (int j = 0; j < nTriangles; j++)
                {
                    b = new byte[Marshal.SizeOf(typeof(short))];
                    fs.Read(b, 0, b.Length); // read indices value
                    pTriangleIndices[j] = (short)RawDeserializeEx(b, typeof(short));
                }

                b = new byte[Marshal.SizeOf(typeof(char))];
                fs.Read(b, 0, b.Length); // read material index
                char materialIndex = (char)RawDeserializeEx(b, typeof(char));

                model_data.Meshes[i] = new Mesh();
                model_data.Meshes[i].materialIndex   = (int)materialIndex;
                model_data.Meshes[i].numTriangles    = nTriangles;
                model_data.Meshes[i].TriangleIndices = pTriangleIndices;
            }
            #endregion

            #region Materials
            b = new byte[Marshal.SizeOf(typeof(short))];
            fs.Read(b, 0, Marshal.SizeOf(typeof(short)));
            short nMaterials = (short)RawDeserializeEx(b, typeof(short));
            model_data.Materials    = new Material[nMaterials];
            model_data.numMaterials = nMaterials;

            for (int i = 0; i < nMaterials; i++)
            {
                b = new byte[Marshal.SizeOf(typeof(MS3DMaterial))];
                fs.Read(b, 0, b.Length); // read material
                MS3DMaterial pMaterial = (MS3DMaterial)RawDeserializeEx(b, typeof(MS3DMaterial));
                model_data.Materials[i]                 = new Material();
                model_data.Materials[i].name            = pMaterial.name;
                model_data.Materials[i].ambient         = pMaterial.ambient;
                model_data.Materials[i].diffuse         = pMaterial.diffuse;
                model_data.Materials[i].specular        = pMaterial.specular;
                model_data.Materials[i].emissive        = pMaterial.emissive;
                model_data.Materials[i].shininess       = pMaterial.shininess;
                model_data.Materials[i].transparency    = pMaterial.transparency;
                model_data.Materials[i].mode            = pMaterial.mode;
                model_data.Materials[i].TextureFilename = CropNull(new string(pMaterial.texture));
                model_data.Materials[i].alpha           = pMaterial.alphamap;

                // set alpha
                model_data.Materials[i].ambient[3]  = model_data.Materials[i].transparency;
                model_data.Materials[i].diffuse[3]  = model_data.Materials[i].transparency;
                model_data.Materials[i].specular[3] = model_data.Materials[i].transparency;
                model_data.Materials[i].emissive[3] = model_data.Materials[i].transparency;
            }
            #endregion

            ReloadTextures();

            #region Animation
            b = new byte[Marshal.SizeOf(typeof(float))];
            fs.Read(b, 0, b.Length);
            float animFPS = (float)RawDeserializeEx(b, typeof(float));
            if (animFPS < 1.0f)
            {
                animFPS = 1.0f;
            }

            // Skip the currentTime value
            fs.Read(b, 0, b.Length);

            b = new byte[Marshal.SizeOf(typeof(int))];
            fs.Read(b, 0, b.Length);
            int totalFrames = (int)RawDeserializeEx(b, typeof(int));

            model_data.totalTime = totalFrames * 1000f / animFPS;
            #endregion

            #region Joints
            b = new byte[Marshal.SizeOf(typeof(short))];
            fs.Read(b, 0, b.Length);
            model_data.numJoints = (short)RawDeserializeEx(b, typeof(short));
            model_data.Joints    = new Joint[model_data.numJoints];

            JointNameListRec[] pNameList = new JointNameListRec[model_data.numJoints];

            #region Building JointNameListRec
            long tempPos = fs.Position;

            for (int i = 0; i < model_data.numJoints; i++)
            {
                b = new byte[Marshal.SizeOf(typeof(MS3DJoint))];
                fs.Read(b, 0, b.Length);
                MS3DJoint pJoint = (MS3DJoint)RawDeserializeEx(b, typeof(MS3DJoint));

                pNameList[i]            = new JointNameListRec();
                pNameList[i].jointIndex = i;
                pNameList[i].Name       = CropNull(new string(pJoint.name));

                // skip forward for the next joint
                b = new byte[Marshal.SizeOf(typeof(MS3DKeyframe)) * (pJoint.numRotationKeyframes + pJoint.numTranslationKeyframes)];
                fs.Read(b, 0, b.Length);
            }

            fs.Seek(tempPos, System.IO.SeekOrigin.Begin);
            #endregion

            #region Load Joints
            for (int i = 0; i < model_data.numJoints; i++)
            {
                b = new byte[Marshal.SizeOf(typeof(MS3DJoint))];
                fs.Read(b, 0, b.Length);
                MS3DJoint pJoint = (MS3DJoint)RawDeserializeEx(b, typeof(MS3DJoint));

                int    parentIndex = -1;
                string parentName  = CropNull(new string(pJoint.parentName));
                if (parentName.Length > 0)
                {
                    for (int j = 0; j < model_data.numJoints; j++)
                    {
                        if (pNameList[j].Name == parentName)
                        {
                            parentIndex = pNameList[j].jointIndex;
                            break;
                        }
                    }

                    if (parentIndex == -1)
                    {
                        return;
                    }
                }

                model_data.Joints[i] = new Joint();
                model_data.Joints[i].localRotation           = pJoint.rotation;
                model_data.Joints[i].localTranslation        = pJoint.translation;
                model_data.Joints[i].parent                  = parentIndex;
                model_data.Joints[i].numRotationKeyframes    = pJoint.numRotationKeyframes;
                model_data.Joints[i].RotationKeyframes       = new Keyframe[pJoint.numRotationKeyframes];
                model_data.Joints[i].numTranslationKeyframes = pJoint.numTranslationKeyframes;
                model_data.Joints[i].TranslationKeyframes    = new Keyframe[pJoint.numTranslationKeyframes];

                model_data.Joints[i].mat_relative = new Matrix();
                model_data.Joints[i].mat_final    = new Matrix();
                model_data.Joints[i].mat_absolute = new Matrix();

                // the frame time is in seconds, so multiply it by the animation fps, to get the frames
                // rotation channel
                for (int j = 0; j < pJoint.numRotationKeyframes; j++)
                {
                    b = new byte[Marshal.SizeOf(typeof(MS3DKeyframe))];
                    fs.Read(b, 0, b.Length);
                    MS3DKeyframe pKeyframe = (MS3DKeyframe)RawDeserializeEx(b, typeof(MS3DKeyframe));

                    SetJointKeyframe(i, j, pKeyframe.time * 1000.0f, ref pKeyframe.parameter, true);
                }

                // translation channel
                for (int j = 0; j < pJoint.numTranslationKeyframes; j++)
                {
                    b = new byte[Marshal.SizeOf(typeof(MS3DKeyframe))];
                    fs.Read(b, 0, b.Length);
                    MS3DKeyframe pKeyframe = (MS3DKeyframe)RawDeserializeEx(b, typeof(MS3DKeyframe));

                    SetJointKeyframe(i, j, pKeyframe.time * 1000.0f, ref pKeyframe.parameter, false);
                }
            }
            #endregion

            pNameList = null;
            #endregion

            #region Comments
            if (fs.Position < totalLength)
            {
                int subVersion = 0;
                b = new byte[Marshal.SizeOf(typeof(int))];
                fs.Read(b, 0, b.Length);
                subVersion = (int)RawDeserializeEx(b, typeof(int));

                if (subVersion == 1)
                {
                    int  numComments = 0;
                    uint commentSize = 0;

                    #region Group Comments
                    b = new byte[Marshal.SizeOf(typeof(int))];
                    fs.Read(b, 0, b.Length);
                    numComments = (int)RawDeserializeEx(b, typeof(int));

                    for (int i = 0; i < numComments; i++)
                    {
                        int    index;
                        string comment = "";

                        fs.Read(b, 0, b.Length);
                        index = (int)RawDeserializeEx(b, typeof(int));

                        b = new byte[Marshal.SizeOf(typeof(uint))];
                        fs.Read(b, 0, b.Length);
                        commentSize = (uint)RawDeserializeEx(b, typeof(uint));

                        if (commentSize > 0)
                        {
                            b = new byte[Marshal.SizeOf(sizeof(char) * commentSize)];
                            fs.Read(b, 0, b.Length);
                            comment = System.Text.Encoding.ASCII.GetString(b);
                        }
                        if (index >= 0 && index < model_data.numMeshes)
                        {
                            model_data.Meshes[index].comment = comment;
                        }
                    }
                    #endregion

                    #region Material Comments
                    b = new byte[Marshal.SizeOf(typeof(int))];
                    fs.Read(b, 0, b.Length);
                    numComments = (int)RawDeserializeEx(b, typeof(int));

                    for (int i = 0; i < numComments; i++)
                    {
                        int    index;
                        string comment = "";

                        fs.Read(b, 0, b.Length);
                        index = (int)RawDeserializeEx(b, typeof(int));

                        b = new byte[Marshal.SizeOf(typeof(uint))];
                        fs.Read(b, 0, b.Length);
                        commentSize = (uint)RawDeserializeEx(b, typeof(uint));

                        if (commentSize > 0)
                        {
                            b = new byte[Marshal.SizeOf(sizeof(char) * commentSize)];
                            fs.Read(b, 0, b.Length);
                            comment = System.Text.Encoding.ASCII.GetString(b);
                        }
                        if (index >= 0 && index < model_data.numMaterials)
                        {
                            model_data.Materials[index].comment = comment;
                        }
                    }
                    #endregion

                    #region Joint Comments
                    b = new byte[Marshal.SizeOf(typeof(int))];
                    fs.Read(b, 0, b.Length);
                    numComments = (int)RawDeserializeEx(b, typeof(int));

                    for (int i = 0; i < numComments; i++)
                    {
                        int    index;
                        string comment = "";

                        fs.Read(b, 0, b.Length);
                        index = (int)RawDeserializeEx(b, typeof(int));

                        b = new byte[Marshal.SizeOf(typeof(uint))];
                        fs.Read(b, 0, b.Length);
                        commentSize = (uint)RawDeserializeEx(b, typeof(uint));

                        if (commentSize > 0)
                        {
                            b = new byte[Marshal.SizeOf(sizeof(char) * commentSize)];
                            fs.Read(b, 0, b.Length);
                            comment = System.Text.Encoding.ASCII.GetString(b);
                        }
                        if (index >= 0 && index < model_data.numJoints)
                        {
                            model_data.Joints[index].comment = comment;
                        }
                    }
                    #endregion

                    #region Model Comments
                    b = new byte[Marshal.SizeOf(typeof(int))];
                    fs.Read(b, 0, b.Length);
                    numComments = (int)RawDeserializeEx(b, typeof(int));

                    if (numComments == 1)
                    {
                        string comment = "";
                        b = new byte[Marshal.SizeOf(typeof(uint))];
                        fs.Read(b, 0, b.Length);
                        commentSize = (uint)RawDeserializeEx(b, typeof(uint));
                        if (commentSize > 0)
                        {
                            b = new byte[Marshal.SizeOf(sizeof(char) * commentSize)];
                            fs.Read(b, 0, b.Length);
                            comment = System.Text.Encoding.ASCII.GetString(b);
                        }
                        model_data.comment = comment;
                    }
                    #endregion
                }
            }
            #endregion

            #region Vertex Extra
            if (fs.Position < totalLength)
            {
                int subVersion = 0;
                b = new byte[Marshal.SizeOf(typeof(int))];
                fs.Read(b, 0, b.Length);
                subVersion = (int)RawDeserializeEx(b, typeof(int));
                if ((subVersion == 1) || (subVersion == 2))
                {
                    for (int i = 0; i < model_data.numVertices; i++)
                    {
                        model_data.Vertices[i].boneIds = new char[3];
                        b = new byte[Marshal.SizeOf(typeof(char))];
                        fs.Read(b, 0, b.Length);
                        model_data.Vertices[i].boneIds[0] = (char)RawDeserializeEx(b, typeof(char));
                        fs.Read(b, 0, b.Length);
                        model_data.Vertices[i].boneIds[1] = (char)RawDeserializeEx(b, typeof(char));
                        fs.Read(b, 0, b.Length);
                        model_data.Vertices[i].boneIds[2] = (char)RawDeserializeEx(b, typeof(char));

                        model_data.Vertices[i].weights = new char[3];
                        fs.Read(b, 0, b.Length);
                        model_data.Vertices[i].weights[0] = (char)RawDeserializeEx(b, typeof(char));
                        fs.Read(b, 0, b.Length);
                        model_data.Vertices[i].weights[1] = (char)RawDeserializeEx(b, typeof(char));
                        fs.Read(b, 0, b.Length);
                        model_data.Vertices[i].weights[2] = (char)RawDeserializeEx(b, typeof(char));

                        if (subVersion == 2)
                        {
                            b = new byte[Marshal.SizeOf(typeof(uint))];
                            fs.Read(b, 0, b.Length);
                            model_data.Vertices[i].extra = (uint)RawDeserializeEx(b, typeof(uint));
                        }
                    }
                }
            }
            #endregion

            #region Joint Extra
            if (fs.Position < totalLength)
            {
                int subVersion = 0;
                b = new byte[Marshal.SizeOf(typeof(int))];
                fs.Read(b, 0, b.Length);
                subVersion = (int)RawDeserializeEx(b, typeof(int));

                if (subVersion == 1)
                {
                    for (int i = 0; i < model_data.numJoints; i++)
                    {
                        model_data.Joints[i].color = new float[3];
                        b = new byte[Marshal.SizeOf(typeof(float))];
                        fs.Read(b, 0, b.Length);
                        model_data.Joints[i].color[0] = (float)RawDeserializeEx(b, typeof(float));
                        fs.Read(b, 0, b.Length);
                        model_data.Joints[i].color[1] = (float)RawDeserializeEx(b, typeof(float));
                        fs.Read(b, 0, b.Length);
                        model_data.Joints[i].color[2] = (float)RawDeserializeEx(b, typeof(float));
                    }
                }
            }
            #endregion

            #region Model Extra
            if (fs.Position < totalLength)
            {
                int subVersion = 0;
                b = new byte[Marshal.SizeOf(typeof(int))];
                fs.Read(b, 0, b.Length);
                subVersion = (int)RawDeserializeEx(b, typeof(int));

                if (subVersion == 1)
                {
                    b = new byte[Marshal.SizeOf(typeof(float))];
                    fs.Read(b, 0, b.Length);
                    model_data.jointSize = (float)RawDeserializeEx(b, typeof(float));

                    b = new byte[Marshal.SizeOf(typeof(int))];
                    fs.Read(b, 0, b.Length);
                    model_data.transparencyMode = (int)RawDeserializeEx(b, typeof(int));

                    b = new byte[Marshal.SizeOf(typeof(float))];
                    fs.Read(b, 0, b.Length);
                    model_data.alphaRef = (float)RawDeserializeEx(b, typeof(float));
                }
            }
            #endregion

            fs.Close();

            try { SetupJoints(); }
            catch { }
        }
Пример #2
0
        /// Loads the MS3D file
        public virtual void LoadModelData(string filename)
        {
            model_data = new Model();
            looping = true;
            System.IO.FileInfo fInfo = new System.IO.FileInfo(filename);
            if (!fInfo.Exists)
            {
                // Display an error message and don't load anything if no file was found
                MessageBox.Show("Unable to find the file: " + filename, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            fileFolder = fInfo.DirectoryName;

            System.IO.Stream fs = new System.IO.FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);

            long totalLength = fs.Length;

            // Read the header data and store it in our m_Header member variable
            byte[] b = new byte[Marshal.SizeOf(typeof(MS3DHeader))];

            fs.Read(b, 0, b.Length);
            MS3DHeader m_Header = (MS3DHeader)RawDeserializeEx(b, typeof(MS3DHeader));
            string id = new string(m_Header.ID);
            // Only Milkshape3D Version 1.3 and 1.4 is supported.

            #region Vertices
            b = new byte[Marshal.SizeOf(typeof(short))];
            fs.Read(b, 0, Marshal.SizeOf(typeof(short)));
            short nVertices = (short)RawDeserializeEx(b, typeof(short));
            model_data.Vertices = new Vertex[nVertices];
            model_data.numVertices = nVertices;

            for (int i = 0; i < nVertices; i++)
            {
                b = new byte[Marshal.SizeOf(typeof(MS3DVertex))];
                fs.Read(b, 0, b.Length);
                MS3DVertex Vertex = (MS3DVertex)RawDeserializeEx(b, typeof(MS3DVertex));
                model_data.Vertices[i] = new Vertex();
                model_data.Vertices[i].boneID = Vertex.boneID;
                model_data.Vertices[i].location = Vertex.vertex;
            }
            #endregion

            #region Triangles
            b = new byte[Marshal.SizeOf(typeof(short))];
            fs.Read(b, 0, Marshal.SizeOf(typeof(short)));
            short nTriangles = (short)RawDeserializeEx(b, typeof(short));
            model_data.Triangles = new Triangle[nTriangles];
            model_data.numTriangles = nTriangles;

            for (int i = 0; i < nTriangles; i++)
            {
                int[] vertexIndices = new int[3] { 0, 0, 0 };
                float[] t = new float[3] { 0, 0, 0 };

                b = new byte[Marshal.SizeOf(typeof(MS3DTriangle))];
                fs.Read(b, 0, b.Length);
                MS3DTriangle pTriangle = (MS3DTriangle)RawDeserializeEx(b, typeof(MS3DTriangle));

                model_data.Triangles[i] = new Triangle();

                vertexIndices[0] = (int)pTriangle.vertexIndices[0];
                vertexIndices[1] = (int)pTriangle.vertexIndices[1];
                vertexIndices[2] = (int)pTriangle.vertexIndices[2];
                t[0] = 1.0f - pTriangle.t[0];
                t[1] = 1.0f - pTriangle.t[1];
                t[2] = 1.0f - pTriangle.t[2];
                model_data.Triangles[i].vertexNormals = pTriangle.vertexNormals;
                model_data.Triangles[i].s = pTriangle.s;
                model_data.Triangles[i].t = t;
                model_data.Triangles[i].vertexIndices = vertexIndices;
            }
            #endregion

            #region Groups
            b = new byte[Marshal.SizeOf(typeof(short))];
            fs.Read(b, 0, Marshal.SizeOf(typeof(short)));
            short nGroups = (short)RawDeserializeEx(b, typeof(short));
            model_data.Meshes = new Mesh[nGroups];
            model_data.numMeshes = nGroups;

            for (int i = 0; i < nGroups; i++)
            {
                b = new byte[Marshal.SizeOf(typeof(byte))];
                fs.Read(b, 0, b.Length); // Flags

                b = new byte[32];
                fs.Read(b, 0, b.Length); // name
                string name = System.Text.Encoding.UTF8.GetString(b);

                b = new byte[Marshal.SizeOf(typeof(short))];
                fs.Read(b, 0, b.Length); // number of Triangle Indices
                nTriangles = (short)RawDeserializeEx(b, typeof(short));
                int[] pTriangleIndices = new int[nTriangles];

                for (int j = 0; j < nTriangles; j++)
                {
                    b = new byte[Marshal.SizeOf(typeof(short))];
                    fs.Read(b, 0, b.Length); // read indices value
                    pTriangleIndices[j] = (short)RawDeserializeEx(b, typeof(short));
                }

                b = new byte[Marshal.SizeOf(typeof(char))];
                fs.Read(b, 0, b.Length); // read material index
                char materialIndex = (char)RawDeserializeEx(b, typeof(char));

                model_data.Meshes[i] = new Mesh();
                model_data.Meshes[i].materialIndex = (int)materialIndex;
                model_data.Meshes[i].numTriangles = nTriangles;
                model_data.Meshes[i].TriangleIndices = pTriangleIndices;
            }
            #endregion

            #region Materials
            b = new byte[Marshal.SizeOf(typeof(short))];
            fs.Read(b, 0, Marshal.SizeOf(typeof(short)));
            short nMaterials = (short)RawDeserializeEx(b, typeof(short));
            model_data.Materials = new Material[nMaterials];
            model_data.numMaterials = nMaterials;

            for (int i = 0; i < nMaterials; i++)
            {
                b = new byte[Marshal.SizeOf(typeof(MS3DMaterial))];
                fs.Read(b, 0, b.Length); // read material
                MS3DMaterial pMaterial = (MS3DMaterial)RawDeserializeEx(b, typeof(MS3DMaterial));
                model_data.Materials[i] = new Material();
                model_data.Materials[i].name = pMaterial.name;
                model_data.Materials[i].ambient = pMaterial.ambient;
                model_data.Materials[i].diffuse = pMaterial.diffuse;
                model_data.Materials[i].specular = pMaterial.specular;
                model_data.Materials[i].emissive = pMaterial.emissive;
                model_data.Materials[i].shininess = pMaterial.shininess;
                model_data.Materials[i].transparency = pMaterial.transparency;
                model_data.Materials[i].mode = pMaterial.mode;
                model_data.Materials[i].TextureFilename = CropNull(new string(pMaterial.texture));
                model_data.Materials[i].alpha = pMaterial.alphamap;

                // set alpha
                model_data.Materials[i].ambient[3] = model_data.Materials[i].transparency;
                model_data.Materials[i].diffuse[3] = model_data.Materials[i].transparency;
                model_data.Materials[i].specular[3] = model_data.Materials[i].transparency;
                model_data.Materials[i].emissive[3] = model_data.Materials[i].transparency;
            }
            #endregion

            ReloadTextures();

            #region Animation
            b = new byte[Marshal.SizeOf(typeof(float))];
            fs.Read(b, 0, b.Length);
            float animFPS = (float)RawDeserializeEx(b, typeof(float));
            if (animFPS < 1.0f)
                animFPS = 1.0f;

            // Skip the currentTime value
            fs.Read(b, 0, b.Length);

            b = new byte[Marshal.SizeOf(typeof(int))];
            fs.Read(b, 0, b.Length);
            int totalFrames = (int)RawDeserializeEx(b, typeof(int));

            model_data.totalTime = totalFrames * 1000f / animFPS;
            #endregion

            #region Joints
            b = new byte[Marshal.SizeOf(typeof(short))];
            fs.Read(b, 0, b.Length);
            model_data.numJoints = (short)RawDeserializeEx(b, typeof(short));
            model_data.Joints = new Joint[model_data.numJoints];

            JointNameListRec[] pNameList = new JointNameListRec[model_data.numJoints];

            #region Building JointNameListRec
            long tempPos = fs.Position;

            for (int i = 0; i < model_data.numJoints; i++)
            {
                b = new byte[Marshal.SizeOf(typeof(MS3DJoint))];
                fs.Read(b, 0, b.Length);
                MS3DJoint pJoint = (MS3DJoint)RawDeserializeEx(b, typeof(MS3DJoint));

                pNameList[i] = new JointNameListRec();
                pNameList[i].jointIndex = i;
                pNameList[i].Name = CropNull(new string(pJoint.name));

                // skip forward for the next joint
                b = new byte[Marshal.SizeOf(typeof(MS3DKeyframe)) * (pJoint.numRotationKeyframes + pJoint.numTranslationKeyframes)];
                fs.Read(b, 0, b.Length);
            }

            fs.Seek(tempPos, System.IO.SeekOrigin.Begin);
            #endregion

            #region Load Joints
            for (int i = 0; i < model_data.numJoints; i++)
            {
                b = new byte[Marshal.SizeOf(typeof(MS3DJoint))];
                fs.Read(b, 0, b.Length);
                MS3DJoint pJoint = (MS3DJoint)RawDeserializeEx(b, typeof(MS3DJoint));

                int parentIndex = -1;
                string parentName = CropNull(new string(pJoint.parentName));
                if (parentName.Length > 0)
                {
                    for (int j = 0; j < model_data.numJoints; j++)
                    {
                        if (pNameList[j].Name == parentName)
                        {
                            parentIndex = pNameList[j].jointIndex;
                            break;
                        }
                    }

                    if (parentIndex == -1)
                        return;
                }

                model_data.Joints[i] = new Joint();
                model_data.Joints[i].localRotation = pJoint.rotation;
                model_data.Joints[i].localTranslation = pJoint.translation;
                model_data.Joints[i].parent = parentIndex;
                model_data.Joints[i].numRotationKeyframes = pJoint.numRotationKeyframes;
                model_data.Joints[i].RotationKeyframes = new Keyframe[pJoint.numRotationKeyframes];
                model_data.Joints[i].numTranslationKeyframes = pJoint.numTranslationKeyframes;
                model_data.Joints[i].TranslationKeyframes = new Keyframe[pJoint.numTranslationKeyframes];

                model_data.Joints[i].mat_relative = new Matrix();
                model_data.Joints[i].mat_final = new Matrix();
                model_data.Joints[i].mat_absolute = new Matrix();

                // the frame time is in seconds, so multiply it by the animation fps, to get the frames
                // rotation channel
                for (int j = 0; j < pJoint.numRotationKeyframes; j++)
                {
                    b = new byte[Marshal.SizeOf(typeof(MS3DKeyframe))];
                    fs.Read(b, 0, b.Length);
                    MS3DKeyframe pKeyframe = (MS3DKeyframe)RawDeserializeEx(b, typeof(MS3DKeyframe));

                    SetJointKeyframe(i, j, pKeyframe.time * 1000.0f, ref pKeyframe.parameter, true);
                }

                // translation channel
                for (int j = 0; j < pJoint.numTranslationKeyframes; j++)
                {
                    b = new byte[Marshal.SizeOf(typeof(MS3DKeyframe))];
                    fs.Read(b, 0, b.Length);
                    MS3DKeyframe pKeyframe = (MS3DKeyframe)RawDeserializeEx(b, typeof(MS3DKeyframe));

                    SetJointKeyframe(i, j, pKeyframe.time * 1000.0f, ref pKeyframe.parameter, false);
                }
            }
            #endregion

            pNameList = null;
            #endregion

            #region Comments
            if (fs.Position < totalLength)
            {
                int subVersion = 0;
                b = new byte[Marshal.SizeOf(typeof(int))];
                fs.Read(b, 0, b.Length);
                subVersion = (int)RawDeserializeEx(b, typeof(int));

                if (subVersion == 1)
                {
                    int numComments = 0;
                    uint commentSize = 0;

                    #region Group Comments
                    b = new byte[Marshal.SizeOf(typeof(int))];
                    fs.Read(b, 0, b.Length);
                    numComments = (int)RawDeserializeEx(b, typeof(int));

                    for (int i = 0; i < numComments; i++)
                    {
                        int index;
                        string comment = "";

                        fs.Read(b, 0, b.Length);
                        index = (int)RawDeserializeEx(b, typeof(int));

                        b = new byte[Marshal.SizeOf(typeof(uint))];
                        fs.Read(b, 0, b.Length);
                        commentSize = (uint)RawDeserializeEx(b, typeof(uint));

                        if (commentSize > 0)
                        {
                            b = new byte[Marshal.SizeOf(sizeof(char) * commentSize)];
                            fs.Read(b, 0, b.Length);
                            comment = System.Text.Encoding.ASCII.GetString(b);
                        }
                        if (index >= 0 && index < model_data.numMeshes)
                            model_data.Meshes[index].comment = comment;
                    }
                    #endregion

                    #region Material Comments
                    b = new byte[Marshal.SizeOf(typeof(int))];
                    fs.Read(b, 0, b.Length);
                    numComments = (int)RawDeserializeEx(b, typeof(int));

                    for (int i = 0; i < numComments; i++)
                    {
                        int index;
                        string comment = "";

                        fs.Read(b, 0, b.Length);
                        index = (int)RawDeserializeEx(b, typeof(int));

                        b = new byte[Marshal.SizeOf(typeof(uint))];
                        fs.Read(b, 0, b.Length);
                        commentSize = (uint)RawDeserializeEx(b, typeof(uint));

                        if (commentSize > 0)
                        {
                            b = new byte[Marshal.SizeOf(sizeof(char) * commentSize)];
                            fs.Read(b, 0, b.Length);
                            comment = System.Text.Encoding.ASCII.GetString(b);
                        }
                        if (index >= 0 && index < model_data.numMaterials)
                            model_data.Materials[index].comment = comment;
                    }
                    #endregion

                    #region Joint Comments
                    b = new byte[Marshal.SizeOf(typeof(int))];
                    fs.Read(b, 0, b.Length);
                    numComments = (int)RawDeserializeEx(b, typeof(int));

                    for (int i = 0; i < numComments; i++)
                    {
                        int index;
                        string comment = "";

                        fs.Read(b, 0, b.Length);
                        index = (int)RawDeserializeEx(b, typeof(int));

                        b = new byte[Marshal.SizeOf(typeof(uint))];
                        fs.Read(b, 0, b.Length);
                        commentSize = (uint)RawDeserializeEx(b, typeof(uint));

                        if (commentSize > 0)
                        {
                            b = new byte[Marshal.SizeOf(sizeof(char) * commentSize)];
                            fs.Read(b, 0, b.Length);
                            comment = System.Text.Encoding.ASCII.GetString(b);
                        }
                        if (index >= 0 && index < model_data.numJoints)
                        model_data.Joints[index].comment = comment;
                    }
                    #endregion

                    #region Model Comments
                    b = new byte[Marshal.SizeOf(typeof(int))];
                    fs.Read(b, 0, b.Length);
                    numComments = (int)RawDeserializeEx(b, typeof(int));

                    if (numComments == 1)
                    {
                        string comment = "";
                        b = new byte[Marshal.SizeOf(typeof(uint))];
                        fs.Read(b, 0, b.Length);
                        commentSize = (uint)RawDeserializeEx(b, typeof(uint));
                        if (commentSize > 0)
                        {
                            b = new byte[Marshal.SizeOf(sizeof(char) * commentSize)];
                            fs.Read(b, 0, b.Length);
                            comment = System.Text.Encoding.ASCII.GetString(b);
                        }
                        model_data.comment = comment;
                    }
                    #endregion
                }
            }
            #endregion

            #region Vertex Extra
            if (fs.Position < totalLength)
            {
                int subVersion = 0;
                b = new byte[Marshal.SizeOf(typeof(int))];
                fs.Read(b, 0, b.Length);
                subVersion = (int)RawDeserializeEx(b, typeof(int));
                if ((subVersion == 1) || (subVersion == 2))
                {
                    for (int i = 0; i < model_data.numVertices; i++)
                    {
                        model_data.Vertices[i].boneIds = new char[3];
                        b = new byte[Marshal.SizeOf(typeof(char))];
                        fs.Read(b, 0, b.Length);
                        model_data.Vertices[i].boneIds[0] = (char)RawDeserializeEx(b, typeof(char));
                        fs.Read(b, 0, b.Length);
                        model_data.Vertices[i].boneIds[1] = (char)RawDeserializeEx(b, typeof(char));
                        fs.Read(b, 0, b.Length);
                        model_data.Vertices[i].boneIds[2] = (char)RawDeserializeEx(b, typeof(char));

                        model_data.Vertices[i].weights = new char[3];
                        fs.Read(b, 0, b.Length);
                        model_data.Vertices[i].weights[0] = (char)RawDeserializeEx(b, typeof(char));
                        fs.Read(b, 0, b.Length);
                        model_data.Vertices[i].weights[1] = (char)RawDeserializeEx(b, typeof(char));
                        fs.Read(b, 0, b.Length);
                        model_data.Vertices[i].weights[2] = (char)RawDeserializeEx(b, typeof(char));

                        if (subVersion == 2)
                        {
                            b = new byte[Marshal.SizeOf(typeof(uint))];
                            fs.Read(b, 0, b.Length);
                            model_data.Vertices[i].extra = (uint)RawDeserializeEx(b, typeof(uint));
                        }
                    }
                }
            }
            #endregion

            #region Joint Extra
            if (fs.Position < totalLength)
            {
                int subVersion = 0;
                b = new byte[Marshal.SizeOf(typeof(int))];
                fs.Read(b, 0, b.Length);
                subVersion = (int)RawDeserializeEx(b, typeof(int));

                if (subVersion == 1)
                {
                    for (int i = 0; i < model_data.numJoints; i++)
                    {
                        model_data.Joints[i].color = new float[3];
                        b = new byte[Marshal.SizeOf(typeof(float))];
                        fs.Read(b, 0, b.Length);
                        model_data.Joints[i].color[0] = (float)RawDeserializeEx(b, typeof(float));
                        fs.Read(b, 0, b.Length);
                        model_data.Joints[i].color[1] = (float)RawDeserializeEx(b, typeof(float));
                        fs.Read(b, 0, b.Length);
                        model_data.Joints[i].color[2] = (float)RawDeserializeEx(b, typeof(float));
                    }
                }
            }
            #endregion

            #region Model Extra
            if (fs.Position < totalLength)
            {
                int subVersion = 0;
                b = new byte[Marshal.SizeOf(typeof(int))];
                fs.Read(b, 0, b.Length);
                subVersion = (int)RawDeserializeEx(b, typeof(int));

                if (subVersion == 1)
                {
                    b = new byte[Marshal.SizeOf(typeof(float))];
                    fs.Read(b, 0, b.Length);
                    model_data.jointSize = (float)RawDeserializeEx(b, typeof(float));

                    b = new byte[Marshal.SizeOf(typeof(int))];
                    fs.Read(b, 0, b.Length);
                    model_data.transparencyMode = (int)RawDeserializeEx(b, typeof(int));

                    b = new byte[Marshal.SizeOf(typeof(float))];
                    fs.Read(b, 0, b.Length);
                    model_data.alphaRef = (float)RawDeserializeEx(b, typeof(float));
                }
            }
            #endregion

            fs.Close();

            try { SetupJoints(); }
            catch { }
        }