在做一个Ogre3d 模型和骨骼动画转换到FBX格式的工具。中间遇到种种问题,下面将主要思路记录下来。

转换Mesh比较简单,就是遍历MeshPtr,获取顶点和索引缓冲、获取UV坐标,然后按FBX SDK的格式重新定义,然后保存即可。这个比较好弄。贴出关键代码:

bool Util::enumMeshVertex(const Ogre::String& strMesh, const Ogre::String& strGroupName, VERTEX_LIST& vecPos, INDEX_LIST& vecIndex)
    {
        Ogre::MeshPtr pMesh = Ogre::MeshManager::getSingleton().load(strMesh, strGroupName);

int nVertexCount = 0;
        int nIndexCount = 0;
        DBGSTRING("NumSubMesh: %d", pMesh->getNumSubMeshes());

for(int i=0; i<pMesh->getNumSubMeshes(); i++) {
            Ogre::SubMesh* pSubMesh = pMesh->getSubMesh(i);
            if(pSubMesh->useSharedVertices) {
                DBGSTRING("useSharedVertices");
                nVertexCount += pMesh->sharedVertexData->vertexCount;
            }else{
                nVertexCount += pSubMesh->vertexData->vertexCount;
            }
            nIndexCount += pSubMesh->indexData->indexCount;
            DBGSTRING("nIndexCount: %d", pSubMesh->indexData->indexCount);
        }

DBGSTRING("nVertexCount: %d, nIndexCount: %d", nVertexCount, nIndexCount);

for(int i=0; i<pMesh->getNumSubMeshes(); ++i) {
            Ogre::SubMesh* pSubMesh = pMesh->getSubMesh(i);

Ogre::VertexData* pVertexData = pSubMesh->useSharedVertices ? pMesh->sharedVertexData : pSubMesh->vertexData;
            const Ogre::VertexElement* posElem = pVertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
            const Ogre::VertexElement* uvElem = pVertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES);
            //const Ogre::VertexElement* normalElem = pVertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_NORMAL);

Ogre::HardwareVertexBufferSharedPtr vbuf = pVertexData->vertexBufferBinding->getBuffer(posElem->getSource());
            Ogre::HardwareVertexBufferSharedPtr uvbuf = pVertexData->vertexBufferBinding->getBuffer(uvElem->getSource());
        
            unsigned char* pVertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
        
            float* pReal;
            float* pUVReal;
            //读取顶点
            for(size_t j=0; j<pVertexData->vertexCount; ++j, pVertex += vbuf->getVertexSize()) {
                VERTEX_DATA vd;

posElem->baseVertexPointerToElement(pVertex, &pReal);
                Ogre::Vector3 pos(pReal[0], pReal[1], pReal[2]);
                vd.position = pos;

vecPos.push_back(vd);
            }
            vbuf->unlock();

//读取UV
            unsigned char* pUV = static_cast<unsigned char*>(uvbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
            for(size_t j=0; j<pVertexData->vertexCount; ++j, pUV += uvbuf->getVertexSize()) {
                uvElem->baseVertexPointerToElement(pUV, &pUVReal);
                vecPos[j].uv = Ogre::Vector2(pUVReal[0], pUVReal[1]);
            }
            uvbuf->unlock();

Ogre::IndexData* pIndexData = pSubMesh->indexData;
            Ogre::HardwareIndexBufferSharedPtr ibuf = pIndexData->indexBuffer;
            bool b32Bit = ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT;

unsigned char* pIndex = static_cast<unsigned char*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
            int nIndexSize = b32Bit ? 4 : 2;

for(size_t k=0; k<pIndexData->indexCount; k++) {
                unsigned long ulIndex = 0;
                if(b32Bit) {
                    memcpy(&ulIndex, pIndex, 4);
                }else{
                    unsigned short usIndex = 0;
                    memcpy(&usIndex, pIndex, 2);
                    ulIndex = static_cast<unsigned long>(usIndex);
                }

vecIndex.push_back(ulIndex);
                pIndex += nIndexSize;
            }
            ibuf->unlock();
        }

return vecPos.size() > 0;
    }

bool Util::exportMesh(const char* szMesh, const char* szGroupName, const char* szFileName)
    {
        VERTEX_LIST vecPos;
        INDEX_LIST vecIndex;

enumMeshVertex(szMesh, szGroupName, vecPos, vecIndex);

if(vecPos.size() <= 0){
            DBGSTRING("获取Mesh顶点数据失败");
            return false;
        }

FbxScene* pScene = FbxOgre::FbxSdk::getScene();
        pScene->Clear();

FbxMesh* pMesh = FbxMesh::Create(pScene, szMesh);

pMesh->InitControlPoints(vecPos.size());
        FbxVector4* pVertex = pMesh->GetControlPoints();
    
        for(int i=0; i<vecPos.size(); i++) {
            Ogre::Vector3 pos = vecPos[i].position;
            pVertex[i] = FbxVector4(pos.x, pos.y, pos.z);
        }

//创建三角形
        int nTriangles = vecIndex.size() / 3;
    
        for(int i=0; i<nTriangles; i++) {
            int nIndex = i*3;
            pMesh->BeginPolygon();
            pMesh->AddPolygon(vecIndex[nIndex]);
            pMesh->AddPolygon(vecIndex[nIndex+1]);
            pMesh->AddPolygon(vecIndex[nIndex+2]);

pMesh->EndPolygon();
        }

FbxNode* pNode = FbxNode::Create(pScene, szMesh);

pNode->SetNodeAttribute(pMesh);

FbxGeometryElementUV* pUVElement = pMesh->CreateElementUV("uvset");
        pUVElement->SetMappingMode(FbxGeometryElement::eByControlPoint);
        pUVElement->SetReferenceMode(FbxGeometryElement::eDirect);
        pUVElement->GetDirectArray().Resize(vecPos.size());
        for(int i=0; i<vecPos.size(); i++) {
            FbxVector2 fbxuv(vecPos[i].uv.x, 1.0f - vecPos[i].uv.y);
            pUVElement->GetDirectArray().SetAt(i, fbxuv);
        }

FbxNode* pRootNode = pScene->GetRootNode();
        pRootNode->AddChild(pNode);

return FbxOgre::FbxSdk::saveScene(szFileName);
    }

FbxOgre是我自己进行的封装,其实就是把FBX SDK的Sample代码修改了一下,具体实现看FBX SDK。

现在主要的问题是Ogre骨骼动画数据的转换,按Ogre skeleton文件读出的数据直接写入FBX的话,导入3d max骨骼的位置和动画的效果惨不忍睹,有些是正的,有些是反的,不同的skeleton文件也会出现不同的错误,头大。欢迎懂的朋友给点指导意见。

谢谢。

Ogre3D Mesh转换到FBX格式相关推荐

  1. CGR模型文件如何转换成FBX格式文件

    最近,收到一个CGR的模型文件,想要转换成FBX格式问题并进行纹理贴图,搜了一圈,费了点时间,终于找到了窍门 1.首先新装个Pro-E 2.用Pro-E打开模型文件 3.选择另存为.stl文件 4.如 ...

  2. FBX格式mesh解析与加载(一)

    ** 理解FBX格式中Mesh数据结构** fbx文件是现在许多建模动画软件和游戏引擎之间共用的模型文件格式.fbx文件分为两种方式从建模软件中导出,一种是二进制文件另一种是ASCII码保存. ASC ...

  3. 在线转换glb格式模型gltf格式模型fbx格式模型obj模型转换

    咱们一般用的软件是3dmax,C4D 这些软件做模型,但是做出来模型不能直接导出是glb格式,可以制作glb模型,扣扣:424081801 咱们可以先导出成fbx通用格式 这样就好办了,win10自带 ...

  4. Html监听Fbx文件加载,FBX格式mesh解析与加载(一)

    FBX格式mesh解析与加载(一) FBX格式mesh解析与加载(一) ** 理解FBX格式中Mesh数据结构** fbx文件是现在许多建模动画软件和游戏引擎之间共用的模型文件格式.fbx文件分为两种 ...

  5. 【Unity3D】使用 FBX 格式的外部模型 ( 向 Unity 中添加 FBX 模型 | 向 Scene 场景中添加 FBX 模型 | 3D 物体渲染 | 3D 物体材质设置 )

    文章目录 一.向 Unity 中添加 FBX 模型 二.向 Scene 场景中添加 FBX 模型 三.3D 物体渲染 四.3D 物体材质设置 一.向 Unity 中添加 FBX 模型 Unity 中使 ...

  6. 88 Three.js 导入FBX格式骨骼绑定模型

    简介 上一节,深入了解了一下SkinnedMesh模型对象的创建.这一节,我们导入外部骨骼绑定的模型,来实现动画显示.由于Three.js支持的三维格式非常多,由于导入模式大同小异,我们就选择两种格式 ...

  7. cesium模型加载-加载fbx格式模型

    整体思路: fbx格式→dae格式→gltf格式→cesium加载gltf格式模型 具体方法: 1. fbx格式→dae格式 工具:3dsMax, 3dsMax插件:OpenCOLLADA, 下载地址 ...

  8. fbx文件导入html,AE插件:导入三维文件FBX格式包括摄像机到AE颠覆性插件FBX to AE...

    AE插件:导入三维文件FBX格式包括摄像机到AE颠覆性插件FBX to AE,可结合E3D V2,粒子插件使用! Valerio Carnevale和Davide Franceschini开发了一款极 ...

  9. FBX格式解析顶点信息和用OpenGL显示

    FbxSDK是解析FBX的工具,在unity和ue中使用较多,下面介绍一下用这个工具解析FBX格式并用OpenGL显示出来. FBX的scene是由一系列node组成的,node包含一个Transfr ...

最新文章

  1. Java学习总结:24
  2. 实现Activity的滑动返回效果
  3. 如何给屏幕设置一个充满全屏的图片
  4. 软件使用: word
  5. 本地图片转base64_从一道面试题说起:GET 请求能传图片吗?
  6. jquery动态改变onclick属性导致失效的问题解决方法
  7. 初中数学知识点总结_初中物理 | 最全知识点总结
  8. [转载] Java关键字(Java 8版本)
  9. 安全性配置-定义任务流节点
  10. 涉密计算机的安全审计和检查,计算机安全保密审计报告.doc
  11. Modifier ‘public‘ is redundant for interface methods错误
  12. lua OOP实现对象的链式调用
  13. 图像处理-RGB彩色图像均衡化处理
  14. golang学习(一)—— 简介
  15. MYSQL 从PS说起,但不止于PS , IS 中innodb buffer 分析(5) -- 附加招聘DEVOPS DBA
  16. 利用PyQt5制作本地音乐播放器
  17. 编译报错“ld: cannot find -lXXX”
  18. Java虚拟机 --- JVM
  19. 人群密度检测matlab算法,基于视频的人员密度检测.doc
  20. 某计算机内存容量是512kb,某计算机主存容量为512kb,Cache容量为16kb,每块有16个字,每字32位。 (1...

热门文章

  1. 网络嗅探器的设计开发------C++
  2. Unity使用Animation动画控制物体实现slep旋转
  3. 淘宝联盟开发系列:阿里妈妈淘宝客申请步骤
  4. NVIDIA JETSON XAVIER NX烧录(sd版本)
  5. 百度定位出现经纬度值为4.9E-324问题的解决过程
  6. zip 伪加密学习,压缩包十六进制数据含义分析
  7. Lattice Diamond安装与学习
  8. 小海豚上网助手 v1.2 下载
  9. ModuleNotFoundError: No module named ‘tensorflow.compat.v2‘解决方法
  10. 小白萌新笔记——鼠标失灵