Я использую пулю для решения любых моих физических задач.
Теперь я пытаюсь сделать что-то вроде «сенсора», цель проста, другие тела совершают свои столкновения и движения вместе, и я хочу иметь возможность посылать сигнал, когда тело достигает определенной области.
Проблема в том, чтобы создать эту область и добавить ее в мир.
Я нашел документацию только по RigidBody и SoftBody, и мне нужно что-то вроде GhostBody, чтобы другой объект мог пересечь его, не подвергаясь столкновениям, но столкновения должны быть обнаружены.
Есть ли у кого-нибудь идеи это сделать?
Я пытался использовать метод addCollisionObject (ghostObject), но любое тело, сталкивающееся с ghostObject, подвержено столкновению.
Добавление btBroadphaseProxy :: SensorTrigger не меняет эффект или просто игнорирует столкновение
Для информации я нашел эту ссылку: https://pybullet.org/Bullet/phpBB3/viewtopic.php?t=7468 коллизии обнаружены, но по-прежнему влияют на перемещение RigidBody
Большое спасибо !
РЕДАКТИРОВАТЬ
На данный момент у меня есть этот код:
/*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);
Вот обратный вызов 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;
}
}
Используя эти маски в методах addRigidBody и addCollisionObject:
- ›- он не выполняет никаких итераций в цикле. (я не хочу)
- ›+ столкновение не влияет на твердое тело (я действительно хочу)
НЕ ИСПОЛЬЗУЯ маску:
- ›+ выполняет итерацию при столкновениях (я действительно хочу)
- ›- столкновение влияет на твердое тело (не хочу)
Похоже, что логика маски для столкновения влияет на A и B, или я не повторяю, как хочу.
Используя этот метод:
world->getBroadphase()->getOverlappingPairCache()->setOverlapFilterCallback(filterCallback);
вместо того :
world->getBroadphase()->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
Я могу сделать что-то подобное в обратном вызове:
// 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;
}
Но это действительно обольстительно ...