Feasibility of Bullet and coarse level threading?

FailMaT_T
Posts: 10
Joined: Thu Jul 03, 2008 4:51 pm

Feasibility of Bullet and coarse level threading?

Post by FailMaT_T »

Hi. I'm developing a multi threaded games engine in C++ on Linux for an honours project at UCT.

I was wondering how feasible is it to run a bullet simulation of the game world in a thread and then have a rendering thread accessing the position and orientation of rigid bodies within the simulation for rendering purposes?

Will I have to spend an unreasonable amount of time modifying the library to include synchronization in the form of a pthread mutex for btRigidBody objects?

Even if I did have a per-object locking system, would it be correct to assume that other threads would not be able to modify(change position/add/remove) objects and only read them since changing the environment during an internal step calculation would lead to non-deterministic operation and undesirable results?

Thanks

Matthew
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: Feasibility of Bullet and coarse level threading?

Post by sparkprime »

You could always just keep the entire bullet state thread-local and communicate with it at key rendezvouz points. You could, for instance have something like the following:

Code: Select all

while (true) {
    doGameLogic(); // updates graphics and physics
    // do these two in parallel:
    { render() | stepSimulation() }
    // back to single threaded
}  
It all depends on how much you want to run in parallel with stepSimulation. If you wanted more parallelism you could do:

Code: Select all

while (true) {
    // do these two in parallel:
    { { doGameLogic() ; render() } | stepSimulation() }
    // back to single threaded
    updateGameLogicFromPhysics();
    updatePhysicsFromGameLogic();
}  
The key idea is to make sure the memory accesses on each side of the | are disjoint.

Alternatively just use the parallel solver within bullet and keep everything else in a single thread.
FailMaT_T
Posts: 10
Joined: Thu Jul 03, 2008 4:51 pm

Re: Feasibility of Bullet and coarse level threading?

Post by FailMaT_T »

I suppose I could do that. The only draw back of a system like that would be the synchronization between rendering and simulation step, meaning that frame rate would be dependent on the simulation step time. What I was hoping to do was have the rendering occur faster and asynchronous to simulation steps which in theory would render a slightly inaccurate world with some of the objects positions and orientations updated and some not etc.
chunky
Posts: 145
Joined: Tue Oct 30, 2007 9:23 pm

Re: Feasibility of Bullet and coarse level threading?

Post by chunky »

I was wondering how feasible is it to run a bullet simulation of the game world in a thread and then have a rendering thread accessing the position and orientation of rigid bodies within the simulation for rendering purposes?
This is kinda what motionstates are for. Just set up all your appropriate motionstates to grab a lock on the object they're moving while they move it, and have your rendering engine lock an object while it grabs the translation from the object?

Gary (-;
FailMaT_T
Posts: 10
Joined: Thu Jul 03, 2008 4:51 pm

Re: Feasibility of Bullet and coarse level threading?

Post by FailMaT_T »

This is kinda what motionstates are for. Just set up all your appropriate motionstates to grab a lock on the object they're moving while they move it, and have your rendering engine lock an object while it grabs the translation from the object?
OK I think I understand what you're saying... so when I call "getMotionState()->getWorldTransform(trans);" on a btRigidBody from a separate thread while the simulation step is currently happening in another thread, can I be sure that the transform data within the btTransform is either all updated or all not updated? (ie not a half updated transform matrix that makes no sense). I apologize if I've completely misunderstood what you've said here, but I only started working with bullet a few days ago
chunky
Posts: 145
Joined: Tue Oct 30, 2007 9:23 pm

Re: Feasibility of Bullet and coarse level threading?

Post by chunky »

OK, a motionstate is a thing that bullet uses to move your objects around for you, including doing the interpolation. I think the easiest way to explain it is with an example. Here's the one I currently use in my Ogre-based game:

Code: Select all

TWShipMotionState::TWShipMotionState(const btTransform &initialpos, Ogre::SceneNode *node) {
	mVisibleobj = node;
	mPos1 = initialpos;
}

TWShipMotionState::~TWShipMotionState() {
}

void TWShipMotionState::getWorldTransform(btTransform &worldTrans) const {
	worldTrans = mPos1;
}

void TWShipMotionState::setWorldTransform(const btTransform &worldTrans) {
	if(NULL == mVisibleobj) return; // silently return before we set a node
	
	btQuaternion rot = worldTrans.getRotation();
	mVisibleobj->setOrientation(rot.w(), rot.x(), rot.y(), rot.z()); /// THIS LINE RIGHT HERE
	
	btVector3 pos = worldTrans.getOrigin();
	mVisibleobj->setPosition(pos.x(), pos.y(), pos.z()); /// AND THIS LINE RIGHT HERE
	// printf("X: %f, Y:%f, Z:%f\n", pos.x(), pos.y(), pos.z());
}
A motionstate is a passive thing the physics uses to set variables somewhere else, rather than an active way to get out the position of a body. [if you just want the position of a body, get the position from the body!]

The code you see here runs from the physics thread. So in setWorldTransform(), you would lock the transform variable in the shape that you're going to be moving, then modify it.
From your rendering thread, you lock the transform variable in the shape before attempting to read it.

Both threads only attempt to access a shared "transform" variable - the motionstate is used as a way for the physics thread to access it, and your rendering code has something else to access it. The rendering code doesn't need to access the motionstate.

Does that make more sense?
Gary (-;
FailMaT_T
Posts: 10
Joined: Thu Jul 03, 2008 4:51 pm

Re: Feasibility of Bullet and coarse level threading?

Post by FailMaT_T »

Ok thanks, I think I've got it.

The motion state object maintains a copy of the body's transform.
When the body's transform is changed, the motion states setWorldTransform is called by the physics with the new transform as the argument.
So all I have to do is extend my own customized motion state object that uses mutex locks in the get and set world transform methods.
The rendering code doesn't need to access the motion state.
But it would be quite easy for the renderer to just use the getWorldTransform method in the motion state if it's got mutex locks in it.


Assuming I've understood correctly, that solves my problem of read only access from another thread, but what about adding removing or applying forces to objects (ie game events/user input that modifies the simulation).I assume these sort of changes have to be done during the internal tick callback?

BTW I found a link to your Bullet Things pdf a day or 2 ago, thanks, it was very helpful.
chunky
Posts: 145
Joined: Tue Oct 30, 2007 9:23 pm

Re: Feasibility of Bullet and coarse level threading?

Post by chunky »

But it would be quite easy for the renderer to just use the getWorldTransform method in the motion state if it's got mutex locks in it
Beware! getWorldTransform is only used to return the initial transform for bullet setup, not later ones after the object has moved.

Code: Select all

class LockingMotionState : public btMotionState {
public:
	LockingMotionState(const btTransform &initialpos);
	~ LockingMotionState();
	
	virtual void getWorldTransform(btTransform &worldTrans) const {
		return mPos1;
	}
	
	virtual void setWorldTransform(const btTransform &worldTrans) {
		MutexLocker(mTransformLock);
		mCurrentPos = worldTrans;
	}

	virtual void getCurrentTransform(btTransfrom &currentTrans) {
		MutexLocker(mTransformLock);
		currentTrans = mCurrentPos;
	}
	
protected:
	btTransform mPos1;
	btTransform mCurrentPos;
	Mutex mTransformLock;
};
Of course, that assumes you have an appropriate Mutex primitive and an appropriate MutexLocker primitive [MutexLocker will lock the mutex when it's created, and unlock it when it's destroyed, ie, leaves scope at the end of that function]

Gary (-;
FailMaT_T
Posts: 10
Joined: Thu Jul 03, 2008 4:51 pm

Re: Feasibility of Bullet and coarse level threading?

Post by FailMaT_T »

Cool, thanks for the example code and the heads up about getWorldTransform

I'm probably going to be using pthreads, so I've got mutexes covered. :)

Thanks again Gary
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: Feasibility of Bullet and coarse level threading?

Post by sparkprime »

FailMaT_T wrote:What I was hoping to do was have the rendering occur faster and asynchronous to simulation steps which in theory would render a slightly inaccurate world with some of the objects positions and orientations updated and some not etc.
I think that would look very bad - objects would jerk around. What you really want is for the graphics to interpolate between the physics ticks, however this is hard to do.

Which is your priority:
simple design?
performance?
quality appearance?
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: Feasibility of Bullet and coarse level threading?

Post by sparkprime »

FailMaT_T wrote:Cool, thanks for the example code and the heads up about getWorldTransform
I'm probably going to be using pthreads, so I've got mutexes covered. :)
pthreads doesn't provide scoped locks like that, since it's a c library. If you want scoped locks you'd better use boost's locks, which are also more portable but marginally slower.

I use boost locks in my project though.
FailMaT_T
Posts: 10
Joined: Thu Jul 03, 2008 4:51 pm

Re: Feasibility of Bullet and coarse level threading?

Post by FailMaT_T »

I think that would look very bad - objects would jerk around
They wouldn't. I've done it before for my 3rd year games practical with a world update thread separate from the rendering thread and a mutex for each game object. The change in position of objects is so minimal that it's completely unnoticeable if say a few objects are still rendered in their old positions.

pthreads doesn't provide scoped locks like that, since it's a c library
Thats correct. But I never said I wanted scoped locks. If you've ever used pthreads before you'll know that you lock and unlock a mutex explicitly using pthread_mutex_lock() and pthread_mutex_unlock().
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: Feasibility of Bullet and coarse level threading?

Post by sparkprime »

FailMaT_T wrote:
I think that would look very bad - objects would jerk around
They wouldn't. I've done it before for my 3rd year games practical with a world update thread separate from the rendering thread and a mutex for each game object. The change in position of objects is so minimal that it's completely unnoticeable if say a few objects are still rendered in their old positions.
It's OK if the physics tick rate is similar or a lot faster than the graphics tick rate, but if your graphics is 75hz and your physics is 74hz then every second you will get a slight jitter. Of course if your objects aren't moving very fast then it won't be noticable but this is a pretty rare situation, you'd have to prevent the camera getting close to objects that are controlled by the physics.

The only reason the bullet demos look good is because they use interpolation. If you do what you plan to do, you should disable bullet's interpolation (since the end of stepSimulation is no longer just before the graphics rendering code), and reimplement it in the right place in your own render loop.

Of course if you really don't care about the jitter then you don't need to use interpolation but you should definitely disable it in bullet.
chunky
Posts: 145
Joined: Tue Oct 30, 2007 9:23 pm

Re: Feasibility of Bullet and coarse level threading?

Post by chunky »

If you've ever used pthreads before you'll know that you lock and unlock a mutex explicitly using pthread_mutex_lock() and pthread_mutex_unlock().
pthreads doesn't provide scoped locks like that, since it's a c library
Just because you're using a C threading library doesn't mean you have to hate yourself at the same time :-)

Code: Select all

class MutexLocker {
protected:
  pthread_mutex_t *mMut;
public:
  explicit MutexLocker(pthread_mutex_t *mut) {
    mMut = mut;
    pthread_mutex_lock(mMut);
  }
  ~MutexLocker() {
    pthread_mutex_unlock(mMut);
  }
};
I'm sure there's a mistake since I just made that up, but it should get the point across; instantiate one with a mutex, and when it leaves scope [ie, at the end of the function], it gets unlocked. life gets a lot easier and you don't have to worry about unlocking mutexes. You can still deadlock by locking them in the wrong order, but it's really hard to deadlock by just forgetting to unlock anything.

Gary (-;
FailMaT_T
Posts: 10
Joined: Thu Jul 03, 2008 4:51 pm

Re: Feasibility of Bullet and coarse level threading?

Post by FailMaT_T »

Cool. I'll take that into consideration and see what works best