9
\$\begingroup\$

I'm writing the game engine that consists of few modules. Two of them are the graphics engine and the physics engine.

I wonder if it's a good solution to share data between them?

Two ways (sharing or not) looks like that:

Without sharing data

GraphicsModel{
    //some common for graphics and physics data like position

    //some only graphic data 
    //like textures and detailed model's verticles that physics doesn't need
};

PhysicsModel{
    //some common for graphics and physics data like position

    //some only physics data 
    //usually my physics data contains A LOT more informations than graphics data
}

engine3D->createModel3D(...);
physicsEngine->createModel3D(...);

//connect graphics and physics data 
//e.g. update graphics model's position when physics model's position will change

I see two main problems:

  1. A lot of redundant data (like two positions for both physics and graphics data)
  2. Problem with updating data (I have to manually update graphics data when physics data changes)

With sharing data

Model{
     //some common for graphics and physics data like position
};

GraphicModel : public Model{
    //some only graphics data 
    //like textures and detailed model's verticles that physics doesn't need
};

PhysicsModel : public Model{
     //some only physics data 
    //usually my physics data contains A LOT more informations than graphics data
}

model = engine3D->createModel3D(...);
physicsEngine->assingModel3D(&model); //will cast to 
//PhysicsModel for it's purposes??

//when physics changes anything (like position) in model 
//(which it treats like PhysicsModel), the position for graphics data 
//will change as well (because it's the same model)

Problems here:

  1. physicsEngine cannot create new objects, just "assing" existing ones from engine3D (somehow it looks more anti-independent for me)
  2. Casting data in assingModel3D function
  3. physicsEngine and graphicsEngine must be careful - they cannot delete data when they don't need them (because second one may need it). But it's rare situation. Moreover, they can just delete the pointer, not the object. Or we can assume that graphicsEngine will delete objects, physicsEngine just pointers to them.

Which way is better?

Which will produce more problems in the future?

I like the second solution more, but I wonder why most graphics and physics engines prefer the first one (maybe because they normally make only graphics or only physics engine and somebody else connect them in the game?).

Have they any more hidden pros & contras?

\$\endgroup\$
1
  • \$\begingroup\$ Exactly my question, too. \$\endgroup\$
    – danijar
    Commented Dec 15, 2012 at 11:44

4 Answers 4

9
\$\begingroup\$

Nowadays, more game engines adopts a component design (e.g. Unity, Unreal). In this kind of design, a GameObject is composed of a list of components. In your situation, there can be a MeshComponent and a PhysicalComponent, both attaching to a single game object.

For simplicity, you can put a world transform variable to the GameObject. During update phrase, PhysicalComponent outputs the world transform to that variable. During rendering, the MeshComponent reads that variable.

The rationale behind this design is to decouple between components. Neither MeshComponent nor PhysicalComponent knows each other. They just depends on a common interface. And it can be easier to extend the system by composition, than using single hierarchy of inheritance.

In a realistic scenario, however, you may need more sophisticated handling between physics/graphics synchronization. For example, the physics simulation may need to be run in fixed time step (e.g. 30Hz), while rendering need to be variable. And you may need to interpolate results from the output of physics engine. Some physics engine (e.g. Bullet) has direct support of this issue though.

Unity provided a good reference of their Components, which worth a look.

\$\endgroup\$
2
  • \$\begingroup\$ This does not answer the question at all, having 2 components says nothing about whether they share the mesh-data or not. \$\endgroup\$ Commented Nov 22, 2012 at 10:30
  • 2
    \$\begingroup\$ Actually, it offers better design, which is completely legitimate. \$\endgroup\$
    – jcora
    Commented Nov 22, 2012 at 12:05
7
\$\begingroup\$

Engines usually pick the first option (own physics-mesh and own render-mesh) because they need very different data, both in quality and quantity.

Quality because the physics engine does not care about texture coordinates, normal groups and all this fancy render stuff for instance. Each of them expects the data in a very specific layout coming down to alignment issues, packing, interleaving of data etc.

Quantity because the physics mesh usually has way less triangles, its a simplified version of the high resolution render mesh.

By decoupling both we make sure that we can tweek one, including changing its data-layout for better performance, without corrupting the other. It's way more scalable.

\$\endgroup\$
0
\$\begingroup\$

Besides @Millo Yip great answer I would like just to remind you that you will need to share the same data with the Controls module and the AI module and if I'm not mistaken most audio libraries have a notion of the position of the sound emiter so you'll need to share the data with that module too.

\$\endgroup\$
0
\$\begingroup\$

As others have said, it's pretty common place that physics has it's internal data state is managed separately from the internal data state of the rendering engine. It's often common to see even the transform data (position/orientation/scale) stored separately from both physics and renderables because it's possible a game object exists which isn't imposed by physics nor is rendered but requires a world position for other mechanics.

How the data gets from physics to renderable is entirely up to you.

You could do this via some inter-subsystem dispatch process using events/messages. You could do this by exposing a public interface of the render subsystem to the physics subsystem so that physics can simply set a particularly renderable's position. Another option is that the renderable subsystem queries the entity for the transform during it's update and does the update of the renderable component's position then followed by drawing.

Naturally, depending on your game a few of these means are going to be more cache friendly and have better performance than others. I wouldn't get caught up too much on a specific way at this point and pick a communication pattern and try it. You can easily rework this part later on to test various means for optimization.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .