Note · 2024年4月18日 0

FbxSDK File Import/Export FBX导入导出备注

FBX SDK用于载入和导出fbx格式的3维模型。

fbxsdk命名规则

PrefixNotes
KFbx大多数FBX SDK的类名前缀. 如: KFbxNode, KFbxScene, KFbxCamera
K很实用组件类都以K开头. 如: KString, KFCurve, KTime
p成员函数的参数由p开头. 如: pWriteFileFormat, pScene, pFilename
l局部变量(local varialbes)以l开头. 如: lWriteFileFormat, lScene, lFilename
g全局变量由g开头. 如: gStart, gStop, gCurrentTime
m成员变量(属性)由m开头. 如: mDescription, mImportname, mSelect

通过SDK manager管理内存(Managing memory with the SDK manager)

KFbxSdkManager(有时也称作SDK manager)是FBX SDK的内存管理者。初始化或者销毁FBX对象都要用到KFbxSdkManager类。
FBX应用通常都是以创建一个SDK manager对象开始,并且一般情况下,一个应用也只需要一个SDK manager对象。
如下代码展示了如何声明并初始化一个SDK manger对象。

KFbxSdkManager* mySdkManager = NULL;
...
mySdkManager = KFbxSdkManager::Create();

几乎所有FBK SDK的类有Create()和Destory()。

初始化(创建)一个FBX类对象

  1. 调用Create()
  2. 传递SDK manager对象,作为参数
// Create a scene object
KFbxScene* myScene = KFbxScene::Create(mySdkManager, "");
// Create a node object
KFbxNode* myNode = KFbxNode::Create(mySdkManager, "");
// Create am importer object
KFbxImporter* myImporter = KFbxImporter::Create(mySdkManager, "");

Create()的SDK manger对象参数将会为所要创建的FBX 对象分配内存。

一般情况下,一个FBX应用只需要一个SDK manager对象,但我们可以创建多个。

Create()的第二个参数是可选对象名。

// Create a scene object
KFbxScene* myScene = KFbxScene::Create(mySdkManager, "My Scene");
// Create a node object
KFbxNode* myNode = KFbxNode::Create(mySdkManager, "My Node");
// Create am importer object
KFbxImporter* myImporter = KFbxImporter::Create(mySdkManager, "My Importer");

销毁FBX类对象

调用Destory()即可。

// Destroy three objects
myImporter->Destroy();
myNode->Destroy();
myExporter->Destroy();

销毁FBX类对象时注意

  • 销毁FBX类对象释放的空间可以被SDK manager复用(new对象时)。
  • 销毁FBX类对象进,无需指定SDK manager。每个FBX对象在创建时都会与创建它的SDK manager建立一个双向引用。
  • 必须调用对象的Destory()来销毁对象。SDK manager会更新其他所有FBX对象与销毁对象的关联(connections)。
  • 关于connectsion,请查阅Connections.

清理FBX应用内存

使用完FBX SDK后,调用SDK manager的Destory()来清理内存。
调用SDK manager的Destory()同时也会销毁所有的FBX SDK对象。

// Delete the FBX SDK manager.
// All the object taht
// (1) have been allocated by the memory manager, AND that
// (2) have not been explicitly destoryed
// will be automatically destoryed.
if (pSdkManager) pSdkmanager->Destory();

创建空场景(Creating am emptry secne)

场景是3维场景元素(meshes, NURBS, cameras, lights, etc)的容器。一个FBX文件有且仅有一个场景。但我们的FBX应用可以包含多个场景。

场景的元素在FBX场景中以场景图(scene graph)的节点形式存在。在FBX中,场景图是树形结构,其中每个节点都有一个
表明节点包含a mesh, a camera, a light等的结构属性(node attribute)。

在载入FBX文件(或者fbxsdk支持的其他格式文件)之前,必须创建一个场景,用这个场景来装载文件里的数据。

// Create am FBX scene object
KFbxScene* myScene = KFbxScene::Create(mySdkManager, "");

创建文件impoter(Creating a file impoter)

载入文件到FBX场景中,必须先创建impoter对象。

// Create an importer
KFbxImpoter* lImporter = KFbxImpoter::Create(mySdkManager, "");

FBX SDK可以导入多种格式文件:二进制文件的FBX文件,ASCII格式的FBX文件,早期的FBX格式文件,一些非FBX格式文件(如Collada)。
用FBX导入的文件都可以称为导入文件(import file)。

const char* ImportFileName;     // Full path\filename of the file to be imported

调用Initialize()指定载入文件的路径与文件名。

const bool lImportStatus = lImporter->Initialize(pFilename);
if (!lImportStatus)
    ...// Problem with the file to be imported

importer需要知道导入文件的格式。文件扩展名不能提供足够的信息,比如.fbx扩展名的文件可以是二进制FBX文件,也可以是ASCII FBX文件。

int lFileFormat = -1;       // File format of the import file
// Detect the file format of the file to be imported
if (!pSdkManager->GetIOPluginRegistry()->DetectFileFormat(
            pFilename,
            lFileFormat
            ))
    { // ... Error handling code for "file not recognized" ... }
    lImporter->SetFileFormat(lFileFormat);

检查版本号(Checking version numbers)

当前使用FBX SDK存在多个版本: FBX SDK 2010.2, FBX SDK 2010.0, FBX SDK 2009, etc.

FBX文件类型也有多个版本号。FBX SDK 2010.2可以导出FBX 6.1格式文件,可以导入5.5, 6.0和6.1格式文件。

我们可以检查使用文件的版本是否支持我们应用使用的FBX SDK版本。

// Get the FBX file format version number for the FBX files generated
// by the version of FBX SDK that you are using.
KFbxSdkManager::GetFileFormatVersion (lSDKMajor, lSDKMinor, lSDKRevision);
// Get the FBX file format versin number of the import file
lImporter->GetFileVersion(lFileMajor, lFileMinor, lFileRevision);

出错处理(Error handling)

对于大多数FBX类的成员函数,如果调用时触发了一个错误,那么:

  • 函数返回false.
  • objectname->GetLastErrorString()返回错误消息.
  • objectname->GetLastErrorID()返回整形数据。我们可以使用FBX的枚举值或已定义的值来处理这些错误。

以下代码是导入文件操作的错误处理示例。

const bool lImportStatus = lImporter->Initialize(pFilename);
if (!lImportStatus) // Problem with the import file
{
    UI_Printf("Call to KFbxImporter::Initialize() failed.");
    UI_Printf("Error returned: %s", lImporter->GetLastErrorString());
    if (lImporter->GetLastErrorID() ==
            KFbxIO::eFILE_VERSION_NOT_SUPPORTED_YET ||
            lImporter->GetLastErrorID() == 
            KFbxIO::eFILE_VERSION_NOT_SUPPORTED_ANYMORE)
    {
        // Handle the error...
    }
}

载入文件的整体或局部(Loading all or part of an import file)

我们可以将导入文件的整体或某些局部导入到FBX场景中。例如,我们可以选择是否导入cameras, lights, animation等。
这些选择称为导入选项(import options)。以下代码设置了某些导入选项。

// Import options determine what kind of data is to be imported.
// True is default, but here we are setting import options explicitly.
IOSREF.setBoolProp(IMP_FBX_MATERIAL,        true);
IOSREF.setBoolProp(IMP_FBX_TEXTURE,         true);
IOSREF.setBoolProp(IMP_FBX_LINK,            false);
IOSREF.setBoolProp(IMP_FBX_SHAPE,           true);
IOSREF.setBoolProp(IMP_FBX_GOBO,            true);
IOSREF.setBoolProp(IMP_FBX_ANIMATION,       true);
IOSREF.setBoolProp(IMP_FBX_GLOBAL_SETTINGS, true);

IOSREF是一个便捷的宏。

#define IOSREF KFbxIOSettings::IOSettingsRef()

我们可以通过如下代码将文件导入到场景中。

lStatus = lImporter->Import(pScene);

importer将场景数据(通过导入选项指定)从导入文件中抽取出来,加载到FBX场景(场景之前可为空或不为空)中。

若导入文件不是FBX格式,importer会进行必要的转换处理,再加载到FBX场景中。

导入选项注意事项

  • 所有选项的默认值都是true,这意味着FBX SDK会导入所有支持的数据。
  • 默认情况下,导入选项应用于所有的导入文件,除非我们显示改变一个或多个选项。
  • 一旦导入选项发生改变,那么当前设置会应用于后面所有的导入过程,直至(a)选项改变(b)程序结束。
  • 在’xfbxiosettingspath.h’可以查看所有导入选项。导入选项前缀是”IMP_”。

保存场景的整体或局部(Saving all or part of a scene)

保存(导出)场景到导出文件与导入文件的过程相似。

  • 我们必须创建一个KFbxExporter类的导出对象。
  • 通过设置导出选项(export options),我们可以控制导出元素或者其他导出因子。所有导出选项可以在’kfbxiosettingspath.h’中查到。
    导出选项的前缀是”EXP_”。
  • 我们必须指定导出文件格式。
  • 我们可以将媒体(textures, sound, movies等)嵌入导出文件,也可以将这些元素存到单独文件中。

将媒体嵌入到FBX文件中(Embedding media in FBX files)

有个选项指定FBX如何处理场景媒体(textures, sound, movies等)导出文件。

bool pEmbedMedia;
... // Set pEmbedMedia to true or false
IOSREF.SetBoolProp(EXP_FBX_EMBEDDED, pEmbedMedia);
  • 如果选项为true,媒体会直接嵌入到导出文件中。只有导出FBX二进制文件时,这个选项才可用。
  • 如果选项为false,媒体不会嵌入到导出文件中。FBX文件会包含媒体文件的相关链接。

当FBX SDK导入媒体文件时,媒体数据会被提取到filename.fbm\文件夹中,这个文件夹与filename.fbx位于同一文件夹中。
如果filename.fbm\不存在,则会先创建一个filename.fbm\。