В Ammo.js MotionState используется для синхронизации положения и ориентации физического тела с визуальным объектом (mesh) в Three.js. MotionState обеспечивает эффективное взаимодействие между движком физики и рендерером, минимизируя необходимость ручного обновления позиции объектов каждый кадр.
MotionState реализуется через объект с методами
getWorldTransform и setWorldTransform.
getWorldTransform вызывается движком физики для получения
текущей трансформации тела, а setWorldTransform
используется для передачи обновленной позиции и ориентации тела обратно
в Three.js mesh.
class MotionState {
constructor(mesh) {
this.mesh = mesh;
this.transform = new Ammo.btTransform();
}
getWorldTransform(worldTrans) {
worldTrans.setOrigin(this.transform.getOrigin());
worldTrans.setRotation(this.transform.getRotation());
}
setWorldTransform(worldTrans) {
const origin = worldTrans.getOrigin();
const rotation = worldTrans.getRotation();
this.mesh.position.set(origin.x(), origin.y(), origin.z());
this.mesh.quaternion.set(rotation.x(), rotation.y(), rotation.z(), rotation.w());
}
}
В этом примере mesh.position и
mesh.quaternion синхронизируются с физическим телом,
обеспечивая точное отображение движка физики в Three.js.
Rigid body в Ammo.js требует описания формы, массы и начальной
трансформации. MotionState интегрируется через конструктор
btRigidBody. Основные шаги:
const transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin(new Ammo.btVector3(0, 10, 0));
transform.setRotation(new Ammo.btQuaternion(0, 0, 0, 1));
const mass = 1;
const localInertia = new Ammo.btVector3(0, 0, 0);
shape.calculateLocalInertia(mass, localInertia);
const motionState = new MotionState(mesh);
const rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, shape, localInertia);
const body = new Ammo.btRigidBody(rbInfo);
physicsWorld.addRigidBody(body);
Использование MotionState гарантирует, что физическая симуляция и визуальное представление будут оставаться синхронизированными без необходимости вручную копировать позиции на каждом кадре.
При каждом обновлении мира физики Ammo.js вызывает метод
setWorldTransform MotionState, что позволяет напрямую
обновлять свойства Three.js объекта. Это значительно снижает нагрузку по
сравнению с ручным чтением позиции и ориентации rigid body.
Пример интеграции с циклом рендеринга Three.js:
function animate() {
requestAnimationFrame(animate);
physicsWorld.stepSimulation(1 / 60, 10);
// Обновление всех объектов происходит автоматически через MotionState
renderer.render(scene, camera);
}
MotionState работает напрямую с btTransform, который
содержит btVector3 для позиции и btQuaternion
для ориентации. При работе с Three.js quaternion используется для
установки ориентации mesh. Важно правильно преобразовывать форматы:
const origin = transform.getOrigin();
const rotation = transform.getRotation();
mesh.position.set(origin.x(), origin.y(), origin.z());
mesh.quaternion.set(rotation.x(), rotation.y(), rotation.z(), rotation.w());
Использование матриц трансформации напрямую
(mesh.matrix) возможно, но рекомендуется работать через
позицию и quaternion для лучшей совместимости с Three.js и
анимациями.
MotionState можно расширять для поддержки:
Применение MotionState позволяет создавать реалистичные физические симуляции, синхронизированные с визуальными объектами Three.js, обеспечивая точность и высокую производительность.