地形的网格可以使用高度图作为数据源生成。高度图可以是位图,可理解成二维数组,地形实际上就是一系列高度不同的网格而已,这样数组中每个元素的索引值刚好可以用来定位不同的网格(x,z),而所储存的值就是网格的高度(y)。
地形的渲染可由四叉树来管理,网格的每个顶点对应四叉树的各个节点,有关四叉树的应用可参考"引擎技术研究之场景管理------四叉树与视椎剔除技术"。
现讨论地形技术的相关应用:
一:地形的生成
1 根据一指定路径的灰度图生成高度图mpBmpHeightMap,并获取mpBmpHeightMap的长度length和宽度width
2 根据length和width创建一顶点指针mpVertexsMap,mpVertexsMap保存地形网格各顶点的位置。调用IDirect3DDevice9的
CreateVertexBuffer((width+1)*(length+1)*sizeof(Vertex),0,
D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1,D3DPOOL_MANAGED,&m_pVB, NULL)
生成顶点缓冲m_pVB,内存大小为(width+1)*(length+1)*sizeof(Vertex),
执行m_pVB->Lock( 0, 0, (void**)&vertex, 0 )锁定顶点缓冲,vertex指向其内存地址。
3 遍历Vertex每个顶点,并计算其位置x, y, z值,其中高度值y可由高度生成函数获取。并将Vertex的每个顶点值传递给mpVertexsMap数组,mpVertexsMap作用在于解除顶点锁定后仍可以使用顶点的位置值。调用IDirect3DDevice9的
CreateIndexBuffer(width*length*2*3*sizeof(DWORD),0,
D3DFMT_INDEX32, D3DPOOL_MANAGED,&m_pIB,NULL)
生成索引缓冲m_pIB,其大小为 width * length*2*3*sizeof(DWORD).
在地形信息更新时执行m_pIB->Lock( 0, 0, (void**)&index, 0 )锁定索引缓冲区,index指向其内存地址。
4 为地形设置纹理,并根据地形网格中外围四个顶点的索引及其位置创建四叉树。
至此,已根据四叉树生成地形网格。
二:地形的剔除
与一般模型的剔除不同,地形剔除技术指的是剔除视椎外的地形区域,即只在视椎内的区域绘制三角形。我们把地形在X,Z平面上划分成均匀大小的16 X 16个块,块的个数可由四叉树的层数决定,本例中层数为4,即有256个节点,每一节点对应一块。每一块包含多个网格,每块的网格数等于地形灰度图像素数除以块数:512 X 512/256=1024,即每块都是32X32的网格。每个网格可划分为两个三角形,即每块有2048个三角形。网格通过顶点索引所组成的三角形描述其所在的一片区域。整个地形用一棵四叉树把这些块组织起来。实时渲染时四叉树负责地形的裁剪,决定哪些块应该绘制,从而得到整个地形要渲染的三角形面片。地形的数据组织如图所示:
具体实现如下:首先锁定索引到索引缓冲区,获取指向索引缓冲区内存的指针index。判断节点的可见状态,并确定当前节点是叶子节点的情况下,则即是对应块的可见状态。若可见则遍历块区域里的每个网格,并由网格里的顶点序列(如下图)(0,2,1)和(1,2,3)根据其索引值生成两三角形,三角形各顶点的索引值可由对应网格的索引获得,由指针index保存三角形的各顶点的索引值,每保存一索引则其索引数目NumIndex递增1。在渲染时传入的三角形个数为NumIndex/3.
三:地形的碰撞检测
通俗地说,就是物体所在位置的高度y值要与地形一致,即其高度要随着地形的变化而变化,有个很好的例子:当物体上坡时,若没有作地形检测,则物体会走进地形里面,只有作了地形检测后,物体的高度才会与地形一致,模拟出自然界中真实的画面。
关键在于怎样获取物体位置对应的地形高度。这个高度插值可由物体所在三角形的三个顶点的y值t0 ,t1 ,t2以及其重心坐标(U,V)求得: t0+V*(t2-t0)+U*(t1-t0)
而我们知道,我们只能判断出物体在哪一个节点的区域里,而区域里有两个三角形,所以我们还要判断物体在哪一个三角形里,如图所示:
1:首先我们要确定物体位置( x , y, z)的范围。定义一函数Restrict(),该函数功能
是调整物体位置使其在地形区域里。
取整: IndexX= int(x) IndexZ= int(z)
调用: Restrict(0,MESH_WIDTH, IndexX); Restrict(0,MESH_LENGTH, IndexZ);
MESH_LENGTH和MESH_WIDTH分别为地形的长度和宽度,执行这两个函数后,若物体不在地
形区域里,则修改物体的X,Z值为地形边界值。
2:计算物体高度值。先计算物体位置和顶点0的距离:
float fOffSetZ=z-(float)IndexZ; float fOffSetX=x-(float)IndexX;
如果fOffSetX+fOffSetZ>=1.0f,则物体在右上那个三角形,否则在左下的三角形。
接着计算相应三角形的重心坐标以及其顶点的高度值:
重心坐标 右上三角形:U=1-(fOffSetX); V=1-(fOffSetZ);
左下三角形:U= fOffSetX; V= fOffSetZ
三个顶点的高度值t0,t1,t2可由对应节点的y值获得。
计算高度插值:H=t0+V*(t2-t0)+U*(t1-t0).
这样可根据高度插值即时更新物体的 y 值,实现地形碰撞检测的功能。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/skydesign/archive/2008/10/05/3017806.aspx