// Function		: loading Percentage.
 // Description	: Shininess and transparency of the material is a percentage,
 //                  so we need a function to load them.
 // Input		: where the percentage should be saved.
 // Output		: nothing.
 private void LoadPercent(ref float Temp)
 {
     Chunk TempChunk = new Chunk();
     ReadChunk(ref TempChunk);
     switch(TempChunk.ID)
     {
     case INT_PERCENTAGE:    //Int Percentage
         ushort Percent = 0;
         ReadGLushort(ref Percent);
         Temp = Percent / 100.0f;
         break;
     case FLOAT_PERCENTAGE:  //Float Percentage
         ReadGLfloat(ref Temp);
         break;
     default:
         SkipNByte(TempChunk.Len - 6);
         break;
     }
 }
 private void ReadChunk(ref Chunk MyChunk )
 {
     ReadGLushort( ref MyChunk.ID );
     ReadGLuint( ref MyChunk.Len );
 }
        // Function		: loading mesh information.
        // Description	: loading mesh information.
        // Input		: chunk info of the mesh.
        // Output		: nothing.
        private void LoadMesh(ref Chunk MyChunk)
        {
            Object _object = MyModel.MyObject[MyModel.MyObject.Count - 1];

            uint BeginPos = NowPos - 6;
            Chunk ThisChunk = new Chunk();
            while(NowPos - BeginPos != MyChunk.Len)
            {
                ReadChunk(ref ThisChunk);
                switch(ThisChunk.ID)
                {
                case OBJECT_VERTICES:  //vertice
                    LoadVertex(ref _object );
                    break;

                case OBJECT_FACES:     //face
                    LoadFaces(ref _object );
                    break;

                case OBJECT_MATERIAL:  //material
                    LoadObjectMaterial(ref _object );
                    break;

                default:              //something we do not need
                    SkipNByte( ThisChunk.Len - 6 );
                    break;
                }
            }
        }
        // Function		: loading objct.
        // Description	: loading objct.
        // Input		: chunk info of the object.
        // Output		: nothing.
        private void LoadObject(ref Chunk MyChunk)
        {
            Object _object = new Object();
            _object.Name = ReadString();
            MyModel.MyObject.Add(_object);

            Chunk ThisChunk = new Chunk();
            UInt32 BeginPos = NowPos - 7 - (uint)_object.Name.Length;
            while(NowPos - BeginPos != MyChunk.Len)
            {
                ReadChunk(ref ThisChunk);
                if(OBJECT_MESH == ThisChunk.ID)
                    LoadMesh(ref ThisChunk);
                else
                    SkipNByte(ThisChunk.Len - 6);
            }
        }
        // Function		: loading material information.
        // Description	: loading material information.
        // Input		: the chunk of material.
        // Output		: nothing.
        private void LoadMaterial( ref Chunk MyChunk )
        {
            Chunk TempChunk = new Chunk();
            Material material = new Material();
            uint BeginPos = NowPos - 6;

            while(NowPos - BeginPos < MyChunk.Len)
            {
                ReadChunk(ref TempChunk);
                switch(TempChunk.ID)
                {
                case MATNAME:                      //material name
                    material.name = ReadString();
                    break;
                case MAT_AMBIENT:                  //material Ambient
                    LoadColor(ref material.ambientColor);
                    break;
                case MAT_DIFFUSE:                  //material Diffuse
                    LoadColor(ref material.diffuseColor);
                    break;
                case MAT_SPECULAR:                 //material Specular
                    LoadColor(ref material.specularColor);
                    break;
                case MAT_SHININESS:                //material Shininess
                    LoadPercent(ref material.shininess);
                    break;
                case MAT_TRANSPARENCY:             //material Transparency
                    LoadPercent(ref material.transparency);
                    break;
                default:
                    SkipNByte(TempChunk.Len - 6);
                    break;
                }
            }
            MyModel.MyMaterial.Add(material);
        }
 // Function		: loading color information.
 // Description	: loading color information.
 // Input		: the color pointer we should save to.
 // Output		: nothing.
 private void LoadColor(ref float[] color)
 {
     Chunk TempChunk = new Chunk();
     ReadChunk(ref TempChunk);
     switch( TempChunk.ID )
     {
     case COLOR_F:
         ReadGLfloat(ref color[ 0 ]);
         ReadGLfloat(ref color[ 1 ]);
         ReadGLfloat(ref color[ 2 ]);
         break;
     case COLOR_24:
         byte Byte = 0;
         for(int i = 0; i != 3; ++i)
         {
             ReadGLubyte(ref Byte);
             color[ i ] = Byte / 255.0f;
         }
         break;
     default:
         SkipNByte(TempChunk.Len - 6);
         break;
     }
 }
        // Function		: loading model.
        // Description	: loading information of a model.
        // Input		: chunk info of model
        // Output		: nothing
        public void LoadModel(ref Chunk MyChunk)
        {
            UInt32 BeginPos = NowPos - 6;
            Chunk TempChunk = new Chunk();
            while(NowPos - BeginPos != MyChunk.Len)
            {
                ReadChunk(ref TempChunk);
                switch(TempChunk.ID)
                {
                case OBJECT:
                    LoadObject(ref TempChunk);
                    break;

                case MATERIAL:
                    LoadMaterial(ref TempChunk);
                    break;

                default:
                    SkipNByte(TempChunk.Len - 6);
                    break;
                }
            }
        }
        // Function		: read 3DS file.
        // Description	: read information from 3DS file, all other functions work for it.
        // Input		: nothing.
        // Output		: nothing.
        public void LoadFile()
        {
            buf = new byte[FileReader.Length];
            if (FileReader.Read(buf, 0, (int)FileReader.Length) <= 0)
                throw new Exception("File read error.");

            Chunk MyChunk = new Chunk();
            ReadChunk(ref MyChunk);
            if(PRIMARY != MyChunk.ID)
                throw new Exception("File format error.");
            FileLength = MyChunk.Len;

            ReadChunk(ref MyChunk);
            ReadGLuint(ref Version);
            while(NowPos < FileLength)
            {
                ReadChunk(ref MyChunk);
                if(MAINOBJECT == MyChunk.ID)
                    LoadModel(ref MyChunk);
                else
                    SkipNByte(MyChunk.Len - 6);
            }

            ComputeNormals();
        }
 private void ReadChunk(ref Chunk MyChunk)
 {
     ReadGLushort(ref MyChunk.ID);
     ReadGLuint(ref MyChunk.Len);
 }