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

发布于 2024-08-01 18:56:14 字数 765 浏览 4 评论 0原文

我必须在大学项目中使用 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 的最佳方法,我同意,但现阶段我看不到更好的方法? 你觉得怎么样?你有什么更好的想法吗?因为我对这样做并不完全满意。

I have to use OGRE3D for a university project however, we are not allowed to use any third party libraries for Physics or collision detection. This includes using OGRE's built in collision detection.

I am having some difficulty with the correct way to approach adding my own custom physics routines to OGRE's built in entities.

OGRE uses "Entity" objects as the most basic of building blocks and for physics you need objects to have mass, velocity, etc attributes.

The thing I am confused about is that OGRE's render/logic loops seem to be hidden away from the user inside the OGRE engine. This is a problem because I need to be able to get every entity in OGRE and perform collision detection and physics calculations with my custom physics engine that I am building.

How can I integrate my own physics/collisions engine classes with OGRE?

Update: Taking the advice below I have subclassed OGRE::Entity, ie:

class PhysicsEntity : public Ogre::Entity;

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

The comments state this is not the best way to comform to OO, and I agree however I cannot see a better way at this stage? What do you think and do you have any better ideas because I'm not totally happy with doing this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浅笑轻吟梦一曲 2024-08-08 18:56:14

贾森·威廉姆斯的回答表明了正确的方向。 一种可能的方法是引入一个代表游戏对象的独立类。 (对于其余的答案,我们这样称呼它,即使您不创建游戏)

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

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

您可能想从表示图形的网格中导出物理体的属性(对于这个答案,我们将其称为“身体”)。 对于忍者,其形状应在某种程度上类似于忍者网格的形状。 我将使用类层次结构之外的一个简单的辅助类来完成此操作。 例如 BodyFactory。

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

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

使用 Ogre(或任何纯图形引擎)时的一般建议:仅将其用于图形。 我理解 Ogre 的 SceneGraph 实现需要用于您自己的场景管理,但是您将自己与引擎绑定得太多,用它们不需要的东西超载了您的接口,并且您不希望它们依赖。 (接口隔离原则)这根本不值得这么麻烦。 将事物分开确实更容易管理和维护。

Jason Williams' answer shows the right track. One possible way is to introduce an independent class representing your GameObject. (Let's call it thus for the rest of the answer, even if you don't create a game)

This GameObject class encapsulates all relevant aspects of your Ninja and boxes and whatever and hides the physical and graphical aspects by composition of other classes representing them. E.g. GraphicalObject, PhysicalObject.

Here is a grossly simplified example:

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;
}

Now GraphicalObject encapsulates an Ogre::SceneNode with its Ogre::Entity attached. PhysicalObject encapsulates your physical body class. Both PhysicalObject and GraphicalObjects may share a common base class that defines the interface to the GameObject class. Above I used actual functions like setPosition, but usually I'd recommend a more generic message interface, but it probably doesn't have to be too complicated in your case.

One problem still is that you want the GameObject position to respond to changes in your physical simulation step. This greatly depends on how your physics engine is designed. But if you have some kind of callback system, then register your PhysicalObject as listener to any events regarding this and change position from their. Same for orientation or transform in general, if you don't distinguish between position and orientation specifically.

You probably want to derive the properties of the physical body (let's call it Body for this answer) from the mesh representing the graphics. In case of the Ninja its shape should somehow resemble that of the ninja mesh. I'd do this with a simple helper class outside the class hierarchy. For instance a BodyFactory.

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

These functions create a fitting physical representation of your physics engine from the mesh data. In the simple case they just use the bounding box, or for more sophisticated bodies they evaluate the actual vertex data, doesn't matter. Maybe you can extend interface for physical attributes not stored in the mesh (specific weight, inertia modifiers (hollow, solid, etc.))

A general advice still when using Ogre (or any pure graphics engine): Use it only for graphics. I understand Ogre's SceneGraph implementation begs to be used for your own scene management, but you bind yourself to the engine so much, overload your interfaces with stuff they don't need and you don't want them to depend on. (Interface Segregation Principle) It is just not worth the hassle. Keeping things separate really is easier to manage and to maintain.

等风来 2024-08-08 18:56:14

通常,您需要一个没有图形的物理对象、一个具有多个图形的物理对象或一个由多个物理对象表示的图形对象。

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

Often you will want a physics object with no graphics, a physics object with multiple graphics, or a graphics object represented by multiple physics objects.

Because of this (and other reasons, such as being able to swap different physics/graphics engines in and out), most engines keep the two systems fairly separate, just using references/links between the graphics and physics system (so that the physics objects can update the graphics entities after you have performed a simulation step)

哆兒滾 2024-08-08 18:56:14

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

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

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

As soon as I read your question I was going to point you to OgreODE, which provides a nice bridge between Ogre3D and ODE. If you may not use ODE, maybe you should nevertheless have a look at it, to get some hints on how to do it? There is also OgreNewt, a similar engine.

I think you need to install a FrameListener, it is called after a Frame has been rendered. Then you can access the SceneManager and its SceneNodes, and read and alter their positions.

However, the Meshes, unless they are basic shapes, are not very viable as model for collision detection, if you want to get a decent performance. This is why I think you should couple your Entities with a few basic shapes (cube, sphere, etc) and work with these instead of the Entity meshes. Subclass the Ogre3D entities and give them a collection of basic shapes and an accessor to them. Your FrameListener then gets the basic shapes of every SceneNode and does its calculations.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文