首页 文章

如何在缩放地形中正确获取点(x,z)处的地形高度

提问于
浏览
1

为了将高度图图像的每个像素正确映射到地形,我们将得到宽度和长度均比高度图的实际宽度和长度小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
}

当我绘制地形时,我使用 stepWidthstepLength 来相应地适当地缩放地形 . 地形将被缩放,但将仅使用1023个四边形,总是1023,不再使用(这很好) . 现在让's say I'移动我的游戏角色,我需要在当前玩家位置获得地形高度 . 我有一个函数,它将获取玩家位置的 xz 坐标并返回该点的高度 . 但是由于地形尺寸是缩放的,我不能只使用 xz 传递给函数,我需要计算正确的,如下所示:

x = x / stepWidth;
z = z / stepLength;

之后,我只需要找到新的 xz 的4个相邻顶点,并在所有顶点高度上执行双线性插值,以计算玩家位置的正确高度 .

This is all working just fine. The terrain is properly drawn and all heights are properly calculated. 我的问题是当我试图绕过这个问题开头解释的"limitation"时 .

为了解决这个问题,我将缩放功能更改为:

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(地形的大小) . 到目前为止一切顺利,地形完全按照我的预期绘制 .

真正的问题是计算高度 . 我想出了计算正确 xz 的等式,用于返回高度的函数, given the new step calculation above . 与之前一样的步长潜水 xz 根本不会削减它 . 现在计算的步骤略有不同,并不像以前那么简单 .

2 回答

  • 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);
    
    }
    
  • 0

    方法太简单了 . 那些建筑物和物体的复杂3D地形怎么样?我已经使用glReadPixels读取深度缓冲区并使用一些简单的数学运算来查找场景中任何位置的地形高度 .

相关问题