Телепортация тела: сброс скоростей при перемещении

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

Линейная и угловая скорость

Каждое тело в Oimo.js хранит два ключевых вектора движения:

  • Линейная скорость (linearVelocity) — вектор скорости перемещения тела в пространстве.
  • Угловая скорость (angularVelocity) — вектор вращения, задающий скорость изменения ориентации тела.

При телепортации тела эти векторы продолжают влиять на его поведение. Например, если объект имел скорость и его позиция мгновенно изменена, при следующем шаге симуляции тело продолжит двигаться с прежней скоростью, что может привести к “выстрелу” тела через другие объекты или некорректным столкновениям.

Методы сброса скоростей

Для корректной телепортации важно обнулить скорости тела сразу после изменения позиции. В Oimo.js это делается напрямую через свойства объекта тела:

body.position.set(x, y, z);  // Новая позиция
body.linearVelocity.set(0, 0, 0);  // Сброс линейной скорости
body.angularVelocity.set(0, 0, 0); // Сброс угловой скорости
  • position.set(x, y, z) — мгновенное перемещение тела в указанные координаты.
  • linearVelocity.set(0, 0, 0) — предотвращает сохранение предыдущей инерции.
  • angularVelocity.set(0, 0, 0) — останавливает вращение тела, обеспечивая стабильность после телепортации.

Влияние на столкновения

Сброс скоростей при телепортации предотвращает непредсказуемые реакции физического движка:

  1. Тела не “пролетают” сквозь другие объекты.
  2. Не возникает накопления импульсов, ведущего к нестабильности симуляции.
  3. Упрощается контроль за положением объекта без необходимости модифицировать силы или массы.

Важно учитывать, что мгновенное перемещение тел может вызвать пересечение с другими объектами. Oimo.js не решает коллизии для тел, которые уже находятся в перекрытии после телепортации. Поэтому иногда рекомендуется:

  • Использовать пошаговую телепортацию, постепенно смещая объект по маленьким шагам, или
  • Проверять свободное пространство перед установкой новой позиции, предотвращая проникновение тела в другие объекты.

Пример комплексной телепортации

function teleportBody(body, newPosition) {
    // Сброс скоростей перед перемещением
    body.linearVelocity.set(0, 0, 0);
    body.angularVelocity.set(0, 0, 0);

    // Перемещение тела
    body.position.copy(newPosition);

    // Обновление матриц и буферов физики
    body.awake();  // активирует тело, если оно было в состоянии покоя
}
  • Метод awake() гарантирует, что тело будет участвовать в следующем шаге симуляции, даже если оно находилось в спящем состоянии.
  • Использование copy() вместо прямого присваивания позволяет избежать ошибок с ссылками на векторы.

Практические рекомендации

  • Сброс скоростей обязателен при телепортации динамических объектов, особенно если они участвуют в столкновениях.
  • Для статических тел сброс linearVelocity и angularVelocity не обязателен, но может быть полезен при переводе объекта в динамическое состояние.
  • Всегда проверять положение после телепортации, чтобы избежать пересечений с другими телами, особенно при плотных сценах или высоких скоростях.

Итоговые принципы

  1. Сначала сбросить скорости, потом перемещать тело.
  2. Использовать awake() для активации тела после перемещения.
  3. Проверять пересечение с другими объектами, чтобы избежать нежелательных коллизий.

Эти шаги обеспечивают предсказуемое поведение объектов в Oimo.js при телепортации и позволяют реализовать точное управление позиционированием без нарушения физической симуляции.