Feasibility of Bullet and coarse level threading?
-
- Posts: 10
- Joined: Thu Jul 03, 2008 4:51 pm
Feasibility of Bullet and coarse level threading?
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
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
-
- Posts: 508
- Joined: Fri May 30, 2008 2:51 am
- Location: Ossining, New York
Re: Feasibility of Bullet and coarse level threading?
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:
It all depends on how much you want to run in parallel with stepSimulation. If you wanted more parallelism you could do:
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.
Code: Select all
while (true) {
doGameLogic(); // updates graphics and physics
// do these two in parallel:
{ render() | stepSimulation() }
// back to single threaded
}
Code: Select all
while (true) {
// do these two in parallel:
{ { doGameLogic() ; render() } | stepSimulation() }
// back to single threaded
updateGameLogicFromPhysics();
updatePhysicsFromGameLogic();
}
Alternatively just use the parallel solver within bullet and keep everything else in a single thread.
-
- Posts: 10
- Joined: Thu Jul 03, 2008 4:51 pm
Re: Feasibility of Bullet and coarse level threading?
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.
-
- Posts: 145
- Joined: Tue Oct 30, 2007 9:23 pm
Re: Feasibility of Bullet and coarse level threading?
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?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?
Gary (-;
-
- Posts: 10
- Joined: Thu Jul 03, 2008 4:51 pm
Re: Feasibility of Bullet and coarse level threading?
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 agoThis 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?
-
- Posts: 145
- Joined: Tue Oct 30, 2007 9:23 pm
Re: Feasibility of Bullet and coarse level threading?
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:
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 (-;
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());
}
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 (-;
-
- Posts: 10
- Joined: Thu Jul 03, 2008 4:51 pm
Re: Feasibility of Bullet and coarse level threading?
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.
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.
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.
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.The rendering code doesn't need to access the motion state.
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.
-
- Posts: 145
- Joined: Tue Oct 30, 2007 9:23 pm
Re: Feasibility of Bullet and coarse level threading?
Beware! getWorldTransform is only used to return the initial transform for bullet setup, not later ones after the object has moved.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
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 ¤tTrans) {
MutexLocker(mTransformLock);
currentTrans = mCurrentPos;
}
protected:
btTransform mPos1;
btTransform mCurrentPos;
Mutex mTransformLock;
};
Gary (-;
-
- Posts: 10
- Joined: Thu Jul 03, 2008 4:51 pm
Re: Feasibility of Bullet and coarse level threading?
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
I'm probably going to be using pthreads, so I've got mutexes covered.
Thanks again Gary
-
- Posts: 508
- Joined: Fri May 30, 2008 2:51 am
- Location: Ossining, New York
Re: Feasibility of Bullet and coarse level threading?
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.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.
Which is your priority:
simple design?
performance?
quality appearance?
-
- Posts: 508
- Joined: Fri May 30, 2008 2:51 am
- Location: Ossining, New York
Re: Feasibility of Bullet and coarse level threading?
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.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.
I use boost locks in my project though.
-
- Posts: 10
- Joined: Thu Jul 03, 2008 4:51 pm
Re: Feasibility of Bullet and coarse level threading?
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.I think that would look very bad - objects would jerk around
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().pthreads doesn't provide scoped locks like that, since it's a c library
-
- Posts: 508
- Joined: Fri May 30, 2008 2:51 am
- Location: Ossining, New York
Re: Feasibility of Bullet and coarse level threading?
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.FailMaT_T wrote: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.I think that would look very bad - objects would jerk around
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.
-
- Posts: 145
- Joined: Tue Oct 30, 2007 9:23 pm
Re: Feasibility of Bullet and coarse level threading?
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().
Just because you're using a C threading library doesn't mean you have to hate yourself at the same timepthreads doesn't provide scoped locks like that, since it's a c library
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);
}
};
Gary (-;
-
- Posts: 10
- Joined: Thu Jul 03, 2008 4:51 pm
Re: Feasibility of Bullet and coarse level threading?
Cool. I'll take that into consideration and see what works best