滑らかなボクセル地形


13

個人的なプロジェクトとして、私はCastle Storyの滑らかな地形のような地形を作成する地形ジェネレーターを作成しようとしています。

あなたがそれを見たことがないなら、ここに: ここに画像の説明を入力してください

ご覧のとおり、ブロックと「スムーズ」ブロックの組み合わせです。

この外観をエミュレートするために私が試みたのは、各サーフェスブロックにミニハイトマップを与えることです。これは通常は機能しますが、いくつかの問題があり、次のような地形が生じます。

ここに画像の説明を入力してください

問題は、各ブロックが1x1x1であるが、特定の場所の高さがマイナスまたは> 1である場合があることです。その場合、クリップして、高さを0または1に設定します。

私が意味することをよりよく説明するために、図を示します。 ここに画像の説明を入力してください

高さを生成するために、基本的に次のことを行います。

genColumn(int x, int z)
{
    int highestBlockY = (int)noise2d(x, z);

    bool is_surface = true;

    for(int y = max_height - 1; y >= 0; y--)
    {
        Block b;

        if(is_surface)
        {
            b = Block.Grass;
            b.HasHeightMap = true;

            // generate heightmap
            for(int ix = 0; ix < 5; ix++)
            {
                for(int iz = 0; iz < 5; iz++)
                {
                    float heightHere = noise2d(x + ix / 4, z + iz / 4) - y;

                    // clip heights
                    if(heightHere > 1)
                        heightHere = 1;

                    if(heightHere < 0)
                        heightHere = 0;

                    b.HeightMap[ix][iz] = heightHere;
                }
            }

            is_surface = false;
        }
        else
        {
            b = Block.Dirt;
        }

        setBlock(x, y, z, b);
    }
}

「本当の」perlinノイズ値を使用して、これに間違って近づいているのでしょうか?

どんな助けも大歓迎です!

回答:


11

技術的な制約のため、このような城ストーリールックス:各あたりわずかハイトのではなく、全体のボリューム内の各ボクセルごとハイトがあることでした表面ボクセルは、ストレージ・コストはO(N ^ 3の順に、非常に大きくなるだろう)これは、より好ましいO(n ^ 2)とは対照的に、禁止的である可能性があります。nは、あなたの世界を表す立方ボクセル空間の辺の長さです。地下ボクセルのハイトマップ情報はグリッド構造に暗黙的に含まれているため、ハイトマップ情報はサーフェス上にあるボクセルに対してのみ明示的に保存する必要があることに注意してください。そのため、Castle Storyの担当者は、頂点をグリッドの隙間にスナップして、ストレージコストとメッシュ構造の複雑さを節約しています...続きを読んでください。

まず、オプションを見てみましょう。

ここに画像の説明を入力してください

(1)は、1つのボクセル列で最上位のボクセルのミニハイトマップ情報のみを必要とするため、物事を難しくします。理由については、最初の段落を参照してください。(1)を見ると、右側の列には最上部と上から2番目の両方のハイトマップ情報があります(傾斜が極端な場合、これは上から3番目などに適用できます)。これはダメです。

(2)おそらくより良いオプションです。つまり、コーナーの頂点がボクセルグリッドの隙間に確実にスナップするようにします。しかし、その後、極端な勾配の問題にどのように対処しますか?さて、単純に垂直の列にスナップするグラデーションを選択する必要があります。したがって、最上位n個のボクセルをクロスカットできるグラデーションを持たないようにします。以下に説明する理由から、45度の勾配は自然なカットオフです。したがって、(3)の代わりに、(4)が得られます。

ここに画像の説明を入力してください

(4)ボクセルのコーナー頂点を最も近いグリッドの隙間にスナップすることが解決策です。視覚効果-対角線エイリアシング-は、Castle Storyのスクリーンショットで見ることができます。ボクセルのカットオフスロープは、1:1の勾配、または45度(直交表示)です。ソリューションから逆戻りして、理由を見てみましょう。

  • ボクセルが垂直に伸びていれば、途切れることのない極端な傾斜を得ることができる唯一の方法は...
  • ....しかし、ボクセルのメッシュは、実際のスムージングされた形状に関係なく、境界領域を超えることはできません。ボクセルは、3Dグリッド内の定義されたスペースに配置する必要があります。これは、正確な形ではない場合、少なくとも軸に沿った境界ボックスを考慮しています。

この方法でアプローチするもう1つの理由は、既に発見したように、スナップ(離散化)を使用しないと、幾何学的に複雑な一連の表面平滑化シナリオが発生するためです。適切なCSGアルゴリズムが提供する精度の度合い。これが、ボクセルを最初に使用する理由です。ボクセルを使用すると、浮動小数点(連続)ポリゴン交差/ CSGアルゴリズムよりも、ボリュームをインクリメンタルに処理しやすくなります。 。


私はこれを実装しようとしましたが、混乱が生じました。「隙間」とはどういう意味ですか?積分グリッド座標を意味していますか?
無題

しゅう 「物事の間に介在する空間。」2Dでは、セルのanxnグリッドがある場合、(n + 1)x(n + 1)の隙間があります。これは3Dに直接拡張されます。それらは各セルを結合する「頂点」であり、ほとんどが複数のセル/ボクセル間で共有されます。それを1D(線)に煮詰めると、セルと隙間の両方が配列として表される場合、セル0は隙間0と隙間1で区切られ、セル1は隙間1と隙間2で区切られます...など
エンジニア

返信いただきありがとうございます!まさにそれを試みましたが、いくつかの不利な結果が得られました。まず、私は単に(xは0または4である、又はzは0又は4の場合)エッジで高さの値を丸める試みたが、それは私を得た:i.imgur.com/eQW7Y.pngpastebin.com/Lr8vyyHB)私は「固定高機能」を追加して次は、私は、途中でポイントを滑らかにしようとした:pastebin.com/AazQ07Xm、しかし、また、私に多くの角度でなく、悪い結果を与えた: i.imgur.com/q1JVPを.png ノイズ関数に何か問題があるのでしょうか?
無題

@ThomasBradsworth悲しいことに、私はあなたが書いて編集するのに1時間以上かかった答えを半分読んだ/理解しただけだと感じています。ノイズを忘れてください。さらに、ノイズ関数を理解していない場合は、当面は方程式から削除してください。問題は、個々のボクセルメッシュデータがどのように構築されるかであり、ノイズがない場合でもハイトマップを作成できるため、ノイズはそれとは関係ありません。最も単純なテストケースで作業します。つまり、高さ配列をハードコードします。次に、結果を表示し、メッシュ生成アルゴリズムを微調整します。期待どおりに動作するまで繰り返します。次に、ノイズを元に戻し、確認します。
エンジニア

「中間」ポイントの高さ値を保存せず、角の高さ値のみを保存する必要があると言っていますか?
無題
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.