DirectX简单的FBX文件加载(网格MESH)

DirectX简单的FBX文件加载(网格MESH)

FBX文件加载需要用到FBX SDK,有关配置可以自己上网或者查看官方文档进行设置(参见)
http://help.autodesk.com/view/FBX/2019/ENU/添加链接描述

这里只关注FBX文件中MESH的读取(也只是读取每个顶点的坐标而已,不进行坐标变换),十分的简单。由于FBX文件是按照节点组成的树形结构,所以这里的读取方法只能读取深度遍历下第一个mesh类型的节点。不过没有关系,可以用Blender把FBX文件的结构进行重塑(比如将mesh合并,调整左右手坐标系等),关键是原理。。。。

1.FBX初始化
先进行必要的FBX初始化然后导入
注意1:FBX不支持中文路径,Blender建模的时候节点命名也不要是中文,不然会乱码。
注意2:FBX网格基本图元有很多,四边形,三角形,五边形……,但是DirectX要三角形,所以要三角化。创建一个FbxGeometryConverter对象对整个场景进行三角化

FbxManager* m_pSdkManager;
FbxIOSettings* m_pios;
FbxImporter* m_pImporter;
m_pSdkManager=FbxManager::Create();	
m_pios=FbxIOSettings::Create(m_pSdkManager,IOSROOT);	
m_pSdkManager->SetIOSettings(m_pios);
m_pImporter=FbxImporter::Create(m_pSdkManager,"");
//开始导入我们需要加载的文件,这里的_filePath就是文件路径,注意FBX不支持中文路径
bool ImportStatus=m_pImporter->Initialize(_filePath,-1,m_pSdkManager->GetIOSettings());
if(!ImportStatus) return ImportStatus; 
//获得根节点
FbxScene* pScene=FbxScene::Create(m_pSdkManager,"myScene");
m_pImporter->Import(pScene);	
FbxNode* pRootNode=pScene->GetRootNode();
//三角化所有数据
FbxGeometryConverter converter(m_pSdkManager);
converter.Triangulate(pScene,true);
//遍历节点
ProcessNode(pRootNode);

2.ProcessNode
该函数实现了节点的遍历,传入根节点即可
FbxNodeAttribute::EType可以查看文档,发现除了FbxMesh我们需要其他暂时用不上
在这里插入图片描述

void FBX::ProcessNode(FbxNode* _pFbxNode){
	FbxNodeAttribute::EType attributeType;
	if(_pFbxNode->GetNodeAttribute()!=NULL){
		attributeType=_pFbxNode->GetNodeAttribute()->GetAttributeType();
		switch(attributeType){
		case FbxNodeAttribute::EType::eMesh:
			//处理网格数据
			ProcessMesh(_pFbxNode);
			break;
		}
	}
	for(int i=0;i<=_pFbxNode->GetChildCount()-1;++i)
		ProcessNode(_pFbxNode->GetChild(i));
}

3.ProcessMesh
要点1:从FbxMesh中获得顶点数组
要点2:从FbxVector4中得到我们需要的x,y,z
要点3:得到索引数组int ctrlPointIndex=pMesh->GetPolygonVertex(i,j)
这里的含义是从第i个三角形中获得第j个顶点的索引

void FBX::ProcessMesh(FbxNode* _pFbxNode){
	if(flag!=true) return; //这里的flag是当前是否遍历到过一个MESH,如果有就不遍历了,因为懒
	flag=false;//遍历过了,调整flag
	FbxMesh* pMesh=_pFbxNode->GetMesh();
	if(!pMesh) return;
	FBX_VERTEX* pVertexArray=NULL;//FBX_VERTEX是我定义的顶点格式,只有x,y,z坐标

	//顶点的存储
	int ctrlcount=pMesh->GetControlPointsCount();
	m_VertexCount=ctrlcount;//就是顶点个数
	pVertexArray=new FBX_VERTEX[ctrlcount];
	D3DXVECTOR3 vertex;
	FbxVector4* pCtrlPoint=pMesh->GetControlPoints();//这里的控制点数组pCtrlPoint其实就是DirectX里顶点的意思,就是顶点数组
	for(unsigned int i=0;i<=ctrlcount-1;i++){
		vertex.x=pCtrlPoint[i].mData[0];//这里得到控制点(顶点)的x,y,z
		vertex.y=pCtrlPoint[i].mData[1];//这段数据的获得找了好多资料才知道的
		vertex.z=pCtrlPoint[i].mData[2];//FBX的样例真心看不懂
		//接下来存入我们的顶点数组中
		pVertexArray[i]=FBX_VERTEX(vertex);
	}
	//创建顶点缓存
	HRESULT hr=m_pd3dDevice->CreateVertexBuffer(
	ctrlcount*sizeof(FBX_VERTEX),0,FVF,D3DPOOL_MANAGED,&m_pVertexBuffer,0);
	if(FAILED(hr)) exit(1);
	//存入顶点缓存中
	FBX_VERTEX* lVertexArray;
	m_pVertexBuffer->Lock(0,0,(void**)&lVertexArray,0);
	memcpy(lVertexArray,pVertexArray,ctrlcount*sizeof(FBX_VERTEX));
	m_pVertexBuffer->Unlock();
	delete [] pVertexArray;

	//索引的存储,故技重施即可,但有一点需要注意
	int* pIndexArray=NULL;
	unsigned int triangleCount=pMesh->GetPolygonCount();//多边形图元的数量
	//因为已经三角化过,所以一定是三角形了
	m_TriangleCount=triangleCount;//三角形面片的数量
	pIndexArray=new int[triangleCount*3];//三角形面皮的数量*3就是索引的数量
	unsigned int index_count=0;
	for(unsigned int i=0;i<=triangleCount-1;i++){
		//这里一定是三角形了也可判断下
		/*
		if(pMesh->GetPolygonSize(i)!=3){return;}
		*/
		for(unsigned int j=0;j<=pMesh->GetPolygonSize(i)-1;j++){
			int ctrlPointIndex=pMesh->GetPolygonVertex(i,j);
			//这里要存入索引数组中
			pIndexArray[index_count]=ctrlPointIndex;
			index_count++;
		}
	}
	//创建索引数组
	hr=m_pd3dDevice->CreateIndexBuffer(
	(index_count+1)*sizeof(int),0,D3DFMT_INDEX32,D3DPOOL_MANAGED,&m_pIndexBuffer,0);
	if(FAILED(hr)) exit(1);
	
	int* lIndexArray;
	m_pIndexBuffer->Lock(0,0,(void**)&lIndexArray,0);
	memcpy(lIndexArray,pIndexArray,(index_count+1)*sizeof(int));
	m_pIndexBuffer->Unlock();
	delete [] pIndexArray;
	
}

4.Draw
开始绘制

void FBX::Draw(D3DXMATRIX _mat)
{
	//_mat暂时不知道干什么,但是有用,可以以后指定模型的位置
	//m_pd3dDevice->BeginScene();
	m_pd3dDevice->SetStreamSource(0,m_pVertexBuffer,0,sizeof(FBX_VERTEX));
	m_pd3dDevice->SetIndices(m_pIndexBuffer);
	m_pd3dDevice->SetFVF(FVF);
	m_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,m_VertexCount,0,m_TriangleCount);
	//m_pd3dDevice->EndScene();
}

这里只展示了部分代码,我将这些东西写了一个FBX类,用来导入FBX文件
实验怎么导入FBX网格文件,以龙书的Camera例程为主体,可以遨游观看FBX文件
效果图:
1.FBX SDK中的humanoid.fbx,这里倒了是因为这个fbx用右手坐标系,而DirectX用左手。因为可以用Blender调整这里也不管了。话说为什么高考数学要用右手坐标系做立体几何???DirectX习惯了表示只会左手坐标系,到头来答案错了一分莫得。。。。
在这里插入图片描述
2.自己用Blender做的一个简单模型(还带有动画,等以后解析完了FBX的动画在看看)
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值