• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

              C++博客 :: 首頁 :: 聯(lián)系 ::  :: 管理
              163 Posts :: 4 Stories :: 350 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(48)

            我參與的團隊

            搜索

            •  

            積分與排名

            • 積分 - 399253
            • 排名 - 59

            最新評論

            閱讀排行榜

            評論排行榜

            這篇渲染模型的文章是由Brett Porter所寫的。
            這篇教程的代碼是從PortaLib3D中提取出來的,PortaLib3D是一個可以讀取3D文件實用庫。
            這篇教程的代碼是以第六課為基礎(chǔ)的,我們只討論改變的部分。

            這課中使用的模型是從Milkshape3D中提取出來的,Milkshape3D是一個非常好的建模軟件,它包含了自己的文件格式,所以你能很容易去分析和理解。

            但是文件格式并不能使你加載一個模型,你必須自己定義一個結(jié)構(gòu)去保存數(shù)據(jù),接著把數(shù)據(jù)讀入那個結(jié)構(gòu),我們將告訴你如何定義這樣一個結(jié)構(gòu)。

            模型的定義在model.h中,好吧我們開始吧:
             
              

            // 頂點結(jié)構(gòu)
            struct Vertex
            {
                char m_boneID;    // 頂點所在的骨骼
                float m_location[3];
            };

            // 頂點的個數(shù)和數(shù)據(jù)
            int m_numVertices;
            Vertex *m_pVertices;

              
             在這一課你,你可以忽略m_boneID,我們將在以后的教程中介紹骨骼動畫。m_location定義頂點的位置。
            下面是三角形結(jié)構(gòu)
             
              

            // 三角形結(jié)構(gòu)
            struct Triangle
            {
                float m_vertexNormals[3][3];
                float m_s[3], m_t[3];
                int m_vertexIndices[3];
            };

            // 使用的三角形
            int m_numTriangles;
            Triangle *m_pTriangles;

              
             3個頂點構(gòu)成一個三角形,m_vertexIndices保存了三個頂點的索引。 m_s 和 m_t儲存了三個頂點的紋理坐標(biāo)。m_vertexNormals保存了三個頂點的法線。
            下面我們定義網(wǎng)格結(jié)構(gòu)
             
              

            // 網(wǎng)格結(jié)構(gòu)
            struct Mesh
            {
                int m_materialIndex;
                int m_numTriangles;
                int *m_pTriangleIndices;
            };

            // 使用的網(wǎng)格
            int m_numMeshes;
            Mesh *m_pMeshes;

              
             m_pTriangleIndices指向包含在網(wǎng)格中三角形的數(shù)據(jù),它是動態(tài)分配的。 m_materialIndex 指向了這個網(wǎng)格所用的材質(zhì)。 
              

            // 材質(zhì)屬性
            struct Material
            {
                float m_ambient[4], m_diffuse[4], m_specular[4], m_emissive[4];
                float m_shininess;
                GLuint m_texture;
                char *m_pTextureFilename;
            };

            // 使用的紋理
            int m_numMaterials;
            Material *m_pMaterials;

              
             這里我們使用與OpenGL中相對的材質(zhì)。
            下面的代碼用來載入模型,我們通過重載loadModelData函數(shù)來實現(xiàn)它。

            我們創(chuàng)建了一個新類MilkshapeModel,它是從Model繼承而來的。 
              

            bool MilkshapeModel::loadModelData( const char *filename )
            {
                ifstream inputFile( filename, ios::in | ios::binary | ios::nocreate );
                if ( inputFile.fail())
                    return false;    // 不能打開文件,返回失敗

              
             以二進制的方式打開文件,如果失敗則返回 
              

                inputFile.seekg( 0, ios::end );
                long fileSize = inputFile.tellg();
                inputFile.seekg( 0, ios::beg );

              
             返回文件大小 
              

                byte *pBuffer = new byte[fileSize];
                inputFile.read( pBuffer, fileSize );
                inputFile.close();

              
             分配一個內(nèi)存,載入文件,并關(guān)閉文件 
              

                const byte *pPtr = pBuffer;
                MS3DHeader *pHeader = ( MS3DHeader* )pPtr;
                pPtr += sizeof( MS3DHeader );

                if ( strncmp( pHeader->m_ID, "MS3D000000", 10 ) != 0 )
                    return false;    // 如果不是一個有效的MS3D文件則返回

                if ( pHeader->m_version < 3 || pHeader->m_version > 4 )
                    return false;    // 如果不能支持這種版本的文件,則返回失敗
              
             上面的文件讀取文件頭 
              

                int nVertices = *( word* )pPtr;
                m_numVertices = nVertices;
                m_pVertices = new Vertex[nVertices];
                pPtr += sizeof( word );

                int i;
                for ( i = 0; i < nVertices; i++ )
                {
                    MS3DVertex *pVertex = ( MS3DVertex* )pPtr;
                    m_pVertices[i].m_boneID = pVertex->m_boneID;
                    memcpy( m_pVertices[i].m_location, pVertex->m_vertex, sizeof( float )*3 );
                    pPtr += sizeof( MS3DVertex );
                }

              
             上面的代碼讀取頂點數(shù)據(jù) 
              

                int nTriangles = *( word* )pPtr;
                m_numTriangles = nTriangles;
                m_pTriangles = new Triangle[nTriangles];
                pPtr += sizeof( word );

                for ( i = 0; i < nTriangles; i++ )
                {
                    MS3DTriangle *pTriangle = ( MS3DTriangle* )pPtr;
                    int vertexIndices[3] = { pTriangle->m_vertexIndices[0], pTriangle->m_vertexIndices[1], pTriangle->m_vertexIndices[2] };
                    float t[3] = { 1.0f-pTriangle->m_t[0], 1.0f-pTriangle->m_t[1], 1.0f-pTriangle->m_t[2] };
                    memcpy( m_pTriangles[i].m_vertexNormals, pTriangle->m_vertexNormals, sizeof( float )*3*3 );
                    memcpy( m_pTriangles[i].m_s, pTriangle->m_s, sizeof( float )*3 );
                    memcpy( m_pTriangles[i].m_t, t, sizeof( float )*3 );
                    memcpy( m_pTriangles[i].m_vertexIndices, vertexIndices, sizeof( int )*3 );
                    pPtr += sizeof( MS3DTriangle );
                }

              
             上面的代碼用來讀取三角形信息,因為MS3D使用窗口坐標(biāo)系而OpenGL使用笛卡兒坐標(biāo)系,所以需要反轉(zhuǎn)每個頂點Y方向的紋理坐標(biāo) 
              

                int nGroups = *( word* )pPtr;
                m_numMeshes = nGroups;
                m_pMeshes = new Mesh[nGroups];
                pPtr += sizeof( word );
                for ( i = 0; i < nGroups; i++ )
                {
                    pPtr += sizeof( byte );   
                    pPtr += 32;   

                    word nTriangles = *( word* )pPtr;
                    pPtr += sizeof( word );
                    int *pTriangleIndices = new int[nTriangles];
                    for ( int j = 0; j < nTriangles; j++ )
                    {
                        pTriangleIndices[j] = *( word* )pPtr;
                        pPtr += sizeof( word );
                    }

                    char materialIndex = *( char* )pPtr;
                    pPtr += sizeof( char );

                    m_pMeshes[i].m_materialIndex = materialIndex;
                    m_pMeshes[i].m_numTriangles = nTriangles;
                    m_pMeshes[i].m_pTriangleIndices = pTriangleIndices;
                }

              
             上面的代碼填充網(wǎng)格結(jié)構(gòu) 
              

                int nMaterials = *( word* )pPtr;
                m_numMaterials = nMaterials;
                m_pMaterials = new Material[nMaterials];
                pPtr += sizeof( word );
                for ( i = 0; i < nMaterials; i++ )
                {
                    MS3DMaterial *pMaterial = ( MS3DMaterial* )pPtr;
                    memcpy( m_pMaterials[i].m_ambient, pMaterial->m_ambient, sizeof( float )*4 );
                    memcpy( m_pMaterials[i].m_diffuse, pMaterial->m_diffuse, sizeof( float )*4 );
                    memcpy( m_pMaterials[i].m_specular, pMaterial->m_specular, sizeof( float )*4 );
                    memcpy( m_pMaterials[i].m_emissive, pMaterial->m_emissive, sizeof( float )*4 );
                    m_pMaterials[i].m_shininess = pMaterial->m_shininess;
                    m_pMaterials[i].m_pTextureFilename = new char[strlen( pMaterial->m_texture )+1];
                    strcpy( m_pMaterials[i].m_pTextureFilename, pMaterial->m_texture );
                    pPtr += sizeof( MS3DMaterial );
                }

                reloadTextures();

              
             上面的代碼加載紋理數(shù)據(jù) 
              

                delete[] pBuffer;

                return true;
            }

              
             上面的代碼設(shè)置好了一切參數(shù),但紋理還沒有載入內(nèi)存,下面的代碼完成這個功能。 
              

            void Model::reloadTextures()
            {
                for ( int i = 0; i < m_numMaterials; i++ )
                    if ( strlen( m_pMaterials[i].m_pTextureFilename ) > 0 )
                        m_pMaterials[i].m_texture = LoadGLTexture( m_pMaterials[i].m_pTextureFilename );
                    else
                        m_pMaterials[i].m_texture = 0;
            }

              
             有了數(shù)據(jù),就可以寫出繪制函數(shù)了,下面的函數(shù)根據(jù)模型的信息,按網(wǎng)格分組,分別繪制每一組的數(shù)據(jù)。 
              

            void Model::draw()
            {
                GLboolean texEnabled = glIsEnabled( GL_TEXTURE_2D );

                // 按網(wǎng)格分組繪制
                for ( int i = 0; i < m_numMeshes; i++ )
                {

                    int materialIndex = m_pMeshes[i].m_materialIndex;
                    if ( materialIndex >= 0 )
                    {
                        glMaterialfv( GL_FRONT, GL_AMBIENT, m_pMaterials[materialIndex].m_ambient );
                        glMaterialfv( GL_FRONT, GL_DIFFUSE, m_pMaterials[materialIndex].m_diffuse );
                        glMaterialfv( GL_FRONT, GL_SPECULAR, m_pMaterials[materialIndex].m_specular );
                        glMaterialfv( GL_FRONT, GL_EMISSION, m_pMaterials[materialIndex].m_emissive );
                        glMaterialf( GL_FRONT, GL_SHININESS, m_pMaterials[materialIndex].m_shininess );

                        if ( m_pMaterials[materialIndex].m_texture > 0 )
                        {
                            glBindTexture( GL_TEXTURE_2D, m_pMaterials[materialIndex].m_texture );
                            glEnable( GL_TEXTURE_2D );
                        }
                        else
                            glDisable( GL_TEXTURE_2D );
                    }
                    else
                    {
                        glDisable( GL_TEXTURE_2D );
                    }

                    glBegin( GL_TRIANGLES );
                    {
                        for ( int j = 0; j < m_pMeshes[i].m_numTriangles; j++ )
                        {
                            int triangleIndex = m_pMeshes[i].m_pTriangleIndices[j];
                            const Triangle* pTri = &m_pTriangles[triangleIndex];

                            for ( int k = 0; k < 3; k++ )
                            {
                                int index = pTri->m_vertexIndices[k];

                                glNormal3fv( pTri->m_vertexNormals[k] );
                                glTexCoord2f( pTri->m_s[k], pTri->m_t[k] );
                                glVertex3fv( m_pVertices[index].m_location );
                            }
                        }
                    }
                    glEnd();
                }

                if ( texEnabled )
                    glEnable( GL_TEXTURE_2D );
                else
                    glDisable( GL_TEXTURE_2D );
            }

              
             有了上面的函數(shù),我們來看看如何使用它們。首先,我們定義一個MilkshapeModel類。 
              

                Model *pModel = NULL;    // 定義一個指向模型類的指針

              
             接著加載模型文件 
              

                pModel = new MilkshapeModel();
                if ( pModel->loadModelData( "data/model.ms3d" ) == false )
                {
                    MessageBox( NULL, "不能加載data/model.ms3d文件", "加載錯誤", MB_OK | MB_ICONERROR );
                    return 0;                                    // 返回失敗
                }

              
             接著載入紋理 
              

                pModel->reloadTextures();

              
             完成了初始化操作,我們來實際繪制我們的模型 
              

            int DrawGLScene(GLvoid)
            {
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    // 情況緩存
                glLoadIdentity();               
                gluLookAt( 75, 75, 75, 0, 0, 0, 0, 1, 0 );

                glRotatef(yrot,0.0f,1.0f,0.0f);

                //繪制模型
                pModel->draw();

                yrot+=1.0f;
                return TRUE;                        //成功返回
            }

              
             簡單吧?下一步我們該做什么?在以后的教程中,我將會加入骨骼動畫的知識,到時候見吧!
             
             
            posted on 2007-12-22 15:08 sdfasdf 閱讀(1585) 評論(0)  編輯 收藏 引用 所屬分類: OPENGL
            久久久国产一区二区三区| 久久久99精品成人片中文字幕 | 久久免费小视频| 精品国际久久久久999波多野| 无遮挡粉嫩小泬久久久久久久| 亚洲熟妇无码另类久久久| 久久久亚洲裙底偷窥综合| 亚洲午夜久久久久久噜噜噜| 精品无码久久久久国产| 88久久精品无码一区二区毛片| 久久精品亚洲欧美日韩久久| 国内精品综合久久久40p| 久久精品www人人爽人人| 欧美亚洲另类久久综合| 97精品伊人久久大香线蕉| 亚洲乱码精品久久久久..| 久久久久四虎国产精品| 中文精品久久久久人妻不卡| 88久久精品无码一区二区毛片| 中文成人无码精品久久久不卡| 久久精品aⅴ无码中文字字幕重口| 91久久精品国产91性色也| 久久乐国产综合亚洲精品| 国产一区二区精品久久| 青青青青久久精品国产h久久精品五福影院1421| 四虎影视久久久免费| 国内精品久久国产大陆| 久久妇女高潮几次MBA| 久久久91人妻无码精品蜜桃HD| 久久精品人人做人人爽97 | 久久伊人色| 精品久久久久久久无码| 一级a性色生活片久久无| 丰满少妇人妻久久久久久4| 久久久精品国产sm调教网站| 久久婷婷人人澡人人| 国产女人aaa级久久久级| 久久99亚洲网美利坚合众国| 狠狠色丁香婷婷久久综合| 久久精品国产亚洲5555| 国产精品成人99久久久久|