【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 3803|回复: 0

FBX(3) 完成模型的载入

[复制链接]
发表于 2012-9-12 17:32:51 | 显示全部楼层 |阅读模式
前面的几天已经解决了FBX文件中读取顶点坐标和顶点色。不过发现了新的问题就是,在3DsMax中创建的模型和读出来的位置不一致。
经过研究发现错误在于 3DsMax 里的坐标系是z轴朝上的右手坐标系,而在我们的D3Dx中采用的坐标系是y轴朝上,z轴朝屏幕内部的左手坐标系。而且这两个坐标系之间没有办法直接转换。因此在我们读取FBX的时候就需要将3DsMax 的坐标系转化成dx坐标系。
未命名副本.jpg
源代码下载:
http://kuai.xunlei.com/d/SHDXVURIKERO
备用地址:
金山快盘附件FBX_Samples03.zip(3.24MB)
为了更客观地看到3DsMax中的模型与绘制的一致,就不能只用Box来测试,因此扩展了一个CD3DStaticMesh类。通过这个类加载各式各样的模型测试,这样才能确保我们的转化工作是对的。(源代码中增加了若干模型)
先介绍一下CD3DStaticMesh类。这里面涉及到d3d的D3DXCreateMeshFVF()创建模型和DrawSubset()绘制模型。
  1. #pragma once
  2. #include <fbxsdk.h>
  3. #include <Windows.h>
  4. #include <d3dx9.h>

  5. class CD3DStaticMesh
  6. {
  7.         struct CUSTOMVERTEX
  8.         {
  9.                 D3DXVECTOR3         pos;
  10.                 unsigned long color;    // The color
  11.         };

  12. public:
  13.         CD3DStaticMesh(void);
  14.         ~CD3DStaticMesh(void);

  15.         bool LoadMeshFromFBX(const char* pSeneName,DWORD Options,DWORD FVF,LPDIRECT3DDEVICE9 pD3DDevice);
  16.         void DrawSubset(DWORD AttribId);
  17.         void Release();

  18. private:        
  19.         bool Initialize();
  20.         bool LoadFile(const char* pSeneName);
  21.         void GetFBXVertexInfo(void* v);
  22.         void GetFBXIndexInfo(void* v);
  23.         void GetPolygonsInfo(FbxMesh* pMesh);
  24.         void FbxObjectContent();
  25.         void FbxObjectContent(FbxNode* pNode);
  26.         void GetMeshInfo(FbxNode* pNode);
  27.         void GetControlsPoints(FbxMesh* pMesh);
  28.         void GetControlsIndexPoints(FbxMesh* pMesh);

  29. private:        
  30.         LPDIRECT3DDEVICE9        m_pd3dDevice;
  31.         FbxManager*                        m_pFBXSDKManager;
  32.         FbxScene*                        m_pFBXSDKScene;
  33.         LPD3DXMESH                        m_pMesh;

  34.         int                                        m_VertexCount;
  35.         int                                        m_FaceCount;
  36.         CUSTOMVERTEX                *m_vBuffer;
  37.         DWORD                                *m_iBuffer;
  38.         int                                        m_VertexColor;
  39. };
复制代码
在源文件中有关创建D3D的mesh文件部分如下:
  1. D3DXCreateMeshFVF(m_FaceCount,m_VertexCount,Options,FVF,pD3DDevice,&m_pMesh);

  2.         if(!m_pMesh)
  3.                 return false;

  4.         GetFBXVertexInfo(m_vBuffer);
  5.         CUSTOMVERTEX* pVertex;
  6.         m_pMesh->LockVertexBuffer( 0, (void**) &pVertex );
  7.         memcpy( pVertex, m_vBuffer,m_VertexCount*sizeof(CUSTOMVERTEX) );
  8.         m_pMesh->UnlockVertexBuffer();

  9.         GetFBXIndexInfo(m_iBuffer);
  10.         DWORD* pIndex;
  11.         m_pMesh->LockIndexBuffer( 0, (void**) &pIndex );
  12.         memcpy( pIndex, m_iBuffer,m_FaceCount*3*sizeof(DWORD) );
  13.         m_pMesh->UnlockIndexBuffer();
复制代码
左手坐标系和右手坐标系: 3DsMax采用的是右手坐标系。
math_vector.jpg
在void GetControlsPoints(FbxMesh* pMesh)函数中处理了顶点位置和坐标系的转换。
  1. void CD3DStaticMesh::GetControlsPoints(FbxMesh* pMesh)
  2. {
  3.         m_VertexCount = pMesh->GetControlPointsCount();
  4.         FbxVector4* lControlPoints = pMesh->GetControlPoints();        
  5.         
  6.         FbxVector4                temp;
  7.         D3DXMATRIX                matrix;
  8.         D3DXMatrixRotationX(&matrix, -(3.14/2));
  9.         m_vBuffer = new CUSTOMVERTEX[m_VertexCount];

  10.         D3DXVECTOR3    Rotemp;
  11.         for (int i = 0; i < m_VertexCount; i++)
  12.         {
  13.                 temp = lControlPoints[i];
  14.                 m_vBuffer[i].pos.x = temp.mData[0]*(-1);
  15.                 m_vBuffer[i].pos.y = temp.mData[1];
  16.                 m_vBuffer[i].pos.z = temp.mData[2];
  17.                 D3DXVec3TransformCoord(&m_vBuffer[i].pos,&m_vBuffer[i].pos,&matrix);
  18.                 m_vBuffer[i].color = 0xffffffff;
  19.         }
  20. }
复制代码
不过经过这样的坐标转换以后,模型位置吻合了。但是因为转换,原来索引绘制的顺序就不对了,微软的d3d采用的是顺时针绘制三角形顶点,现在反向以后三角形必须要逆时针绘制。
  1. void CD3DStaticMesh::DrawSubset(DWORD AttribId)
  2. {
  3.         m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
  4.         m_pMesh->DrawSubset(AttribId);
  5.         m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
  6. }
复制代码
经过这样的转换,在3DsMax中的模型创建什么样的模型,就会在d3d中完全一致的显示出来。

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2024-4-29 23:31

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表