Изменение положения твердого тела в физике пули

Я пишу движок рендеринга анимации персонажей, который использует Bullet Physics в качестве движка физического моделирования.

Последовательность начнется без модели на экране, затем этой модели будет назначена анимация, модель будет перемещена в кадр 0 анимации, и движок начнет рендеринг модели с анимацией.

Как правильно переместить твердые тела на модели персонажа, когда она инициализирована в кадре 0?

В настоящее время я использую этот код, который вызывается сразу после того, как анимация назначается модели и кости перемещаются в позицию 0 кадра:

_world->removeRigidBody(_body);
bool k = (_type == Kinematics);
_body->setCollisionFlags(_body->getCollisionFlags() & ~btCollisionObject::CF_NO_CONTACT_RESPONSE);
btTransform tr = BulletPhysics::ConvertD3DXMatrix(&(_bone->getCombinedTrans()));
tr *= _trans;
_body->setCenterOfMassTransform(tr);
_body->clearForces();
_body->setLinearVelocity(btVector3(0,0,0));
_body->setAngularVelocity(btVector3(0,0,0));
_world->addRigidBody(_body, _groupID, _groupMask);

Проблема в том, что иногда это работает, а иногда нет. Для примера возьмем юбку модели. Иногда он появляется в естественном положении, иногда с небольшим смещением и упадет на место, а в других случаях он оказывается полностью разрезанным через тело, как если бы столкновение было отключено и какая-то сила толкнула его в этом направлении. В большинстве случаев это имеет смысл, потому что в тестовой анимации я использую исходное положение модели в центре экрана, но анимация начинается с левой стороны экрана. Кто-нибудь знает, как это решить?

Я знаю, что кости на юбке не проблема, потому что я отключил физику и заставил ее вручную обновлять положения костей в каждом кадре, и все было в правильных положениях на протяжении всей анимации.

РЕДАКТИРОВАТЬ: У меня также есть ограничения, может это быть причиной этого?


person bearsomg    schedule 03.09.2012    source источник


Ответы (3)


Вот мой метод репозиции, который делает именно это.

void LimbBt::reposition(btVector3 position,btVector3 orientation) {
    btTransform initialTransform;

    initialTransform.setOrigin(position);
    initialTransform.setRotation(orientation);

    mBody->setWorldTransform(initialTransform);
    mMotionState->setWorldTransform(initialTransform);
}

Состояние движения mMotionState - это состояние движения, которое вы создали для btRigidBody в начале. Просто добавьте к нему clearForces () и velocity, чтобы тело не двигалось с новой позиции, как если бы оно прошло через портал. Это должно сработать. Здесь у меня хорошо работает.

Изменить: ограничения будут адаптированы, если вы правильно переместите все твердые тела. Для этой цели легко вычислить относительное положение и изменить положение всей жесткой конструкции с ограничениями в соответствии с этим. Если вы сделаете это неправильно, вы получите сильное подергивание, поскольку ограничения будут пытаться отрегулировать вашу конструкцию численно, вызывая высокие силы, если зазоры между ограничениями велики.

Edit2: Другая проблема заключается в том, что если вам нужно детерминированное поведение (каждый раз, когда вы сбрасываете свои тела, они должны падать точно одинаково), тогда вам придется убить свой старый динамический мир, воссоздать его и добавить все снова тела. В мире хранится некоторая информация о телах, которую сейчас просто невозможно очистить. Это может измениться в будущем, поскольку bullet4 будет поддерживать детерминированные сбросы. Но пока, если вы проводите эксперименты с детерминированными сбросами, вам нужно отбросить мир и воссоздать его.

источник: обсуждение с Эрвином Кумансом, разработчиком Bullet Physics.

person Ben    schedule 24.08.2015

Я не могу сказать вам, что вызывает необычный результат при перемещении твердых тел, но я определенно могу посочувствовать!

Чтобы решить эту проблему, вам нужно сделать три вещи:

  1. Преобразуйте твердые тела в кинематические
  2. Отрегулируйте World Transform состояния движения тел, а НЕ твердого тела
  3. Преобразуйте кинематическое тело обратно в твердое тело
person 0tombo0    schedule 22.08.2013
comment
Это совершенно не нужно. Просто телепортируйте RigidBody. - person Joehot200; 20.04.2015
comment
Измените его мировую трансформацию, и тогда достаточно четких сил, линейных и угловых скоростей. - person Ben; 06.09.2016
comment
@ Joehot200 «Телепортация» РБ - это, по сути, та же операция, которую я описываю здесь, но вы просто используете классный мир, чтобы описать ее. - person 0tombo0; 27.09.2019
comment
@ 0tombo0 Должен признаться, не совсем понимаю, о чем я там думал, в 2015 году! - person Joehot200; 12.11.2019

Короткий протестированный фрагмент кода эффективно телепортирует твердое тело, обновляя его состояние движения до нового положения и ориентации, а также обнуляя все скорости и силы, действующие на него.

    void teleport(btVector3 position, btQuaternion& orientation) const {

        btTransform transform;
        transform.setIdentity();

        transform.setOrigin(position);
        transform.setRotation(orientation); 

        m_rigidBodyVehicle->setWorldTransform(transform);
        m_rigidBodyVehicle->getMotionState()->setWorldTransform(transform);

        m_rigidBodyVehicle->setLinearVelocity(btVector3(0.0f, 0.0f, 0.0f));
        m_rigidBodyVehicle->setAngularVelocity(btVector3(0.0f, 0.0f, 0.0f));
        m_rigidBodyVehicle->clearForces();
}
person LastBlow    schedule 28.01.2019