Добавление и удаление ограничений из мира

В библиотеке Ammo.js ограничения (constraints) используются для соединения двух тел так, чтобы их движение соответствовало заданным физическим правилам. Они позволяют создавать шарниры, пружины, подвесы, тяги и сложные механизмы. Контроль за добавлением и удалением ограничений обеспечивает гибкость моделирования и позволяет динамически изменять поведение объектов в симуляции.

Типы ограничений

Ammo.js поддерживает несколько типов ограничений:

  • Point-to-Point (P2P) — соединяет две точки на разных телах, сохраняя фиксированное расстояние.
  • Hinge — создает шарнирное соединение с одной осью вращения.
  • Slider — позволяет телу перемещаться вдоль одной оси с ограничением угла вращения.
  • ConeTwist — комбинирует вращение и конусное ограничение, полезно для суставов.
  • Generic6Dof — универсальное ограничение с возможностью ограничения всех шести степеней свободы (3 линейные и 3 угловые).

Каждое ограничение создается через соответствующий конструктор и добавляется в мир физики (btDiscreteDynamicsWorld) с помощью метода addConstraint.

Создание ограничений

Пример создания простого шарнирного соединения:

// Тела, которые нужно соединить
let bodyA = ...; // Ammo.btRigidBody
let bodyB = ...;

// Позиции соединения в локальных координатах тел
let pivotA = new Ammo.btVector3(0, 1, 0);
let pivotB = new Ammo.btVector3(0, -1, 0);

// Создание Point-to-Point constraint
let p2pConstraint = new Ammo.btPoint2PointConstraint(bodyA, bodyB, pivotA, pivotB);

// Добавление ограничения в мир
physicsWorld.addConstraint(p2pConstraint, true);

Ключевой момент: второй аргумент метода addConstraint (true) указывает на пользовательское смягчение реакции силы (disableCollisionsBetweenLinkedBodies). Это позволяет избежать нежелательных столкновений между соединенными телами.

Настройка параметров ограничений

После создания ограничения можно задавать параметры жесткости, пружинности и угловых ограничений:

// Пример настройки Generic6Dof
let dof = new Ammo.btGeneric6DofConstraint(bodyA, bodyB, frameA, frameB, true);

// Ограничение перемещения по оси X от -1 до 1
dof.setLinearLowerLimit(new Ammo.btVector3(-1, 0, 0));
dof.setLinearUpperLimit(new Ammo.btVector3(1, 0, 0));

// Ограничение вращения по оси Z от -45 до 45 градусов
dof.setAngularLowerLimit(new Ammo.btVector3(0, 0, -Math.PI/4));
dof.setAngularUpperLimit(new Ammo.btVector3(0, 0, Math.PI/4));

// Включение пружинности
dof.enableSpring(2, true);
dof.setStiffness(2, 10);

Примечание: Параметры должны задаваться до начала симуляции или динамически изменяться через методы setParam.

Удаление ограничений

Удаление ограничения из мира выполняется с помощью метода removeConstraint. После этого объект ограничения нужно вручную освободить из памяти, чтобы избежать утечек:

// Удаление из мира
physicsWorld.removeConstraint(p2pConstraint);

// Очистка памяти
Ammo.destroy(p2pConstraint);

Важно соблюдать порядок: сначала удаляется из мира, затем освобождается память. Если попытаться удалить объект, который еще активен в симуляции, это приведет к ошибкам.

Динамическое добавление и удаление

В сценариях реального времени часто требуется менять соединения между объектами на лету. Ammo.js позволяет безопасно добавлять и удалять ограничения в любом кадре симуляции.

if (shouldAttach) {
    physicsWorld.addConstraint(newConstraint, true);
} else {
    physicsWorld.removeConstraint(existingConstraint);
    Ammo.destroy(existingConstraint);
}

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

Управление столкновениями связанных тел

При добавлении ограничения можно указать, разрешены ли столкновения между соединенными телами. Аргумент disableCollisionsBetweenLinkedBodies в addConstraint позволяет:

  • true — отключить столкновения, что необходимо для механических систем.
  • false — оставить столкновения, если нужно имитировать столкновения мягких связей.

Это важно при моделировании цепей, мостов и механизмов с множеством соединений.

Оптимизация и рекомендации

  • Использовать Point-to-Point для простых соединений и Generic6Dof для сложных механизмов.
  • Минимизировать количество ограничений на сцену, так как каждое добавляет вычислительную нагрузку.
  • Освобождать объекты ограничений после удаления, чтобы избежать утечек памяти.
  • Настраивать параметры пружинности и жесткости, исходя из массы тел и желаемой динамики, чтобы избежать неустойчивых колебаний.

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