【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绘制出这个茶壶!

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值