1

大学のプロジェクトで OGRE3D を使用する必要がありますが、物理演算や衝突検出にサードパーティのライブラリを使用することは許可されていません。これには、OGRE に組み込まれている衝突検出の使用が含まれます。

独自のカスタム物理ルーチンを OGRE の組み込みエンティティに追加する正しい方法に問題があります。

OGRE は「エンティティ」オブジェクトをビルディング ブロックの最も基本的なものとして使用し、物理学ではオブジェクトに質量、速度などの属性が必要です。

私が混乱しているのは、OGRE のレンダリング/ロジック ループが、OGRE エンジン内のユーザーから隠されているように見えることです。OGRE のすべてのエンティティを取得し、構築中のカスタム物理エンジンで衝突検出と物理計算を実行できるようにする必要があるため、これは問題です。

独自の物理/衝突エンジン クラスを OGRE と統合するにはどうすればよいですか?

更新: 以下のアドバイスを受けて、OGRE::Entity をサブクラス化しました。

class PhysicsEntity : public Ogre::Entity;

PhysicsEntity *ent1 = (PhysicsEntity*)mSceneMgr->createEntity("PhysicsNinja", "ninja.mesh");;
SceneNode *node1 = mSceneMgr->getRootSceneNode()->createChildSceneNode("NinjaNode1");
node2->attachObject((Ogre::Entity*)ent1);

コメントでは、これは OO に準拠するための最良の方法ではないと述べられていますが、私は同意しますが、この段階でより良い方法を見つけることはできませんか? 私はこれを行うことに完全に満足していないので、あなたはどう思いますか、そして何か良いアイデアはありますか.

4

3 に答える 3

4

ジェイソン・ウィリアムズの答えは正しい道を示しています。考えられる 1 つの方法は、ゲームオブジェクトを表す独立したクラスを導入することです。(ゲームを作成していなくても、残りの答えについてはこのように呼びましょう)

この GameObject クラスは、Ninja やボックスなどの関連するすべての側面をカプセル化し、それらを表す他のクラスの構成によって物理的およびグラフィカルな側面を隠します。例: GraphicalObject、PhysicalObject。

以下は非常に単純化された例です。

class GameObject
{
public:
   void setPosition(Vector3 pos)
   {
      m_position = pos;
      m_graphical->setPosition(pos);
      m_physical->setPosition(pos);
   }

private:
   GraphicalObject m_graphical;
   PhysicalObject m_physical;
   Vector3 m_position;
}

GraphicalObject は Ogre::SceneNode を Ogre::Entity が添付された状態でカプセル化します。PhysicalObject は、身体クラスをカプセル化します。PhysicalObject と GraphicalObjects はどちらも、GameObject クラスへのインターフェイスを定義する共通の基本クラスを共有できます。上記では setPosition のような実際の関数を使用しましたが、通常はより一般的なメッセージ インターフェイスをお勧めしますが、おそらくあなたのケースでは複雑すぎる必要はありません。

問題の 1 つは、GameObject の位置を物理シミュレーション ステップの変化に対応させたいということです。これは、物理エンジンの設計方法に大きく依存します。ただし、何らかのコールバック システムがある場合は、PhysicalObject をこれに関するイベントのリスナーとして登録し、それらのイベントから位置を変更します。位置と向きを明確に区別しない場合は、一般的に向きまたは変換についても同じです。

おそらく、グラフィックを表すメッシュから物理的なボディ (この回答では Body と呼びましょう) のプロパティを取得したいと思うでしょう。忍者の場合、その形状は何らかの形で忍者メッシュの形状に似ている必要があります。クラス階層外の単純なヘルパー クラスを使用してこれを行います。たとえば、BodyFactory です。

class BodyFactory
{
public:
   static Body* createEllipsoidBody(MeshPtr mesh);
   static Body* createCuboidBody(MeshPtr mesh);
   static Body* createConvexHullBody(MeshPtr mesh);
}

これらの関数は、メッシュ データから物理エンジンの適切な物理表現を作成します。単純なケースではバウンディング ボックスを使用するだけですが、より洗練されたボディでは実際の頂点データを評価することは問題ではありません。おそらく、メッシュに保存されていない物理属性 (特定の重量、慣性モディファイア (中空、固体など)) のインターフェイスを拡張できます。

Ogre (または純粋なグラフィック エンジン) を使用する場合の一般的なアドバイス: グラフィックにのみ使用してください。Ogre の SceneGraph 実装が独自のシーン管理に使用されることを懇願することは理解していますが、エンジンにあまりにも縛られ、必要のないものでインターフェイスを過負荷にし、依存させたくない. (インターフェイス分離の原則) 手間をかけるだけの価値はありません。物事を分離しておくと、管理と保守が本当に簡単になります。

于 2009-08-16T22:57:21.210 に答える
2

多くの場合、グラフィックスのない物理オブジェクト、複数のグラフィックスを持つ物理オブジェクト、または複数の物理オブジェクトによって表されるグラフィックス オブジェクトが必要になります。

このため (および、異なる物理/グラフィック エンジンを交換できるなどのその他の理由で)、ほとんどのエンジンは、グラフィックと物理システムの間の参照/リンクを使用するだけで、2 つのシステムをかなり分離したままにします (物理オブジェクトがシミュレーション ステップの実行後にグラフィックス エンティティを更新できます)

于 2009-08-16T06:35:28.250 に答える
1

あなたの質問を読んですぐに、Ogre3D と ODE の間の素晴らしい架け橋を提供する OgreODE を紹介するつもりでした。ODE を使用しない可能性がある場合でも、ODE を調べて、その方法に関するヒントを得る必要がありますか? 同様のエンジンである OgreNewt もあります。

FrameListener をインストールする必要があると思います。Frame がレンダリングされた後に呼び出されます。その後、SceneManager とその SceneNodes にアクセスし、それらの位置を読み取って変更できます。

ただし、メッシュは、基本的な形状でない限り、適切なパフォーマンスを得たい場合、衝突検出のモデルとしてはあまり有効ではありません。これが、エンティティをいくつかの基本的な形状 (立方体、球体など) と結合し、エンティティ メッシュの代わりにこれらを使用する必要があると私が考える理由です。Ogre3D エンティティをサブクラス化し、基本的な形状のコレクションとそれらへのアクセサーを提供します。その後、FrameListener はすべての SceneNode の基本形状を取得し、その計算を行います。

于 2009-08-16T06:50:25.780 に答える