Получение скорости и состояния колёс

В Ammo.js колёса обычно создаются через объект btVehicleTuning в сочетании с btRaycastVehicle. Основная идея заключается в том, что физический мир моделируется телами (btRigidBody), а колёса добавляются к этим телам с определёнными параметрами подвески, сцепления и торможения. Каждое колесо привязывается к кузову автомобиля через точку крепления, ориентацию и радиус.

Для корректной работы важно понимать, что колёса не являются отдельными физическими телами в стандартном смысле. Их движение рассчитывается через лучевой кастинг (raycast) — луч проходит от точки подвески вниз, определяя контакт с поверхностью, с помощью чего вычисляются сила и скорость колеса.

let tuning = new Ammo.btVehicleTuning();
let vehicle = new Ammo.btRaycastVehicle(tuning, chassisBody, vehicleRaycaster);
vehicle.setCoordinateSystem(0, 1, 2); // X: право, Y: вверх, Z: вперед

Получение скорости колеса

Скорость колеса в Ammo.js не является прямым свойством btWheelInfo. Для вычисления используется функция getWheelInfo(index), которая возвращает объект колеса, содержащий массивы и методы для получения текущей информации.

let wheel = vehicle.getWheelInfo(wheelIndex);
let wheelVelocity = wheel.getDeltaRotation() / timeStep * wheel.getRadius();

Ключевые моменты:

  • getDeltaRotation() возвращает вращение колеса за последний шаг симуляции.
  • Деление на timeStep даёт угловую скорость в радианах в секунду.
  • Умножение на радиус колеса переводит угловую скорость в линейную скорость на поверхности.

Дополнительно, для определения абсолютной линейной скорости колеса относительно мира можно использовать вектор:

let wheelTransform = wheel.getWorldTransform();
let velocityVector = wheelTransform.getBasis().getColumn(2).op_mul(wheelVelocity);

Здесь ось Z в локальной системе колеса соответствует направлению движения. Полученный вектор позволяет вычислять скорость движения колеса в трёхмерном пространстве.

Состояние колеса

Состояние колеса включает несколько критически важных характеристик: сжатие подвески, угол поворота, проскальзывание и контакт с поверхностью. Все они доступны через методы btWheelInfo:

  • Сжатие подвески:
let suspensionLength = wheel.getSuspensionRelativeVelocity();
let compression = wheel.getSuspensionRestLength() - suspensionLength;

getSuspensionRelativeVelocity() возвращает скорость, с которой подвеска колеса сжимается или растягивается. Разница между исходной длиной и текущей длиной подвески даёт степень сжатия.

  • Угол поворота колеса:
let steeringAngle = wheel.getSteering();

Угол задаётся в радианах и используется для расчёта направления движения колеса.

  • Присутствие контакта с поверхностью:
let isInContact = wheel.getIsInContact();

Если значение true, колесо касается поверхности, и силы сцепления применяются корректно.

  • Проскальзывание:
let lateralSlip = wheel.getSideSlip();
let longitudinalSlip = wheel.getSuspensionRelativeVelocity() - wheelVelocity;

lateralSlip отражает боковое проскальзывание, а longitudinalSlip — продольное, полезно для моделирования блокировки колёс и ABS.

Изменение параметров колеса на лету

Ammo.js позволяет динамически менять характеристики колёс в процессе симуляции. Например, изменение силы амортизации подвески или угла поворота:

wheel.setSuspensionStiffness(20);
wheel.setSteeringValue(Math.PI / 6); // 30 градусов

Также можно управлять силой торможения и ускорения:

vehicle.applyEngineForce(engineForce, wheelIndex);
vehicle.setBrake(brakeForce, wheelIndex);

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

Взаимодействие с рендером

Для визуализации колёс важно синхронизировать трансформацию колёс с их физическим состоянием. Обычно это делается путём извлечения матрицы трансформации из btWheelInfo и передачи её объекту рендера:

let wheelTransform = wheel.getWorldTransform();
let origin = wheelTransform.getOrigin();
let rotation = wheelTransform.getRotation();

threeWheel.position.set(origin.x(), origin.y(), origin.z());
threeWheel.quaternion.set(rotation.x(), rotation.y(), rotation.z(), rotation.w());

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

Оптимизация работы с колёсами

  • Вызывать getWheelInfo один раз на кадр и хранить результат, чтобы избежать многократных обращений к внутренним структурам Ammo.js.
  • Использовать setCoordinateSystem для согласования локальных осей с системой рендера.
  • Проверять контакт колеса с поверхностью перед применением сил сцепления или торможения, чтобы избежать артефактов.

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