Флаги тела: CF_STATIC_OBJECT, CF_KINEMATIC_OBJECT, CF_NO_CONTACT_RESPONSE

В физическом движке Ammo.js управление телами происходит через указание их типа. Тип тела определяет, как оно взаимодействует с другими объектами, какие законы физики на него распространяются и как рассчитываются столкновения. Основные флаги тел:

  • CF_STATIC_OBJECT
  • CF_KINEMATIC_OBJECT
  • CF_NO_CONTACT_RESPONSE

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


CF_STATIC_OBJECT

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

Характеристики:

  • Масса всегда считается бесконечной (неподвижная).
  • Может быть использован для создания стен, пола, платформ.
  • Коллизии с динамическими телами учитываются, но тело само не изменяет позицию.
  • Не требует расчета интеграции движения, что экономит ресурсы.

Пример кода:

const shape = new Ammo.btBoxShape(new Ammo.btVector3(1, 1, 1));
const transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin(new Ammo.btVector3(0, 0, 0));

const mass = 0; // статическое тело всегда имеет массу 0
const localInertia = new Ammo.btVector3(0, 0, 0);

const motionState = new Ammo.btDefaultMotionState(transform);
const rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, shape, localInertia);
const body = new Ammo.btRigidBody(rbInfo);

body.setCollisionFlags(body.getCollisionFlags() | Ammo.cf_static_object);
physicsWorld.addRigidBody(body);

CF_KINEMATIC_OBJECT

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

Ключевые особенности:

  • Тело не подчиняется законам физики, но другие объекты сталкиваются с ним корректно.
  • Можно менять позицию и ориентацию вручную каждый кадр, используя setWorldTransform().
  • Масса объекта считается нулевой.
  • Идеально подходит для игровых персонажей, движущихся платформ и объектов с анимацией.

Пример кода:

const shape = new Ammo.btBoxShape(new Ammo.btVector3(1, 1, 1));
const transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin(new Ammo.btVector3(0, 5, 0));

const motionState = new Ammo.btDefaultMotionState(transform);
const rbInfo = new Ammo.btRigidBodyConstructionInfo(0, motionState, shape, new Ammo.btVector3(0, 0, 0));
const body = new Ammo.btRigidBody(rbInfo);

body.setCollisionFlags(body.getCollisionFlags() | Ammo.cf_kinematic_object);
body.setActivationState(Ammo.DISABLE_DEACTIVATION);

physicsWorld.addRigidBody(body);

// Перемещение тела вручную
function updateKinematicPosition(newPosition) {
    const transform = new Ammo.btTransform();
    body.getMotionState().getWorldTransform(transform);
    transform.setOrigin(new Ammo.btVector3(newPosition.x, newPosition.y, newPosition.z));
    body.getMotionState().setWorldTransform(transform);
}

CF_NO_CONTACT_RESPONSE

CF_NO_CONTACT_RESPONSE применяется для тел, которые должны существовать в мире, но не влиять на другие объекты через столкновения.

Особенности:

  • Тело проходит сквозь другие объекты, не создавая физических реакций.
  • Используется для триггеров, сенсоров, зон обнаружения.
  • Можно комбинировать с другими флагами для более гибкого поведения.

Пример кода:

const shape = new Ammo.btBoxShape(new Ammo.btVector3(2, 2, 2));
const transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin(new Ammo.btVector3(0, 10, 0));

const motionState = new Ammo.btDefaultMotionState(transform);
const rbInfo = new Ammo.btRigidBodyConstructionInfo(0, motionState, shape, new Ammo.btVector3(0, 0, 0));
const body = new Ammo.btRigidBody(rbInfo);

body.setCollisionFlags(body.getCollisionFlags() | Ammo.cf_no_contact_response);
physicsWorld.addRigidBody(body);

Использование:

  • Датчики подбора предметов.
  • Зоны триггеров для событий игры.
  • Объекты, которые должны пересекать другие без физической реакции.

Комбинирование флагов

Флаги тел можно комбинировать с помощью побитового OR (|). Например, кинетическое тело-триггер:

body.setCollisionFlags(
    body.getCollisionFlags() | Ammo.cf_kinematic_object | Ammo.cf_no_contact_response
);

Такое тело управляется вручную, не подчиняется физике, и не толкает другие объекты, но при этом может использоваться для обнаружения пересечений с другими телами.


Влияние флагов на производительность

  • CF_STATIC_OBJECT — минимальная нагрузка, так как тело не интегрируется.
  • CF_KINEMATIC_OBJECT — средняя нагрузка, требует обновления трансформаций каждый кадр.
  • CF_NO_CONTACT_RESPONSE — низкая нагрузка при взаимодействии с динамикой, идеален для сенсоров.

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