1

ハイトマップ イメージのすべてのピクセルをテレインに適切にマッピングするには、ハイトマップの実際の幅と長さより 1 単位少ない幅と長さのテレインになります。たとえば、幅がわずか 2 ピクセルの画像がある場合、各ピクセルはクワッドの各頂点にマップされます。2 ピクセルありますが、地形は 1 ユニットしかありません。

地形をスケーリングして、地形の端にある空のクワッドを埋めることで、この問題を「修正」しようとしています。ただし、(x,z) ポイントで地形の高さを取得しようとすると、これが問題になります。問題は、ご覧のとおり、正確にはスケーリングではありません。

まず、動作するコードを見てみましょう。スケーリングが不足しているクワッドを考慮していないもの。スケーリングなしで 1023x1023 の四角形 (実際には三角形を使用していますが、四角形で説明するのは簡単です) で地形を作成する 1024x1024 の高さマップがあります。

次に、次の関数に適切な引数を渡して、地形を 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 であり、それ以上は使用されません (これで問題ありません)。ここで、ゲーム キャラクターを動かしていて、現在のプレイヤーの位置で地形の高さを取得する必要があるとします。xプレイヤーの位置と座標を取り、zその時点での高さを返す関数があります。しかし、地形の寸法はスケーリングされているため、関数に渡された をそのまま使用することはできませんxz次のように、正しいものを計算する必要があります。

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

その後、新しい 4 つの隣接する頂点を見つけ、すべての頂点の高さに対して双一次補間を実行して、プレーヤーの位置の正しい高さを計算するだけxですz

これはすべて正常に機能しています。地形が適切に描画され、すべての高さが適切に計算されます。私の問題は、この質問の冒頭で説明した「制限」を回避しようとするときです。

この問題を回避するために、スケール関数を次のように変更します。

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、高さを返す関数で使用される方程式を理解できません。ダイビングと、以前のようにステップサイズを使用しても、うまくいきません。ステップの計算方法が少し異なり、以前ほど単純ではありません。xz

4

2 に答える 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);

}
于 2011-04-28T17:53:05.300 に答える
0

方法が単純すぎる。建物やオブジェクトを含む複雑な 3D 地形はどうですか? glReadPixels を使用して深度バッファーを読み取り、簡単な数学を使用して、シーン内の任意の場所の地形上の高さを見つけました。

于 2014-04-24T16:49:38.830 に答える