• <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++博客 :: 首頁(yè) :: 聯(lián)系 ::  :: 管理
              163 Posts :: 4 Stories :: 350 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(48)

            我參與的團(tuán)隊(duì)

            搜索

            •  

            積分與排名

            • 積分 - 400062
            • 排名 - 59

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

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

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

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

            模型的定義在model.h中,好吧我們開(kāi)始吧:
             
              

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

            // 頂點(diǎn)的個(gè)數(shù)和數(shù)據(jù)
            int m_numVertices;
            Vertex *m_pVertices;

              
             在這一課你,你可以忽略m_boneID,我們將在以后的教程中介紹骨骼動(dòng)畫(huà)。m_location定義頂點(diǎn)的位置。
            下面是三角形結(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è)頂點(diǎn)構(gòu)成一個(gè)三角形,m_vertexIndices保存了三個(gè)頂點(diǎn)的索引。 m_s 和 m_t儲(chǔ)存了三個(gè)頂點(diǎn)的紋理坐標(biāo)。m_vertexNormals保存了三個(gè)頂點(diǎn)的法線。
            下面我們定義網(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ù),它是動(dòng)態(tài)分配的。 m_materialIndex 指向了這個(gè)網(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中相對(duì)的材質(zhì)。
            下面的代碼用來(lái)載入模型,我們通過(guò)重載loadModelData函數(shù)來(lái)實(shí)現(xiàn)它。

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

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

              
             以二進(jìn)制的方式打開(kāi)文件,如果失敗則返回 
              

                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();

              
             分配一個(gè)內(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;    // 如果不是一個(gè)有效的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 );
                }

              
             上面的代碼讀取頂點(diǎn)數(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 );
                }

              
             上面的代碼用來(lái)讀取三角形信息,因?yàn)镸S3D使用窗口坐標(biāo)系而OpenGL使用笛卡兒坐標(biāo)系,所以需要反轉(zhuǎn)每個(gè)頂點(diǎ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ù),但紋理還沒(méi)有載入內(nèi)存,下面的代碼完成這個(gè)功能。 
              

            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ù),就可以寫(xiě)出繪制函數(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ù),我們來(lái)看看如何使用它們。首先,我們定義一個(gè)MilkshapeModel類。 
              

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

              
             接著加載模型文件 
              

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

              
             接著載入紋理 
              

                pModel->reloadTextures();

              
             完成了初始化操作,我們來(lái)實(shí)際繪制我們的模型 
              

            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;                        //成功返回
            }

              
             簡(jiǎn)單吧?下一步我們?cè)撟鍪裁矗吭谝院蟮慕坛讨校覍?huì)加入骨骼動(dòng)畫(huà)的知識(shí),到時(shí)候見(jiàn)吧!
             
             
            posted on 2007-12-22 15:08 sdfasdf 閱讀(1588) 評(píng)論(0)  編輯 收藏 引用 所屬分類: OPENGL
            欧美国产成人久久精品| 潮喷大喷水系列无码久久精品| 91精品国产乱码久久久久久| 久久精品亚洲男人的天堂| 亚洲精品乱码久久久久久蜜桃不卡 | AAA级久久久精品无码区| 色综合久久综合中文综合网| 伊人久久无码精品中文字幕| 欧美日韩久久中文字幕| 亚洲精品无码专区久久久| 色综合久久综合中文综合网| 久久久久亚洲av成人无码电影| 久久天天躁夜夜躁狠狠| 中文字幕无码av激情不卡久久| AV无码久久久久不卡蜜桃| 久久久一本精品99久久精品66| 久久国产精品99精品国产| 久久免费高清视频| 午夜精品久久久内射近拍高清| 久久久久亚洲爆乳少妇无| 久久综合给久久狠狠97色| 久久久久亚洲AV成人网| 亚洲中文字幕无码久久综合网| 国产精品久久久久无码av| 国产视频久久| 精品蜜臀久久久久99网站| 久久丫忘忧草产品| 很黄很污的网站久久mimi色| 国内精品伊人久久久久777| 久久精品一区二区国产| 亚洲日本va中文字幕久久| 精品久久久无码人妻中文字幕 | 久久精品国产亚洲7777| 亚洲精品国产美女久久久| 久久丫精品国产亚洲av不卡| 久久精品成人欧美大片| 久久99精品久久久久久hb无码 | 久久精品国产99久久久| 精品久久久久成人码免费动漫 | 99精品久久久久中文字幕| 久久久WWW免费人成精品|