スターマップを生成するにはどうすればよいですか?


8

スターマップを生成しようとしています。

私の試みは:

  1. マップの幅と高さがあります。
  2. 幅と高さの領域全体にランダムにポイント(星)を配置します。

単純なアプローチですが、ランダムに星を互いに非常に近くに配置するという問題があります。

この問題を解決するための1つの方法は、最小距離を設定することです。星を生成するときに、新しい星から生成されたすべての星までの距離を比較し、最小距離を下回る場合は新しい星を生成しますが、それは効率的です。任意のヒント?


3
より効率的な方法があるかもしれませんが、なぜそれがうまくいかないのですか?この実装に問題がありますか?あなたは時期尚早に最適化していますか?
ヴァイランクール

星図の目的は何ですか?背景ですか、それとも競技場のようなものですか?
エリック

@AlexandreVaillancourtええ、私はまだ何個の星を生成したいのかわかりません。
zebleckDAMM 2016

@Erikは背景ではなく、やり取りできる星
zebleckDAMM

そして...あなたはそれをランタイムまたはオフラインで行いますか?
ヴァイランクール

回答:


13

A ポアソンディスクサンプリング分布を使用すると、最小の距離離れてランダムな点を選択するために、&ができますBridsonのアルゴリズムは十分な速さをリアルタイムであなたの星の数があまりにも巨大な取得していない提供のために-効率的にO(n)の中に問題を解決することができます。

Bridsonのアルゴリズムは、出力領域を最小許容距離を基準にしたサイズのセルのグリッドに分割し、各セルに1つのポイントしか表示されないようにします。次に、新しいポイントを追加することを検討する場合、ポイントのリスト全体ではなく、隣接するセルのディスク形状のコレクションをチェックするだけで済みます。たとえば、次の画像について考えてみます。

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

候補の青いドットが既存のドットに近すぎるかどうかを確認する場合、既存のすべてのドットに対してチェックする必要はありません。代わりに、隣接するセルのドットに検索を制限できます(これはルックアップテーブルを使用してすばやく見つけることができます)。Mike Bostockには、進行中のアルゴリズムを示す素晴らしいアニメーションがあります。

標準の実装では、ポイント間の固定された最小距離のみが考慮されます。Herman Tullekenのポアソンディスクサンプリング記事(ソースコードを含む)は、画像のさまざまな部分で最小距離を変化させるための適応について説明しています。基本的にはディザリングアルゴリズムのようです。記事の雲に示されているようにパーリンノイズ/シンプレックスノイズを使用すると、より自然に見える星図が得られる場合があります。たとえば、左側の画像を使用して右側を生成しました。

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

これを行うには、候補点を検討するときに、最初に入力画像の値を確認します。これにより、0から1までの値が得られます。次に、これを点間の望ましい最小および最大距離にスケーリングします。この場合、5ピクセルと20ピクセルを選択しました。したがって、暗い領域に点を配置すると、私の星は互いに5ピクセル近くになり、明るい領域に星を配置すると、最大20ピクセル離れることがあります。

出力ポイントが均一な最小距離を使用していないため、ブリドソンの高速化は可変距離サンプリングでは正確に機能しないことに注意してください。ただし、出力グリッドを使用して検索を減らすことができます。グリッドを小さくすると、ルックアップテーブルが大きくなりメモリが増える代わりに、最近傍の検索が速くなります。


2
リンクはとてもいいです。ただし、時間の経過とともに迷子になる可能性があります。ここに詳細を含めるとさらに良い場合があります。
Trilarion

それを防ぐために、もう少し説明とイラストを追加しました。
Pikalek

1

非常に素朴だが単純な解決策の1つは、常に「最小」距離をジャンプし、その上にランダムな量を追加することです。これは、星がバディバディになることは決してないことを意味し、少なくとも多少の偏差が発生します。

例えば

for (int x = 0; x < MAX_WIDTH; x+= MIN_SEPERATION_X)
{
  x += generateRandom();

  for (int y = 0; y < MAX_HEIGHT; y+= MIN_SEPERATION_Y)
  {
    y += generateRandom();

    if (x < MAX_WIDTH && y < MAX_HEIGHT)
    {
      image[x + y * width] = STAR;
    }
  }
}

(お好みの乱数生成機能を挿入)


しかし、そこで別の星にぶつかったらどうなるでしょうか。(また、このようにする場合、星は傾いた帯にある必要があります。)
Trilarion

1
別の星を打つことは可能ですか?画像全体で1回の反復のみを想定しています。両方の数値は常に最小分離によって変化しないのではないですか?恒星のマージはかなり厄介なので、それらが起こらないことを確認することは良いことだと私は同意します。超新星を引き起こすことは非常に思いがけないバグでしょう。
Huxellberger

常に乱数を追加するので、min_separationは保証されません(このアルゴリズムでは使用できません)。少なくとも、乱数がmin_separationを超えないようにしてください。保証される最小距離は、min_separation-max(generate_Random)になります。しかし、それは本当に悪いアプローチではありません。+1
Trilarion

このアプローチでは、yが変化してもx座標が変化しないため、星の列がきれいな垂直線で生成される傾向があります。密集したコレクションでは、これがランダムまたは自然に見えることはほとんどありません。
DMGregory

0

プレイスペースのXYZサイズがわかっている場合は、そのスペースでランダムなスポットを選択できます

次に、SphereCastを実行して、近すぎるものがないかどうかを確認します。

//pseudo code

SpawnStar(){
 Vector3 spot = new vector3(random(0,world size),random(0,world size,random(0,world size)

  while(true){
  SphereCast(spot, radius)
   if(hit something){
      spot = get new random spot
    }else{
     SpawnStar();
     brake;
    }
  } 
}

これの問題は、それはおそらくリアルタイムではあまり良くないということですが、事前に生成されたものでは問題なく、かなり高速です。


1
SphereCastが何であれ、これは質問で言及され、非効率的と見なされているソリューションではないでしょうか?
Trilarion


1
私はあなたがOverlapSphereを意味すると思います。SphereCastは線に沿って球を発射するため、カプセル型の検出フットプリントを持ちます。
DMGregory
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.