Физическая пуля - есть ли «призрачное» тело?

Я использую пулю для решения любых моих физических задач.

Теперь я пытаюсь сделать что-то вроде «сенсора», цель проста, другие тела совершают свои столкновения и движения вместе, и я хочу иметь возможность посылать сигнал, когда тело достигает определенной области.

Проблема в том, чтобы создать эту область и добавить ее в мир.

Я нашел документацию только по 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;
    }

Но это действительно обольстительно ...


person Goozzi    schedule 09.09.2020    source источник
comment
Я не знаю Bullet (кроме названия), но я знаю вашу проблему. В нашем собственном ПО мы можем включить асимметричное столкновение: то есть мы можем разрешить столкновение A с B и отключить столкновение B с A. Итак, если A является датчиком, а B объект A распознает столкновение с B но B не распознает A. (Фактически, мы добавили эту функцию для асимметричного обнаружения столкновений, чтобы решить эту проблему с датчиком.) Возможно, это идея поискать, можно ли / как это сделать в Bullet ...   -  person Scheff's Cat    schedule 09.09.2020
comment
Ty @Scheff, я попробую применить фильтр маски столкновений к твердым телам   -  person Goozzi    schedule 09.09.2020
comment
У меня сложилось впечатление, что pyBullet - это тег для привязки пули Python, но это может быть неправильно. (Я знаю, что pyQt - это привязка Python для Qt, но это может быть ложным другом.) Тег pyBullet еще не имеет описания, поэтому его трудно оправдать. Хотя pybullet, похоже, не так популярен, поэтому, вероятно, отказ от него не повредит. ;-)   -  person Scheff's Cat    schedule 09.09.2020
comment
Да, это имеет смысл, веб-домен - это PyBullet.org, и если вы нажмете кнопку загрузки, он станет bulletphysic   -  person Goozzi    schedule 09.09.2020


Ответы (1)


Здесь уже ответил: Призрачные объекты - bulletphysics Строка:

level_sensor->setCollisionFlags(btCollisionObject::CF_NO_CONTACT_RESPONSE);

скучал

person Goozzi    schedule 09.09.2020