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