Выбрать главу
Implementing an Index Buffer in DirectX

The first thing that we are going to do is add an index buffer to our CCuboid class. To do this, we need to add the following code:

Step 1: Creating the Index Buffer

First of all, create two new member variables: one LPDIRECT3DINDEXBUFFER8 called m_pIndexBuffer and a DWORD called m_dwNumOfIndices. m_pIndexBuffer will be a pointer to our index buffer and m_dwNumOfIndices will be the total number of indices for our object, in this case 36 (6 faces x 2 triangles per face x 3 vertices per triangle), which will be set in the constructor.

Then we have a new method called CreateIndexBuffer. We'll call this method once at start-up (in the constructor) before we set our vertex values in our vertex buffer. We populate the values in an index buffer in the same way that we populate vertices in a vertex buffer. First we create the index buffer and get a pointer to it (m_pIndexBuffer). We then store the 36 indices in a temporary WORD array ready to be copied into the index buffer. Then we lock the index buffer, copy the stored indices into it and then unlock it.

LPDIRECT3DINDEXBUFFER8 m_pIndexBuffer;

DWORD m_dwNumOfIndices;

bool CCuboid::CreateIndexBuffer() {

 VOID* pBufferIndices;

 //Create the index buffer from our device

 if (FAILED(m_pD3DDevice->CreateIndexBuffer(m_dwNumOfIndices * sizeof(WORD), 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &m_pIndexBuffer))) {

  return false;

 }

 //Set values for the index buffer

 WORD pIndices[] = {

  0, 1, 2, 3, 2, 1, //Top

  4, 5, 6, 7, 6, 5, //Face 1

  8, 9,10,11,10, 9, //Face 2

  12,13,14,15,14,13, //Face 3

  16,17,18,19,18,17, //Face 4

  20,21,22,23,22,21}; //Bottom

 //Get a pointer to the index buffer indices and lock the index buffer

 m_pIndexBuffer->Lock(0, m_dwNumOfIndices * sizeof(WORD), (BYTE**)&pBufferIndices, 0);

 //Copy our stored indices values into the index buffer

 memcpy(pBufferIndices, pIndices, m_dwNumOfIndices * sizeof(WORD));

 //Unlock the index buffer

 m_pIndexBuffer->Unlock();

 return true;

}

Step 2: Modify the Vertex Buffer

In our UpdateVertices method, we need to make a few changes. First, and most importantly, notice that we are only defining 24 vertices in our cvVertices array rather than 36. As in the last tutorial, we initialise our vertex normals to zero.

The other difference in this tutorial is that we will calculate the average normal for shared vertices. We don't really need to do this for a cube's shared vertices, but we will as a demonstration of how to do it. To do this, we need to new arrays: pNumOfSharedPolygons and pSumVertexNormal. These arrays are used in parallel, pNumOfSharedPolygons will keep a count of how many times a given vertex is used (shared) and pSumVertexNormal will add together each triangle normal for faces that share a given vertex. We'll then use these arrays to calculate the average normal for each vertex.

Once we have defined our vertices, we loop through the indices in our index buffer. So, for each triangle we calculate its face normal, increment the vertices count for each of the three vertices and add the face normal to the vertices normal array.

Then we loop through each vertex, and calculate it's average normal by dividing the sum of face normals by the number of times it has been used. We then normalize this value to ensure that the x, y and z parts of the normal vector are between 0 and 1. Finally, we apply the average normal to each vertex and copy the vertices into our vertex buffer as before.

bool CCuboid::UpdateVertices() {

 DWORD i;

 VOID* pVertices;

 WORD* pBufferIndices;

 D3DXVECTOR3 vNormal;

 DWORD dwVertex1;

 DWORD dwVertex2;

 DWORD dwVertex3;

 WORD* pNumOfSharedPolygons = new WORD[m_dwNumOfVertices]; //Array holds how many times this vertex is shared

 D3DVECTOR* pSumVertexNormal = new D3DVECTOR[m_dwNumOfVertices]; //Array holds sum of all face normals for shared vertex

 //Clear memory

 for (i = 0; i < m_dwNumOfVertices; i++) {

  pNumOfSharedPolygons[i] = 0;

  pSumVertexNormal[i] = D3DXVECTOR3(0,0,0);

 }

 CUBOID_CUSTOMVERTEX cvVertices[] = {

  //Top Face

  {m_rX – (m_rWidth / 2), m_rY + (m_rHeight / 2), m_rZ – (m_rDepth / 2), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,}, //Vertex 0

  {m_rX – (m_rWidth / 2), m_rY + (m_rHeight / 2), m_rZ + (m_rDepth / 2), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,}, //Vertex 1

  {m_rX + (m_rWidth / 2), m_rY + (m_rHeight / 2), m_rZ – (m_rDepth / 2), 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,}, //Vertex 2

  {m_rX + (m_rWidth / 2), m_rY + (m_rHeight / 2), m_rZ + (m_rDepth / 2), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,}, //Vertex 3

  //Face 1

  {m_rX – (m_rWidth / 2), m_rY – (m_rHeight / 2), m_rZ – (m_rDepth / 2), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,}, //Vertex 4

  {m_rX – (m_rWidth / 2), m_rY + (m_rHeight / 2), m_rZ – (m_rDepth / 2), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,}, //Vertex 5

  {m_rX + (m_rWidth / 2), m_rY – (m_rHeight / 2), m_rZ – (m_rDepth / 2), 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,}, //Vertex 6

  {m_rX + (m_rWidth / 2), m_rY + (m_rHeight / 2), m_rZ – (m_rDepth / 2), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,}, //Vertex 7

  //Face 2

  {m_rX + (m_rWidth / 2), m_rY – (m_rHeight / 2), m_rZ – (m_rDepth / 2), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,}, //Vertex 8

  {m_rX + (m_rWidth / 2), m_rY + (m_rHeight / 2), m_rZ – (m_rDepth / 2), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,}, //Vertex 9

  {m_rX + (m_rWidth / 2), m_rY – (m_rHeight / 2), m_rZ + (m_rDepth / 2), 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,}, //Vertex 10

  {m_rX + (m_rWidth / 2), m_rY + (m_rHeight / 2), m_rZ + (m_rDepth / 2), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,}, //Vertex 11

  //Face 3

  {m_rX + (m_rWidth / 2), m_rY – (m_rHeight / 2), m_rZ + (m_rDepth / 2), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,}, //Vertex 12

  {m_rX + (m_rWidth / 2), m_rY + (m_rHeight / 2), m_rZ + (m_rDepth / 2), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,}, //Vertex 13

  {m_rX – (m_rWidth / 2), m_rY – (m_rHeight / 2), m_rZ + (m_rDepth / 2), 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,}, //Vertex 14

  {m_rX – (m_rWidth / 2), m_rY + (m_rHeight / 2), m_rZ + (m_rDepth / 2), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,}, //Vertex 15

  //Face 4

  {m_rX – (m_rWidth / 2), m_rY – (m_rHeight / 2), m_rZ + (m_rDepth / 2), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,}, //Vertex 16

  {m_rX – (m_rWidth / 2), m_rY + (m_rHeight / 2), m_rZ + (m_rDepth / 2), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,}, //Vertex 17