Before I actually start implementing Bullet, I need to know a few things:
The guide says that Bullet uses 60hz as it's internal rate, meaning must iterate the Simulator 60 times per second. However, Torque uses a tick of 32ms, which comes to roughly 31.25hz. Can the tick rate in Bullet be changed?
Alternatively, when accessing data via a MotionState, does Bullet implement some sort of semaphore, so that I may run Bullet in its own thread with its own timing at 60hz, and read the data from the master thread?
Otherwise, how would I integrate these two systems?
The smallest common between 31.25 and 60 is 1500, and 1500 / 60 is 25... so am I looking at 25 substeps? Or 1500 / 31.25 = 48, so 48?
Integrating into Torque at 31.5hz
-
- Posts: 169
- Joined: Sun Jan 14, 2007 7:56 pm
- Location: Norway
Re: Integrating into Torque at 31.5hz
Hi there,
Bullet's tick rate can be freely chosen. It defaults to 60Hz, but you can use whatever you like. Lower frequencies might cause more instability, so you'll have to experiment. You set the tick rate in the third optional argument to btDynamicsWorld::stepSimulation, here's a copy/paste from btDynamicsWorld.h:
If you do call stepSimulation every 32 ms, you can disable Bullet's internal sub-stepping by setting maxSubSteps to 0,
float tick = 32.0/1000.0;
stepSimulation(tick, 0, tick);
Here Bullet will do one single iteration only, and the timeStep used for integrating movement is 32 ms.
Best regards,
Ola
Bullet's tick rate can be freely chosen. It defaults to 60Hz, but you can use whatever you like. Lower frequencies might cause more instability, so you'll have to experiment. You set the tick rate in the third optional argument to btDynamicsWorld::stepSimulation, here's a copy/paste from btDynamicsWorld.h:
Code: Select all
///stepSimulation proceeds the simulation over 'timeStep', units in preferably in seconds.
///By default, Bullet will subdivide the timestep in constant substeps of each 'fixedTimeStep'.
///in order to keep the simulation real-time, the maximum number of substeps can be clamped to 'maxSubSteps'.
///You can disable subdividing the timestep/substepping by passing maxSubSteps=0 as second argument to stepSimulation, but in that case you have to keep the timeStep constant.
virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.))=0;
float tick = 32.0/1000.0;
stepSimulation(tick, 0, tick);
Here Bullet will do one single iteration only, and the timeStep used for integrating movement is 32 ms.
Best regards,
Ola
-
- Posts: 11
- Joined: Sun Oct 18, 2009 1:18 am
Re: Integrating into Torque at 31.5hz
Cool.
Also, is Bullet threaded, or is it halting... IE, when I commence a step, does it halt the simulation until completion, or can I continue doing whatever it was that I was doing?
If it's threaded, is there a way to know when it's "safe" to use a MotionState to get data from it, or is it locked with a semaphore?
Also, is Bullet threaded, or is it halting... IE, when I commence a step, does it halt the simulation until completion, or can I continue doing whatever it was that I was doing?
If it's threaded, is there a way to know when it's "safe" to use a MotionState to get data from it, or is it locked with a semaphore?
-
- Posts: 169
- Joined: Sun Jan 14, 2007 7:56 pm
- Location: Norway
Re: Integrating into Torque at 31.5hz
Hi again,
it's not threaded, and it's not thread safe. So you'll have to modify the code to suit your needs. Take a look into the source code, starting from stepSimulation in btDiscreteDynamicsWorld, and you'll see how it's put together.
I have one project where the physics run in a separate thread at 60Hz. I created my own dynamics word class inheriting btDiscreteDynamicsWorld and went from there. I think all I had to do was to use mutex locking to prevent adding/removing rigid bodies while timeStep was running, and also similar protection to the motion states. Since most methods are virtual, it's easy to create "wrapper" methods in your own class, example (myClass inherits btDiscreteDynamicsWorld)
Keep in mind that Bullet's motion states are designed for running everything in a single thread. So to properly smooth the positions in between frames, you will have to come up with your own way of interpolating between two simulation step transforms when rendering a frame.
Cheers,
Ola
it's not threaded, and it's not thread safe. So you'll have to modify the code to suit your needs. Take a look into the source code, starting from stepSimulation in btDiscreteDynamicsWorld, and you'll see how it's put together.
I have one project where the physics run in a separate thread at 60Hz. I created my own dynamics word class inheriting btDiscreteDynamicsWorld and went from there. I think all I had to do was to use mutex locking to prevent adding/removing rigid bodies while timeStep was running, and also similar protection to the motion states. Since most methods are virtual, it's easy to create "wrapper" methods in your own class, example (myClass inherits btDiscreteDynamicsWorld)
Code: Select all
void myClass::doSomething()
{
mutex.lock();
btDiscreteDynamicsWorld::doSomething();
mutex.unlock()
}
Cheers,
Ola
-
- Posts: 11
- Joined: Sun Oct 18, 2009 1:18 am
Re: Integrating into Torque at 31.5hz
The biggest problem is that, say I have 4000 objects in my sim, and I want to do anything on a SINGLE object, be it rip a transform, apply an impulse, whatnot.
The issue then becomes that the system only allows so many semaphores, so we end up defining a single locking semaphore, but that means if I want to modify a SINGLE object, I stall the ENTIRE physics simulator because that mutex is for ALL objects.
Now, say I am in a render pass in my main sim ripping transforms, I am competing directly between physics and graphics semaphore-wise - the alternative is to do batch reads/writes.
That might be the best way is to make a single lock for batch operations instead of atomic mutexes, as that way there is less competition and less stalling - during a phase where I am requesting graphics information and/or applying operations to objects, the physics simulator should be stopped, not just stalled.
EDIT - I'll look at the code tonight, but I'm at work tonight and don't have access to a dev system, and I'm here for the next 9 hours
so I'm just trying to get as much info into my head now so I'm ready to just dig in.
The issue then becomes that the system only allows so many semaphores, so we end up defining a single locking semaphore, but that means if I want to modify a SINGLE object, I stall the ENTIRE physics simulator because that mutex is for ALL objects.
Now, say I am in a render pass in my main sim ripping transforms, I am competing directly between physics and graphics semaphore-wise - the alternative is to do batch reads/writes.
That might be the best way is to make a single lock for batch operations instead of atomic mutexes, as that way there is less competition and less stalling - during a phase where I am requesting graphics information and/or applying operations to objects, the physics simulator should be stopped, not just stalled.
EDIT - I'll look at the code tonight, but I'm at work tonight and don't have access to a dev system, and I'm here for the next 9 hours
