![](/images/cnblogs_com/xfxsworld/yuanchuang.gif)
地形一般是用网格再从高度图里读取每个顶点的高度来生成。若进一步,想实现摄像机在地形上行走的效果,就需要算出地形上任意一点的高度。总结了3个方法:
一:
《Introduction to 3D Game Programming With Directx 9.0》这本书里介绍的,利用向量来算。
![11.jpg](http://www.cnitblog.com/images/cnitblog_com/xfxsworld/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
![](http://www.cnitblog.com/Images/OutliningIndicators/None.gif)
2
![](http://www.cnitblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
3
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
4
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
5
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
6
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
7
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
8
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
9
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
10
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
11
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
12
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
13
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
14
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
15
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
16
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
17
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
18
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
19
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
20
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
21
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
22
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
23
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
24
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
25
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
26
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
27
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
28
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
29
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
30
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
31
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
32
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
33
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
34
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
35
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
36
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
37
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
38
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
39
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
40
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
41
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
42
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
43
![](http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
44
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
45
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
46
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
47
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
48
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
49
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
50
![](http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
51
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
52
![](http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
53
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
54
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
55
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
56
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
57
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
58
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
59
![](http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
60
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
61
![](http://www.cnitblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
62
![](http://www.cnitblog.com/Images/OutliningIndicators/None.gif)
用到的2个函数
1
float Terrain::Lerp(float a, float b, float t) //一个插值函数
2
{
3
return (a - (a*t) + (b*t));
4
}
5![](http://www.cnitblog.com/Images/OutliningIndicators/None.gif)
6
int Terrain::GetHeightMapEntry(int row, int col) //读取高度函数
7
{
8
return _heightmap[row * _numVertsPerRow + col]; // 高度图数据存在_heightmap里
9
}
![](http://www.cnitblog.com/Images/OutliningIndicators/None.gif)
2
![](http://www.cnitblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
3
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
4
![](http://www.cnitblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
5
![](http://www.cnitblog.com/Images/OutliningIndicators/None.gif)
6
![](http://www.cnitblog.com/Images/OutliningIndicators/None.gif)
7
![](http://www.cnitblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
8
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
9
![](http://www.cnitblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
二:
先计算出摄像机所在三角形的平面方程,然后带入摄像机的X,Z坐标,即可得高度Y
具体实现过程见http://creatorchen1984.spaces.live.com/ 《获取地形上某一点高度》,写的十分详细
三:
网上找的一个方法
假设你的地形为terrain[][];用下面的函数求出地形上点(x,z);的y值,将人物的高度加上这个y值即可.
1
float GetHeight(GLfloat x, GLfloat z)
2
{
3
float h=0;
4
float Xb,Yb;
5
int Xa,Ya;
6
Xa=(int)x;
7
Ya=(int)z;
8
Xb=x-Xa;
9
Yb=z-Ya;
10
float a=terrain[Xa][Ya].y;
11
float b=terrain[Xa+1][Ya].y;
12
float c=terrain[Xa][Ya+1].y;
13
float d=terrain[Xa+1][Ya+1].y;
14
h=(a*(1-Xb)+b*Xb)*(1-Yb)+(c*(1-Xb)+d*Xb)*Yb;
15
return h;
16
}
17![](http://www.cnitblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cnitblog.com/Images/OutliningIndicators/None.gif)
2
![](http://www.cnitblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
3
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
4
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
5
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
6
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
7
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
8
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
9
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
10
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
11
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
12
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
13
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
14
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
15
![](http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif)
16
![](http://www.cnitblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
17
![](http://www.cnitblog.com/Images/OutliningIndicators/None.gif)
版权声明:本篇为原创文章,允许转载,但转载时请务必以超链接形式标明文章的原始出处和作者信息。请尊重本人的劳动成果,谢谢!
小祥的BLOG http://xfxsworld.cnblogs.com