В Ammo.js объект MotionState отвечает
за связь между физическим телом и его представлением в сцене. Он
обеспечивает синхронизацию позиции и ориентации тела в физическом мире с
визуальной частью приложения, что особенно важно для динамических
объектов.
Каждое тело (btRigidBody) может иметь собственный
MotionState. Его основная задача — предоставление
текущей трансформации тела (позиции и ориентации) и
возможность её установки. MotionState используется движком
для оптимизации: физический движок обновляет только трансформации, а
визуальная часть читает их без дополнительных вычислений.
MotionState содержит два ключевых метода:
getWorldTransform(worldTrans) — получает текущую
трансформацию тела.setWorldTransform(worldTrans) — устанавливает
трансформацию, обычно вызывается движком при изменении позиции объекта в
физическом мире.Фактически, MotionState — это интерфейс, через который
происходит обмен информацией между движком и визуальной моделью.
Для получения позиции и ориентации объектов можно использовать
стандартный класс Ammo.btDefaultMotionState:
const startTransform = new Ammo.btTransform();
startTransform.setIdentity();
startTransform.setOrigin(new Ammo.btVector3(0, 10, 0)); // начальная позиция
const motionState = new Ammo.btDefaultMotionState(startTransform);
btTransform задаёт начальную трансформацию тела.setIdentity() сбрасывает трансформацию до
стандартной (нулевая позиция, отсутствие вращения).setOrigin() устанавливает начальное положение
объекта.Чтобы извлечь текущую позицию тела, необходимо:
btRigidBody:const bodyMotionState = rigidBody.getMotionState();
btTransform для хранения
трансформации:const trans = new Ammo.btTransform();
getWorldTransform:bodyMotionState.getWorldTransform(trans);
getOrigin():const origin = trans.getOrigin();
const x = origin.x();
const y = origin.y();
const z = origin.z();
Результатом являются координаты объекта в мировых единицах.
Для получения вращения используется getRotation()
объекта btTransform:
const rotation = trans.getRotation();
const qx = rotation.x();
const qy = rotation.y();
const qz = rotation.z();
const qw = rotation.w();
Это стандартный кватернион, который можно использовать для установки
вращения визуального объекта, например в Three.js через
Quaternion.
После получения позиции и кватерниона можно синхронизировать физическое тело с графическим объектом:
mesh.position.set(x, y, z);
mesh.quaternion.set(qx, qy, qz, qw);
Такое обновление необходимо выполнять каждый кадр после шага
симуляции physicsWorld.stepSimulation(deltaTime).
btRigidBody.getCenterOfMassTransform(), что уменьшает
нагрузку на движок.btTransform
нужно создавать один раз и переиспользовать для каждого кадра, чтобы
минимизировать выделение памяти и нагрузку сборщика мусора.setWorldTransform, но это следует делать аккуратно, чтобы
не нарушить работу физики.function updateMeshFromPhysics(rigidBody, mesh) {
const motionState = rigidBody.getMotionState();
if (motionState) {
const trans = new Ammo.btTransform();
motionState.getWorldTransform(trans);
const origin = trans.getOrigin();
mesh.position.set(origin.x(), origin.y(), origin.z());
const rotation = trans.getRotation();
mesh.quaternion.set(rotation.x(), rotation.y(), rotation.z(), rotation.w());
}
}
Этот подход обеспечивает корректную и эффективную синхронизацию между физикой и визуализацией, особенно при работе с множеством динамических объектов в реальном времени.
getWorldTransform и
setWorldTransform позволяет безопасно получать и задавать
позицию и ориентацию.btTransform критична для
производительности при больших сценах.Этот механизм является фундаментальной частью интеграции Ammo.js с графическими движками и обеспечивает точное соответствие физического мира визуальной сцене.