第一范文网 - 专业文章范例文档资料分享平台

最好的D3D教程-第九章:有纹理的球体、圆柱体和锥体

来源:用户分享 时间:2025/8/23 4:37:00 本文由loading 分享 下载这篇文档手机版
说明:文章内容仅供预览,部分内容可能不全,需要完整文档或者需要复制内容,请下载word后使用。下载word有问题请添加微信号:xxxxxxx或QQ:xxxxxx 处理(尽可能给您提供完整文档),感谢您的支持与谅解。

DirectX Tutorials www.andypike.com By Andy Pike 第九章:有纹理的球体、圆柱体和锥体

Introduction (序)

这一章我们将学习怎样创建有纹理的球体、圆柱体和锥体,我们也会为它们设置法线,这样它们就能产生正确的阴影了。而且,我们将会使所有的类都从一个基类CBase派生,这是一个能以HTML格式来生成记录文件的和有计算法线向量功能的类。我们这一章的例子将会含有两个圆柱体、两个圆锥体和一个简单的绕太阳旋转的地月模型。

How to make a cylinder (怎样生成圆柱体)

我们的圆柱体将会含有两个三角扇形,一个做顶,一个做底;它的周身将由一个三角带来完成。下图(9.1)演示了它的构成,顶点和三角形的分布;并且也演示了它的一个段上的几个顶点的法线是什么样子的。这里我们只用顶点缓冲而不用索引缓冲,原因是我们想要它的顶、底与周身相拼接的地方的一些重合顶点拥有不同的法线,如果用索引缓冲就不行了(因为它的实现是把几个重合的顶点看作一个)。X

Fig 9.1

要创建一个圆柱体我们需要指定它的分段数,在上面的图示中为8。当然,分段数越多,看起来就会越平滑(越接近圆)。我们还需要指定它的高和半径,这样它的顶点、法线、纹理坐标就都出来了。下面的代码片断能告诉你这一切是怎样完成的。 bool CCylinder::UpdateVertices() { CYLINDER_CUSTOMVERTEX* pVertex; WORD wVertexIndex = 0; int nCurrentSegment; //Lock the vertex buffer if(FAILED(m_pVertexBuffer->Lock(0, 0, (BYTE**)&pVertex, 0))) { LogError(\ return false; } float rDeltaSegAngle = (2.0f * D3DX_PI / m_nSegments); float rSegmentLength = 1.0f / (float)m_nSegments; - 1 -

DirectX Tutorials www.andypike.com By Andy Pike //Create the sides triangle strip for(nCurrentSegment = 0; nCurrentSegment <= m_nSegments; 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 = x0; pVertex->ny = 0.0f; 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 = 0.0f; pVertex->nz = z0; pVertex->tu = 1.0f - (rSegmentLength * (float)nCurrentSegment); pVertex->tv = 1.0f; pVertex++; } //Create the top triangle fan: Center 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 top triangle fan: Edges for(nCurrentSegment = 0; nCurrentSegment <= m_nSegments; 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++; } //Create the bottom triangle fan: Center pVertex->x = 0.0f; pVertex->y = 0.0f - (m_rHeight / 2.0f); pVertex->z = 0.0f; - 2 -

DirectX Tutorials www.andypike.com By Andy Pike 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: Edges 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(\ return false; } return true; }

那末然后呢?锁定顶点缓冲之后我们需要计算每个段的角度,也就是用分段数来平分2XPI个弧度,它将会被保存在rDeltaSegAngle中,在以后定义顶点位置时将会被用到。我们为它的周身设置纹理坐标时还得计算每段的长度,也就是用分段数来平分纹理坐标的最大值1.0。

然后我们还得定义它的周身。我们有一个循环,它会顺序的处理每一个分段,计算分段的顶和底的顶点的x和z值,它的y值很好计算,正的半个高度和负的半个高度就是了。我们用段的长度来计算当前段的纹理坐标。

然后,我们就能定义顶和底的三角扇形了。首先我们定义它们的中心点(圆心),然后用相同的计算方法得出边缘的顶点。完成后,顶点缓冲就应该满了,我们解锁它准备渲染。

How to make a cone (怎样生成圆锥体)

我们的锥体将由一个三角扇形来构成底,一个三角列来构成周身。像圆柱体一样,我们需要指定它的段数、高和半径。下图(9.2)演示了它的构成方法,图中的锥体为8个段,红线演示了其中一个段的法线。我们将同时使用索引缓冲和顶点缓冲。同时,我们也设置了正确的法线,得到了正确的阴影。

- 3 -

DirectX Tutorials www.andypike.com By Andy Pike Fig 9.2

我们需要指定锥体的段数,上图中的段数为8,当然,段数越多效果越好。我们还需要指定它的高和半径,这样它的顶点、法线、纹理坐标就都出来了。下面的代码片断能告诉你这一切是怎样完成的。 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(\ return false; } //Lock the index buffer if(FAILED(m_pIndexBuffer->Lock(0, m_dwNumOfIndices, (BYTE**)&pIndices, 0))) { LogError(\ 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; - 4 -

最好的D3D教程-第九章:有纹理的球体、圆柱体和锥体.doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印
本文链接:https://www.diyifanwen.net/c3au2j0m3jc6m3qp9y5pq_1.html(转载请注明文章来源)
热门推荐
Copyright © 2012-2023 第一范文网 版权所有 免责声明 | 联系我们
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ:xxxxxx 邮箱:xxxxxx@qq.com
渝ICP备2023013149号
Top