网站运营问题,租外国服务器做的网站要备案吗,查询网站收录命令,中国招标与采购网Windows环境配置
FBX SDK安装后#xff0c;目录下有三个文件夹#xff1a;
include 头文件lib 编译的二进制库#xff0c;根据你项目的配置去包含相应的库samples 官方使用案列
动态链接
libfbxsdk.dll, libfbxsdk.lib是动态库#xff0c;需要在配置属性-C/C-预…Windows环境配置
FBX SDK安装后目录下有三个文件夹
include 头文件lib 编译的二进制库根据你项目的配置去包含相应的库samples 官方使用案列
动态链接
libfbxsdk.dll, libfbxsdk.lib是动态库需要在配置属性-C/C-预处理器-预处理器定义中添加FBXSDK_SHARED;
静态链接
libfbxsdk-md.lib, libfbxsdk-mt.lib 是两种静态库不同的是运行库选项在配置属性-C/C-代码生成-运行库中设置/MD或/MT/MDd和/MTd时debug模式。
mt 编译时将LIBCMT.lib编译到obj文件中连接器通过它处理外部符号会将引用的外部库集成到生成的库里面;md 编译时将MSVCRT.lib编译到obj文件中链接器会链接到MSVCRT.dll因此生成的库会比mt的小;
如果时debug模式的静态链接还需要在配置属性-链接器-输入-忽略特定默认库项添加LIBCMT配置属性-链接器-输入-附加依赖项项添加wininet.lib
注意FBX SDK可以使用多线程但是不保证线程安全。
FBX SDK基础知识
内存管理
FbxManager类用来管理FBX SDK对象的创建和销毁且每一个程序里面只能有一个FbxManager的实例。
// 创建FbxManager的实例
FbxManager* lSdkManager FbxManager::Create();
// 使用FbxManager来创建对象
FbxScene* lScene FbxScene::Create(lSdkManager, Scene Name);
// 释放所有FbxManager分配的内存
lSdkManager-Destroy();导入导出设置
FbxIOSettings ioSettings FbxIOSettings::Create(lSdkManager, IOSROOT); // 创建FbxIOSettings
mFbxSettings-SetBoolProp(IMP_FBX_MATERIAL, true); // 设置材质导入
lSdkManager-SetIOSettings(ioSettings); // 应用设置设置导入导出对象所有设置的默认值为true
mFbxSettings-SetBoolProp(IMP_FBX_MATERIAL, true) // 输入设置以“IMP_”为前缀
mFbxSettings-SetBoolProp(EXP_FBX_MATERIAL, true) // 输出设置以“EXP_”为前缀导出文件格式设置
EXP_FBX 导出二进制FBX文件能嵌入媒体文件 EXP_ASCIIFBX 导出ascii FBX文件 EXP_DXF 导出DXF文件 EXP_COLLADA 导出collada文件 EXP_OBJ 导出OBJ文件
嵌入媒体文件
只有binary fbx文件才能嵌入媒体文件。当导入有媒体文件嵌入的fbx文件(myExportFile.fbx)时将提取嵌入的媒体文件到当前目录下的myExportFile.fbm/subdirectory文件夹中。
mFbxSettings-SetBoolProp(EXP_FBX_EMBEDDED, true); // 导出Fbx binary文件时媒体文件嵌入到导出文件中设置密码保护
导出时设置密码
FbxString lString;// 将密码设置给lStringmFbxSettings-SetStringProp(EXP_FBX_PASSWORD, lString);
mFbxSettings-SetBoolProp(EXP_FBX_PASSWORD_ENABLE, true);导入时填写密码
FbxString lString;// 将密码设置给lStringmFbxSettings-SetStringProp(IMP_FBX_PASSWORD, lString);
mFbxSettings-SetBoolProp(IMP_FBX_PASSWORD_ENABLE, true);打印支持的写入和读取文件格式
void PrintWriterFormatAndReaderFormat(FbxManager* fbxManager)
{FbxIOPluginRegistry* ioPlugin fbxManager-GetIOPluginRegistry();int readerFormatCnt ioPlugin-GetReaderFormatCount();printf(read format count %d\n, readerFormatCnt);for (int i 0; i readerFormatCnt; i){const char* extension ioPlugin-GetReaderFormatExtension(i);const char* desc ioPlugin-GetReaderFormatDescription(i);printf(extension %s description %s\n, extension, desc);}int writerFormatCnt ioPlugin-GetWriterFormatCount();printf(writer format count %d\n, writerFormatCnt);for (int i 0; i writerFormatCnt; i){const char* extension ioPlugin-GetWriterFormatExtension(i);const char* desc ioPlugin-GetWriterFormatDescription(i);printf(extension %s description %s\n, extension, desc);}
}导入导出场景
导入场景
FbxImporter* lImporter FbxImporter::Create(lSdkManager, );
bool lImportStatus lImporter-Initialize(lFileName, -1, mFbxSettings); // -1 表示让fbxsdk根据文件的扩展名去判断文件的格式
if(!lImportStatus)
{printf(Call to FbxImporter::Initialize() failed.\n);printf(Error returned: %s\n\n, lImporter-GetStatus().GetErrorString());exit(-1);
}// 将文件中的内容导入到scene对象中
FbxScene* scene FbxScene::Create(lSdkManager, );
lImporter-Import(scene);// 导入完成后就可以安全销毁减少内存占用
lImporter-Destroy();索引非嵌入的多媒体文件
当ASCII FBX或其他不包含嵌入媒体的文件格式定位引用的媒体文件时遵循下面两个步骤 使用绝对路径来检查引用的多媒体文件是否存在这个绝对路径是导出场景到Fbx文件时指定的 FbxFileTexture::SetFileName() // The resource file is in the applications directory.
FbxString lTexPath gAppPath \\Crate.jpg;// Create a texture object.
FbxFileTexture* lTexture FbxFileTexture::Create(pScene,Crate Texture);// Set the textures absolute file path.
lTexture-SetFileName(lTexPath.Buffer())如果绝对路径不存在多媒体文件则使用相对路径相对路径在导出场景到FBX文件时会自动保存
获取导入文件的版本
int lFileMajor, lFileMinor, lFileRevision;
lImporter-GetFileVersion(lFileMajor, lFileMinor, lFileRevision);导出场景
FbxExporter* lExporter FbxExporter::Create(lSdkmanager, );
const char* lFilename file.fbx;
bool lExportStatus lExporter-Initialize(lFilename, -1, lSdkManager-GetIOSettings());
if(!lExportStatus) {printf(Call to FbxExporter::Initialize() failed.\n);printf(Error returned: %s\n\n, lExporter-GetStatus().GetErrorString());return false;
}FbxScene* scene FbxScene::Create(lSdkManager, myScene);
lExporter-Export(lScene);
lExporter-Destroy();坐标系和单位转换
我们读取FBX文件的数据到自己的应用中需要的坐标系和单位可能和FBX文件的不一样这时需要去修改这些设置。使用FBX SDK创建的对象是右手坐标系Y轴向上。
// 转换为OpenGL坐标系
FbxGlobalSettings globalSettings mScene-GetGlobalSettings();
if (globalSettings.GetAxisSystem() ! FbxAxisSystem::OpenGL)
{FbxAxisSystem::OpenGL.ConvertScene(mScene);
}// 转换为m作为单位
FbxSystemUnit systemUnit globalSettings.GetSystemUnit();
if (globalSettings.GetSystemUnit() ! FbxSystemUnit::m)
{const FbxSystemUnit::ConversionOptions options {false, // mConvertRrsNodestrue, // mConvertLimitstrue, // mConvertClusterstrue, // mConvertLightIntensitytrue, // mConvertPhotometricLPropertiestrue, // mConvertCameraClipPlanes};FbxSystemUnit::m.ConvertScene(mScene, options);
}注意坐标系转换只会作用到节点Transform的pre-rotaion和动画单位转换只会作用到节点Transform的scale和动画并不会作用到顶点的值比如位置法线和UV。因此顶点值的转换需要自己去处理。
OpenGL和DirectX坐标系的转换
OpenGL坐标系是Y轴向上X轴向右Z轴向屏幕外DirectX坐标系是Y轴向上X轴向右Z轴向屏幕内。如果将DirectX坐标系的顶点转换为OpenGL坐标系的顶点我们以OpenGL的坐标系为世界坐标系三个轴的基向量为 x ⃗ 0 ( 1 , 0 , 0 ) y ⃗ 0 ( 0 , 1 , 0 ) z ⃗ 0 ( 0 , 0 , 1 ) \vec x_0(1,0,0)\vec y_0(0,1,0)\vec z_0(0,0,1) x 0(1,0,0)y 0(0,1,0)z 0(0,0,1)则DirectX坐标系的三个轴的基向量为 x ⃗ d ( 1 , 0 , 0 ) y ⃗ d ( 0 , 1 , 0 ) z ⃗ d ( 0 , 0 , − 1 ) \vec x_d(1,0,0)\vec y_d(0,1,0)\vec z_d(0,0,-1) x d(1,0,0)y d(0,1,0)z d(0,0,−1)。若点 P ( x p , y p , z p ) P(x_p,y_p,z_p) P(xp,yp,zp)为DirectX坐标系中的一点将其转换为OpenGL坐标系为 ( ( x p , 0 , 0 ) ⋅ x ⃗ d , ( 0 , y p , 0 ) ⋅ y ⃗ d , ( 0 , 0 , z p ) ⋅ z ⃗ d ) ( x p , y p , − z p ) ((x_p,0,0) \cdot \vec x_d, (0,y_p,0) \cdot \vec y_d, (0,0,z_p) \cdot \vec z_d)(x_p,y_p,-z_p) ((xp,0,0)⋅x d,(0,yp,0)⋅y d,(0,0,zp)⋅z d)(xp,yp,−zp)所以x,y坐标保持不变z坐标取反。顶点的位置法线可以按照这个规则处理。
因为OpenGL是右手坐标系DirectX是左手坐标系它们三角面的顶点的顺序是相反所以 ( v 1 , v 2 , v 3 ) (v_1,v_2,v_3) (v1,v2,v3)要变成 ( v 1 , v 3 , v 2 ) (v_1,v_3,v_2) (v1,v3,v2)。
顶点的UV V n e w 1 − V V_{new}1-V Vnew1−V怎么得出来的目前不清楚。
FBX场景 每个FBX文件是一个FbxSceneFbxScene由FbxNode以树状层级结构组成。
一个场景由许多元素组成包含meshes, lights, cameras, skeletons, NURBS等这些元素继承FbxNodeAttributeFbxNode是一个或多个场景元素的容器。
FbxNode* lRootNode lScene-GetRootNode();
if(lRootNode) {for(int i 0; i lRootNode-GetChildCount(); i)PrintNode(lRootNode-GetChild(i));
}// Print a node, its attributes, and all its children recursively.
void PrintNode(FbxNode* pNode) {const char* nodeName pNode-GetName();FbxDouble3 translation pNode-LclTranslation.Get();FbxDouble3 rotation pNode-LclRotation.Get();FbxDouble3 scaling pNode-LclScaling.Get();// Print the nodes attributes.for(int i 0; i pNode-GetNodeAttributeCount(); i)PrintAttribute(pNode-GetNodeAttributeByIndex(i));// Recursively print the children.for(int j 0; j pNode-GetChildCount(); j)PrintNode(pNode-GetChild(j));
}FBX对象属性特性
FbxObject
FBX对象都继承于FbxObject比如FbxSceneFbxNodeFbxImporter, FbxExporter, FbxCollection等。
FbxCollection是FBX object的容器FbxAnimLayer, FbxAnimStack, FbxScene都是继承于它。
遍历场景的动画
int numStacks mScene-GetSrcObjectCountFbxAnimStack();
for (int i 0; i numStacks; i)
{FbxAnimStack* animStack FbxCastFbxAnimStack(mScene-GetSrcObject(i));int numAnimLayers animStack-GetMemberCountFbxAnimLayer();for (int layerIdx 0; layerIdx numAnimLayers; layerIdx){FbxAnimLayer* animLayer animStack-GetMemberFbxAnimLayer(layerIdx);···}
}FbxProperty
FbxProperty目前我知道的就是获取FbxNode的变换数据。
FbxDouble* lTranslation lNode-LclTranslation.Get().mData;
FbxDouble* lRotation lNode-LclRotation.Get().mData;
FbxDouble* lScaling lNode-LclScaling.Get().mData;属性的创建和销毁
// 创建FBX Property
FbxProperty p FbxProperty::Create(pScene, DTDouble3, Vector3Property);
FbxSetFbxDouble3(p, FbxDouble3(1.1, 2.2, 3.3);// ... initialize FbxNode* lNode ...
FbxDouble3 translation lNode-LclTranslation.Get();
FbxDouble3 rotation lNode-LclRotation.Get();
FbxDouble3 scaling lNode-LclScaling.Get(); FbxNodeAttribute
FbxNodeAttribute定义了一个场景元素比如FbxMeshFbxSkeleton。
遍历FbxNode的FbxNodeAttribute
FbxNode* pNode;
int attrCount pNode-GetNodeAttributeCount();
for (int i 0; i attrCount; i)
{FbxNodeAttribute* attribute pNode-GetNodeAttributeByIndex(i);FbxNodeAttribute::EType type attribute-GetAttributeType();switch (type){case fbxsdk::FbxNodeAttribute::eSkeleton:mSkeletonNodes.push_back(pNode);break;case fbxsdk::FbxNodeAttribute::eMesh:mFbxMeshes.push_back((FbxMesh*)attribute);break;default:break;}
}对象和属性的关系
FbxObjec和FbxObjectFbxProperty和FbxPropertyFbxObject和FbxProperty直接可以建立父子关系FBX SDK里面叫Connection。 GetSrcXXX可以理解为获取子对象GetDstXX可以理解为获取父对象
object-property FbxObject::GetSrcProperty()获取节点的属性FbxProperty::GetDstObject()获取属性绑定的节点object-object FbxObject::GetSrcObject()获取子节点FbxProperty::GetDstObject()获取父节点property-property FbxProperty::GetSrcProperty()获取子属性FbxProperty::GetDstObject()获取父属性
参考
FBX SDK文档官方案列