views:

82

answers:

1

I am currently integrating an entity component system, as seen here, with a physics engine and a graphics engine. This was all fine until recently deciding that the physics should be running in its own thread. (Thanks Glenn Fiedler!)

As it is now I am simply locking a mutex shared by all subsystems when accessing components.

Snippet from the physics loop:

lock_guard<mutex> lock( m_EntMutex );
entitymap::iterator it;
for ( it = m_Ents.begin(); it != m_Ents.end(); ++it )
{
    // Get physics component from entity
    // This is guaranteed to work ( component must exist for it to present in the map )
    shared_ptr<comp_phys> phys( static_cast<comp_phys*>( it->second->getComponent( COMP_PHYS ).lock().get() ) );
    // Get resulting Box2D vector
    b2Vec2 vec = phys->getBody()->GetPosition();

    // Get position component from entity
    // Same as above, but this is the component shared with the graphics subsystem   
    shared_ptr<comp_pos> pos( static_cast<comp_pos*>( it->second->getComponent( COMP_POS ).lock().get() ) );
    // Update position component from Box2D vector
    pos->setPosition( vec.x, vec.y, 0 );
}

Snippet from graphics loop:

lock_guard<mutex> lock( m_EntMutex );
entitymap::iterator it;
for ( it = m_Ents.begin(); it != m_Ents.end(); ++it )
{
    // Get position component from entity
    // This is shared with the physics subsystem
    shared_ptr<comp_pos> pos( static_cast<comp_pos*>( it->second->getComponent( COMP_POS ).lock().get() ) );
    // Get position from position component
    doubleVec3 vec = p->getPosition();

    // Get graphics component from entity
    shared_ptr<comp_gfx> gfx( static_cast<comp_gfx*>( it->second->getComponent( COMP_GFX ).lock().get() ) );
    // Update graphics component from position component
    gfx->getObject()->getParentSceneNode()->setPosition( float(vec.x), float(vec.y), float(vec.z) );
} 

This is obviously a very naïve implementation, so I tried making the individual components have their own mutexes. It seemed the logical performance choice, but then the physics results (as queried through the position component) wouldn't always be consistent and reliable.

What would be the most efficient manner of accomplishing a smooth updating process? Should I let it update the entire world in one go or do something more incremental?

Edit: It has come to my attention that the pointer acquisition scheme is flawed, but let us assume that the pointers are valid.

+1  A: 

When it comes to physics engines running in game engines I would suggest that you have a syncpoint once per frame where you copy over the positions/whatever information you might need from the physics system into your component system. Call it dubbel-buffering if you'd like. An internal and external instance of your position (world matrix / velocities etc).

Up to one frame delay on physics-positions is not something that any gamer will notice.

On another note, I prefer implementing physics engines in a way that use as many threads as possible while the rest of the game engine preferably does nothing. Bullet and Havok seem to work best with this solution.

Simon
I should add that you want to stop your physics engine from integrating when you do the syncpoints.
Simon
I agree. Having many syncpoints may look efficient but you will still need to make a barrier before drawing the scene, defeating the purpose of per-component locks. Note also that you often want to let the physics run on a different framerate than the graphics. I would focus on one lock per physics update and let the game engine interpolate from the recent physics data on each graphics frame.
Staffan E