VC++游戏开发随记之三十九.docx
《VC++游戏开发随记之三十九.docx》由会员分享,可在线阅读,更多相关《VC++游戏开发随记之三十九.docx(38页珍藏版)》请在冰豆网上搜索。
![VC++游戏开发随记之三十九.docx](https://file1.bdocx.com/fileroot1/2023-1/8/24aa403f-bb03-4703-be49-2271e6759698/24aa403f-bb03-4703-be49-2271e67596981.gif)
VC++游戏开发随记之三十九
【VisualC++】游戏开发笔记三十九浅墨DirectX教程之七他山之石:
几种几何体的快捷绘制法
本篇文章里,我们对Direct3D之中几种几何体的简洁绘制方法进行了详细的剖析,最后依旧是提供文章配套的详细注释的demo源代码的欣赏,并在文章末尾提供了源代码下载。
(这标题有些歧义的,这个几种是修饰几何体的,而绘制的方法只有一种:
D)
首先需要跟大家道声歉,上个周末因为浅墨个人的原因。
没把想写的内容的思路整理好,所以就停更了一次。
好了,别的废话咱不说了,下面直奔本周主题~
一、D3D中内置的几何体概述
通过前面的讲解大家应该会发现,使用顶点缓存和索引缓存通过绘制三角形单元来绘制图形还是有一点复杂的,需要一定的想象力和大量顶点和索引的设置,我们一般很少去这样通过逐个设置顶点缓存和索引缓存来进行画面上几何体的绘制的。
而比较人性化的是,Direct3D为我们提供了几种特殊的生成简单3D几何体的网格数据的方法。
可以说是在我们学习从文件载入网格数据之前,为我们提供了很多便利,丰富了我们的学习时的图形素材。
下面我们就来看看这几个快捷的几何体绘制函数,他们分别是立方体(Cube),圆环体(Torus),多边形(Polygon),球面体(Sphere),茶壶(Teapot)和圆柱体(Cylinder)。
我们可以在DirectXSDK(以目前最新的MicrosoftDirectXSDK(June2010)为例)的WindowsDirectXGraphics.chm文档中依次展开【WindowsDirectXGraphicsDocumentation】->【Direct3D9Graphics】->【ReferenceforDirect3D9】->【D3DXReference】->【D3DXFunctions】->【ShapeDrawingFunctions】找到这些函数的说明文档,这是这些函数最官方最原始的参考地址了。
不过显然这些DirectXSDKDocument都是纯英文的,和大众之间的距离还是比较疏远。
先给大家看看这几个函数的全家福,后面我们会全部详细介绍使用方法的:
D3DXCreateBox 用于创建一个盒子,立方体
D3DXCreateSphere 用于创建一个球面体
D3DXCreateCylinder 用于创建一个柱体
D3DXCreateTeapot 用于创建一个茶壶
D3DXCreatePolygon 用于创建一个多边形
D3DXCreateTorus 用于创建一个圆环体
我们可以看到这些函数的名字取的都非常的憨厚老实,一开始是D3DX,然后紧跟其后一个Create,表示是在创建某东西,最后跟上对应的几何体名,比如Teapot茶壶,这样连起来就非常好记忆了,D3DXCreateTeapot。
二、D3D中几种内置的几何体绘制四步曲
首先需要说明的是下面提到的ID3DXMesh接口类型是后面我们在讲解网格相关知识的时候重点讲解的内容,这里大家先对其有一个大概的印象就可以了。
想要通过这几个函数快捷绘制出一个几何体,需要以下几步:
1.定义一个ID3DXMesh接口类型的对象。
2.调用这六个函数的其中一个对我们在第一步里面定义的这个对象进行初始化,也就是把创建好的网格存储在我们定义好的ID3DXMesh类型的对象中
3.在Direct3D渲染五步曲的第三步,也就是在BeginScene之后调用DrawSubset方法进行网格图形的绘制,即是拿着第二步里面初始化好的ID3DXMesh接口类型的对象指一下DrawSubset(0)方法就好了
4.绘制完成之后,调用ID3DMesh接口的Release方法,或者我们自定义的COM接口释放宏进行资源的释放。
总结起来也就简明扼要八个字:
定义,创建,绘制,释放
方便大家理解各个过程,给出一个配套的注释好的代码:
[cpp] viewplaincopyprint?
1.//四步曲之一,定义
2.ID3DXMesh* meshBox;
3.//四步曲之二,创建
4.D3DXCreateBox( g_pd3dDevice, 2.0f, 2.0f, 2.0f,&meshBox, 0 );
5.//四步曲之三,绘制
6.g_pd3dDevice->BeginScene();
7.meshBox->DrawSubset(0);
8.//四步曲之四,释放
9.meshBox->Release();
三、D3D中几种内置几何体的创建详细剖析
这一小节里面讲解的都是上文我们提到的几何体绘制四步曲的第二步里面的具体创建方法,但是配套的调用实例都包含了四步曲里面的前三步,大家需要注意下。
1.立方体的创建——D3DXCreateBox方法
D3DXCreateBox方法用于创建一个立方体,或者说是一个盒子。
[cpp] viewplaincopyprint?
1.HRESULT D3DXCreateBox(
2. __in LPDIRECT3DDEVICE9 pDevice,//Direct3D设备对象
3. __in FLOAT Width, //盒子的宽度
4. __in FLOAT Height,//盒子的高度
5. __in FLOAT Depth,//盒子的深度
6. __out LPD3DXMESH *ppMesh,//存储着盒子网格的指针
7. __out LPD3DXBUFFER *ppAdjacency//存储三角形索引的指针
8.);
█第一个参数,LPDIRECT3DDEVICE9类型的pDevice,指向IDirect3DDevice9接口的指针,这样一般就填我们在初始化四步曲里面创建的有效的Direct3D绘制”金钥匙”——Direct3D设备对象g_pd3dDevice。
表示Direct3D设备对象和我们创建的这个盒子网格之间关联起来了。
█第二个参数,FLOAT类型的Width,表示我们创建的盒子沿着X轴的宽度。
█第三个参数,FLOAT类型的Height,表示我们创建的盒子沿着Y轴的高度。
█第四个参数,FLOAT类型的Depth,表示我们创建的盒子沿着Z轴的深度。
█第五个参数,LPD3DXMESH类型的*ppMesh,一个存储着我们创建的形状的指针的地址,也就是绘制用D3DXCreateBox函数创建的网格的金钥匙,后面需要绘制我们用这个函数创建的盒子网格的话,拿这个指针指一下DrawSubset方法,也就是这样写g_box->DrawSubset(0);
█第六个参数,LPD3DXBUFFER类型的*ppAdjacency,它存储着我们在这里绘制的网格的三角形索引的指针,我们不用他的话,设为0就可以了。
下面是一个调用实例,创建一个长方体:
[cpp] viewplaincopyprint?
1.//用此函数产生一个长方体
2. ID3DXMesh* meshBox;
3. D3DXCreateBox(
4. g_pd3dDevice, //D3D绘制对象
5. 2.0f, //宽度
6. 2.0f, //高度
7. 2.0f, //深度
8. &meshBox,//对应COM对象
9. 0 //指向ID3DXBuffer,存放相邻平面的信息,通常设置成0(或NULL)
10. );
11. g_pd3dDevice->BeginScene();
12. meshBox->DrawSubset(0);
2.柱体的创建——D3DXCreateCylinder方法
D3DXCreateCylinder方法用于创建柱体。
[cpp] viewplaincopyprint?
1.HRESULT D3DXCreateCylinder(
2. __in LPDIRECT3DDEVICE9 pDevice,
3. __in FLOAT Radius1,
4. __in FLOAT Radius2,
5. __in FLOAT Length,
6. __in UINT Slices,
7. __in UINT Stacks,
8. __out LPD3DXMESH *ppMesh,
9. __out LPD3DXBUFFER *ppAdjacency
10.);
█第一个参数,LPDIRECT3DDEVICE9类型的pDevice,指向IDirect3DDevice9接口的指针,这样一般就填我们在初始化四步曲里面创建的有效的Direct3D绘制”金钥匙”——Direct3D设备对象g_pd3dDevice。
表示Direct3D设备对象和我们创建的这个柱体网格之间关联起来了。
█第二个参数,FLOAT类型的Radius1,表示我们创建的柱体沿Z轴负方向的半径大小,这个参数显然必须大于等于0.0f。
█第三个参数,FLOATRadius2,表示我们创建的柱体沿Z轴正方向的半径大小,这个参数显然必须大于等于0.0f。
█第四个参数,FLOAT类型的Length,表示我们创建的柱体沿Z轴的长度。
█第五个参数,UINT类型的Slices,表示柱体的外围有几个面,举个例子,如果设为8的话,我们创建的就是八角柱了。
█第六个参数,UINT类型的Stacks,表示柱体的两端间共有几段,这个后面光照效果的时候需要要用到的。
█第七个参数,LPD3DXMESH类型的*ppMesh,一个存储着我们创建的形状的指针的地址,也就是绘制用D3DXCreateCylinder函数创建的网格的金钥匙,后面需要绘制我们用这个函数创建的柱体网格的话,拿这个指针指一下DrawSubset方法,也就是这样写g_Cylinder->DrawSubset(0);
█第八个参数,LPD3DXBUFFER类型的*ppAdjacency,它存储着我们在这里绘制的网格的三角形索引的指针,我们不用他的话,设为0就可以了。
3.2D多边形的创建——D3DXCreatePolygon方法
D3DXCreatePolygon方法用于快速创建一个2D多边形。
[cpp] viewplaincopyprint?
1.HRESULT D3DXCreatePolygon(
2. __in LPDIRECT3DDEVICE9 pDevice,
3. __in FLOAT Length,
4. __in UINT Sides,
5. __out LPD3DXMESH *ppMesh,
6. __out LPD3DXBUFFER *ppAdjacency
7.);
█第一个参数,LPDIRECT3DDEVICE9类型的pDevice,指向IDirect3DDevice9接口的指针,这样一般就填我们在初始化四步曲里面创建的有效的Direct3D绘制”金钥匙”——Direct3D设备对象g_pd3dDevice。
表示Direct3D设备对象和我们创建的这个2D多边形网格之间关联起来了。
█第二个参数,UINT类型的Sides,表示我们创建的多边形每条边的长度。
█第三个参数,FLOATRadius2,表示我们创建的多边形的包含几个三角形。
█第四个参数,LPD3DXMESH类型的*ppMesh,一个存储着我们创建的形状的指针的地址,也就是绘制用D3DXCreateCylinder函数创建的网格的金钥匙,后面需要绘制我们用这个函数创建的2D多边形网格的话,拿这个指针指一下DrawSubset方法,也就是这样写g_Polygon->DrawSubset(0);
█第五个参数,LPD3DXBUFFER类型的*ppAdjacency,它存储着我们在这里绘制的网格的三角形索引的指针,我们不用他的话,设为0就可以了。
下面是一个调用实例
[cpp] viewplaincopyprint?
1.//用此函数产生一个2D 多边体
2. ID3DXMesh* meshPolygon;
3. D3DXCreatePolygon(
4. g_pd3dDevice, //D3D绘制对象
5. 2.0f, //每条边的长度
6. 6, //包含几个三角形
7. &meshPolygon,
8. 0 //通常设置成0(或NULL)
9. );
10. g_pd3dDevice->BeginScene();
11. meshPolygon->DrawSubset(0);
4.球面体创建——D3DXCreateSphere方法
D3DXCreateSphere方法用于创建一个球面体。
[cpp] viewplaincopyprint?
1.HRESULT D3DXCreateSphere(
2. __in LPDIRECT3DDEVICE9 pDevice,
3. __in FLOAT Radius,
4. __in UINT Slices,
5. __in UINT Stacks,
6. __out LPD3DXMESH *ppMesh,
7. __out LPD3DXBUFFER *ppAdjacency
8.);
█第一个参数,LPDIRECT3DDEVICE9类型的pDevice,指向IDirect3DDevice9接口的指针,这样一般就填我们在初始化四步曲里面创建的有效的Direct3D绘制”金钥匙”——Direct3D设备对象g_pd3dDevice。
表示Direct3D设备对象和我们创建的这个2D多边形网格之间关联起来了。
(浅墨在这里是复制粘贴上面的介绍,因为这个参数在本篇文章里介绍的几个创建几何体函数中都是一样的)
█第二个参数,UINT类型的Sides,表示我们创建的多边形每条边的长度。
█第三个参数,UINT类型的Slices,表示我们创建的球面体绕主轴线切片数,也就是用几条经线来进行绘制。
█第四个参数,UINT类型的Stacks,表示我们创建的球面体绕主轴线的纬线数,也就是用几条纬线来进行绘制。
█第五个参数,LPD3DXMESH类型的*ppMesh,一个存储着我们创建的形状的指针的地址,也就是绘制用D3DXCreateCylinder函数创建的网格的金钥匙,后面需要绘制我们用这个函数创建的球面体网格的话,拿这个指针指一下DrawSubset方法,也就是这样写g_Polygon->DrawSubset(0);
█第六个参数,LPD3DXBUFFER类型的*ppAdjacency,它存储着我们在这里绘制的网格的三角形索引的指针,我们不用他的话,设为0就可以了。
依然是一个调用实例:
[cpp] viewplaincopyprint?
1.//用此函数产生一个球面体
2. ID3DXMesh* meshSphere;
3. D3DXCreateSphere(
4. g_pd3dDevice, //D3D绘制对象
5. 1.0f, //球面体半径
6. 10, //用几条经线绘制
7. 10, //用几条维线绘制
8. &meshSphere,
9. 0 //通常设置成0(或NULL)
10. );
11. g_pd3dDevice->BeginScene();
12. meshSphere->DrawSubset(0);
看到这里如果大家觉得累了,来看几幅游戏美图吧,今天浅墨给大家准备的是2012年8月份刚上市的游戏大作《暗黑血统2》的桌面壁纸,这款游戏浅墨最近在玩,感觉还不错:
是不是很酷呢?
上面的第二张图片浅墨可是做了很长时间的壁纸的呢。
好了,下面我们继续来讲解。
五茶壶的创建——D3DXCreateTeapot方法
D3DXCreateTeapot方法用于创建一个茶壶。
[cpp] viewplaincopyprint?
1.HRESULT D3DXCreateTeapot(
2. __in LPDIRECT3DDEVICE9 pDevice,
3. __out LPD3DXMESH *ppMesh,
4. __out LPD3DXBUFFER *ppAdjacency
5.);
这个函数相对来说参数很少,他并没有给我们提供茶壶具体参数的设置。
█第一个参数,LPDIRECT3DDEVICE9类型的pDevice,指向IDirect3DDevice9接口的指针,这样一般就填我们在初始化四步曲里面创建的有效的Direct3D绘制”金钥匙”——Direct3D设备对象g_pd3dDevice。
表示Direct3D设备对象和我们创建的这个2D多边形网格之间关联起来了。
(浅墨在这里是复制粘贴上面的介绍,因为这个参数在本篇文章里介绍的几个创建几何体函数中都是一样的)
█第二个参数,LPD3DXMESH类型的*ppMesh,一个存储着我们创建的形状的指针的地址,也就是绘制用D3DXCreateCylinder函数创建的网格的金钥匙,后面需要绘制我们用这个函数创建的茶壶网格的话,拿这个指针指一下DrawSubset方法,也就是这样写g_Polygon->DrawSubset(0);
█第三个参数,LPD3DXBUFFER类型的*ppAdjacency,它存储着我们在这里绘制的网格的三角形索引的指针,我们不用他的话,设为0就可以了。
依然是一个调用实例:
[cpp] viewplaincopyprint?
1.//用此函数产生一个茶壶
2. ID3DXMesh* meshTeapot;
3. D3DXCreateTeapot(
4. g_pd3dDevice, //D3D绘制对象
5. &meshTeapot,
6. 0 //通常设置成0(或NULL)
7. );
8. g_pd3dDevice->BeginScene();
9. meshTeapot->DrawSubset(0);
六、圆环的创建——D3DXCreateTorus方法
D3DXCreateTorus方法用于创建一个圆环体。
[cpp] viewplaincopyprint?
1.HRESULT D3DXCreateTorus(
2. __in LPDIRECT3DDEVICE9 pDevice,
3. __in FLOAT InnerRadius,
4. __in FLOAT OuterRadius,
5. __in UINT Sides,
6. __in UINT Rings,
7. __out LPD3DXMESH *ppMesh,
8. __out LPD3DXBUFFER *ppAdjacency
9.);
█第一个参数,LPDIRECT3DDEVICE9类型的pDevice,指向IDirect3DDevice9接口的指针,这样一般就填我们在初始化四步曲里面创建的有效的Direct3D绘制”金钥匙”——Direct3D设备对象g_pd3dDevice。
表示Direct3D设备对象和我们创建的这个2D多边形网格之间关联起来了。
(浅墨在这里是复制粘贴上面的介绍,因为这个参数在本篇文章里介绍的几个创建几何体函数中都是一样的)
█第二个参数,FLOAT类型的InnerRadius,表示我们创建的圆环的內圈半径。
█第三个参数,FLOAT类型的OuterRadius,表示我们创建的圆环的外圈半径。
█第四个参数,UINT类型的Sides,表示我们创建的圆环的外圈有几个面,也就是大圆的轮廓是几边形,这个值显然要大于等于3.
█第五个参数,UINT类型的Rings,表示我们创建的圆环的内圈与外圈之间有几个面。
█第六个参数,LPD3DXMESH类型的*ppMesh,一个存储着我们创建的形状的指针的地址,也就是绘制用D3DXCreateCylinder函数创建的网格的金钥匙,后面需要绘制我们用这个函数创建的圆环体网格的话,拿这个指针指一下DrawSubset方法,也就是这样写g_Polygon->DrawSubset(0);
█第七个参数,LPD3DXBUFFER类型的*ppAdjacency,它存储着我们在这里绘制的网格的三角形索引的指针,我们不用他的话,设为0就可以了。
依然是一个调用实例:
[cpp] viewp