使用FBX SDK 2020克隆导出带嵌入纹理FBX文件的问题
问题与解答
问题描述
使用CloneManager克隆包含2-3个网格、材质及纹理的场景组,目标是导出带有材质和嵌入纹理的FBX文件。目前已分离出目标模型,但模型无纹理显示;克隆后的新场景中网格虽包含指向fbm路径的纹理路径,但打开文件时仍看不到纹理,且对应fbm文件未自动生成。有两个疑问:
- 是否真正克隆了纹理?
- 是否成功导出了纹理?
代码片段
#include <iostream> #include "Common.h" #include "Util.h" #include <string> #include <fbxsdk/core/fbxobject.h> #include "fbxsdk.h" using namespace std; int main(int, char **) { std::cout << "Hello, Start!\n"; FbxManager *lSdkManager = nullptr; FbxScene *lScene = nullptr; // Prepare the FBX SDK. InitializeSdkObjects(lSdkManager, lScene); string lFilePath = "/Users/Downloads/new_scene1_0.fbx"; string targetPath = "/Users/CLionProjects/CMakeLists/test/"; LoadScene(lSdkManager, lScene, lFilePath.c_str()); FbxNode *rootNode = lScene->GetRootNode(); int childCount = rootNode->GetChildCount(); for (int i = 0; i < 1; i++) { auto pScene = FbxScene::Create(lSdkManager, "My Scene"); auto node = rootNode->GetChild(i); // clone CloneAndSetting(lScene, pScene, node); auto pSceneRoot = pScene->GetRootNode(); GetNodeNameAndAttributeTypeName(pSceneRoot); GetDefaultTranslationInfo(pSceneRoot); GetNodeVisibility(pSceneRoot); std::cout << "pScene srcCount: " << pScene->GetSrcObjectCount() << "\n"; std::cout << "pScene geoCount: " << pScene->GetGeometryCount() << "\n"; std::cout << "pScene matCount: " << pScene->GetMaterialCount() << "\n"; std::cout << "pScene nodeCount: " << pScene->GetNodeCount() << "\n"; GetNodeCountInfo(pSceneRoot); // find the first group node FbxObject *shapeNode = nullptr; for (int j = 0; j < pSceneRoot->GetSrcObjectCount(); ++j) { auto obj = pSceneRoot->GetSrcObject(j); string name = obj->GetName(); if (name.find("Shape") != string::npos) { shapeNode = obj; } } // disconnect some connection, and connect the shape to root pSceneRoot->DisconnectAllSrcObject(); GetNodeCountInfo(pSceneRoot); //shapeNode->DisconnectAllDstObject(); shapeNode->ConnectDstObject(pSceneRoot); GetNodeCountInfo(pSceneRoot); for (int j = 0; j < pSceneRoot->GetChildCount(); j++) { auto shape = pSceneRoot->GetChild(j); std::cout << "c name: " << shape->GetName() << "\n"; std::cout << "c type: " << shape->GetTypeName() << "\n"; std::cout << "c dst: " << shape->GetDstObject()->GetName() << "\n"; int groupCount = shape->GetChildCount(); for (int k = 0; k < groupCount; k++) { auto group = shape->GetChild(k); auto groupChildCount = group->GetChildCount(); for (int l = 0; l < groupChildCount; l++) { FbxNode *meshNode = group->GetChild(l); FbxSurfaceMaterial *meshMat = meshNode->GetMaterial(0); FbxProperty meshMatProp = meshMat->FindProperty(FbxSurfaceMaterial::sDiffuse); string texPath = nullptr; int layeredTextureCount = meshMatProp.GetSrcObjectCount<FbxLayeredTexture>(); if (layeredTextureCount != 0) { std::cout << "link layer" << "\n"; auto *layeredTexture = meshMatProp.GetSrcObject<FbxLayeredTexture>(); for (int m = 0; m < layeredTexture->GetSrcObjectCount<FbxTexture>(); m++) { auto *fbxFileTexture = FbxCast<FbxFileTexture>(layeredTexture->GetSrcObject<FbxTexture>(m)); string fileName = fbxFileTexture->GetFileName(); texPath = fileName; } } int textureCount = meshMatProp.GetSrcObjectCount<FbxTexture>(); if (textureCount != 0) { std::cout << "link mat" << "\n"; auto *fbxTexture = FbxCast<FbxTexture>(meshMatProp.GetSrcObject<FbxTexture>(0)); auto *fbxFileTexture = FbxCast<FbxFileTexture>(fbxTexture); string fileName = fbxFileTexture->GetFileName(); std::cout << "fileName: " << fileName << "\n"; texPath = fileName; } meshNode->GetMesh()->Set } } } for (int j = 0; j < pSceneRoot->GetSrcObjectCount(); j++) { std::cout << "s name: " << pSceneRoot->GetSrcObject(j)->GetName() << "\n"; std::cout << "s type: " << pSceneRoot->GetSrcObject(j)->GetTypeName() << "\n"; std::cout << "s dst: " << pSceneRoot->GetSrcObject(j)->GetDstObject()->GetName() << "\n"; } std::cout << "-----start generate------\n"; string meshName = node->GetName(); meshName = targetPath + meshName + ".fbx"; lSdkManager->GetIOSettings()->SetBoolProp(EXP_FBX_EMBEDDED, true); SaveScene(lSdkManager, pScene, meshName.c_str()); pScene->Destroy(); std::cout << "----" << i << " end----\n"; } }
解答
1. 是否真正克隆了纹理?
没有完整克隆纹理数据,仅复制了纹理的路径引用:
- 你的
CloneAndSetting函数如果使用默认克隆逻辑,FBX SDK默认只会克隆节点、网格、材质的结构,对于外部纹理文件,仅复制路径引用,不会将纹理数据克隆到新场景中。 - 代码中仅遍历读取了纹理路径,未执行克隆纹理对象的逻辑,新场景里的纹理只是原场景的引用,并非独立资源。
pSceneRoot->DisconnectAllSrcObject()操作会断开根节点的所有源连接,其中可能包含材质与纹理的关联,进一步导致纹理无法被新场景识别。
2. 是否成功导出了纹理?
没有成功导出嵌入纹理:
- 虽然设置了
EXP_FBX_EMBEDDED为true,但新场景中仅存纹理路径,没有实际包含纹理对象,FBX SDK无法找到纹理文件进行嵌入。 - 代码中
meshNode->GetMesh()->Set是不完整的,会导致编译错误或逻辑中断,影响材质纹理的关联处理。 - 缺少纹理嵌入的关键配置,部分FBX SDK版本需要显式开启
EXP_FBX_TEXTURE_EMBED参数才能嵌入纹理。
修复方案
- 确保克隆完整纹理对象:修改
CloneAndSetting中的克隆逻辑,使用深度克隆模式,将纹理复制到新场景:FbxNode* clonedNode = node->Clone(pScene, FbxObject::eDeepClone, FbxObject::eCloneChildren); pScene->GetRootNode()->AddChild(clonedNode); - 修复连接操作:不要直接断开根节点的所有源连接,仅断开不需要的关联,避免破坏材质与纹理的连接。
- 补全代码:删除或补全
meshNode->GetMesh()->Set这行不完整的代码,保证逻辑正常执行。 - 完善导出配置:添加纹理嵌入的相关设置:
lSdkManager->GetIOSettings()->SetBoolProp(EXP_FBX_EMBEDDED, true); lSdkManager->GetIOSettings()->SetBoolProp(EXP_FBX_TEXTURE_EMBED, true); - 验证纹理存在:导出前通过
pScene->GetTextureCount()检查新场景中是否包含纹理对象,确认克隆成功。
内容的提问来源于stack exchange,提问作者zhipeng pei
相关产品推荐
相关产品推荐

