|
|
3DS 文件在 Directx中渲染的实现
刚接触directx的,人经常碰到3D文件格式,无法读取的问题。在DX,SDK里只介绍了两种外部文件读取方式.x和.obj,对于.x文件dx内部有相当完善的内部接口函数,可以处理文件的读取渲染。包括实现LOD渲染,分块渲染,甚至是内置特效处理,而且速度运行极快。更重要的是。x的文件通俗易懂,所以大部分初学DX的朋友为了把别的文件格式转化到。x上来煞费了不少苦心。就我所知maya配合DX 的插件,3D MAX结合pandaX插件,Milkship等都能完成这个工作。但是有时候总会碰到无法正确转化的情况,而且对于大量的3DS文件,一个个通过软件转化实在很累,特别是被微软的基本格式束缚,绝非我愿,因此实现在DX下渲染3ds文件势在必行。可惜网上大多找到GL下渲染的实例,所以本着学习共进的思想决定动手自己来一个。
总体思路是这样的:提取3ds文件信息-〉信息模块化->建立绘图缓冲装载信息->实现渲染
首先, 建立如下结构体(来自引用部分:3DS.H 到处可以下到,而且内容大同小异,我在这里借用的是相对组织明了,简便的一个)
// 定义3D点的类,用于保存模型中的顶点
class CVector3
{
public:
float x, y, z;
};
// 定义2D点类,用于保存模型的UV纹理坐标
class CVector2
{
public:
float x, y;
};
// 面的结构定义
struct tFace
{
int vertIndex[3]; // 顶点索引
int coordIndex[3]; // 纹理坐标索引
};
// 材质信息结构体
struct tMaterialInfo
{
char strName[255]; // 纹理名称
char strFile[255]; // 如果存在纹理映射,则表示纹理文件名称
BYTE color[3]; // 对象的RGB颜色
int texureId; // 纹理ID
float uTile; // u 重复
float vTile; // v 重复
float uOffset; // u 纹理偏移
float vOffset; // v 纹理偏移
} ;
// 对象信息结构体
struct t3DObject
{
int numOfVerts; // 模型中顶点的数目
int numOfFaces; // 模型中面的数目
int numTexVertex; // 模型中纹理坐标的数目
int materialID; // 纹理ID
bool bHasTexture; // 是否具有纹理映射
char strName[255]; // 对象的名称
CVector3 *pVerts; // 对象的顶点
CVector3 *pNormals; // 对象的法向量
CVector2 *pTexVerts; // 纹理UV坐标
tFace *pFaces; // 对象的面信息
};
// 模型信息结构体
struct t3DModel
{
UINT texture[MAX_TEXTURES];
int numOfObjects; // 模型中对象的数目
int numOfMaterials; // 模型中材质的数目
vector<tMaterialInfo> pMaterials; // 材质链表信息
vector<t3DObject> pObject; // 模型中对象链表信息
};
通过采用递归算法读取全部文件信息后,我们得到一个包含了我们下一步渲染所需要的全部信息的t3DObject结构体对象,具体读取实现这里不需要我赘述了吧,网上讲的太多了,呵呵 。
接着,我们开始建立顶点,以及索引缓冲区,以及材质区
D3DMATERIAL9* g_pMeshMaterials = NULL; // Materials for our mesh
LPDIRECT3DTEXTURE9* g_pMeshTextures = NULL; // Textures for our mesh
DWORD g_dwNumMaterials = 0L; // Number of mesh materials
LPDIRECT3DVERTEXBUFFER9
*g_pSubBuffer =NULL; //group for each sub
LPDIRECT3DINDEXBUFFER9 *g_pIndexBuffer =NULL;
int* g_pNumVerts =NULL;
int* g_pNumFaces =NULL;
我们将使用循环依次读入每一个t3DObject结构体sub对象的子对象内容,tMaterialInfo pMaterials; // 材质信息,t3DObject pObject; // 模型中对象信息
具体实现可以参照我的源码,就是lock和unlock,呵呵。(对了,3ds。h往往读出的文件是适合GL右手系模型,而至少DX9及其以前都是左手系的,所以要注意顶点座标的转化),具体实现还是仁者见仁,方法不唯一。
最后,我们采用drawindexPrimative ,哈哈画出来了。
源码地址:
见附件
该原代码可能需要2006,8月前dx的sdk 才可编译运行,07的sdk据说有问题 还在处理中 有成功的希望回贴
exe运行 需要d3dx9_31.dll 没有的可以去网上下 很多的,然后放到systerm32 下 ,或者我的exe目录下即可
|
|