Выбрать главу

bool CCone::UpdateVertices() {

 CONE_CUSTOMVERTEX* pVertex;

 WORD* pIndices;

 WORD wVertexIndex = 0;

 int nCurrentSegment;

 //Lock the vertex buffer

 if (FAILED(m_pVertexBuffer->Lock(0, 0, (BYTE**)&pVertex, 0))) {

  LogError("<li>CCone: Unable to lock vertex buffer.");

  return false;

 }

 //Lock the index buffer

 if (FAILED(m_pIndexBuffer->Lock(0, m_dwNumOfIndices, (BYTE**)&pIndices, 0))) {

  LogError("<li>CCone: Unable to lock index buffer.");

  return false;

 }

 float rDeltaSegAngle = (2.0f * D3DX_PI / m_nSegments);

 float rSegmentLength = 1.0f / (float)m_nSegments;

 float ny0 = (90.0f – (float)D3DXToDegree(atan(m_rHeight / m_rRadius))) / 90.0f;

 //For each segment, add a triangle to the sides triangle list

 for (nCurrentSegment = 0; nCurrentSegment < m_nSegments; nCurrentSegment++) {

  float x0 = m_rRadius * sinf(nCurrentSegment * rDeltaSegAngle);

  float z0 = m_rRadius * cosf(nCurrentSegment * rDeltaSegAngle);

  pVertex->x = 0.0f;

  pVertex->y = 0.0f + (m_rHeight / 2.0f);

  pVertex->z = 0.0f;

  pVertex->nx = x0;

  pVertex->ny = ny0;

  pVertex->nz = z0;

  pVertex->tu = 1.0f – (rSegmentLength * (float)nCurrentSegment);

  pVertex->tv = 0.0f;

  pVertex++;

  pVertex->x = x0;

  pVertex->y = 0.0f – (m_rHeight / 2.0f);

  pVertex->z = z0;

  pVertex->nx = x0;

  pVertex->ny = ny0;

  pVertex->nz = z0;

  pVertex->tu = 1.0f – (rSegmentLength * (float)nCurrentSegment);

  pVertex->tv = 1.0f;

  pVertex++;

  //Set three indices (1 triangle) per segment

  *pIndices = wVertexIndex;

  pIndices++;

  wVertexIndex++;

  *pIndices = wVertexIndex;

  pIndices++;

  wVertexIndex += 2;

  if (nCurrentSegment == m_nSegments – 1) {

   *pIndices = 1;

   pIndices++;

   wVertexIndex--;

  } else {

   *pIndices = wVertexIndex;

   pIndices++;

   wVertexIndex--;

  }

 }

 //Create the bottom triangle fan: Center vertex

 pVertex->x = 0.0f;

 pVertex->y = 0.0f – (m_rHeight / 2.0f);

 pVertex->z = 0.0f;

 pVertex->nx = 0.0f;

 pVertex->ny = –1.0f;

 pVertex->nz = 0.0f;

 pVertex->tu = 0.5f;

 pVertex->tv = 0.5f;

 pVertex++;

 //Create the bottom triangle fan: Edge vertices

 for (nCurrentSegment = m_nSegments; nCurrentSegment >= 0; nCurrentSegment--) {

  float x0 = m_rRadius * sinf(nCurrentSegment * rDeltaSegAngle);

  float z0 = m_rRadius * cosf(nCurrentSegment * rDeltaSegAngle);

  pVertex->x = x0;

  pVertex->y = 0.0f – (m_rHeight / 2.0f);

  pVertex->z = z0;

  pVertex->nx = 0.0f;

  pVertex->ny = –1.0f;

  pVertex->nz = 0.0f;

  float tu0 = (0.5f * sinf(nCurrentSegment * rDeltaSegAngle)) + 0.5f;

  float tv0 = (0.5f * cosf(nCurrentSegment * rDeltaSegAngle)) + 0.5f;

  pVertex->tu = tu0;

  pVertex->tv = tv0;

  pVertex++;

 }

 if (FAILED(m_pVertexBuffer->Unlock())) {

  LogError("<li>CCone: Unable to unlock vertex buffer.");

  return false;

 }

 if (FAILED(m_pIndexBuffer->Unlock())) {

  LogError("<li>CCone: Unable to unlock index buffer.");

  return false;

 }

 return true;

}

So what is going on here? Well, as with the cylinder, we lock the vertex and index buffers ready for writing. Then we use the same calculations as before to calculate the segment angle and segment length. We also calculate the y part of the normals for the side's vertices. This is done by using simple trigonometry with the height and radius to form a right-angled triangle, so that we can find the correct Normal angle. Then, as with the cylinder, we loop around once for each segment adding a new triangle to the index buffer and vertices to the vertex buffer as required.

Once we've done that, we use the same method as the cylinder to define the triangle fan for the base of the cone. We then unlock the index and vertex buffers, and are ready for rendering.

How to make a sphere

Our sphere will be made up from a simple triangle list. We will need to specify the number of rings and segments for the sphere. The more rings and segments there are, the smoother and rounder the sphere will appear. The sphere will be made up using an index and vertex buffer. Fig 9.3 below shows a wireframe screenshot of a sphere. It shows how the sphere is constructed and divided into rings and segments.

Fig 9.3

To create the sphere we can use the following code snippet. The code below has been adapted from a sample by "Laurent" posted on the GameDev.net DirectX forum. To view the post in full go to http://www.gamedev.net/community/forums/topic.asp?topic_id=85779. I would like to thank Laurent for giving me permission to use the code in this tutorial.

bool CSphere::UpdateVertices() {

 //Code adapted from a sample by "Laurent" posted on the GameDev.net DirectX forum

 //http://www.gamedev.net/community/forums/topic.asp?topic_id=85779

 WORD* pIndices;

 SPHERE_CUSTOMVERTEX* pVertex;

 WORD wVertexIndex = 0;

 int nCurrentRing;

 int nCurrentSegment;

 D3DXVECTOR3 vNormal;

 //Lock the vertex buffer

 if (FAILED(m_pVertexBuffer->Lock(0, 0, (BYTE**)&pVertex, 0))) {

  LogError("<li>CSphere: Unable to lock vertex buffer.");

  return false;

 }

 //Lock the index buffer

 if (FAILED(m_pIndexBuffer->Lock(0, m_dwNumOfIndices, (BYTE**)&pIndices, 0))) {

  LogError("<li>CSphere: Unable to lock index buffer.");

  return false;

 }