4

ダイヤモンドスクエアアルゴリズムを使用してランダムな地形を生成しています。 これらの大きな円錐形を地形に突き刺すか、地形に突き刺す以外は問題ありません。 問題は、すべての時点でポイントがどちらかの方法が高すぎるか、あまりにも低く設定されているようです。ここでダイヤモンドスクエアアルゴリズムのスムージング問題

は、問題の絵
screenshot

あり、より良い、私は滑らかさが本当に高く設定すると
screenshot closeup

そしてここでは私のコードで見ることができます -

private void CreateHeights() 
    { 
     if (cbUseLand.Checked == false) 
      return; 
     int 
      Size = Convert.ToInt32(System.Math.Pow(2, int.Parse(tbDetail.Text)) + 1), 
      SideLength = Size - 1, 
      d = 1025/(Size - 1), 
      HalfSide; 
     Heights = new Point3D[Size, Size]; 
     float 
      r = float.Parse(tbHeight.Text), 
      Roughness = float.Parse(RoughnessBox.Text); 

     //seeding all the points 
     for (int x = 0; x < Size; x++) 
      for (int y = 0; y < Size; y++) 
       Heights[x, y] = Make3DPoint(x * d, 740, y * d); 

     while (SideLength >= 2) 
     { 
      HalfSide = SideLength/2; 

      for (int x = 0; x < Size - 1; x = x + SideLength) 
      { 
       for (int y = 0; y < Size - 1; y = y + SideLength) 
       { 
        Heights[x + HalfSide, y + HalfSide].y = 
         (Heights[x, y].y + 
         Heights[x + SideLength, y].y + 
         Heights[x, y + SideLength].y + 
         Heights[x + SideLength, y + SideLength].y)/4 - r + ((float)(random.NextDouble() * r) * 2); 
       } 
      } 

      for (int x = 0; x < Size - 1; x = x + SideLength) 
      { 
       for (int y = 0; y < Size - 1; y = y + SideLength) 
       { 
        if (y != 0) 
         Heights[x + HalfSide, y].y = (Heights[x, y].y + Heights[x + SideLength, y].y + Heights[x + HalfSide, y + HalfSide].y + Heights[x + HalfSide, y - HalfSide].y)/4 - r + ((float)(random.NextDouble() * r) * 2); 
        if (x != 0) 
         Heights[x, y + HalfSide].y = (Heights[x, y].y + Heights[x, y + SideLength].y + Heights[x + HalfSide, y + HalfSide].y + Heights[x - HalfSide, y + HalfSide].y)/4 - r + ((float)(random.NextDouble() * r) * 2); 
       } 
      } 
      SideLength = SideLength/2; 
      r = r/Roughness; 
     } 
    } 
+0

これは非常に面白いです...私はランダム性を完全に取り出したので、 4つの周辺ポイントの平均ですが、私はどこでもこれらの "ディンプル"を取得します。 – Frobot

+0

両方のループでランダム性を取りましたか? –

+0

はい私は完全に任意のランダム性を取り除きました。途中でポイントを盛り上げて、エッジの周りから真ん中にかけてスムーズに移行する必要がありますが、ポイントが乱れている部分はまだあります。 – Frobot

答えて

6

ギャビン・S. P. Miller氏は、SIGGRAPHにフルニエ、Fussel &カーペンターのオリジナルのアルゴリズムは、根本的な欠陥だった方法について'86講演を行いました。だからあなたが見ているのは、Diamond Squareアルゴリズムの素朴な実装では普通です。平滑化のための別のアプローチが必要です。ダイヤモンドスクエアの各ステップをポストするか、ダイヤモンドスクエアのすべての反復(またはその両方)のポストプロセスにする必要があります。ミラーがこれに対処しました。重み付けとボックスまたはガウスフィルタリングは1つのオプションです。初期の配列を最初の4点よりも大きな程度に播種する(すなわち、ダイヤモンド・スクエアの最初のいくつかのステップの結果セットを手動で複製するか、組み込みのインテリジェンスを使用する代わりにバイアスのない値を供給する)。ダイヤモンドスクエアを使用してディテールを増やす前に配列に与える初期情報が多いほど、結果は向上します。

理由は、正方形のステップが実行される方法にあるように見えます。ダイヤモンドのステップでは、四角形の四隅の平均を取ってその四角形の中心を作りました。次に、次のSquareステップでは、直角に隣接する4つの隣接するものの平均を取る。そのうちの1つはで、先ほど作成した正方形の中心点である。あなたは問題を見ることができますか?それらのオリジナルのコーナー高さ値は、その後のダイアモンド・スクエア・イテレーションに多すぎる寄与をしています。なぜなら、彼ら自身の影響と作成した中間点の両方に寄与しているからです。これは、尖塔(押し出しと侵入)を引き起こします。なぜなら、局所的に導かれたポイントは、それらの初期のポイントに向かってより強く傾向があります。そして(通常3つの)他のポイントも同様です。ダイアモンド・スクエアを使用して深度を上げます。したがって、これらの種類の "エイリアシング"問題は、配列の初期状態が不明な場合にのみ表示されます。実際に発生するアーチファクトは、4ポイントだけを使用して開始するという直接的な幾何学的結果と見ることができます。

次のいずれかを行うことができます

  • は地元のフィルタリングを行います - 一般的に高価。
  • 初期配列をより完全に事前シードする - 何らかの知能が必要です。
  • 与えられた初期点のセットからステップをあまりにも滑らかにしないでください。初期配列をシードしても適用されます。それは、あなた自身の最大変位パラメータと関連した相対深度の問題です。
0

私は、各反復における変位rのサイズは、現在の長方形のサイズに比例すると信じています。この背後にあるロジックは、フラクタルサーフェスはスケール不変であるため、任意の長方形の高さの変化は、その長方形のサイズに比例する必要があります。

コードの高さのばらつきはrに比例するため、現在のグリッドサイズのサイズに比例するようにしてください。換言すると、rにループの前の粗さを掛け、各反復でrを2で割る。

だから、あなたが書くべき代わり

r = r/Roughness; 

r = r/2; 
+0

私はあなたが何を意味するのか見ていますが、 "粗さ"はプログラムのテキストボックスから取られています。デフォルトでは2.5ですが、私も考えることのできるすべての数と一緒に2を試しました。この数値は、地形がどのように滑らかで/ギザギザになっていて、変更可能であると考えられるかを制御します。 – Frobot

0

上記のアルゴリズムの実際の欠陥は、概念化と実装のエラーです。アルゴリズムとしてのダイヤモンド・スクエアは、いくつかのアーチファクトを有するが、これは距離に基づくアーチファクトである。したがって、いくつかのピクセルの技術的な最大値は他のいくつかのピクセルより高いです。いくつかのピクセルはランダム性によって直接値が与えられ、他のピクセルはダイヤモンドと二乗された中点補間プロセスによってそれらの値を獲得する。

エラーはゼロから開始したことです。そして、その値を現在の値に繰り返し追加しました。これにより、二乗されたダイヤモンドの範囲がゼロから始まり、上方に伸びる。ランダム性に応じて、実際にはゼロから始まり、上下に移動する必要があります。したがって、トップレンジのものは重要ではありません。しかし、あなたがこれを認識せず、ゼロから始まりそこから変動するのではなく、値に加えられたすべてを純粋に実装すれば、隠された成果物が公開されます。

ミラーのメモは正しいものの、一般的にはノイズ内に隠されています。この実装は、これらの問題を示しています。それはNOTノーマルです。そして、いくつかの異なる方法で修正することができます。これは、このアルゴリズムを拡張してメモリの制限とサイズ制限をすべて無くし、無限かつ確定的な1にした後、私はここでもコアアイデアから切り離した理由の1つでした(3dに拡張してGPUを最適化する問題また、役割を果たした。2

diamond squared artifacts

0

だけではなく、平均して平滑化し、あなたは実現するのは簡単です。両極端を取り出す2-D median filterを使用し、通常で所望の効果を生成することができます

関連する問題