为了将高度图图像的每个像素正确映射到地形,我们将得到宽度和长度均比高度图的实际宽度和长度小1个单位的地形。例如,如果我们的图像宽度仅为2像素,则每个像素将映射到四边形的每个顶点。我们有2个像素但只有1个单位的地形。
我试图通过缩放地形来填补地形尽头的空四边形来“解决”这个问题。然而,当我试图在某个(x,z)点获得地形的高度时,这是有问题的。问题并不完全是您所看到的缩放。
首先,让我们看看有效的代码。缩放不考虑丢失四边形的那个。我有一个1024x1024高度图,它将创建一个1023x1023四边形的地形(我实际上使用三角形,但很容易用四边形解释),没有任何缩放。
现在让我们通过将适当的参数传递给以下函数来将地形缩放到类似2000x2000的地方:
void Terrain::ScaleDimension(float dimWidth, float dimLength) {
if(dimWidth <= 0.0f || dimLength <= 0.0f) return;
stepWidth = dimWidth / width; // 1.953125 = 2000 / 1024
stepLength = dimLength / length; // 1.953125 = 2000 / 1024
}
绘制地形时,我使用stepWidth
和stepLength
来相应地缩放地形。地形将被缩放,但将仅使用1023个四边形,总是1023,不再使用(这很好)。现在让我们说我正在移动我的游戏角色,我需要在当前玩家位置获得地形高度。我有一个功能,它将采用玩家位置的x
和z
坐标并返回该点的高度。但是由于地形维度是缩放的,我不能只使用传递给函数的x
和z
,我需要计算正确的,如下所示:
x = x / stepWidth;
z = z / stepLength;
之后,我只需要找到新x
和z
的4个相邻顶点,并对所有顶点高度执行双线性插值,以计算玩家位置的正确高度。
这一切都很好。正确绘制地形并正确计算所有高度。我的问题是当我试图绕过这个问题开头解释的“限制”时。
为了解决这个问题,我将缩放功能更改为:
void Terrain::ScaleDimension(float dimWidth, float dimLength) {
if(dimWidth <= 0.0f || dimLength <= 0.0f) return;
stepWidth = dimWidth / (width - 1.0f);
stepLength = dimLength / (length - 1.0f);
}
假设我的地形大小(我传递给上面的比例函数的值)与高度图的大小完全相同,即1024x1204。这将给我一步1.000977517106549364613880742913
,这将使1023四边形完全适合从0到1024(地形的大小)。到目前为止一切都那么好,地形完全按照我的预期绘制。
真正的问题是计算高度。我尝试了很多东西,但我无法弄清楚方程式,以计算在返回高度的函数上使用的正确x
和z
,给定新步骤上面的计算。像我之前一样潜水x
和z
步长只是不会削减它。现在计算的步骤略有不同,并不像以前那么简单。
答案 0 :(得分:0)
如果您希望从0..1023
缩放到0..1999
,则需要在每个位置进行采样以获得正确的值。
Given: old new
0,0 == 0,0
0,1023 == 0,1999
1023,0 == 1999,0
1023,1023 == 1999,1999
换句话说,四个角保持不变。
现在,您需要计算任何给定点的高度,您可以这样称呼它:
float height = convert(1500,1450,1024,2000);
float convert(int newx, int newy, int origScale, int newScale) {
float factor = ((float)(origScale)) / (float)(newScale);
float oldx = newx * factor;
float oldy = newy * factor;
int oldxlo = floorInt(oldx); // oldx == 3.4, oldxlo = 3
int oldxhi = ceilInt(oldx); // oldx == 3.4, oldxhi = 34
int oldylo = floorInt(oldy); // oldy == 3.4, oldylo = 3
int oldyhi = ceilInt(oldy); // oldy == 3.4, oldyhi = 34
float topLeftHeight = getHeight(oldxlo,oldylo);
float topRightHeight = getHeight(oldxhi,oldylo);
float botLeftHeight = getHeight(oldxlo,oldyhi);
float botRightHeight = getHeight(oldxhi,oldyhi);
// now you have the heights of the four corners of the old grid
// that surround the new grid. You can use a form of interpolation on this grid,
// I'm sure you can find one somewhere.
Point3D topLeft(oldxlo,oldylo,topLeftHeight);
Point3D topRight(oldxhi,oldylo,topRightHeight);
Point3D botLeft(oldxlo,oldyhi,botLeftHeight);
Point3D botRight(oldxhi,oldyhi,botRightHeight);
// or something
return bilinearInterpolate(topLeft,topRight,botLeft,botRight,newx,newy);
}
答案 1 :(得分:0)
方法太简单了。那些建筑物和物体的复杂3D地形怎么样?我使用glReadPixels读取深度缓冲区&amp;使用一些简单的数学方法在场景中的任何地方找到高于地形的高度。