小祥的BLOG

游戏开发
posts - 7, comments - 14, trackbacks - 0, articles - 0
  IT博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

地形高度算法小结

Posted on 2007-11-15 19:26 小祥 阅读(805) 评论(0)  编辑 收藏 引用 所属分类: D3D
地形一般是用网格再从高度图里读取每个顶点的高度来生成。若进一步,想实现摄像机在地形上行走的效果,就需要算出地形上任意一点的高度。总结了3个方法:
 
一:
《Introduction to 3D Game Programming With Directx 9.0》这本书里介绍的,利用向量来算。
11.jpg
 

 1 float  Terrain::GetHeight( float  x,  float  z)
 2 {
 3    //  Translate on xz-plane by the transformation that takes
 4   //  the terrain START point to the origin.
 5  x  =  (( float )_width  /   2.0f +  x;
 6  z  =  (( float )_depth  /   2.0f -  z;
 7   //  Scale down by the transformation that makes the 
 8   //  cellspacing equal to one.  This is given by 
 9   //  1 / cellspacing since; cellspacing * 1 / cellspacing = 1.
10  x  /=  ( float )_CellSpacing;
11  z  /=  ( float )_CellSpacing;
12   //  From now on, we will interpret our positive z-axis as
13   //  going in the 'down' direction, rather than the 'up' direction.
14   //  This allows to extract the row and column simply by 'flooring'
15   //  x and z:
16   float  col  =  ::floorf(x);
17   float  row  =  ::floorf(z);
18   //  get the heights of the quad we're in:
19   //  
20      //   A   B
21      //   *---*
22      //     | / |
23      //   *---*  
24      //   C   D
25   float  A  =  GetHeightMapEntry(row,   col);
26   float  B  =  GetHeightMapEntry(row,   col + 1 );
27   float  C  =  GetHeightMapEntry(row + 1 , col);
28   float  D  =  GetHeightMapEntry(row + 1 , col + 1 );
29   //
30   //  Find the triangle we are in:
31   //
32   //  Translate by the transformation that takes the upper-left
33   //  corner of the cell we are in to the origin.  Recall that our 
34   //  cellspacing was nomalized to 1.  Thus we have a unit square
35   //  at the origin of our +x -> 'right' and +z -> 'down' system.
36   float  dx  =  x  -  col;
37   float  dz  =  z  -  row;
38   //  Note the below compuations of u and v are unneccessary, we really
39   //  only need the height, but we compute the entire vector to emphasis
40   //  the books discussion.
41   float  height  =   0.0f ;
42   if (dz  <   1.0f   -  dx)   //  upper triangle ABC
43   {
44    float  uy  =  B  -  A;  //  A->B
45    float  vy  =  C  -  A;  //  A->C
46    //  Linearly interpolate on each vector.  The height is the vertex
47    //  height the vectors u and v originate from {A}, plus the heights
48    //  found by interpolating on each vector u and v.
49   height  =  A  +  Lerp( 0.0f , uy, dx)  +  Lerp( 0.0f , vy, dz);
50  }

51   else   //  lower triangle DCB
52   {
53    float  uy  =  C  -  D;  //  D->C
54    float  vy  =  B  -  D;  //  D->B
55    //  Linearly interpolate on each vector.  The height is the vertex
56    //  height the vectors u and v originate from {D}, plus the heights
57    //  found by interpolating on each vector u and v.
58   height  =  D  +  Lerp( 0.0f , uy,  1.0f   -  dx)  +  Lerp( 0.0f , vy,  1.0f   -  dz);
59  }

60   return  height;
61 }

62
 
用到的2个函数

1float Terrain::Lerp(float a, float b, float t)     //一个插值函数
2{
3 return (a - (a*t) + (b*t));
4}

5
6int Terrain::GetHeightMapEntry(int row, int col)         //读取高度函数
7{
8 return _heightmap[row * _numVertsPerRow + col];   // 高度图数据存在_heightmap里
9}

 
二:
先计算出摄像机所在三角形的平面方程,然后带入摄像机的X,Z坐标,即可得高度Y
具体实现过程见http://creatorchen1984.spaces.live.com/ 《获取地形上某一点高度》,写的十分详细
 
三:
网上找的一个方法
假设你的地形为terrain[][];用下面的函数求出地形上点(x,z);的y值,将人物的高度加上这个y值即可.
 1float GetHeight(GLfloat x, GLfloat z)
 2
 3float h=0;
 4float Xb,Yb;
 5int Xa,Ya;
 6Xa=(int)x;
 7Ya=(int)z;
 8Xb=x-Xa;
 9Yb=z-Ya;
10float a=terrain[Xa][Ya].y;
11float b=terrain[Xa+1][Ya].y;
12float c=terrain[Xa][Ya+1].y;
13float d=terrain[Xa+1][Ya+1].y;
14h=(a*(1-Xb)+b*Xb)*(1-Yb)+(c*(1-Xb)+d*Xb)*Yb;
15return h;
16}
 
17
只有注册用户登录后才能发表评论。