6

パーリン ノイズに基づいてマップ ジェネレーターをコーディングしていて、問題が発生しました。

30% の水と 70% の土のタイルが必要だとしましょう。通常の乱数発生器では問題ありません。

tile = rnd.nextFloat() < 0.7f ? DIRT : WATER;

しかし、パーリン ノイズは正規分布 (範囲は -1 から 1、平均は 0) であるため、それほど簡単ではありません。

法線を一様分布に変換する方法、またはノイズ値からパーセンテージを取得できる別の方法を知っている人はいますか?

編集: 70% は単なる例です。任意の値を動的に、せいぜい 0.1% の精度で使用できるようにしたいと考えています。

EDIT2:パーリンノイズを通常の分布ではなく、均一な分布に変換したい(すでに似ている)。

4

6 に答える 6

6

正確に 30% の水 (またはその他の指定値) を取得したい場合は、これを行うことができます。

  1. 高さマップを生成します。
  2. すべての高さの値をリストに入れます。
  3. リストを並べ替えます。
  4. リストの30%に表示される値を水位として選択します。
于 2012-07-14T23:00:02.293 に答える
4

パーリン ノイズ分布はのようなガウス分布に過ぎず、真の正規分布ではありません。

さらに、ピークは非常に狭く、標準偏差は約 0.1 です (正確な数値はわかりません)。

しきい値を ~ 0.1 に設定するだけで、それより70% 低い値と 30% 高い値が得られます。

于 2012-07-14T22:25:43.517 に答える
4

私が考え出した解決策: まず、1 億個のパーリン ノイズを生成し、それらを配列に格納します。それを並べ替えた後、10,000 ごとの値を 1000 分の 1 のしきい値として使用できます。これで、これらのしきい値をハードコードできるようになったので、実行時にルックアップするための 1,000 個の浮動小数点数を持つ配列ができました。

利点:

実行時の配列へのアクセスは 1 回だけなので、非常に高速です。

欠点:

アルゴリズムを変更した場合は、しきい値配列を再生成する必要があります。次に、平均は約 10/10 にスケーリングされ、50% のしきい値は 49.5% または 50.5% になります (< または <= 演算子を使用するかどうかによって異なります)。第 3 に、メモリ フットプリントの増加 (1 ミルあたりの精度で 4kb)。パーセント精度または対数精度スケールを使用して、これを減らすことができます。

生成コード:

final PerlinNoiseGenerator perlin = new PerlinNoiseGenerator(new Random().nextInt());

final int size = 10000; //Size gets sqared, so it's actually 100,000,000

final float[] values = new float[size * size];
for (int x = 0; x < size; x++)
    for (int y = 0; y < size; y++) {
        final float value = perlin.noise2(x / 10f, y / 10f);
        values[x * size + y] = value;
    }
System.out.println("Calculated");

Arrays.sort(values);
System.out.println("Sorted");

final float[] steps = new float[1000];
steps[999] = 1;
for (int i = 0; i < 999; i++)
    steps[i] = values[size * size / 1000 * (i + 1)];
System.out.println("Calculated steps");

for (int i = 0; i < 10; i++) {
    System.out.println();
    for (int j = 0; j < 100; j++)
        System.out.print(steps[i * 100 + j] + "f, "); //Output usuable for array initialization
    System.out.println();
    System.out.println();
}

参照コード:

public final static float[] perlinThresholds = new float[]{}; //Initialize it with the generated thresholds.

public static float getThreshold(float percent) {
    return perlinThresholds[(int)(percent * 1000)];
}

public static float getThreshold(int promill) {
    return perlinThresholds[promill];
}

X
于 2012-07-15T12:15:14.780 に答える
0

まあ、もしそれがほぼガウスであれば、70% は 0.75 未満のすべてになります。この表を参照してください: http://www.roymech.co.uk/Useful_Tables/Statistics/Statistics_Normal_table.html

于 2012-07-14T22:29:29.663 に答える
0

単純に 1 を足して 2 で割りますか? これにより、0.5 を中心とした 0 から 1 までの分布が得られます。

編集: 70% 対 30% のしきい値分割が必要な場合は、通常の法則の累積分布関数を使用する必要があります。x を下回る確率が 0.7 のような x を見つけるだけです。これは正規分布でのみ機能することに注意してください。分布が常に -1 と 1 の間にある場合、それは正規分布ではありません。正規分布の出力間隔は -∞ と +∞ であると想定されます。@paxinum が言及した解決策は、自分で計算を行うよりも簡単です。

于 2012-07-14T22:15:25.700 に答える