1

3D モデル (シーン グラフ) を表すオブジェクトのツリーがあります。ツリー ノードはさまざまなタイプです (共通の基本クラスからの派生クラスとして実装されます)。たとえば、ポリゴンを表すノードや、その子ノードに座標変換 (回転、平行移動) を適用するノードがあります。また、サードパーティ ベンダーが新しいノード タイプを実装し、それらをプラグイン (GUI フレームワークとして Qt を使用) で追加できる必要があることも要件です。したがって、コンパイル時にタイプが不明なノードがツリーに存在する可能性があります。

ここで、このシーン グラフのビューとして機能するクラスを実装したいと思います。すべてのツリー ノード タイプに対して、ビューは適切なアクション (ポリゴンの描画、変換など) を実行する必要があります。私の考えは、すべてのノード タイプにビュー クラスを実装し、ノード タイプに応じてトップレベル ビュー クラスをこれらのクラスに委譲させることです。(サード パーティ ベンダーは、独自のビュー デリゲート クラスを実装できるようになります)

だから私の質問は、ノードのタイプをパフォーマンスと拡張可能な方法で決定するにはどうすればよいですか?

これまでの私の考え:

  1. すべてのノード クラスにタイプ識別子を追加できます。これは単に整数である可能性があります (パフォーマンス上の理由から、文字列は適していません)。問題は、サード パーティ ベンダーの型識別子の管理です。同じ識別子が異なるノード タイプ (異なるベンダーなど) に使用されていないことを確認するにはどうすればよいですか?

  2. 描画コードを実装するか、少なくとも適切な描画デリゲート オブジェクトをノード内で直接呼び出すことができます。しかし、私のノードオブジェクトは、ビューオブジェクトについて何も知らないことが望ましいです。また、すべてのノード オブジェクトに専用のビュー オブジェクトを与えることはできません (数万のノードについて話している)。

それで、あなたのアイデアは何ですか?これを処理するための完全に異なる方法はおそらくありますか?覚えておいてください: リアルタイムでグラフを描画する必要があるため、このソリューションではハッシュ テーブル ルックアップやその他の計算集約型アルゴリズムは必要ありません。

前もってありがとう、McNumber

4

3 に答える 3

2

シーン グラフは通常、MVC システムのビュー レイヤーにあります。結局のところ、シーンの種類は、あなたが見る部分を暗示しています. 一般的には、適切な OpenGL コンテキスト (または使用する描画 API が同等のものとして定義されているもの) を設定した後、シーン グラフのルート ノードで何らかの「レンダリング」メソッドを呼び出し、そのすべての子孫を再帰的にレンダリングします。

シーン グラフは、多くの場合、他の種類の状態を表していません。たとえば、物理シミュレーションを使用するゲームでは、シーン グラフを保持してレンダリングを実行しますが、物理オブジェクトのリストは物理エンジンによって個別に維持され、非常に個別の構造に従います。物理エンジンは、互いに物理的に近くにあるオブジェクトがローカルな方法でトラバースされる場合に最適に機能します。レンダリングは、同様のレンダリング特性を持つ (同じテクスチャから作成された) オブジェクトがローカルな方法でトラバースされる場合に最適に機能します。

したがって、シーン グラフ上のノードは、それが表すモデル インスタンスの位置を検索し、それをレンダラーに送信してから、そのオブジェクト タイプの描画プリミティブを送信する方法を認識します。


それはさておき、実際にそのようなことを実装するということは、シーン グラフのルート ノードが応答しなければならないグローバル レベルでのインタラクションの種類について考えることを意味します。典型的な場合、それはおそらくレンダリングを意味します。

class SceneNode
{
  public:
    virtual void render() = 0;
};

そこから行う最も明白なことは、実際にノードのツリーを持つように、子を持つノードを作成することです。

class ListSceneNode : public SceneNode
{
  private:
    typedef std::vector<std::shared_ptr<SceneNode> > ChildList;
    ChildList children;

  public:
    void render() { 
      for(ChildList::iterator i = children.begin() ; i != children.end(); ++i)
        i->render();
    }
};
于 2010-11-26T08:15:17.277 に答える
0

しばらく非アクティブなスレッドですが、その後進歩したか、または同じ分野でまだ働いているかどうか疑問に思っています.

私は同様の問題を抱えています。モデル (SceneGraph)、GUI (win32)、レンダリング (OpenGL) をすべてまとめて既存のコードベースを分離して、適切なモデル/ビュー フレームワーク (個別のコントローラーはありません) にします。GUI のモデル/ビューの分離が機能し、現在 OpenGL レンダリングに取り組んでいます。私自身への最初の「単純な」要求として、モデル レイヤーに OpenGL ヘッダーを含めることが許可されていないという意味で、システムを制限することから始めました。これにより、モデル側の SceneGraph に加えて、ビュー側に個別の OpenGL "RenderGraph" がすぐに必要になります。SceneGraph 内のすべての可能なノードは、独自のビュー表現を取得します(あなたが述べているように)。典型的な OpenGL レンダリング データ (頂点配列など) はビュー側にとどまるため、私はそれが好きです。

SceneGraph と Rendergraph の階層は現時点では似ていますが、状態の変化に基づいて異なる構造を持つことは想像できます (TokenMacGuy が言及しているように)。SceneGraph が変更された場合 (GUI によってトリガーされ、モデルによって伝達された場合)、この変更通知を RenderGraph でローカルに処理する必要があります。これには、オブジェクトの追加/削除/移動などのアクションが含まれます。これは少し面倒ですが、管理可能です。

現時点での主な問題は、SceneGraph (モデル) と "ViewGraph" (View/GUI) の関係が、SceneGraph と RenderGraph (View/OpenGL) の関係とは少し異なることです。最初のケースでは、モデル ノードとビュー ノードの間に「水平」接続を設定できますが、2 番目のケースでは、中間ノードを変更すると、多くの場合、RenderGraph 全体をルート ノードから上に再レンダリングする必要があります。それをフレームワークに組み込むためのエレガントな方法が見つかりませんでした。

例として、SceneGraph に車のモデルがあるとします。葉のどこかに「左前タイヤのバルブの直径」があります。これは ViewGraph のテキスト コントロールで表され、ユーザーがそれを変更すると、SceneGraph の対応するリーフが調整されます。問題ありません。ローカルの変更です。モデルはこの変更を受け取り、RenderGraph に通知を送信して OpenGL レンダリングを更新します。この通知を受け取る RenderGraph のノードは、それ自体を再レンダリングする必要があるだけでなく、RenderGraph 全体を再描画する必要があります。

敬具、 ダニエル・デッカーズ

于 2012-12-20T16:20:42.653 に答える
0

レンダー クラスの一部として、表示操作を一連の単純な操作 ((x,y) 位置に移動、長さ N の線を引くなど) に分割するのはどうでしょうか。次に、各モデル ノードは独自のレンダリング操作を持つことができます。この操作では、インターフェイスにこれらの単純な操作を持つレンダー オブジェクトの操作を呼び出します。

render クラスの実装は、Qt 呼び出しに関してこれらの単純な操作を実装できます。最上位の View クラスは、ノードで render メソッドを呼び出すだけです (ノード クラスの永続的な属性にしたくない場合は、適切なレンダリング オブジェクトを引数として渡すこともできます)。

于 2010-11-26T09:33:16.700 に答える