代码之家  ›  专栏  ›  技术社区  ›  Brock Woolf

将自定义物理类与Ogre 3D集成?

  •  1
  • Brock Woolf  · 技术社区  · 15 年前

    我必须在大学项目中使用ogre3d,但是我们不允许使用任何第三方库进行物理或碰撞检测。这包括使用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提交Comform的最佳方法,我同意,但是我在这个阶段看不到更好的方法?你觉得怎么样?你有什么更好的主意吗?因为我不太喜欢这样做。

    3 回复  |  直到 9 年前
        1
  •  4
  •   haffax    9 年前

    杰森·威廉姆斯的回答显示了正确的方向。一种可能的方法是引入一个表示游戏对象的独立类。(让我们在剩下的答案中这样称呼它,即使你不创造一个游戏)

    这个gameobject类封装了忍者和魔盒的所有相关方面,并通过表示它们的其他类的组合隐藏了物理和图形方面。例如图形对象、物理对象。

    下面是一个非常简单的例子:

    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,但通常我会推荐一个更通用的消息接口,但在您的例子中,它可能不需要太复杂。

    还有一个问题是,你想让游戏对象的位置对你的物理模拟步骤的变化做出反应。这很大程度上取决于你的物理引擎是如何设计的。但是,如果您有某种回调系统,那么将您的physicalObject注册为与此相关的任何事件的侦听器,并从中更改位置。一般来说,方向或变换也是一样的,如果你不明确区分位置和方向的话。

    您可能希望从表示图形的网格中派生物理体的属性(我们称之为body)。在忍者的情况下,它的形状应该类似于忍者网。我将在类层次结构之外使用一个简单的助手类来完成这项工作。例如车身工厂。

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

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

    在使用ogre(或任何纯图形引擎)时仍有一个一般性建议:仅用于图形。我理解Ogre的scenegraph实现要求用于您自己的场景管理,但是您太多地将自己绑定到引擎,用它们不需要的东西过载您的接口,您不希望它们依赖。( Interface Segregation Principle )这不值得麻烦。把事情分开确实更容易管理和维护。

        2
  •  2
  •   Jason Williams    15 年前

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

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

        3
  •  1
  •   Ozan HELPY    15 年前

    当我读到你的问题时,我会指给你看Ogreode,它在Ogre3d和Ode之间提供了一个很好的桥梁。如果您可能不使用ODE,也许您应该看看它,以获得一些关于如何做的提示?还有Ogrenewt,一个类似的引擎。

    我认为您需要安装一个frameListener,它是在渲染完一个帧之后调用的。然后您可以访问scenemanager及其scenenodes,并读取和更改它们的位置。

    然而,除非网格是基本形状,否则对于碰撞检测模型来说,如果您希望获得一个良好的性能,网格不是非常可行的。这就是为什么我认为应该将实体与一些基本形状(立方体、球体等)结合在一起,并使用这些形状而不是实体网格。对ogre3D实体进行子类化,并为其提供基本形状集合和访问器。然后,您的框架侦听器获取每个场景的基本形状并进行计算。