update: also available in Polish (slides) Bullet i dźwięki pdf
I decided to create short tutorial about physics based sound. In previous post video you was able to hear my audio. Now I would like to share my short conception with you. Example written in bullet physics engine.
Of course the only way to determine collisions is to search contacts points used by physics engine. But contact points aren’t obvious. We must to check if they meet interesting for us conditions. Currently I am using two physics sounds:
Impact sound
It should be played when some object hits other object. Typically this is short, loud sound dependent on the materials which objects are made of. Browsing contacts should be done after stepSimulation method defined in collisionWorld class if you have implemented fixed time step physics (see fix-your-timestep article) if you don’t, you can do it using bullet’s internal tick callback.
So you probably want to play “hit” sound when contact point meets this contitions (they work well for me)
- object really collide with other so contact point distance is less then zero
- hitting force reaches certain threshold (you must try which is best for you)
- optionally lifetime of contact point = 1, so it is just created (I have this condition just in case)
Scratching sound
When some object is sliding on other. It also could depend on objects materials and as extension it can also depend on object sliding velocity (of course if you have such option in your sound library). If greater velocity then sound pitch (frequency) should be greater. Such action will give realism to the sound, like in real world. Here are my conditions for sliding sound effect:
- length of difference of two object velocity vectors greater than some small amount (depends on your physics world scaling). Vectors difference is needed to ensure that object is really sliding, this also prevents situation when one object is at rest on another moving object. In this case sliding sound shouldn’t be played, all two object have some velocity, but relatively to each other they aren’t moving and difference of this objects velocities is of course 0
- contact point distance is less than small value but greater than zero, so one object is located on second
My code example ( magic values works for me, but i have the world scaled by 64 ):
[sourcecode language=”cpp”]
for (int i=0;i< dynamicsWorld->getDispatcher()->getNumManifolds();i++)
{
btPersistentManifold* contactManifold = dynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i);
for(int t=0;tgetNumContacts();++t)
{
auto point=contactManifold->getContactPoint(t);
if(point.getDistance()<-0.5f && point.getLifeTime()==1 && point.getAppliedImpulse()>100.f)
{
//play impact sound
}else
if(((contactManifold->getBody0()->getLinearVelocity()-contactManifold->getBody1()->getLinearVelocity()).length()>4.f) && point.getDistance()<1.5f )
{
//play sliding sound
}
}
}
[/sourcecode]
This easy, short code can really improve audio of your applications. There is still issue – how to play this sounds. I’m using such rules: For impact sound, I’m just playing it on first available channel. For sliding sound I’m using resume / pause method, but You can handle it yourself.