以文本方式查看主题 - 计算机科学论坛 (http://bbs.xml.org.cn/index.asp) -- 『 C/C++编程思想 』 (http://bbs.xml.org.cn/list.asp?boardid=61) ---- 使用.x文件模型(1) (http://bbs.xml.org.cn/dispbbs.asp?boardid=61&rootid=&id=74523) |
-- 作者:卷积内核 -- 发布时间:4/27/2009 10:22:00 AM -- 使用.x文件模型(1) 利用.x文件模型渲染三维模型,首先需要将.x文件中的各种数据分别加载到内存中,主要包括顶点数据、材质数据和纹理数据等。
网格模型接口ID3DXMESH Direct3D扩展实用库定义了多边形网格模型接口ID3DXMesh来表示一个复杂的三维物体模型,它是一个COM接口,继承自ID3DXBaseMesh。 Direct3D扩展实用库函数D3DXCreateMesh()可用于创建一个Direct3D网格模型对象,该函数声明如下: Creates a mesh object using a declarator. HRESULT D3DXCreateMesh( DWORD NumFaces, DWORD NumVertices, DWORD Options, CONST LPD3DVERTEXELEMENT9 * pDeclaration, LPDIRECT3DDEVICE9 pD3DDevice, LPD3DXMESH * ppMesh); D3DXMESH typedef enum D3DXMESH{ D3DXMESH_32BIT = 0x001, D3DXMESH_DONOTCLIP = 0x002, D3DXMESH_POINTS = 0x004, D3DXMESH_RTPATCHES = 0x008, D3DXMESH_NPATCHES = 0x4000, D3DXMESH_VB_SYSTEMMEM = 0x010, D3DXMESH_VB_MANAGED = 0x020, D3DXMESH_VB_WRITEONLY = 0x040, D3DXMESH_VB_DYNAMIC = 0x080, D3DXMESH_VB_SOFTWAREPROCESSING = 0x8000, D3DXMESH_IB_SYSTEMMEM = 0x100, D3DXMESH_IB_MANAGED = 0x200, D3DXMESH_IB_WRITEONLY = 0x400, D3DXMESH_IB_DYNAMIC = 0x800, D3DXMESH_IB_SOFTWAREPROCESSING = 0x10000, D3DXMESH_VB_SHARE = 0x1000, D3DXMESH_USEHWONLY = 0x2000, D3DXMESH_SYSTEMMEM = 0x110, D3DXMESH_MANAGED = 0x220, D3DXMESH_WRITEONLY = 0x440, D3DXMESH_DYNAMIC = 0x880, D3DXMESH_SOFTWAREPROCESSING = 0x18000,} D3DXMESH, *LPD3DXMESH; 一般情况下,参数Option置为D3DMESH_SYSTEMMEM或D3DMESH_MANAGED,表示对Direct3D顶点缓冲区和索引缓冲区使用D3DPOOL_SYSTEMMEM或D3DPOOL_MANAGED内存。 调用D3DXCreateMesh()函数创建了网格模型对象后,还需要为其载入模型数据,而载入模型数据是比较复杂的。所以在大多数情况下,不直接调用该函数,它被封装在Direct3D扩展实用库函数中,由Direct3D在内部完成网格模型对象的创建和模型数据的载入操作。
通过.x文件生成网格模型 复杂的三维模型实际上是由许许多多的多边形构成的,所以首先需要得到这些构成模型的多边形。使用Direct3D功能扩展库函数D3DXLoadMeshFromX(),可以从.X文件中提取多边形信息(包括顶点坐标、颜色、法向量和纹理信息等),生成网格模型。该函数的声明如下: Loads a mesh from a DirectX .x file. HRESULT D3DXLoadMeshFromX( LPCTSTR pFilename, DWORD Options, LPDIRECT3DDEVICE9 pD3DDevice, LPD3DXBUFFER * ppAdjacency, LPD3DXBUFFER * ppMaterials, LPD3DXBUFFER * ppEffectInstances, DWORD * pNumMaterials, LPD3DXMESH * ppMesh); Remarks All the meshes in the file will be collapsed into one output mesh. If the file contains a frame hierarchy, all the transformations will be applied to the mesh. For mesh files that do not contain effect instance information, default effect instances will be generated from the material information in the .x file. A default effect instance will have default values that correspond to the members of the D3DMATERIAL9 structure. The default texture name is also filled in, but is handled differently. The name will be Texture0@Name, which corresponds to an effect variable by the name of "Texture0" with an annotation called "Name." This will contain the string file name for the texture. LPD3DXBUFFER因数据操作的方便性而诞生,它的好处是可以存储顶点位置坐标、材质、纹理等多种类型的Direct3D数据,而不必对每种数据声明一种函数接口类型。可使用接口函数ID3DXBuffer::GetBufferPointer()获取缓冲区中的数据,使用ID3DXBuffer::GetBufferSize()获取缓冲区数据大小。
载入材质和纹理 如果函数D3DXLoadMeshFromX()调用成功,那么参数ppMaterials就会获取.x文件中三维模型导出的材质和纹理信息,而pNumMaterials则会获得材质的数目,将材质和纹理信息从中提取出来的代码如下: bool init_geometry(){ ID3DXBuffer* material_buffer;
渲染网格模型 网格模型接口ID3DXMesh实际上是三维物体的顶点缓冲区的集合,它将创建顶点缓冲区、定义灵活顶点格式和绘制顶点缓冲区等功能封装在一个COM对象里,极大地方便了三维物体的绘制。对于以ID3DXMesh表示的三维物体,可以遍历它所有的顶点缓冲区,按照相应的顶点格式将它们分别渲染,也可以直接调用它的接口函数ID3DXMesh::DrawSubset()绘制图形,该函数的声明如下: Draws a subset of a mesh. HRESULT DrawSubset( DWORD AttribId); Remarks An attribute table is used to identify areas of the mesh that need to be drawn with different textures, render states, materials, and so on. In addition, the application can use the attribute table to hide portions of a mesh by not drawing a given attribute identifier (AttribId) when drawing the frame. 渲染网格模型的代码如下: void render(){ g_device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_X#050505, 1.0f, 0); 示例程序运行效果图: |
-- 作者:卷积内核 -- 发布时间:4/27/2009 10:23:00 AM -- 源程序: #include <d3dx9.h> #pragma warning(disable : 4127) #define CLASS_NAME "GameApp" #define release_com(p) do { if(p) { (p)->Release(); (p) = NULL; } } while(0) IDirect3D9* g_d3d; void setup_world_matrix() void setup_view_proj_matrix() D3DXVECTOR3 eye(0.0f, 10.0f, -20.0f); D3DXMATRIX mat_view; // setup projection matrix D3DXMATRIX mat_proj; bool init_geometry() /* if(FAILED(D3DXLoadMeshFromX("airplane.x", D3DXMESH_MANAGED, g_device, NULL, &material_buffer, NULL, D3DXMATERIAL* xmaterials = (D3DXMATERIAL*) material_buffer->GetBufferPointer(); g_mesh_materials = new D3DMATERIAL9[g_num_materials]; for(DWORD i = 0; i < g_num_materials; i++) // set ambient reflected coefficient, because .x file do not set it. g_mesh_textures[i] = NULL; if(xmaterials[i].pTextureFilename != NULL && strlen(xmaterials[i].pTextureFilename) > 0) material_buffer->Release(); return true; bool init_d3d(HWND hwnd) if(g_d3d == NULL) D3DPRESENT_PARAMETERS d3dpp; d3dpp.Windowed = TRUE; if(FAILED(g_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, setup_view_proj_matrix(); g_device->SetRenderState(D3DRS_LIGHTING, FALSE); void cleanup() if(g_mesh_textures) delete[] g_mesh_textures; void render() g_device->BeginScene(); setup_world_matrix(); for(DWORD i = 0; i < g_num_materials; i++) g_mesh->DrawSubset(i); g_device->Present(NULL, NULL, NULL, NULL); LRESULT WINAPI WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) case WM_DESTROY: return DefWindowProc(hwnd, msg, wParam, lParam); int WINAPI WinMain(HINSTANCE inst, HINSTANCE, LPSTR, INT) wc.cbSize = sizeof(WNDCLASSEX); if(! RegisterClassEx(&wc)) HWND hwnd = CreateWindow(CLASS_NAME, "Direct3D App", WS_OVERLAPPEDWINDOW, 200, 100, 640, 480, if(hwnd == NULL) if(init_d3d(hwnd)) MSG msg; while(msg.message != WM_QUIT) cleanup(); return 0; |
W 3 C h i n a ( since 2003 ) 旗 下 站 点 苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》 |
265.625ms |