|  | 
 
| 前面的几天已经解决了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()绘制模型。
 在源文件中有关创建D3D的mesh文件部分如下:复制代码#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;
};
左手坐标系和右手坐标系: 3DsMax采用的是右手坐标系。复制代码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();
   在void GetControlsPoints(FbxMesh* pMesh)函数中处理了顶点位置和坐标系的转换。
 不过经过这样的坐标转换以后,模型位置吻合了。但是因为转换,原来索引绘制的顺序就不对了,微软的d3d采用的是顺时针绘制三角形顶点,现在反向以后三角形必须要逆时针绘制。复制代码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;
        }
}
经过这样的转换,在3DsMax中的模型创建什么样的模型,就会在d3d中完全一致的显示出来。复制代码void CD3DStaticMesh::DrawSubset(DWORD AttribId)
{
        m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
        m_pMesh->DrawSubset(AttribId);
        m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
}
 | 
 |