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 ...