如何正确获取缩放地形中点 (x,z) 处的地形高度
为了正确地将高度图图像的每个像素映射到地形,我们最终得到的地形宽度和长度都比高度图的实际宽度和长度小 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
根本不会削减它。现在该步骤的计算方式略有不同,并且不像以前那么简单。
To properly map every pixel of a heightmap image to a terrain, we will end up with a terrain both in width and length 1 unit less that the actual width and length of the heightmap. For instance, if we have an image with just 2 pixels wide, each pixel will map to each vertex of a quad. We have 2 pixels but only 1 unit of terrain.
I'm trying to "fix" this problem by scaling the terrain to fill the empty quad in the end of the terrain. However, this is being problematic when I try to get the height of the terrain in some (x,z) point. The problem is not exactly the scaling as you'll see.
First, let's look at the code that works. The one where the scaling does not take into account the missing quad. I have a 1024x1024 heightmap which will create a terrain with 1023x1023 quads (I'm actually using triangles, but it's easy to explain with quads) without any scaling.
Now let's scale the terrain to something like 2000x2000 by passing the appropriate arguments to the following function:
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
}
When I draw the terrain, I use stepWidth
and stepLength
to properly scale the terrain accordingly. The terrain will be scaled, but only 1023 quads will be used, always 1023, no more (which is fine). Now let's say I'm moving my game character and I need to get the terrain height in the current player position. I have a function that will take the x
and z
coordinates of the player position and return the height at that point. But since the terrain dimension is scaled, I can't just use the x
and z
passed to the function, I need to calculate the right ones, like this:
x = x / stepWidth;
z = z / stepLength;
After that, I just need to find the 4 adjacent vertices of the new x
and z
and perform a bilinear interpolation on all vertices heights to calculate the correct height on the player's position.
This is all working just fine. The terrain is properly drawn and all heights are properly calculated. My problem is when I try to get around the "limitation" explained in the beginning of this question.
To get around the problem I change my scale function to this:
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);
}
Let's say my terrain size (the values I pass to the scale function above) is exactly the same size of the heightmap, that is 1024x1204. This will give me a step of 1.000977517106549364613880742913
which will make the 1023 quads to exactly fit from 0 to 1024 (the size of the terrain). So far so good, the terrain is drawn exactly as I expected.
The real problem is calculating the height. I've tried many things but I just can't figure it out the equation to calculate the correct x
and z
to be used on the function that returns the height, given the new step calculation above. Diving x
and z
with the step size like I did before simply won't cut it. The step is now calculated a little differently and not as simple as before.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您想从
0..1023
放大到0..1999
,您需要沿每个位置进行采样以获得正确的值。换句话说,四个角保持不变。
现在,您需要计算任何给定点的高度,您可以这样称呼它:
If you want to go from
0..1023
scaled up to0..1999
you need to sample along each position to get the proper values.In other words, the four corners stay the same.
Now, you need to compute the height of any given point, you'd call it like this:
方法过于简单。包含建筑物和物体的复杂 3D 地形怎么样?我使用 glReadPixels 来读取深度缓冲区和使用一些简单的数学计算来查找场景中任意位置的地形高度。
Methods are too simplistic. What about complex 3D terrain with buildings and objects? I've used glReadPixels to read the depth buffer & use some simple math to find the height-above-terrain anywhere in a scene.