当前位置:首页 > 最好的D3D教程-第九章:有纹理的球体、圆柱体和锥体
DirectX Tutorials www.andypike.com By Andy Pike 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); - 5 -
DirectX Tutorials www.andypike.com By Andy Pike 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(\ return false; } if(FAILED(m_pIndexBuffer->Unlock())) { LogError(\ return false; } return true; } 生成圆锥体的方法与生成圆柱体的方法是相似的,具体的细节你可以直接去读源代码,这里就不再罗嗦了。
How to make a sphere (怎样生成球体)
我们的球体是由一个三角列构成的。我们需要指定它的环数和段数,当然,环数与段数越多,它看起来就越光滑。我们将会使用索引缓冲和顶点缓冲。下图(9.3)演示了它的构成方法。
Fig 9.3
- 6 -
DirectX Tutorials www.andypike.com By Andy Pike 要创建球体我们可以使用下面的代码片断,它出自GameDev.net的DX论坛,是 “Laurent” 贴的一个例子的改编。 在此我要感谢他,允许我在本DirectX 教程中使用他的这段代码。如果你想看那个帖子的全部内容,请到http://www.gamedev.net/community/forums/topic.asp?topic_id=85779。 bool CSphere::UpdateVertices() { //Code adapted from a sample by \ //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(\ return false; } //Lock the index buffer if(FAILED(m_pIndexBuffer->Lock(0, m_dwNumOfIndices, (BYTE**)&pIndices, 0))) { LogError(\ return false; } //Establish constants used in sphere generation FLOAT rDeltaRingAngle = (D3DX_PI / m_nRings); FLOAT rDeltaSegAngle = (2.0f * D3DX_PI / m_nSegments); //Generate the group of rings for the sphere for(nCurrentRing = 0; nCurrentRing < m_nRings + 1; nCurrentRing++) { FLOAT r0 = sinf(nCurrentRing * rDeltaRingAngle); FLOAT y0 = cosf(nCurrentRing * rDeltaRingAngle); //Generate the group of segments for the current ring for(nCurrentSegment = 0; nCurrentSegment < m_nSegments + 1; nCurrentSegment++) { FLOAT x0 = r0 * sinf(nCurrentSegment * rDeltaSegAngle); FLOAT z0 = r0 * cosf(nCurrentSegment * rDeltaSegAngle); vNormal.x = x0; vNormal.y = y0; vNormal.z = z0; D3DXVec3Normalize(&vNormal, &vNormal); //Add one vertex to the strip which makes up the sphere pVertex->x = x0; pVertex->y = y0; pVertex->z = z0; pVertex->nx = vNormal.x; pVertex->ny = vNormal.y; pVertex->nz = vNormal.z; pVertex->tu = 1.0f - ((FLOAT)nCurrentSegment / (FLOAT)m_nSegments); pVertex->tv = (FLOAT)nCurrentRing / (FLOAT)m_nRings; - 7 -
DirectX Tutorials www.andypike.com By Andy Pike pVertex++; //Add two indices except for the last ring if(nCurrentRing != m_nRings) { *pIndices = wVertexIndex; pIndices++; *pIndices = wVertexIndex + (WORD)(m_nSegments + 1); pIndices++; wVertexIndex++; } } } if(FAILED(m_pIndexBuffer->Unlock())) { LogError(\ return false; } if(FAILED(m_pVertexBuffer->Unlock())) { LogError(\ return false; } return true; } 嗯,首先我们得锁定索引缓冲和顶点缓冲。然后我们用和前面一样的方法计算出了段的角度,用类似的方法计算出了环的角度。计算环的角度时我们只需要平分一个半圆(PI弧度)就行了。
当我们确定了环角和段角之后,我们会有一个循环,它能一环一环的生成球上的所有的顶点,索引缓冲会把它们连结成三角形列。我们还为每个顶点都设置了法线。球的半径是按照1来计算的,然后我们再通过缩放比例矩阵把它调整为想要的半径。最后,解锁顶点和索引缓冲,准备渲染。
译者:注意,程序中球体的“环角”与地球的纬度的划分方法并不相同,不要混淆。
最后我们会得到类似这样的屏幕:
- 8 -
DirectX Tutorials www.andypike.com By Andy Pike
HTML Logging (HTML格式的程序日志)
这回我们程序的LOG文件已改用HTML格式的记录方式了,运行一下程序就知道了。程序还增加了一些新的函数,自己去看源代码吧,这里就不多说了。
Summary (摘要)
Now we can create quite a few shapes: a cube, a sphere, a cone, a cylinder and even a simple terrain. These shapes are pretty basic, but can be very useful when you start creating your own scenes. In the next tutorial, we'll look at creating more complex objects like aliens, guns and vehicles.
现在我们可以创建一些像立方体、球体这样的基本对象了,它们在构建场景的时候是很有用的。下一章我们会学习模型的载入方法。
- 9 -
共分享92篇相关文档