3D游戏从入门到精通-11

时间:2022-05-25 19:58:27
 
 
2.10.1索引缓冲区
上面已经学习了最简单的三角形显示,了解了整个3D物体的显示流程,下面来学习一个复杂一点的物体显示,使用12个三角形构造成的正方体显示。并且通过个例子学会使用索引缓冲区,提高图形绘制的速度和效率。
1、             使用三角形构造立方体
由前面可知,任何复杂的物体,都是由三角形组成的。现在就用12三角形构造一个正方体。先创建12点个顶点的缓冲区,然后再往里填写合适的数据,然后显示它出来。下面来仔细分析这段代码:
在函数HRESULT CCAICube::Init(IDirect3DDevice9* pd3dDevice)里,先创建12顶点数据。
const int nVTCount = 6*2*3;
 // 创建顶点缓冲区。
 if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( nVTCount * sizeof(VT_CAICUBE),
       0, VT_CAICUBE::dwFVF,
       D3DPOOL_MANAGED, &m_pVB, NULL ) ) )
 {
       //创建顶点缓冲区失败。
       return DXTRACE_ERR( "CreateVertexBuffer", hr );
 }
           这段代码,跟以前的代码一样创建顶点缓冲区。
接着下来就指明所有三角形的坐标:
// 用三角形填充顶点缓冲区。
 VT_CAICUBE* pVertices;
 
 if( FAILED( hr = m_pVB->Lock( 0, 0, (VOID**)&pVertices, 0 ) ) )
 {
       //锁住顶点缓冲区。
       return DXTRACE_ERR( "Lock", hr );
 }
 
 // 三角形组成的立方体表面。
 //第一个面
 pVertices[0].vPosition = D3DXVECTOR3( -1.0f, -1.0f, -1.0f ); 
 pVertices[1].vPosition = D3DXVECTOR3( -1.0f, 1.0f, -1.0f ); 
 pVertices[2].vPosition = D3DXVECTOR3( 1.0f, 1.0f, -1.0f );
 
 //
 pVertices[3].vPosition = D3DXVECTOR3( -1.0f, -1.0f, -1.0f ); 
 pVertices[4].vPosition = D3DXVECTOR3( 1.0f, 1.0f, -1.0f );
 pVertices[5].vPosition = D3DXVECTOR3( 1.0f, -1.0f, -1.0f );
 
 
 //第二个面
 pVertices[6].vPosition = D3DXVECTOR3( -1.0f, 1.0f, -1.0f ); 
 pVertices[7].vPosition = D3DXVECTOR3( -1.0f, 1.0f, 1.0f ); 
 pVertices[8].vPosition = D3DXVECTOR3( 1.0f, 1.0f, -1.0f );
 
 //
 pVertices[9].vPosition = D3DXVECTOR3(   -1.0f, 1.0f, 1.0f );
 pVertices[10].vPosition = D3DXVECTOR3( 1.0f, 1.0f, 1.0f );
 pVertices[11].vPosition = D3DXVECTOR3( 1.0f, 1.0f, -1.0f );
 
 
 //第三个面
 pVertices[12].vPosition = D3DXVECTOR3( -1.0f, 1.0f, 1.0f );
 pVertices[13].vPosition = D3DXVECTOR3( -1.0f, -1.0f, 1.0f );
 pVertices[14].vPosition = D3DXVECTOR3( 1.0f, 1.0f, 1.0f );
 
 //
 pVertices[15].vPosition = D3DXVECTOR3( 1.0f, 1.0f, 1.0f );
 pVertices[16].vPosition = D3DXVECTOR3( -1.0f, -1.0f, 1.0f );
 pVertices[17].vPosition = D3DXVECTOR3( 1.0f, -1.0f, 1.0f );
 
 //第四个面
 pVertices[18].vPosition = D3DXVECTOR3( -1.0f, -1.0f, 1.0f );
 pVertices[19].vPosition = D3DXVECTOR3( 1.0f, -1.0f, -1.0f );
 pVertices[20].vPosition = D3DXVECTOR3( 1.0f, -1.0f, 1.0f );
 
 //
 pVertices[21].vPosition = D3DXVECTOR3( -1.0f, -1.0f, 1.0f );   
 pVertices[22].vPosition = D3DXVECTOR3( -1.0f, -1.0f, -1.0f );
 pVertices[23].vPosition = D3DXVECTOR3( 1.0f, -1.0f, -1.0f );
 
 
 //第五个面
 pVertices[24].vPosition = D3DXVECTOR3( 1.0f, 1.0f, 1.0f );   
 pVertices[25].vPosition = D3DXVECTOR3( 1.0f, -1.0f, -1.0f );
 pVertices[26].vPosition = D3DXVECTOR3( 1.0f, 1.0f, -1.0f );
 
 //
 pVertices[27].vPosition = D3DXVECTOR3( 1.0f, -1.0f, -1.0f );   
 pVertices[28].vPosition = D3DXVECTOR3( 1.0f, 1.0f, 1.0f );
 pVertices[29].vPosition = D3DXVECTOR3( 1.0f, -1.0f, 1.0f );
 
 //第六个面
 pVertices[30].vPosition = D3DXVECTOR3( -1.0f, 1.0f, -1.0f );
 pVertices[31].vPosition = D3DXVECTOR3( -1.0f, -1.0f, -1.0f );    
 pVertices[32].vPosition = D3DXVECTOR3( -1.0f, 1.0f, 1.0f );
 
 //
 pVertices[33].vPosition = D3DXVECTOR3( -1.0f, 1.0f, 1.0f );    
 pVertices[34].vPosition = D3DXVECTOR3( -1.0f, -1.0f, -1.0f );
 pVertices[35].vPosition = D3DXVECTOR3( -1.0f, -1.0f, 1.0f );
 
 //解锁顶点缓冲区。
 m_pVB->Unlock();
上面从第一个面开始,就每个面两个三角形地填写,并且是按左中手坐标系的方向来填写三角形的顶点。
接着修改渲染的代码,改为渲染12个三角形,代码如下:
// 渲染顶点缓冲区的内容。
 m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(VT_CAICUBE) );
 m_pd3dDevice->SetFVF( VT_CAICUBE::dwFVF );
 m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 12 );
这样显示出来的立方体是那个面都可以看得到的,如果不按左手坐标系填写,就会有一些面看不到的。
 
通过上面的代码,是否看到要显示一个简单的立方体,就需要复杂地填写顶点了,并且要小心翼翼地写代码,一不小心写错了,就看不见了。因此,再复杂的物体,一般是通过使用3D建模软件来构造的。通过上面的代码,也发现了一个问题,就是整个正方体,其实只有8个顶点,而上面的三角形列表里有很多顶点是重复的,对于只有12个三角形来说,也许不是很重要。但是对于数以万计的三角形来说,这样的重复顶点就会浪费很多内存,浪费系统的带宽,并且需要重复渲染顶点。有没有更好的方法来解决这个问题呢?答案是肯定的,下面接着就来学习索引缓冲区。
 
 
电子书 MM3D 引擎源程序 例子源程序 49 元一套
联系人:蔡军生  
联系方式:
QQ: 9073204
EMAIL: caimouse1976 at sina.com