В физическом движке Ammo.js управление телами происходит через указание их типа. Тип тела определяет, как оно взаимодействует с другими объектами, какие законы физики на него распространяются и как рассчитываются столкновения. Основные флаги тел:
Каждый из них используется в специфических сценариях симуляции и позволяет оптимизировать производительность.
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 используется для тел, которые
управляются напрямую скриптом или анимацией, но взаимодействуют
с динамическими объектами через коллизии.
Ключевые особенности:
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 применяется для тел, которые
должны существовать в мире, но не влиять на другие объекты через
столкновения.
Особенности:
Пример кода:
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
);
Такое тело управляется вручную, не подчиняется физике, и не толкает другие объекты, но при этом может использоваться для обнаружения пересечений с другими телами.
Понимание и правильное использование этих флагов позволяет эффективно управлять физикой сцены, избегать лишних вычислений и обеспечивать стабильную симуляцию сложных миров.