2

I'm using bullet to manage any of my physics problems.

Now I'm trying to do something like a 'sensor', the goal is easy, other bodies are doing their collisions and movements together and I want to be able to send a signal when a body reach a specific area.

The problem is to create this area and add it into the world

I only found documentation about RigidBody and SoftBody, and I need something like a "GhostBody" that other object can cross it without be affected by the collision but the collisions have to be detected.

Do anyone have any idea to do it ?

I tried to use the method addCollisionObject(ghostObject), but any body colliding with the ghostObject is affected by the collision.

Adding btBroadphaseProxy::SensorTrigger don't change the effect or just ignore the collision

For info i found this link : https://pybullet.org/Bullet/phpBB3/viewtopic.php?t=7468 collisions are detected but still affect the movment of the RigidBody

Thank you a lot !

EDIT

For now i have this code :

    /*Rigid Body ---------------- */
    shape = new btBoxShape(btVector3(0.5f, 0.75f, 0.5f));
    btTransform transform ;
    transform.setIdentity();
    transform.setOrigin( btVector3(0.0f, 0.95f, 0.0f) );

    btVector3 localInertia(0.0f, 0.0f, 0.0f);
    btScalar mass = 0.5f ;
    if(mass)
    {
        shape->calculateLocalInertia(mass, localInertia);
    }
    motionState = new btDefaultMotionState(transform);

    btRigidBody::btRigidBodyConstructionInfo boxRigidBodyConstructionInfo(mass, motionState, shape, localInertia);

    
    body = new btRigidBody(boxRigidBodyConstructionInfo);

    body->setActivationState(DISABLE_DEACTIVATION);

    world->addRigidBody(body, btBroadphaseProxy::KinematicFilter, btBroadphaseProxy::AllFilter & ~btBroadphaseProxy::SensorTrigger);

    /*GhostObject ---------------- */
    transform.setIdentity();
    transform.setOrigin( btVector3(0.0f, 0.1f, 0.0f) );
    level_sensor = new btGhostObject();
    level_sensor->setCollisionShape(new btBoxShape(btVector3(0.5f, 0.1f, 0.5f)));
    level_sensor->setWorldTransform(transform);
    world->addCollisionObject(level_sensor,btBroadphaseProxy::SensorTrigger, btBroadphaseProxy::KinematicFilter);
    world->getBroadphase()->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback()); 
    world->setInternalTickCallback(motorPreTickCallback);

Here is the callback motorPreTickCallback :

void motorPreTickCallback (btDynamicsWorld *world, btScalar timeStep)
{
    for(int i = 0; i < level_sensor->getNumOverlappingObjects(); i++)
    {
        btRigidBody *pRigidBody = dynamic_cast<btRigidBody *>(level_sensor->getOverlappingObject(i));
        std::cout << "Collision !!!!" << std::endl;
    }
}

By using those masks in the methods addRigidBody and addCollisionObject :

-> - it is not doing any iteration in the loop. ( i don't want )

-> + the collision has no effect on the rigidBody ( i do want )

By NOT using any mask :

-> + it is doing iteration on collisions ( i do want )

-> - the collision affect the rigidBody ( i don't want )

It look like the mask logic for collision affect A & B or i'm not iterating like I want.

By using this method :

world->getBroadphase()->getOverlappingPairCache()->setOverlapFilterCallback(filterCallback);

instead of :

world->getBroadphase()->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());

I can do something like this in the callback :

// return true when pairs need collision
    virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
    {
        bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
        collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
        
        //add some additional logic here that modified 'collides'

        //if(proxy0->m_clientObject is type of sensor )
        //  Cast then sensor.method(proxy1->m_clientObject)

        //if(proxy0->m_clientObject is type of sensor )
        //  Cast then sensor.method(proxy1->m_clientObject)

        return collides;
    }

But it's really hugly ...

Goozzi
  • 209
  • 1
  • 7
  • I don't know Bullet (beyond its name) but I know your problem. In our own S/W, we are able to enable the collision asymmetrically: i.e. we can enable that A collides with B and disable that B collides with A. So, if A is the sensor and B the object A will recognize collision with B but B will not recognize A. (Actually, we added this feature for asymmetric collision detection just to solve this sensor issue.) Maybe, that's an idea to search whether/how this can be done in Bullet... – Scheff's Cat Sep 09 '20 at 13:42
  • Ty @Scheff, i'll try to apply collisions mask filter on the rigid bodies – Goozzi Sep 09 '20 at 14:01
  • I was under impression that pyBullet is the tag for the Python binding of bullet but that might be wrong. (I know that pyQt is the Python binding for Qt but that might be a "false friend".) The pyBullet tag has not yet a description so it is hard to justice. Though, [tag:pyBullet] seems not to be that popular so it's probably no damage to drop it. ;-) – Scheff's Cat Sep 09 '20 at 14:17
  • Yeah that make sense, the web domain is PyBullet.org and if you click on download it become bulletphysic – Goozzi Sep 09 '20 at 14:23

1 Answers1

2

Already answered here : Ghost objects - bulletphysics The line :

level_sensor->setCollisionFlags(btCollisionObject::CF_NO_CONTACT_RESPONSE);

was missing

Goozzi
  • 209
  • 1
  • 7