3

短縮版:

値がわずかに変化するにもかかわらず、時間の経過とともにほぼ並べ替えられたデータをほぼ並べ替えられた順序で保持する手法を探しています。

シナリオは次のとおりです。

3Dグラフィックスの世界では、描画する前にオブジェクトを前から後ろに並べると便利なことがよくあります。シーンが変更されたり、シーンのビューが変更されたりすると、このデータは再並べ替えが必要になる場合がありますが、通常は並べ替えの順序に非常に近くなります(つまり、フレーム間であまり変化しません)。また、データが正確にソートされた順序であることが重要ではありません。発生する最悪の事態は、ポリゴンがレンダリングされてから完全に非表示になることです。これは小さなパフォーマンスヒットですが、世界の終わりではありません。

これを念頭に置いて、事前にデータを並べ替えてから、フレームごとに1回データに最小限のパッチを適用して、データがほとんど並べ替えられたままになるようにすることは可能ですか?このシナリオでは、ほとんどのオブジェクトが昇順である場合、データはほとんどソートされていると見なされます。つまり、適切な場所から10ステップ離れた1つのオブジェクトは、適切な場所から1ステップ離れた10個のオブジェクトよりもはるかに優れています(10倍優れています)。

また、データは通常1秒あたり30回(またはそれ以上)レンダリングされるため、データには半定期的にパッチが適用され続ける可能性があることにも注意してください。計算が効率的である限り、変更が停止してリストが完全にソートされるまで、時間をかけて計算を続けることができます。

既存のアイデア:

この問題に対する私のひざの反応は次のとおりです。

  1. n log nデータがロードされたとき、および大きな変更(非常に簡単に追跡できます)にデータに並べ替えを適用します。

  2. データがゆっくりと変化し始めたら(たとえば、シーンが回転しているとき)、データにある種の単一の(線形)パスを適用して、後方に隣接するものをスワップし、ソート順を維持しようとします(これは基本的にシェルソートだと思います-多分あるかもしれませんこのシングルパスに使用するより良いアルゴリズム)。

  3. 変更が停止し、データが完全に並べ替えられるまで、各フレームの部分的な並べ替えを1回繰り返します。

  4. 手順2に戻り、さらに変更が加えられるのを待ちます。

4

5 に答える 5

5

入力がほとんどソートされている場合は O(n) 時間、データがソートされていない場合は O(n log n) で実行されるさまざまなソートがあります。結構気軽に使えそうです。Timsort はそのようなソートの 1 つであり、Python と Java の両方で現在デフォルトのソートになっていると思います。Smoothsort は、自分で実装するのがかなり簡単なもう 1 つの方法です。

于 2012-06-26T19:39:03.710 に答える
3

あなたの説明から、データ自体を変更せずにソート順が変更されたように聞こえます。たとえば、カメラを変更すると、ポリゴンを変更していなくても、並べ替え順序が変更されるはずです。

その場合、ソート順の変更が発生したときにそれを直接検出することはできません。できれば、ポリゴンのリスト用のバケットを作成し、そのバケット内の「十分な」ポリゴンに触れたときにバケットを再分類します。

しかし、あなたのシステムはそのようには機能しないに違いありません。並べ替えは、ビュー ポートによって決まります。その場合、並べ替えの前にあるポリゴンは、最後にあるポリゴンよりもはるかに重要です。

したがって、ポリゴン リストを 5 分の 1 などに分割します。最初の 5 分の 1 がカメラに最も近い部分になるように、前から後ろへ。フレームごとに最初のセグメントを完全にソートします。2 番目のセグメントをサブ セグメント (もう一度 5 つ) に分割し、各サブ セグメントをフレームごとに並べ替えて、5 フレームごとに 2 番目の 5 番目が完全に並べ替えられるようにします。3 番目から 5 番目のセグメントを 15 のサブ セグメントに分割し、それぞれ 5 フレームごとに実行して、残りが 75 フレームごとに完全にソートされるようにします。60 fps では、表示リストが 1 秒に 1 回以上完全に並べ替えられます。

リストの前面に優先順位を付ける利点は 1 です。前面のポリゴンは画面上で大きくなる傾向があり、深度テストに失敗する頻度が高くなります。リストの最後にある悪い注文は、多くの場合、問題にならないだけではありません。2. リストの先頭は、カメラの変更による並べ替えの影響を受けやすくなります。

また、ポリゴンが 2 つのソートで正しいセグメントに移行できるように、少しオーバーラップするセグメント範囲を選択します。

@OP: もう少し考えてみます。おそらく、シーンの複雑さで爆発するのではなく、並べ替えのコストを制限したままにすることに関心があるでしょう。特に、非常に複雑なシーンは、驚くべきことに、悪い並べ替えの影響を受けにくいはずです (通常、ポリゴンが小さくなるため)。

フレームごとに実行する一定量の並べ替えを定義できます。予算の 50% をリストの先頭部分にできるだけ多く使用し、予算の 25% を次の地域の並べ替えに使用し、残りの 25% を均等に使用します。

フレームごとに 1000 個のポリゴンを並べ替え、シーン内に 10000 個のポリゴンがあるとします。フレームごとに最初の 500 ポリゴンを並べ替えます。次の領域の 10 フレームごとに 250 ポリゴンを並べ替えます。したがって、フレーム 1 では 501 ~ 750、フレーム 2 では 751 ~ 1000 などです。次に、リストの残りを 250 フレーム セグメントに分割し、必要な数のフレームについてラウンド ロビンで並べ替えます。

これにより、シーンがますます複雑になってもソート コストが一定に保たれ、調整も簡単です。ソート バジェットを余裕のある範囲に調整するだけです。

于 2012-06-26T18:43:58.730 に答える
1

ここでは、他の多くのソリューションから借用したソリューションを提案します。もちろん、初期化時にオブジェクトの完全な並べ替えから始めます。

私がすることは、常に、フレームごとにオブジェクトに対して 10 回の線形時間実行を実行することです (オブジェクトが既に完全にソートされていることがわかった場合は早期終了します)。各実行は、たとえば、配列全体にわたるシェル ソートスタイルのギャップを伴うバブル ソートの 1 つのパスである可能性があります。0 から n-gap-1 までのすべての i について、A[i] と A[i+gap] を比較し、ソートされていない場合は交換してください。ギャップの固定シーケンスを使用することも、フレーム間で変化させることもできます。いずれにせよ、オブジェクトが変化しない十分な数のフレームを実行すると、完全に並べ替えられたシーケンスが得られます。各反復が「ソート性」を改善する限り、さまざまなタイプのサブアルゴリズムを組み合わせて実行することもできます。

Rafael Baptista のアイデアを追加して、シーンの前面を簡単に優先することができます。これには、前面セグメントで 1 回余分に実行するか、前半のギャップを 2 で分割するか、またはそのような方法を選択します。

于 2012-06-26T23:08:54.563 に答える
0

シェル ソートは、一意の値がほとんどないリストや、「短いコードが必要でコール スタックを使用しない」シナリオに適しています。

あなたの場合、Adaptive sortと呼ばれるものが必要です。これは、アルゴリズムが「入力の既存の順序を利用する」ことを意味します。

スペースが狭い場合は、順応性があり適切な場所にあるストレート挿入ソートを使用できます。

それ以外の場合は、@RunningWild が提案したように、Timsort と Smoothsort を試すことができます。どちらも適応ソート アルゴリズムです。

于 2012-06-26T20:12:28.850 に答える
0

カメラを 90 度回転させるだけで、並べ替えの基準がまったく別の軸にあるため、想定した問題ほどうまくいきません。(たとえば、X 軸と Y 軸は独立しています。X 軸を見下ろすと、並べ替え順序は X 軸に依存しなくなり、Y 軸を見下ろすと、並べ替え順序は Y 軸に依存しなくなります。) 5 度回転しただけでも、(Z オーダーに関する限り) 遠く離れた "近い" ものが突然 "遠く" になる可能性があります。

正直なところ、オブジェクトの描画呼び出しの生成は、通常、オブジェクトの並べ替えよりもはるかに時間がかかります。特に、シナリオ用に最適化された並べ替えアルゴリズムがあり、ゲームが最新の視覚的複雑さを備えている場合は特にそうです。

特にヒストグラムベースのアルゴリズムまたは基数スタイルのアルゴリズムでは、並べ替えは実​​質的に O(n) になる可能性があります。(はい、基数ソートは整数に適用されるため、世界座標を整数にスケーリングする必要がありますが、巨大な世界がない限り、通常はそれで十分です。)

そうは言っても、描画しているすべてのものに対して既に O(n) ops を実行しているため、特に高レベルと低レベルの最適化の両方で、フレームごとに再分類することは大きな問題にはなりません。

この問題に対処するもう 1 つの一般的な方法は、シーン グラフを使用することですが、目的のためには、基本的にフレームごとに再ソートすることになります。ただし、錐台カリング、シャドウ カリング、および詳細レベルの計算をシーン グラフ トラバーサルに組み込むことができます。

近似値を探している場合は、z 距離の並べ替えを行う代わりに、真の距離の並べ替えを行い、近くのオブジェクトの並べ替え順序をより頻繁に更新し、遠くのオブジェクトの頻度を減らします (カメラが移動した距離によって異なります)。これは、オブジェクトから離れている場合、移動してもビューアーに対する角度が頻繁に変化しないため、古い並べ替えデータが有効である可能性が高くなるため、機能する可能性があります。ゲームが問題なくマップ上をテレポートできるアルゴリズムが好きなので、私はこれが好きではありません。(注意してください。ディスクからのアセットのストリーミングは、テレポートの真の問題になります。)

于 2012-06-26T19:28:56.417 に答える