将自定义物理课与OGRE 3D集成?

时间:2009-08-16 06:07:20

标签: physics collision-detection ogre3d

我必须将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合作的最佳方式,但我同意在这个阶段我看不到更好的方法?你觉得怎么样?你有什么更好的想法,因为我对这样做并不是很满意。

3 个答案:

答案 0 :(得分:4)

杰森威廉姆斯的答案显示了正确的轨道。一种可能的方法是引入一个表示GameObject的独立类。 (即使你没有创建游戏,我们也可以这样称呼其余的答案)

此GameObject类封装了忍者和盒子的所有相关方面,以及通过代表它们的其他类的组合隐藏物理和图形方面。例如。 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 :: Entity的Ogre :: SceneNode。 PhysicalObject封装了您的物理体类。 PhysicalObject和GraphicalObjects都可以共享一个公共基类,它定义了GameObject类的接口。上面我使用了像setPosition这样的实际函数,但通常我会推荐一个更通用的消息接口,但在你的情况下它可能不一定太复杂。

一个问题仍然是您希望GameObject位置响应物理模拟步骤中的更改。这在很大程度上取决于物理引擎的设计方式。但是如果你有某种回调系统,那么将你的PhysicalObject注册为关于这个的任何事件的监听器,并改变它们的位置。如果您没有具体区分位置和方向,则一般情况下的方向或变换也相同。

您可能希望从表示图形的网格派生物理实体的属性(让我们称之为Body for this answer)。在忍者的情况下,它的形状应该以某种方式类似于忍者网。我会在类层次结构之外使用一个简单的辅助类来完成此操作。例如BodyFactory。

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

这些函数根据网格数据创建物理引擎的拟合物理表示。在简单的情况下,他们只使用边界框,或者对于更复杂的实体,他们评估实际的顶点数据并不重要。也许您可以扩展未存储在网格中的物理属性的接口(特定重量,惯性修改器(空心,实体等))

使用Ogre(或任何纯图形引擎)时的一般建议:仅用于图形。我理解Ogre的SceneGraph实现需要用于你自己的场景管理,但你将自己绑定到引擎上,用你不需要的东西重载接口,你不希望它们依赖。 (Interface Segregation Principle)这不值得麻烦。将事物分开确实更容易管理和维护。

答案 1 :(得分:2)

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

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

答案 2 :(得分:1)

一旦我读到你的问题,我就会指向OgreODE,它在Ogre3D和ODE之间提供了一个很好的桥梁。如果你可能不使用ODE,也许你应该看看它,以获得一些如何做到这一点的提示?还有OgreNewt,一个类似的引擎。

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

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