|
Posted on 2007-11-15 19:26 小祥 阅读(954) 评论(0) 编辑 收藏 引用 所属分类: D3D
地形一般是用网格再从高度图里读取每个顶点的高度来生成。若进一步,想实现摄像机在地形上行走的效果,就需要算出地形上任意一点的高度。总结了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个函数
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
|