You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 21:15:34