2

一連の不透明な長方形を効率的に描画/カリングするのに助けが必要です。つまり、これは机の上のインデックス カードのスタックです。詳細は次のとおりです。

  • 回転がないため、すべてが単純な整数座標であり、軸が整列しています
  • カードは完全に不透明です
  • カードは任意の整数の X、Y 位置を持つことができます
  • すべてのカードは同じサイズです
  • Zオーダーのカードのリストがあります

私は(本質的に)2つの選択肢があると思います:

1) デスクトップ ビューポート内のすべてのカードが逆 z オーダーで完全に描画されるブルート フォース ペインターのアプローチ。長所:シンプル。短所: a) ちらつきを避けるためにオフスクリーン バッファが必要です。b) 各カードの高価な領域を描画するのに多くの時間が浪費される可能性があります。

2) 可視部分のみが描画されるように、すべてのカードの可視 (または隠蔽) 長方形のリストを生成するアルゴリズム。

選択肢 2 は、特にアルゴリズムに関してアドバイスが必要な場所であり、「よりスマートな」描画サイクルの長所と短所です。

言語/プラットフォームにとらわれないアドバイスをお待ちしております。問題があれば、これは MS Windows に実装されます。

ハイブリッド アプローチを含め、あらゆる提案を歓迎します。正確な答えはコードの詳細に大きく依存する可能性が高いことを認識していますが、現時点では一般化された概念でも満足しています!

追加メモ: 何千枚ものカードを積み重ねることが可能になるため、純粋にブルート フォース ペインターのアプローチを避けることに非常に意欲的です。同じことが密接にタイル張りされた多くのカードにも当てはまり、最悪の場合、それらの境界線だけが表示されます.そのような場合、可能であれば複雑な内部のペイントをスキップしたいと思います.

4

2 に答える 2

0

わかりました、この問題を解決できると私が考える方法について、いくつかのルーズな疑似コードを示します。

z オーダーで並べ替えられたカードのリストから始めます。各カードには、カードの完全な境界ボックスに設定された 1 つの四角形から開始する必要がある、可視四角形のリスト (後で説明します) があります。ループは、最初に最も低い z オーダーのカードから開始されます。

Cards.SortZOrder();
foreach Card in Cards do
  Card.ResetVisibleRects; // VisibleRects.DeleteAll; VisibleRects.Add(BoundingBox);

CurrentCard = Cards.Last;
TestCard = CurrentCard;

ここでの考え方は、「現在の」カードから上に向かって作業し、それぞれのより高いカードがどのような影響を与えるかを確認するというものです。上位の各カードをテストすると、3 つの可能性があります。完全に見逃すか、完全に覆い隠すか、部分的に覆い隠すかのいずれかです。完全なミスの場合、現在のカードには影響しないため、テスト カードを無視します。完全にあいまいにするために、現在のカードはカリングされます。部分的なオーバーラップは、(潜在的に) 下の四角形を 2 つに分割する可能性があるため、可視の四角形のリストの出番です。(2枚のトランプまたはインデックスカードをつかむだけで、これがどのように展開するかを簡単に確認できます。上のカードは、エッジを共有している場合、下のカードがその辺の1つを調整するか、下のカードが分割されます。エッジを共有していない場合は、2 つの四角形に分割されます)。

警告: これは非常に最適化されておらず、展開されていないコードです...原則について話すためだけに。そして、はい、私は「goto」を使用しようとしています...必要に応じて私をからかってください。

[GetNextCard]
TestCard = Cards.NextHighest(TestCard);

[OverlapTest]
// Test the overlap of TestCard against all our VisibleRects.
// The first time through this test, CurrentCard will have only one
// rect in the VisibleRect list, but that rect may get split up later.
// OverlapTests() checks each rect in the VisibleRects list, and
// creates an Overlap record for any of the rects that do overlap,
// like: Overlap.RectIndex, Overlap.Type. It also summarizes the
// results into the .Summary field. 

Result = CurrentCard.OverlapTests(TestCard);

case Result.Summary
  none: 
    goto [GetNextCard];

  complete:
    CurrentCard.Culled = true;

    // we're now done with this CurrentCard, so we move upwards
    CurrentCard = TestCard;
    goto [GetNextCard]

  partial:
    // since there was some overlap, we need to adjust,
    // split, or delete some or all of our visible rectangles.
    // (we won't delete them all, that would have been caught above)

    foreach Overlap in Result.Overlaps
      R = CurrentCard.VisibleRects[Overlap.RectIndex];
      case Overlap.Type
        partial: CurrentCard.SplitOrAdjust(R, TestCard);
        complete: CurrentCard.Delete(R);
      end case

    // so we've either added new rects, or deleted some, but either 
    // way, we're done with this test card. We leave CurrentCard
    // where it is and loop to look at the next higher card.
    goto [GetNextCard]

CurrentCard = Cards.First最上部のカードが常に完全に表示されるため、テストが行​​われます。

ここでさらにいくつかの考え...

これは、実際のコードではかなり簡単だと思います。それについて最も複雑なことは、長方形を 2 つに分割することであり、それがすべて整数演算であるという事実を考えると、たとえそれが些細なことであってもです。

また、これはすべてのペイント サイクルで実行する必要はありません。コンテンツ、位置、または z オーダーに変更がある場合にのみ実行する必要があります。

リストを通過すると、カードのペイント準備完了リストが残ります。カリングされていない各カードには、ディスプレイのクリッピング/ダーティ領域内に収まる可能性のある長方形が少なくとも 1 つあります。カードをペイントすると、表示されている長方形のリストを調べることができ、レンダリングにコストがかかる可能性のあるカードの部分の描画をスキップできる可能性があります。

于 2012-11-03T05:30:12.217 に答える
0

一番下から一番上まで各カードの輪郭線だけをペイントするのはどうですか? 次に、フラッド フィルを実行して、輪郭の内側をペイントできます。この方法では、交差点がある境界に対応する数ピクセルのみを再描画します。

編集:アイデアを説明するのに役立つ画像をアップロードしました。

メソッドのパート 1 パート2

最初のステップは、Z オーダーを割り当てるカードの境界線をマークすることです (左上の画像)。このように、上書きがありますが、少量のピクセルである境界線のみです。

その後、次の 2 つのルールに従って、カードのテクスチャをペイントできます (Z オーダーが最も低いものから)。

  • 境界から始めて、境界に到達するまで空白をペイントします。
  • 境界線の Z オーダーが現在のものである場合は、それをペイントします。
  • 見つかった境界線の Z オーダーが現在の Z オーダーよりも小さい場合は、空白であったため、ペイントを続行します。
  • それ以外の場合は、Z オーダーが大きい境界線を見つけたので、そのブロックをスキップします。
  • 次のカード。

それが役に立てば幸い :)

于 2012-10-24T20:58:19.790 に答える