Page 1 of 1

irrBullet - how to check collision and play a sound

Posted: Thu Nov 11, 2010 10:24 pm
by cookie
Hm, maybe not the best Topic Title, but here is my problem:

I want to play a sound (with irrKlang. I know how to do this :>) when an physic object hits another one or the floor of the room or something different. I know how to detect collision but I've had this problem a few months ago: when I'm inside a room - which was given to irrBullet as rigidbody - and I want detect collision with this room, it shows always that there is an collision, because I'm standing INSIDE the room and this means I'm inside the "collision box".
Now I want to know: is there a way to fix this (no, I don't want to build each side of my room manually in the level editor by placing physic-using cubes all around it) or is there another possibility to check when I have to play a sound?
I can check collisions with other rigid-bodies, thats no problem, but when I want to check the "world" (thats the "collision-attribute" for all non-dynamical objects in my engine) then I'll become this "error".

I hope you understand what I mean and can help me!

Thanks for answers

Posted: Fri Nov 12, 2010 5:58 am
by codydbgt
ever tried your own colistion code like just for the things u want or talking about..........and i could help you if you posed some code.

Posted: Fri Nov 12, 2010 11:12 am
by serengeor
if you want to know when you're colliding with the mesh of the world, you make a collision shape of "btBvhTriangleMeshShape", then it will collide with the triangles of the mesh, instead of collision box.

Read more on http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=39007

It creates the map in the CPhysics constructor, so you'll have to rewrite what you need.

Hope I understood the problem.

And you should make some kind of variable, so you wouldnt play the sound every frame that it collides.

Posted: Fri Nov 12, 2010 12:37 pm
by cookie
Thanks for the answers.

No, both of you didn't understand my problem :>

So here is an better description of my problem:

1. I've got a room. The room-node is given to irrBullet to create an IBvhTriangleMeshShape of it.

2. I add the attributes "collided" and "world" as bools to the room-rigid-body:

Code: Select all

rbody->getAttributes()->addBool("world", true);
    rbody->getAttributes()->addBool("collided",false);
collided is true when a collision with this attribute was detected else it will be false.
World is in every rigidbody which belongs to the static objects of the world.

3. The IBvhTriangleMeshShape was created and work, all movements of the rigid bodys are correct.

4. Now I want to check if there is a collision between a rigid-body and a rigid-body with the attribute world:

Code: Select all

if(rbody->hasCollidedWithAttribute("world"))
            {
                if(rbody->getAttributes()->getAttributeAsBool("collided") == false)
                {
                    rbody->getAttributes()->setAttribute("collided", true);
                   //here would be played the sound, but thats not my problem now ;)
                }
            }
            else
           {
                rbody->getAttributes()->setAttribute("collided", false);
         }
5. When I'm inside of the room with the attribute "world" the collision result will be true, although there isn't a collision with the "world" attribute.
The reason why irrbullet thinks there is already a collision is:
I'm inside of this room, so irrBullet thinks the rigidBodie already collided with it, so it shows me all the time there would be a collision...

Do you understand my problem now?

Posted: Fri Nov 12, 2010 3:59 pm
by serengeor
Oh dang, this is irrBullet, no wonder why i havent found anything about getAttribute method on bullets API page :lol:

Can't help much with irrBullet, you should consider posting this in the irrbullets thread, maybe there you could get your answer quicker.

Posted: Fri Nov 12, 2010 9:29 pm
by cookie
Cobra isn't avaible I think...because I wrote him a few days ago a PM and he didn't answer until now :0

But I've got an update for my problem, which is...bad...

I tried it again with this code:

Code: Select all

list<IRigidBody*>::Iterator current_body= dynamic_bodies.begin();
    for (; current_body !=dynamic_bodies.end();)
    {
            if((*current_body)->hasCollidedWithAttribute("world"))
            {
                if((*current_body)->getAttributes()->getAttributeAsBool("collided") == false)
                {
                    (*current_body)->getAttributes()->setAttribute("collided", true);
                    std::cout<<"collision!"<<std::endl;
                }
            }
            else
            {
                 (*current_body)->getAttributes()->setAttribute("collided", false);
                 std::cout<<NO collision!"<<std::endl;
            }
    }
The code checks all dynamic bodies in the dynamic_bodies list about a collision with the attribute "world" which is avaible in every static rigid body in my scene... but when I start my program, I see the first frame and then the programm doesn't want to continue... it plays the background sounds of the scene but I can't move and all the physics are frozen too... I _really_ don't know what the code above do that the program won't continue... the last message in my debugger is "collision!" so it seems that one collision was detected and then the program stopped to continue ._. maybe the first collision with the world objects hurt my programs feelings so hard that it refuse to going on in the code :D


I hope somebody can help me...

[EDIT]

Uh... it wasn't the collision on its self, I just forgot to write "++current_body" to continue in the loop >.<

[EDIT 2]

Hm...that's weird but now the collision detecting is working perfect ._.
Well, thanks for your help...the topic can be closed :D

Posted: Sat Nov 13, 2010 2:54 am
by cobra
Hi cookie.

Sorry about the delayed response to your problem.


Anyway, I advise against using IRigidBody::hasCollidedWithAttribute().
I will probably remove it in the next irrBullet release.

0.1.7 is actually mature, and it has been for a while, so I'll probably get around to a release soon. I've been busy with others things and working on my game.


Here's the way you should handle your collisions:

Code: Select all

void ICollisionProcessor::processCollisions()
{
    irrBulletWorld* DynamicsWorld = FightersTW->getDynamicsWorld();
    for(int i=0; i < DynamicsWorld->getNumManifolds(); i++)
    {
        ICollisionCallbackInformation *info = 0;
        info = DynamicsWorld->getCollisionCallback(i);

        int numContacts = info->getPointer()->getNumContacts();
        for(int j=0; j < numContacts; j++)
        {
            if(verifyCollisionCallback(info))
            {
                if(info->getContactPoint(j).getDistance()<1.5f && info->getContactPoint(j).getLifeTime() < 2.0f)
                {
                    handleWeaponVersusTerrain(info, j);
                    handleChildObjectVersusTerrain(info, j);
                    handleChildObjectVersusWater(info, j);
                    handleMainObjectVersusTerrain(info, j);
                }
            }
        }
        info->getPointer()->clearManifold();
    }
}
Each function called in there with the beginning "handle" checks to see what type of objects are colliding (by checking attributes).

Good luck! :)

Posted: Sat Nov 13, 2010 9:42 am
by cookie
Okay, thank you.

Is there a way to check just for example my dynamic bodies, when I've got them in a list like the code a few posts above?

Posted: Sat Nov 13, 2010 9:27 pm
by cobra
cookie:

Either way you'd be cycling through all the collision manifolds and points, so it's best to do it the way I advised.

Posted: Sun Nov 14, 2010 1:39 pm
by cookie
Allright, but whats happening in the functions with "handle" at the beginning?
... checks to see what type of objects are colliding (by checking attributes)
How do you do that?

Posted: Sun Nov 14, 2010 9:57 pm
by cobra
cookie:

Just use a switch-case or if statement to check attributes of types that you want to handle. You must first add these attributes when you create the rigid-body, or some time before you start trying to access them.

Code: Select all

if(info->getBody1()->getAttributes()->getAttributeAsInt("Type") == OT_WORLD_OBJECT)

Posted: Mon Nov 15, 2010 3:23 pm
by cookie
Thank you.

So now 2 more questions:

What does the function "verifyCollisionCallback" do?

and

Which of the colliding bodys is info->getBody1, the one I check about collision or the body which collides with the body I'm checking? I think the one which I want to check...

Thanks for your help.

Posted: Tue Nov 16, 2010 2:00 am
by cobra
verifyCollisionCallback() just checks the two bodies (info->getBody1() and info->getBody0()) to see if they both contain the attribute with the name "collide."


Also, you'll just have to check both of the bodies to find the attributes you want.

I think the way Bullet adds them is the object with the highest velocity might be getBody1(), but I'm not sure.

Anyway, just find the one with the right attribute, for instance weapon, and then handle it accordingly from there.

Posted: Tue Nov 16, 2010 2:18 pm
by cookie
Allrigt, it works perfect :)

Thank you!

Only problem now: the sounds get played to often on every little movement of the rigid bodys, but I think I can fix this.

Posted: Tue Nov 16, 2010 7:12 pm
by cobra
cookie:

You need to set an attribute to false, and check to see if that's true before you register a collision.

For instance, add the attribute as a bool with the name "isDestroyed" and set it to true on collision.

Or set a "last collision" float attribute in the bodies, then on collide you can set that value to the timer's current time. Then if the time is, say, greater than lastCollisionTime + 2000, you could play the sound. If not, you would not play the sound.

Hope that works out for you.

- Josiah