• <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>

            白云哥

            身披半件長工衣,懷揣一顆地主心

             

            魔獸mdx文件導出為Ogre Mesh的小進展

                最近一直在試圖把魔獸3的mdx文件轉為Ogre Mesh,學習一下基礎的3D編程。Ogre Mesh的導出在很久之前也曾試圖做過,并且還把WOW的m2模型以及WMO模型導入到了Max中,但是只做到了骨架的導入,動畫數據始終出不來,于是放棄。

             

                這次依然是碰到這里的問題,導出靜態的Mesh很快就完成,包括模型與材質,代碼也比較簡單。

             

            // 模型數據
            bool ModelLoaderMdx::loadGeosets(Ogre::MeshPtr model, MdxDataStreamPtr dataStream, int size)
            {
                unsigned int index = 0;
                while(size > 0)
                {
                    int geosetSize = dataStream->read<int>();
                    size -= geosetSize;
            
                    Ogre::String meshName = m_modelName + Ogre::String("_sub_") + Ogre::StringConverter::toString(index++);
                    Ogre::SubMesh* subMesh = model->createSubMesh(meshName);
                
                    // 硬件緩沖編號
                    // 分別為頂點坐標 法線 貼圖坐標
            #define HARDWARE_BUFFER_SOURCE_VERTEX 0
            #define HARDWARE_BUFFER_SOURCE_NORMAL 1
            #define HARDWARE_BUFFER_SOURCE_TEXPOS 2
            
            
                    //
                    // 頂點數據
                    //
                    if(!expectTag(dataStream, 'VRTX')) 
                    {
                        OGRE_EXCEPT(Ogre::Exception::ERR_INTERNAL_ERROR, "Expect VRTX data for geoset",
                            "ModelLoaderMdx::loadGeosets");
                    }
            
                    unsigned int vertexCount = dataStream->read<unsigned int>();
            
                    // 不使用共享頂點數據
                    // 每個SubMesh都創建自己的VertexData
                    subMesh->useSharedVertices = false;
                    subMesh->vertexData = OGRE_NEW Ogre::VertexData();
            
                    subMesh->vertexData->vertexStart = 0;
                    subMesh->vertexData->vertexCount = vertexCount;
            
                    subMesh->vertexData->vertexDeclaration->addElement(
                        HARDWARE_BUFFER_SOURCE_VERTEX, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
            
                    size_t vertexSize = sizeof(float) * 3;
                    assert(subMesh->vertexData->vertexDeclaration->getVertexSize(HARDWARE_BUFFER_SOURCE_VERTEX) == vertexSize);
                    if (subMesh->vertexData->vertexDeclaration->getVertexSize(HARDWARE_BUFFER_SOURCE_VERTEX) != vertexSize)
                    {
                        OGRE_EXCEPT(Ogre::Exception::ERR_INTERNAL_ERROR, "VertexSize error", 
                            "ModelLoaderMdx::loadGeoset");
                    }
            
                    Ogre::HardwareVertexBufferSharedPtr vertexBuffer;
                    vertexBuffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
                        vertexSize,
                        vertexCount,
                        Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
                    void* vertexBufferData = vertexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD);
            
                    unsigned int vertexBufferDataPos = 0;
                    for (unsigned int i = 0; i < vertexCount; ++i)
                    {
                        Ogre::Vector3 data(
                            dataStream->read<float>(),
                            dataStream->read<float>(),
                            dataStream->read<float>()
                            );
                        transformCoord(data);
                        memcpy((char*)vertexBufferData + vertexBufferDataPos, &data, sizeof(Ogre::Vector3));
                        vertexBufferDataPos += sizeof(Ogre::Vector3);
                    }
            
                    vertexBuffer->unlock();
                    subMesh->vertexData->vertexBufferBinding->setBinding(HARDWARE_BUFFER_SOURCE_VERTEX, vertexBuffer);
            
            
                    //
                    // 法線數據
                    //
                    if(!expectTag(dataStream, 'NRMS'))
                    {
                        OGRE_EXCEPT(Ogre::Exception::ERR_INTERNAL_ERROR, "Expect NRMS data for material",
                            "ModelLoaderMdx::loadGeosets");
                    }
            
                    unsigned int normalCount = dataStream->read<unsigned int>();
                    if(normalCount != vertexCount)
                    {
                        std::stringstream stream;
                        stream << "Normal count mismatch, " << normalCount << " normals for " << vertexCount << " vertices)!";
                        OGRE_EXCEPT(Ogre::Exception::ERR_INTERNAL_ERROR, stream.str(), 
                            "ModelLoaderMdx::loadGeoset");
                    }
            
                    subMesh->vertexData->vertexDeclaration->addElement(
                        HARDWARE_BUFFER_SOURCE_NORMAL, 0, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
            
                    size_t normalSize = sizeof(float) * 3;
                    assert(subMesh->vertexData->vertexDeclaration->getVertexSize(HARDWARE_BUFFER_SOURCE_NORMAL) == normalSize);
                    if (subMesh->vertexData->vertexDeclaration->getVertexSize(HARDWARE_BUFFER_SOURCE_NORMAL) != normalSize)
                    {
                        OGRE_EXCEPT(Ogre::Exception::ERR_INTERNAL_ERROR, "NormalSize error", 
                            "ModelLoaderMdx::loadGeoset");
                    }
            
                    Ogre::HardwareVertexBufferSharedPtr normalBuffer;
                    normalBuffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
                        normalSize,
                        normalCount,
                        Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
                    void* normalBufferData = normalBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD);
            
                    unsigned int normalBufferDataPos = 0;
                    for (unsigned int i = 0; i < normalCount; ++i)
                    {
                        Ogre::Vector3 data(
                            dataStream->read<float>(),
                            dataStream->read<float>(),
                            dataStream->read<float>()
                            );
                        transformCoord(data);
                        memcpy((char*)normalBufferData + normalBufferDataPos, &data, sizeof(Ogre::Vector3));
                        normalBufferDataPos += sizeof(Ogre::Vector3);
                    }
            
                    normalBuffer->unlock();
                    subMesh->vertexData->vertexBufferBinding->setBinding(HARDWARE_BUFFER_SOURCE_NORMAL, normalBuffer);
            
            
            …………
                    //
                    // 頂點索引
                    //
                    if(!expectTag(dataStream, 'PVTX')) 
                    {
                        OGRE_EXCEPT(Ogre::Exception::ERR_INTERNAL_ERROR, "Expect PVTX data for geoset",
                            "ModelLoaderMdx::loadGeosets");
                    }
            
                    unsigned int indexCount = dataStream->read<unsigned int>();
                    assert(totalIndexCount == indexCount);
                    if (totalIndexCount != indexCount)
                    {
                        std::stringstream stream;
                        stream << "indexCount is " << indexCount << ", but totalIndexCount for all faces is " << totalIndexCount;
                        OGRE_EXCEPT(Ogre::Exception::ERR_INTERNAL_ERROR, stream.str(), 
                            "ModelLoaderMdx::loadGeoset");
                    }
            
                    subMesh->indexData->indexStart = 0;
                    subMesh->indexData->indexCount = indexCount;
            
                    Ogre::HardwareIndexBufferSharedPtr indexBuffer;
                    indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
                        Ogre::HardwareIndexBuffer::IT_16BIT,
                        indexCount,
                        Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
            
                    void* indexBufferData = indexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD);
                    dataStream->read(indexBufferData, indexCount * sizeof(unsigned short));
            
                    // 三角形反轉, 將原來的反面朝外
                    unsigned short* tmpData = (unsigned short*)indexBufferData;
                    for (unsigned int i = 0; i < indexCount; i += 3)
                    {
                        unsigned short tmp = tmpData[i + 1];
                        tmpData[i + 1] = tmpData[i + 2];
                        tmpData[i + 2] = tmp;
                    }
            
                    indexBuffer->unlock();
            
            
                    subMesh->indexData->indexBuffer = indexBuffer;
                    subMesh->operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST;
            
            
            …………
            
                    // 材質ID
                    unsigned int materialID = dataStream->read<unsigned int>();
                    Ogre::String materialName = m_modelName + Ogre::String("_") + boost::lexical_cast<Ogre::String>(materialID);
                    subMesh->setMaterialName(materialName);
            
            …………
            
                    //
                    // 貼圖坐標
                    //
                    if(!expectTag(dataStream, 'UVBS')) 
                    {
                        OGRE_EXCEPT(Ogre::Exception::ERR_INTERNAL_ERROR, "Expect UVBS data for geoset",
                            "ModelLoaderMdx::loadGeosets");
                    }
            
                    unsigned int texturePositionCount = dataStream->read<unsigned int>();
                    if(texturePositionCount != vertexCount)
                    {
                        std::stringstream stream;
                        stream << "Texture position count mismatch, " << texturePositionCount << " texture positions for " << vertexCount << " vertices)!";
                        OGRE_EXCEPT(Ogre::Exception::ERR_INTERNAL_ERROR, stream.str(), 
                            "ModelLoaderMdx::loadGeoset");
                    }
            
                    // TextureCoord Data
                    subMesh->vertexData->vertexDeclaration->addElement(
                        HARDWARE_BUFFER_SOURCE_TEXPOS, 0, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES);
            
                    size_t texPosSize = sizeof(float) * 2;
                    assert(subMesh->vertexData->vertexDeclaration->getVertexSize(HARDWARE_BUFFER_SOURCE_TEXPOS) == texPosSize);
                    if (subMesh->vertexData->vertexDeclaration->getVertexSize(HARDWARE_BUFFER_SOURCE_TEXPOS) != texPosSize)
                    {
                        OGRE_EXCEPT(Ogre::Exception::ERR_INTERNAL_ERROR, "TexturePositionSize error", 
                            "ModelLoaderMdx::loadGeoset");
                    }
            
                    Ogre::HardwareVertexBufferSharedPtr texPosBuffer;
                    texPosBuffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
                        texPosSize,
                        texturePositionCount,
                        Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
                    void* texPosBufferData = texPosBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD);
                    dataStream->read(texPosBufferData, texPosSize * texturePositionCount);
                    texPosBuffer->unlock();
                    subMesh->vertexData->vertexBufferBinding->setBinding(HARDWARE_BUFFER_SOURCE_TEXPOS, texPosBuffer);
                }
            
                return true;
            }

             

                但是到了動畫數據這里問題又出來了,而且mdx模型與m2模型還有些差別,mdx模型中沒有骨骼數據,只有max中最簡單的三種變換數據,Ogre中只有MorphAnimation能夠實現此種動畫。

             

                Ogre的MorphAnimation的第一個KeyFrame必須帶有完整的頂點信息,而mdx模型中旋轉、縮放與位移是分開的,也就是一個KeyFrame上可能只有一種變換,或者多種。而實際上在max中制作動畫的時候這三種變換也是獨立開的,Ogre的論壇上找到一篇討論有人提到了這個問題,可惜制作者的回復是MorphAnimation只實現到這樣……

             

                也確實,現在除了一些小物件的動畫外,主角,怪物的動畫都用skeleton了,也許MorphAnimation就快退出歷史的舞臺,在Ogre中看不到了,也不能指望會有什么改進。

             

                繼續實現之,那就只能在有KeyFrame的地方把三種變換都計算一次,然后取得最終變換后的位置數據,也就是做人工的動畫幀采樣。在War3EditorSource的基礎上做了些修改,終于,一幀幀的動畫計算出來了。

             

            mdx2mesh_anim

             

                不過問題依然還有很多,比如mdx模型,尤其是怪物和角色模型中大量用到了ReplacableTexture,這些需要通過讀配置文件來獲取可用的貼圖,另外模型上附帶的粒子特效、紋理動畫等都還沒有導出,看看這個沒有貼圖的攻擊中的蝎子,前面的路仍然很遠。

             

            mdx2mesh_anim_attack

            posted on 2009-08-07 22:42 白云哥 閱讀(2317) 評論(0)  編輯 收藏 引用 所屬分類: Ogre

            導航

            統計

            常用鏈接

            留言簿(4)

            隨筆分類

            隨筆檔案

            相冊

            我的鏈接

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            狠狠综合久久综合88亚洲| 欧美激情精品久久久久| 欧美伊人久久大香线蕉综合69| 久久播电影网| 亚洲精品国精品久久99热一| 久久91精品久久91综合| 久久99精品久久久久久水蜜桃| 午夜视频久久久久一区 | 久久精品午夜一区二区福利| 国产精品美女久久久久| 精品99久久aaa一级毛片| 2021国内久久精品| 久久99国产精品一区二区| 日韩欧美亚洲国产精品字幕久久久| 综合网日日天干夜夜久久| 国产午夜精品久久久久九九电影| 精产国品久久一二三产区区别| 国产午夜福利精品久久2021| 久久国产视屏| 精品久久777| 久久精品中文闷骚内射| 国产精品美女久久福利网站| 青青青青久久精品国产h| 色婷婷综合久久久久中文| 青青青青久久精品国产h久久精品五福影院1421 | 精品国产一区二区三区久久| 久久人人爽人人爽人人片AV东京热| 久久99久久99精品免视看动漫| 尹人香蕉久久99天天拍| 色婷婷噜噜久久国产精品12p| 久久久91精品国产一区二区三区 | 国产成人无码精品久久久免费| 日产精品99久久久久久| 国产精品久久久久免费a∨| 久久久久久久综合日本| 久久美女人爽女人爽| 狠狠色丁香久久综合五月| 久久人人妻人人爽人人爽| 亚洲欧美成人综合久久久| 狠狠色丁香久久婷婷综合图片| 久久综合视频网|