|
前面的几天已经解决了FBX文件中读取顶点坐标和顶点色。不过发现了新的问题就是,在3DsMax中创建的模型和读出来的位置不一致。
经过研究发现错误在于 3DsMax 里的坐标系是z轴朝上的右手坐标系,而在我们的D3Dx中采用的坐标系是y轴朝上,z轴朝屏幕内部的左手坐标系。而且这两个坐标系之间没有办法直接转换。因此在我们读取FBX的时候就需要将3DsMax 的坐标系转化成dx坐标系。
源代码下载:
http://kuai.xunlei.com/d/SHDXVURIKERO
备用地址:
金山快盘附件:FBX_Samples03.zip(3.24MB)
为了更客观地看到3DsMax中的模型与绘制的一致,就不能只用Box来测试,因此扩展了一个CD3DStaticMesh类。通过这个类加载各式各样的模型测试,这样才能确保我们的转化工作是对的。(源代码中增加了若干模型)
先介绍一下CD3DStaticMesh类。这里面涉及到d3d的D3DXCreateMeshFVF()创建模型和DrawSubset()绘制模型。- #pragma once
- #include <fbxsdk.h>
- #include <Windows.h>
- #include <d3dx9.h>
- class CD3DStaticMesh
- {
- struct CUSTOMVERTEX
- {
- D3DXVECTOR3 pos;
- unsigned long color; // The color
- };
- public:
- CD3DStaticMesh(void);
- ~CD3DStaticMesh(void);
- bool LoadMeshFromFBX(const char* pSeneName,DWORD Options,DWORD FVF,LPDIRECT3DDEVICE9 pD3DDevice);
- void DrawSubset(DWORD AttribId);
- void Release();
- private:
- bool Initialize();
- bool LoadFile(const char* pSeneName);
- void GetFBXVertexInfo(void* v);
- void GetFBXIndexInfo(void* v);
- void GetPolygonsInfo(FbxMesh* pMesh);
- void FbxObjectContent();
- void FbxObjectContent(FbxNode* pNode);
- void GetMeshInfo(FbxNode* pNode);
- void GetControlsPoints(FbxMesh* pMesh);
- void GetControlsIndexPoints(FbxMesh* pMesh);
- private:
- LPDIRECT3DDEVICE9 m_pd3dDevice;
- FbxManager* m_pFBXSDKManager;
- FbxScene* m_pFBXSDKScene;
- LPD3DXMESH m_pMesh;
- int m_VertexCount;
- int m_FaceCount;
- CUSTOMVERTEX *m_vBuffer;
- DWORD *m_iBuffer;
- int m_VertexColor;
- };
复制代码 在源文件中有关创建D3D的mesh文件部分如下:- D3DXCreateMeshFVF(m_FaceCount,m_VertexCount,Options,FVF,pD3DDevice,&m_pMesh);
- if(!m_pMesh)
- return false;
- GetFBXVertexInfo(m_vBuffer);
- CUSTOMVERTEX* pVertex;
- m_pMesh->LockVertexBuffer( 0, (void**) &pVertex );
- memcpy( pVertex, m_vBuffer,m_VertexCount*sizeof(CUSTOMVERTEX) );
- m_pMesh->UnlockVertexBuffer();
- GetFBXIndexInfo(m_iBuffer);
- DWORD* pIndex;
- m_pMesh->LockIndexBuffer( 0, (void**) &pIndex );
- memcpy( pIndex, m_iBuffer,m_FaceCount*3*sizeof(DWORD) );
- m_pMesh->UnlockIndexBuffer();
复制代码 左手坐标系和右手坐标系: 3DsMax采用的是右手坐标系。
在void GetControlsPoints(FbxMesh* pMesh)函数中处理了顶点位置和坐标系的转换。- void CD3DStaticMesh::GetControlsPoints(FbxMesh* pMesh)
- {
- m_VertexCount = pMesh->GetControlPointsCount();
- FbxVector4* lControlPoints = pMesh->GetControlPoints();
-
- FbxVector4 temp;
- D3DXMATRIX matrix;
- D3DXMatrixRotationX(&matrix, -(3.14/2));
- m_vBuffer = new CUSTOMVERTEX[m_VertexCount];
- D3DXVECTOR3 Rotemp;
- for (int i = 0; i < m_VertexCount; i++)
- {
- temp = lControlPoints[i];
- m_vBuffer[i].pos.x = temp.mData[0]*(-1);
- m_vBuffer[i].pos.y = temp.mData[1];
- m_vBuffer[i].pos.z = temp.mData[2];
- D3DXVec3TransformCoord(&m_vBuffer[i].pos,&m_vBuffer[i].pos,&matrix);
- m_vBuffer[i].color = 0xffffffff;
- }
- }
复制代码 不过经过这样的坐标转换以后,模型位置吻合了。但是因为转换,原来索引绘制的顺序就不对了,微软的d3d采用的是顺时针绘制三角形顶点,现在反向以后三角形必须要逆时针绘制。- void CD3DStaticMesh::DrawSubset(DWORD AttribId)
- {
- m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
- m_pMesh->DrawSubset(AttribId);
- m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
- }
复制代码 经过这样的转换,在3DsMax中的模型创建什么样的模型,就会在d3d中完全一致的显示出来。
|
|