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

杰森威廉姆斯的回答显示了正确的轨道。一种可能的方法是引入一个代表您的 GameObject 的独立类。(让我们这样称呼它作为其余的答案,即使您不创建游戏)

这个 GameObject 类封装了 Ninja 和盒子的所有相关方面以及其他任何东西,并通过代表它们的其他类的组合来隐藏物理和图形方面。例如图形对象、物理对象。

这是一个非常简化的示例:

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::Entity 的 Ogre::SceneNode。PhysicalObject 封装了你的物理体类。PhysicalObject 和 GraphicalObjects 都可以共享一个公共基类,该基类定义了 GameObject 类的接口。上面我使用了像 setPosition 这样的实际函数,但通常我会推荐一个更通用的消息接口,但在你的情况下它可能不必太复杂。

一个问题仍然是您希望 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

通常你会想要一个没有图形的物理对象,一个有多个图形的物理对象,或者一个由多个物理对象表示的图形对象。

由于这个(以及其他原因,例如能够交换不同的物理/图形引擎),大多数引擎将两个系统保持相当独立,仅使用图形和物理系统之间的引用/链接(以便物理对象可以在执行模拟步骤后更新图形实体)

于 2009-08-16T06:35:28.250 回答
1

当我读到你的问题时,我打算将你指向 OgreODE,它在 Ogre3D 和 ODE 之间提供了一个很好的桥梁。如果您可能不使用 ODE,也许您仍然应该看一下它,以获得有关如何使用它的一些提示?还有 OgreNewt,一个类似的引擎。

我认为你需要安装一个 FrameListener,它在 Frame 被渲染后调用。然后您可以访问 SceneManager 及其 SceneNode,并读取和更改它们的位置。

但是,如果您想获得不错的性能,除非它们是基本形状,否则网格作为碰撞检测模型不是很可行。这就是为什么我认为您应该将您的实体与一些基本形状(立方体、球体等)结合起来并使用这些而不是实体网格。子类化 Ogre3D 实体并为它们提供基本形状的集合和它们的访问器。然后您的 FrameListener 获取每个 SceneNode 的基本形状并进行计算。

于 2009-08-16T06:50:25.780 回答