Example #1
0
        //读入顶点索引
        void ReadVertexIndices(t3DObject pObject, tChunk pPreviousChunk)
        {
            int index = 0;

            //读入该对象中面的数目
            pPreviousChunk.bytesRead += fread(ref pObject.numOfFaces, 2, m_FilePointer);

            //分配所有的储存空间,并初始化结构
            pObject.pFaces = new tFace[pObject.numOfFaces];

            //遍历对象中所有的面
            for (int i = 0; i < pObject.numOfFaces; i++)
            {
                pObject.pFaces[i] = new tFace();
                for (int j = 0; j < 4; j++)
                {
                    //读入当前对象的第一个点
                    pPreviousChunk.bytesRead += fread(ref index, 2, m_FilePointer);

                    if (j < 3)
                    {
                        pObject.pFaces[i].vertIndex[j] = index;
                    }
                }
            }
        }
Example #2
0
        //读入对象的材质名称
        void ReadObjectMaterial(t3DModel pModel, t3DObject pObject, tChunk pPreviousChunk)
        {
            String strMaterial = "";          //用来保存对象的材质名称

            int[] buffer = new int[50000];    //用来读入不需要的数据

            //读入赋予当前对象的材质名称
            pPreviousChunk.bytesRead += getStr(ref strMaterial);

            //遍历所有的纹理
            for (int i = 0; i < pModel.numOfMaterials; i++)
            {
                //如果读入的纹理与当前纹理名称匹配

                if (strMaterial.Equals(pModel.pMaterials[i].strName))
                {
                    //设置材质ID
                    pObject.materialID = i;
                    //判断是否是纹理映射,如果strFile是一个长度大于1的字符串,则是纹理
                    if (pModel.pMaterials[i].strFile.Length > 0)
                    {
                        //设置对象的纹理映射标志
                        pObject.bHasTexture = true;
                    }
                    break;
                }
                else
                {
                    //如果该对象没有材质,则设置ID为-1
                    pObject.materialID = -1;
                }
            }
            pPreviousChunk.bytesRead += fread(ref buffer, pPreviousChunk.length - pPreviousChunk.bytesRead, m_FilePointer);
        }
Example #3
0
        //读入对象的UV坐标
        void ReadUVCoordinates(t3DObject pObject, tChunk pPreviousChunk)
        {
            //为了读入对象的UV坐标,首先需要读入数量,再读入具体的数据

            //读入UV坐标的数量
            pPreviousChunk.bytesRead += fread(ref pObject.numTexVertex, 2, m_FilePointer);

            //初始化保存UV坐标的数组
            pObject.pTexVerts = new CVector2[pObject.numTexVertex];

            //读入纹理坐标
            pPreviousChunk.bytesRead += fread(ref pObject.pTexVerts, pPreviousChunk.length - pPreviousChunk.bytesRead, m_FilePointer);
        }
Example #4
0
        //处理所有的文件中的对象信息
        void ProcessNextObjectChunk(t3DModel pModel, t3DObject pObject, tChunk pPreviousChunk)
        {
            m_CurrentChunk = new tChunk();

            //继续读入块的内容直至本子块结束
            while (pPreviousChunk.bytesRead < pPreviousChunk.length)
            {
                ReadChunk(m_CurrentChunk);

                if (m_CurrentChunk.ID == FileHead.OBJECT_MESH)//正读入的是一个新块
                {
                    //使用递归函数调用,处理该新块
                    ProcessNextObjectChunk(pModel, pObject, m_CurrentChunk);
                }
                else if (m_CurrentChunk.ID == FileHead.OBJECT_VERTICES)//读入的是对象顶点
                {
                    ReadVertices(pObject, m_CurrentChunk);
                }
                else if (m_CurrentChunk.ID == FileHead.OBJECT_FACES)//读入的是对象的面
                {
                    ReadVertexIndices(pObject, m_CurrentChunk);
                }
                else if (m_CurrentChunk.ID == FileHead.OBJECT_MATERIAL)//读入的是对象的材质名称
                {
                    //该块保存了对象材质的名称,可能是一个颜色,也可能是一个纹理映射。
                    //同时在该块中也保存了纹理对象所赋予的面

                    //下面读入对象的材质名称
                    ReadObjectMaterial(pModel, pObject, m_CurrentChunk);
                }
                else if (m_CurrentChunk.ID == FileHead.OBJECT_UV)//读入对象的UV纹理坐标
                {
                    ReadUVCoordinates(pObject, m_CurrentChunk);
                }
                else
                {
                    //掠过不需要读入的块
                    while (m_CurrentChunk.bytesRead != m_CurrentChunk.length)
                    {
                        int[] b = new int[1];
                        m_CurrentChunk.bytesRead += fread(ref b, 1, m_FilePointer);
                    }
                }

                //添加从最后块中读入的字节数
                pPreviousChunk.bytesRead += m_CurrentChunk.bytesRead;
            }
            //当前快设置为前面的块
            m_CurrentChunk = pPreviousChunk;
        }
Example #5
0
        //读入对象的顶点
        void ReadVertices(t3DObject pObject, tChunk pPreviousChunk)
        {
            //在读入实际的顶点之前,首先必须确定需要读入多少个顶点。

            //读入顶点的数目
            pPreviousChunk.bytesRead += fread(ref pObject.numOfVerts, 2, m_FilePointer);

            //分配顶点的储存空间,然后初始化结构体
            pObject.pVerts = new CVector3[pObject.numOfVerts];

            //读入顶点序列
            pPreviousChunk.bytesRead += fread(ref pObject.pVerts, pPreviousChunk.length - pPreviousChunk.bytesRead, m_FilePointer);

            //因为3DMax的模型Z轴是指向上的,将y轴和z轴翻转——y轴和z轴交换,再把z轴反向

            //遍历所有的顶点
            //for (int i = 0; i < pObject.numOfVerts; i++)
            //{
            //    float fTempY = pObject.pVerts[i].y;
            //    pObject.pVerts[i].y = pObject.pVerts[i].z;
            //    pObject.pVerts[i].z = -1 * fTempY;
            //}
        }
Example #6
0
        //模型单位归一化
        protected void LoadBox()
        {
            boxMax   = new CVector3();
            boxMin   = new CVector3();
            boxMax.x = float.MinValue;
            boxMax.y = float.MinValue;
            boxMax.z = float.MinValue;
            boxMin.x = float.MaxValue;
            boxMin.y = float.MaxValue;
            boxMin.z = float.MaxValue;

            //获取模型的边界值
            for (int i = 0; i < model.numOfObjects; i++)
            {
                t3DObject pObject = model.pObject[i];
                for (int j = 0; j < pObject.numOfVerts; j++)
                {
                    float x = pObject.pVerts[j].x / 1000;
                    float y = pObject.pVerts[j].y / 1000;
                    float z = pObject.pVerts[j].z / 1000;
                    if (boxMin.x > x)
                    {
                        boxMin.x = x;
                    }
                    if (boxMin.y > y)
                    {
                        boxMin.y = y;
                    }
                    if (boxMin.z > z)
                    {
                        boxMin.z = z;
                    }
                    if (boxMax.x < x)
                    {
                        boxMax.x = x;
                    }
                    if (boxMax.y < y)
                    {
                        boxMax.y = y;
                    }
                    if (boxMax.z < z)
                    {
                        boxMax.z = z;
                    }
                }
            }
            //计算模型的宽度、高度和深度
            w = (boxMax.x - boxMin.x); // OutputAbs(boxMax.x) + OutputAbs(boxMin.x);
            h = (boxMax.y - boxMin.y); // OutputAbs(boxMax.y) + OutputAbs(boxMin.y);
            d = (boxMax.z - boxMin.z); // OutputAbs(boxMax.z) + OutputAbs(boxMin.z);
            //计算模型的中心
            cx = (boxMax.x + boxMin.x) / 2.0;
            cy = (boxMax.y + boxMin.y) / 2.0;
            cz = (boxMax.z + boxMin.z) / 2.0;
            //计算归一化所需的缩放比例
            scale = OutputMax(OutputMax(w, h), d);
            scale = 4.0f / scale;//根据模型实际来决定
            //导入模型的单位为mm,将单位转换为m
            for (int i = 0; i < model.numOfObjects; i++)
            {
                t3DObject pObject = model.pObject[i];
                for (int j = 0; j < pObject.numOfVerts; j++)
                {
                    pObject.pVerts[j].x /= 1000;
                    pObject.pVerts[j].y /= 1000;
                    pObject.pVerts[j].z /= 1000;
                    //pObject.pVerts[j].x -= (float)cx;
                    //pObject.pVerts[j].y -= (float)cy;
                    //pObject.pVerts[j].z -= (float)cz;
                }
            }
        }
Example #7
0
        //下面的这些函数主要用来计算顶点的法向量,顶点的法向量主要用来计算光照
        //计算对象的法向量
        private void ComputeNormals(t3DModel pModel)
        {
            CVector3 vVector1, vVector2, vNormal;

            CVector3[] vPoly;

            vPoly = new CVector3[3];
            //如果模型中没有对象,则返回
            if (pModel.numOfObjects <= 0)
            {
                return;
            }

            //遍历模型中所有的对象
            for (int index = 0; index < pModel.numOfObjects; index++)
            {
                //获得当前对象
                t3DObject pObject = pModel.pObject[index];

                //分配需要的空间
                CVector3[] pNormals     = new CVector3[pObject.numOfFaces];
                CVector3[] pTempNormals = new CVector3[pObject.numOfFaces];
                pObject.pNormals = new CVector3[pObject.numOfVerts];

                //遍历对象所有面
                for (int i = 0; i < pObject.numOfFaces; i++)
                {
                    vPoly[0] = pObject.pVerts[pObject.pFaces[i].vertIndex[0]];
                    vPoly[1] = pObject.pVerts[pObject.pFaces[i].vertIndex[1]];
                    vPoly[2] = pObject.pVerts[pObject.pFaces[i].vertIndex[2]];

                    //计算面的法向量
                    vVector1 = Vector(vPoly[0], vPoly[2]);
                    vVector2 = Vector(vPoly[2], vPoly[1]);

                    vNormal         = Cross(vVector1, vVector2);
                    pTempNormals[i] = vNormal;
                    vNormal         = Normalize(vNormal);
                    pNormals[i]     = vNormal;
                }

                //下面求顶点的法向量:顶点法向量是以该点为顶点的所有三角形法向量之和
                CVector3 vSum = new CVector3();
                vSum.x = 0; vSum.y = 0; vSum.z = 0;
                int shared = 0;

                //遍历所有的顶点
                for (int i = 0; i < pObject.numOfVerts; i++)
                {
                    for (int j = 0; j < pObject.numOfFaces; j++)
                    {
                        if (pObject.pFaces[j].vertIndex[0] == i ||
                            pObject.pFaces[j].vertIndex[1] == i ||
                            pObject.pFaces[j].vertIndex[2] == i)
                        {
                            vSum = AddVector(vSum, pTempNormals[j]);
                            shared++;
                        }
                    }
                    pObject.pNormals[i] = DivideVectorByScaler(vSum, (float)(-1 * shared));

                    //规范化最后的顶点法向量
                    pObject.pNormals[i] = Normalize(pObject.pNormals[i]);

                    vSum.x = 0; vSum.y = 0; vSum.z = 0;
                    shared = 0;
                }
            }
        }
Example #8
0
        //读出3ds文件的主要部分
        void ProcessNextChunk(t3DModel pModel, tChunk pPreviousChunk)
        {
            t3DObject newObject = new t3DObject();
            int       version   = 0;

            m_CurrentChunk = new tChunk();

            //  下面每读一个新块,都要判断一下块的ID,如果该块是需要的读入的,则继续进行
            //  如果是不需要读入的块,则略过

            // 继续读入子块,直到达到预定的长度
            while (pPreviousChunk.bytesRead < pPreviousChunk.length)
            {
                //读入下一个块
                ReadChunk(m_CurrentChunk);

                //判断ID号
                if (m_CurrentChunk.ID == FileHead.VERSION)
                {
                    m_CurrentChunk.bytesRead += fread(ref version, m_CurrentChunk.length - m_CurrentChunk.bytesRead, m_FilePointer);

                    // 如果文件版本号大于3,给出一个警告信息
                    if (version > 3)
                    {
                        Debug.WriteLine("Warning:  This 3DS file is over version 3 so it may load incorrectly");
                    }
                }
                else if (m_CurrentChunk.ID == FileHead.OBJECTINFO)
                {
                    //读入下一个块
                    ReadChunk(m_TempChunk);

                    //获得网络的版本号
                    m_TempChunk.bytesRead += fread(ref version, m_TempChunk.length - m_TempChunk.bytesRead, m_FilePointer);

                    //增加读入的字节数
                    m_CurrentChunk.bytesRead += m_TempChunk.bytesRead;

                    //进入下一个块
                    ProcessNextChunk(pModel, m_CurrentChunk);
                }
                else if (m_CurrentChunk.ID == FileHead.MATERIAL)//材质信息
                {
                    //材质的数目递增
                    pModel.numOfMaterials++;
                    //在纹理链表中添加一个空白纹理结构
                    pModel.pMaterials.Add(new tMaterialInfo());
                    //进入材质装入函数
                    ProcessNextMaterialChunk(pModel, m_CurrentChunk);
                }
                else if (m_CurrentChunk.ID == FileHead.OBJECT)//对象的名称
                {
                    //对象数目递增
                    pModel.numOfObjects++;

                    //添加一个新的tObject节点到对象的链表中
                    pModel.pObject.Add(new t3DObject());

                    //获得并保存对象的名称,然后增加读入的字节数
                    m_CurrentChunk.bytesRead += getStr(ref pModel.pObject[pModel.numOfObjects - 1].strName);

                    //进入其余对象信息的读入
                    ProcessNextObjectChunk(pModel, pModel.pObject[pModel.numOfObjects - 1], m_CurrentChunk);
                }
                else
                {
                    // 跳过关键帧块的读入,增加需要读入的字节数 EDITKEYFRAME
                    // 跳过所有忽略的块的内容的读入,增加需要读入的字节数
                    while (m_CurrentChunk.bytesRead != m_CurrentChunk.length)
                    {
                        int[] b = new int[1];
                        m_CurrentChunk.bytesRead += fread(ref b, 1, m_FilePointer);
                    }
                }
                //添加从最后块中读入的字节数
                pPreviousChunk.bytesRead += m_CurrentChunk.bytesRead;
            }
            //当前快设置为前面的块
            m_CurrentChunk = pPreviousChunk;
        }
Example #9
0
        public void DrawModel()                             //画出模型
        {
            GL.glPushMatrix();
            GL.glRotatef(270.0f, 1.0f, 0.0f, 0.0f);

            GL.glEnable(GL.GL_BLEND);
            GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
            GL.glDepthMask((byte)Traparent);
            //画太阳

            //画读入的模型
            #region
            for (int i = 0; i < this.model.numOfObjects; i++)
            {
                if (this.model.pObject.Count <= 0)
                {
                    break;
                }

                t3DObject pObject = this.model.pObject[i];
                // if (!floors.Contains(pObject.strName.Substring(1, 1))) continue;

                if (pObject.bHasTexture)
                {
                    GL.glEnable(GL.GL_TEXTURE_2D);

                    GL.glColor4ub(255, 255, 255, (byte)Transparency);
                    GL.glBindTexture(GL.GL_TEXTURE_2D, this.g_Texture[pObject.materialID]);
                }
                else
                {
                    GL.glDisable(GL.GL_TEXTURE_2D);
                    GL.glColor3ub(255, 255, 255);
                }
                GL.glBegin(GL.GL_TRIANGLES);
                for (int j = 0; j < pObject.numOfFaces; j++)
                {
                    for (int whichVertex = 0; whichVertex < 3; whichVertex++)
                    {
                        int index = pObject.pFaces[j].vertIndex[whichVertex];

                        GL.glNormal3f(pObject.pNormals[index].x, pObject.pNormals[index].y, pObject.pNormals[index].z);

                        if (pObject.bHasTexture)
                        {
                            if (pObject.pTexVerts != null)
                            {
                                GL.glTexCoord2f(pObject.pTexVerts[index].x, pObject.pTexVerts[index].y);
                            }
                        }
                        else
                        {
                            if (this.model.pMaterials.Count != 0 && pObject.materialID >= 0)
                            {
                                int[] color = this.model.pMaterials[pObject.materialID].color;
                                GL.glColor3ub((byte)color[0], (byte)color[1], (byte)color[2]);
                            }
                        }
                        GL.glVertex3f(pObject.pVerts[index].x * (float)scale, pObject.pVerts[index].y * (float)scale, pObject.pVerts[index].z * (float)scale);
                    }
                }
                GL.glEnd();
                GL.glDisable(GL.GL_TEXTURE_2D);
            }
            GL.glDisable(GL.GL_BLEND);
            GL.glPopMatrix();
            #endregion
        }