您的位置:首页 > 其它

Windows 8 Directx 开发学习笔记(五)山峰河谷模型的简单实现

2012-11-06 14:07 841 查看
通过之前对DirectX示例程序代码的研究,基本了解DirectX最简单的工作过程,为了更好的理解整个过程,基于示例程序做一个山峰河谷的简单模型。首先还是根据模板创建正方体的示例程序,Visual C++ -〉Windows应用商店 -〉DirectX3D应用程序,如图1。设置好名称后完成创建。



程序显示一个类似山峰河谷的模型,只要将正方体的数据替换成模型数据即可。在不改变示例程序其他部分的前提下,要提供的模型数据只需包括顶点坐标和颜色,索引数组两部分,其中最重要的部分就是顶点坐标的生成。
在DirectX的右手坐标系中,y方向为垂直方向,表示高度,x和z方向定义水平面。DirectX只绘制三角形,如果将山峰河谷模型投影在xz平面,那么xz平面就是由许多三角形组成的网格。假设相邻的两个三角形能构成一个正方形,如图2,顶点的x和z坐标就很容易生成。获得xz坐标之后,将其代入高度计算公式即可算出y。为表现出山峰河谷的效果,不同的高度范围应该有不同的颜色,可以使用条件判断进行设置。



首先找到CubeRenderer.cpp中的CreateDeviceResources方法,删除里面定义正方体顶点的代码。设x和z的变化范围为0-127,间隔均为1,定义常量和颜色如下:

const int xRange = 128;
const int zRange = 128;
const float dx = 1.0f;
const XMFLOAT3 WHITE(1.0f,1.0f, 1.0f);
const XMFLOAT3BEACH_SAND(1.0f, 0.96f, 0.62f);
const XMFLOAT3LIGHT_YELLOW_GREEN(0.48f, 0.77f, 0.46f);
const XMFLOAT3DARK_YELLOW_GREEN(0.1f, 0.48f, 0.19f);
const XMFLOAT3DARKBROWN(0.45f, 0.39f, 0.34f);


接着创建一个xRange*zRange大小的数组存储顶点信息。生成顶点坐标时,从原点开始按行扫描,获得xz坐标后代入上面的公式计算出y坐标。然后根据y坐标进行判断,不同的高度值对应的不同颜色,模拟山峰效果。

VertexPositionColorVertices[xRange*zRange];
 
for(int row=0;row<zRange; ++row)
{
    float zPos = row*dx;
 
    for(int col=0;col<xRange; ++col)
    {
         float xPos = col*dx;
         float yPos = 0.3f *(zPos*sinf(0.1f*xPos) + xPos*cosf(0.1*zPos));
         Vertices[xRange*row + col].pos = XMFLOAT3(xPos, yPos,zPos);
 
         if(yPos <-10.0f)
             Vertices[xRange*row + col].color =BEACH_SAND;
         else if (yPos <5.0f)
             Vertices[xRange*row + col].color =LIGHT_YELLOW_GREEN;
         else if (yPos <10.0f)
             Vertices[xRange*row + col].color =DARK_YELLOW_GREEN;
         else if (yPos <12.0f)
             Vertices[xRange*row+ col].color = DARKBROWN;
         else
             Vertices[xRange*row + col].color =WHITE;
    }
}


然后就是创建索引数组。每个正方形由两个三角形组成,所以索引数组的大小为3*2*(xRange-1)*(zRange-1)。与上面生成顶点相同,生成索引时也从原点开始,不过每次存储的是两个三角形的顶点序号。

unsigned shortIndices[3*2*(xRange-1)*(zRange-1)];
 
int tempIndice = 0;
for(int row=0;row<(zRange-1); ++row)
{
    for(int col=0;col<(xRange-1); ++col)
    {
         Indices[tempIndice] = xRange*row + col;
         Indices[tempIndice+1] = xRange*row +col + 1;
         Indices[tempIndice+2] = xRange*(row+1)+ col;
 
         Indices[tempIndice+3] = xRange*(row+1)+ col;
         Indices[tempIndice+4] = xRange*row +col + 1;
         Indices[tempIndice+5] = xRange*(row+1)+ col + 1;
                 
         tempIndice += 6;
    }
}


模型生成后还有工作要做,因为生成的模型比正方体大很多,为了显示模型全貌,需要调整可视距离。将CreateWindowSizeDependentResources中XMMatrixPerspectiveFovRH方法的参数由100.0f改成1000.0f。
另外,在Update方法中,摄像机的位置和焦点也要调整,而且这次不需要模型随时间旋转,所以固定旋转角度为0度,代码如下。

XMVECTOR eye =XMVectorSet(0, 30.0f, 0, 0.0f);
XMVECTOR at =XMVectorSet(50.0f, -0.1f, 50.0f, 0.0f);
XMVECTOR up =XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
 
XMStoreFloat4x4(&m_constantBufferData.view,XMMatrixTranspose(XMMatrixLookAtRH(eye, at, up)));
XMStoreFloat4x4(&m_constantBufferData.model,XMMatrixTranspose(XMMatrixRotationY(0.0f)));


按F5运行查看效果,如图3。



静态的模型看上去没什么感觉,可以通过移动摄像机的位置,简单模拟飞过整个区域的效果,这样感觉好些。只需要添加一个随时间变化的变量flyPos来更新摄像机的位置,焦点坐标同时改变是为了保持视线方向不变。

float flyPos = timeTotal * 5;
XMVECTOR eye =XMVectorSet(flyPos, 30.0f, flyPos, 0.0f);
XMVECTOR at =XMVectorSet(50.0f + flyPos, -0.1f, 50.0f + flyPos, 0.0f);


虽然只是一个简单粗糙的山峰河谷模型实现,在编写过程中还是遇到点问题,尤其是寻找一个合适的摄像机位置和焦点。不过通过实现这个模型,对DirectX的三维空间和工作原理有了更深的体会。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐