地形高度算法小结
地形一般是用网格再从高度图里读取每个顶点的高度来生成。若进一步,想实现摄像机在地形上行走的效果,就需要算出地形上任意一点的高度。总结了3个方法:
一:
《Introduction to 3D Game Programming With Directx 9.0》这本书里介绍的,利用向量来算。
地形一般是用网格再从高度图里读取每个顶点的高度来生成。若进一步,想实现摄像机在地形上行走的效果,就需要算出地形上任意一点的高度。总结了3个方法:
一:
《Introduction to 3D Game Programming With Directx 9.0》这本书里介绍的,利用向量来算。
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 {
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}
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
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
版权声明:本篇为原创文章,允许转载,但转载时请务必以超链接形式标明文章的原始出处和作者信息。请尊重本人的劳动成果,谢谢!
小祥的BLOG http://xfxsworld.cnblogs.com