Синхронизация визуальных колёс с физикой

Ammo.js — это JavaScript-порт популярной библиотеки Bullet Physics, предоставляющий возможности полноценной физической симуляции в браузере. Для создания реалистичного движения транспортных средств ключевым аспектом является синхронизация визуальных колёс с физическим движением, обеспечиваемая системой колесных тел в Ammo.js.

В основе лежит btRaycastVehicle, который моделирует поведение автомобиля с помощью физики, не создавая отдельные твёрдые тела для каждого колеса. Колёса задаются через btWheelInfo, в котором описываются параметры подвески, сцепления с поверхностью и радиус.

let wheelInfo = vehicle.addWheel(
    wheelPosition,    // btVector3: позиция колеса относительно центра тела
    wheelDirection,   // btVector3: направление силы тяжести
    wheelAxle,        // btVector3: направление оси колеса
    suspensionRestLength, // длина подвески
    wheelRadius,      // радиус колеса
    tuning,           // объект btVehicleTuning
    isFrontWheel      // boolean: переднее или заднее
);

Ключевые параметры btWheelInfo:

  • m_suspensionStiffness — жесткость подвески. Большие значения делают подвеску более жёсткой.
  • m_wheelsDampingRelaxation и m_wheelsDampingCompression — демпфирование подвески при сжатии и расслаблении.
  • m_frictionSlip — коэффициент сцепления колеса с поверхностью.
  • m_rollInfluence — влияние силы крена на транспортное средство.

Связь визуального объекта и физического колеса

Визуальное колесо в Three.js или Babylon.js обычно является отдельной меш-геометрией. Оно не участвует в физике напрямую: позиция и поворот задаются на основе состояния btRaycastVehicle.

function updateWheelTransform(vehicle, wheelMeshes) {
    for (let i = 0; i < vehicle.getNumWheels(); i++) {
        let wheelTransform = vehicle.getWheelTransformWS(i);
        let origin = wheelTransform.getOrigin();
        let rotation = wheelTransform.getRotation();

        wheelMeshes[i].position.set(origin.x(), origin.y(), origin.z());
        wheelMeshes[i].quaternion.set(rotation.x(), rotation.y(), rotation.z(), rotation.w());
    }
}

Особенности синхронизации:

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

Управление колесами и движением

Движение автомобиля формируется через приложение сил и моментов к колесам. Основные методы:

  • applyEngineForce(force, wheelIndex) — прикладывает силу двигателя к конкретному колесу.
  • setBrake(brakeForce, wheelIndex) — тормозной момент.
  • setSteeringValue(steering, wheelIndex) — поворот передних колес.

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

// пример управления
vehicle.applyEngineForce(engineForce, 2); // заднее колесо
vehicle.setBrake(brakeForce, 0);          // переднее колесо
vehicle.setSteeringValue(steeringAngle, 0);

Подвеска и неровности поверхности

Реализм движения обеспечивается имитацией работы подвески. Система колес использует лучевое отслеживание (raycast), чтобы вычислить точку контакта с поверхностью. Параметры подвески влияют на:

  • амплитуду вертикальных колебаний колеса,
  • угол наклона при крене,
  • распределение веса автомобиля на оси.

Правильная настройка подвески позволяет колёсам не «врезаться» в землю и обеспечивает реалистичные отскоки при столкновениях с препятствиями.

Оптимизация производительности

Ammo.js выполняет сложные расчёты физики, поэтому при синхронизации колес важно:

  1. Обновлять только необходимые трансформации — избегать лишних вычислений в рендере.
  2. Использовать один массив для всех wheelMeshes, чтобы циклы for были минимальными.
  3. Контролировать частоту симуляции: например, выполнять физику с фиксированным шагом 1/60 секунды, а визуальное обновление можно делать с переменным FPS.

Настройка визуальной ориентации

Частая ошибка — некорректная ориентация колеса в Three.js. Для её исправления:

  • Убедиться, что ось колеса совпадает с wheelAxle при создании btWheelInfo.
  • Учесть начальный поворот меша, если модель колеса из внешнего источника имеет «неправильную» ориентацию.
  • При необходимости использовать дополнительный THREE.Object3D контейнер для корректного поворота.

Дополнительные возможности

  • Динамическая деформация колеса: можно изменять масштаб по оси подвески для имитации сжатия.
  • Анимация тормозных дисков и амортизаторов: привязывается к состоянию m_suspensionLength.
  • Эффекты скольжения и заноса: визуально реализуются через угол поворота колеса относительно направления движения (slip angle).

Синхронизация визуальных колёс с физикой в Ammo.js требует точного следования данным btRaycastVehicle и постоянного обновления их состояния в рендере. Это позволяет получить реалистичное поведение автомобиля на любой поверхности и обеспечивает плавность и правдоподобность анимации.