В библиотеке Ammo.js ограничения (constraints) используются для соединения двух тел так, чтобы их движение соответствовало заданным физическим правилам. Они позволяют создавать шарниры, пружины, подвесы, тяги и сложные механизмы. Контроль за добавлением и удалением ограничений обеспечивает гибкость моделирования и позволяет динамически изменять поведение объектов в симуляции.
Ammo.js поддерживает несколько типов ограничений:
Каждое ограничение создается через соответствующий конструктор и
добавляется в мир физики
(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 — оставить столкновения, если нужно имитировать
столкновения мягких связей.Это важно при моделировании цепей, мостов и механизмов с множеством соединений.
Умелое использование добавления и удаления ограничений позволяет строить динамические сцены, где объекты могут соединяться и разъединяться в процессе симуляции, создавая реалистичное физическое поведение.