【DirectX12】3.配置FBX_SDK
配置FBX_SDK
1.介紹
FBX格式是現在最主流的用于游戲的3D模型格式,要使用DirectX12繪制模型,當然需要先用這個庫來解析模型數據。它的版權協議如下:
不是開源的并且是非商用的,假設你完成了一個引擎到時候還需要聯系他們討論版權的問題,不過前提是你想盈利。出于研究技術的目的,所以不用考慮這么多,大不了到時候再換一個格式即可。
先在官網下載對應的安裝文件:
https://www.autodesk.com/developer-network/platform-technologies/fbx-sdk-2020-2
我現在用上了vs2019,所以下載的是2020.2 vs2019的版本。
2.復制文件
安裝之后就有include和lib文件了,同時也要拷貝上License文件到我們的項目里。如下:
?
所以附加包含目錄如下:
$(SolutionDir)\FBX_SDK\include
而庫目錄如下:
$(SolutionDir)FBX_SDK\lib\vs2019\$(PlatformName)\$(Configuration)
由于$(PlatformName)返回的平臺名是Win32,而不是x86,所以需要改一下文件夾的名字,如下:
最后附加依賴項添加上:
libfbxsdk.lib
官網的教程說還需要加上預處理器定義FBXSDK_SHARED,因為我們是以動態鏈接的方式使用的。所以dll文件還需要拷貝一下,是在exe目錄:
3.準備一個茶壺
用3ds max創建一個茶壺并導出fbx格式的文件,當然也可以用網上找別人的fbx文件,不過我想從最簡單的一步一步做起這樣不容易出錯,我用的3ds max 2021。
導出fbx拷貝到對應的資源目錄(這里還包含上一章的shader文件,和生成的log文件):
4.示例代碼
我先快速的測試官方給出的示例代碼,這樣更方便理解并測試有沒有配置成功:
DNDFBX.h
/** * @file DNDFBX.h * @brief 用于封裝FBX SDK解析FBX文件 * * * @version 1.0 * @author lveyou * @date 21_03_27 * 修訂說明: 1 */#pragma once#include <fbxsdk.h>#include "DNDDebug.h"namespace DND {/*** Print the required number of tabs.*/void PrintTabs();/*** Return a string-based representation based on the attribute type.*/FbxString GetAttributeTypeName(FbxNodeAttribute::EType type);/*** Print an attribute.*/void PrintAttribute(FbxNodeAttribute* pAttribute);/*** Print a node, its attributes, and all its children recursively.*/void PrintNode(FbxNode* pNode);class DNDFBX{public:void _init();private:FbxManager* _lSdkManager;};extern DNDFBX g_fbx; }DNDFBX.cpp
#include "DNDFBX.h" #include "DNDString.h"namespace DND {DNDFBX g_fbx;/* Tab character ("\t") counter */int numTabs = 0;void PrintTabs(){for (int i = 0; i < numTabs; i++){g_debug.Write(L"\t");}}FbxString GetAttributeTypeName(FbxNodeAttribute::EType type){switch (type) {case FbxNodeAttribute::eUnknown: return "unidentified";case FbxNodeAttribute::eNull: return "null";case FbxNodeAttribute::eMarker: return "marker";case FbxNodeAttribute::eSkeleton: return "skeleton";case FbxNodeAttribute::eMesh: return "mesh";case FbxNodeAttribute::eNurbs: return "nurbs";case FbxNodeAttribute::ePatch: return "patch";case FbxNodeAttribute::eCamera: return "camera";case FbxNodeAttribute::eCameraStereo: return "stereo";case FbxNodeAttribute::eCameraSwitcher: return "camera switcher";case FbxNodeAttribute::eLight: return "light";case FbxNodeAttribute::eOpticalReference: return "optical reference";case FbxNodeAttribute::eOpticalMarker: return "marker";case FbxNodeAttribute::eNurbsCurve: return "nurbs curve";case FbxNodeAttribute::eTrimNurbsSurface: return "trim nurbs surface";case FbxNodeAttribute::eBoundary: return "boundary";case FbxNodeAttribute::eNurbsSurface: return "nurbs surface";case FbxNodeAttribute::eShape: return "shape";case FbxNodeAttribute::eLODGroup: return "lodgroup";case FbxNodeAttribute::eSubDiv: return "subdiv";default: return "unknown";}}void PrintAttribute(FbxNodeAttribute* pAttribute){if (!pAttribute) return;FbxString typeName = GetAttributeTypeName(pAttribute->GetAttributeType());FbxString attrName = pAttribute->GetName();PrintTabs();// Note: to retrieve the character array of a FbxString, use its Buffer() method.//printf(, );//g_debug.Line(String::Format(L"<attribute type='%s' name='%s'/>", String::Mbtowc(typeName.Buffer()).c_str(), String::Mbtowc(attrName.Buffer()).c_str()));}void PrintNode(FbxNode* pNode){PrintTabs();const char* nodeName = pNode->GetName();FbxDouble3 translation = pNode->LclTranslation.Get();FbxDouble3 rotation = pNode->LclRotation.Get();FbxDouble3 scaling = pNode->LclScaling.Get();// Print the contents of the node.g_debug.Line(String::Format(L"<node name='%s' translation='(%f, %f, %f)' rotation='(%f, %f, %f)' scaling='(%f, %f, %f)'>",String::Mbtowc(nodeName).c_str(),translation[0], translation[1], translation[2],rotation[0], rotation[1], rotation[2],scaling[0], scaling[1], scaling[2]));numTabs++;// Print the node's 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));numTabs--;PrintTabs();g_debug.Line(L"</node>");}void DNDFBX::_init(){// Change the following filename to a suitable filename value.const char* lFilename = "teapot.fbx";// Initialize the SDK manager. This object handles all our memory management._lSdkManager = FbxManager::Create();// Create the IO settings object.FbxIOSettings* ios = FbxIOSettings::Create(_lSdkManager, IOSROOT);_lSdkManager->SetIOSettings(ios);// Create an importer using the SDK manager.FbxImporter* lImporter = FbxImporter::Create(_lSdkManager, "");// Use the first argument as the filename for the importer.if (!lImporter->Initialize(lFilename, -1, _lSdkManager->GetIOSettings())) {g_debug.Line(L"Call to FbxImporter::Initialize() failed.");g_debug.Line(String::Mbtowc((string("Error returned: ") + string(lImporter->GetStatus().GetErrorString())).c_str(), false));auto v = lImporter->GetStatus().GetCode();exit(-1);}// Create a new scene so that it can be populated by the imported file.FbxScene* lScene = FbxScene::Create(_lSdkManager, "myScene");// Import the contents of the file into the scene.lImporter->Import(lScene);// The file is imported; so get rid of the importer.lImporter->Destroy();// Print the nodes of the scene and their attributes recursively.// Note that we are not printing the root node because it should// not contain any attributes.FbxNode* lRootNode = lScene->GetRootNode();if (lRootNode) {for (int i = 0; i < lRootNode->GetChildCount(); i++)PrintNode(lRootNode->GetChild(i));}// Destroy the SDK manager and all the other objects it was handling._lSdkManager->Destroy();return;}}前面幾個函數均是讀取數據并打印,而_init函數是最基礎的使用方式,其中lImporter->Initialize總是失敗,我一直以為是我導出的fbx文件設置不對,實際上只是文件放錯位置了,沒有讀取到文件。但是它錯誤提示竟然是Unexpected file type,很坑人啊。最后成功的打印出了一些數據。
下一步我的目標就是用DirectX12繪制出這個茶壺!
?
?
?
總結
以上是生活随笔為你收集整理的【DirectX12】3.配置FBX_SDK的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【DirectX12】2.示例三角形绘制
- 下一篇: 【DirectX12】4.用FBX_SD