Взаимодействие мягких и твёрдых тел

Ammo.js представляет собой JavaScript-порт библиотеки Bullet Physics и предоставляет полноценный физический движок для работы с жёсткими и мягкими телами. Взаимодействие мягких тел (soft bodies) с твёрдыми объектами (rigid bodies) требует понимания нескольких ключевых принципов: структуры данных, интеграции симуляции и обработки коллизий.


Мягкие тела: структура и свойства

Мягкое тело в Ammo.js создаётся как сетчатая структура узлов (nodes), соединённых между собой связями (links). Основные параметры, влияющие на физику мягкого тела:

  • Масса узла (mass) — определяет инерцию и сопротивление движения.
  • Коэффициент демпфирования (damping) — уменьшает скорость колебаний.
  • Жёсткость (stiffness) — влияет на сопротивление деформации.
  • Плотность (density) — задаёт распределение массы по узлам.
  • Параметры сглаживания (pose matching, bending constraints) — обеспечивают стабильность формы при столкновениях.

Создание мягкого тела через Ammo.js выглядит так:

const softBodyHelpers = new Ammo.btSoftBodyHelpers();
const softBody = softBodyHelpers.CreateFromTriMesh(
    physicsWorld.getWorldInfo(),
    vertices, indices, indices.length / 3, true
);
softBody.get_m_cfg().set_viterations(40);
softBody.get_m_cfg().set_piterations(40);
softBody.setTotalMass(1, false);
physicsWorld.addSoftBody(softBody, 1, -1);

Ключевой момент: viterations и piterations отвечают за точность расчёта вершин и связей соответственно. Увеличение этих параметров повышает стабильность симуляции, но снижает производительность.


Твёрдые тела: основы взаимодействия

Твёрдые тела в Ammo.js создаются через btRigidBody и обладают свойствами:

  • Масса (mass) — определяет подверженность внешним силам.
  • Форма (shape) — коллизионная геометрия, например btBoxShape, btSphereShape.
  • Коэффициент трения и упругости (friction, restitution) — влияют на взаимодействие с другими объектами.
const boxShape = new Ammo.btBoxShape(new Ammo.btVector3(1,1,1));
const transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin(new Ammo.btVector3(0,5,0));
const motionState = new Ammo.btDefaultMotionState(transform);
const localInertia = new Ammo.btVector3(0,0,0);
boxShape.calculateLocalInertia(1, localInertia);
const rigidBodyInfo = new Ammo.btRigidBodyConstructionInfo(1, motionState, boxShape, localInertia);
const rigidBody = new Ammo.btRigidBody(rigidBodyInfo);
physicsWorld.addRigidBody(rigidBody);

Настройка взаимодействия мягких и твёрдых тел

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

  1. Регистрация коллизий

Мягкие тела имеют типы коллизий, которые определяются через конфигурацию softBody.get_m_cfg(). Для взаимодействия с твёрдыми телами нужно установить флаги:

softBody.get_m_cfg().set_collisions(
    Ammo.btSoftBodyConfig.SDF_RS + Ammo.btSoftBodyConfig.CL_SS
);
  • SDF_RS — столкновение мягкого тела с твёрдым телом.
  • CL_SS — внутренние столкновения мягкого тела (самосоприкосновение).
  1. Влияние твёрдого тела на мягкое

Твёрдые тела могут деформировать мягкие при контакте, если соблюдаются следующие условия:

  • Мягкое тело имеет достаточную жёсткость связей (stiffness).
  • Масса мягкого тела соизмерима с массой твёрдого объекта.
  • Настроено адекватное демпфирование, чтобы избежать чрезмерного колебания.
  1. Влияние мягкого тела на твёрдое

Для того чтобы мягкое тело могло толкать твёрдое, необходимо:

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

Тонкая настройка симуляции

Стабильность — основной вызов при взаимодействии мягких и твёрдых тел. Рекомендации:

  • Увеличение итераций: viterations и piterations для мягких тел.
  • Снижение массы твёрдого тела для чувствительных столкновений.
  • Использование сглаживания позы (pose matching): уменьшает разрывы и искажения сетки.
  • Разделение шагов симуляции: интеграция мягких тел с меньшим временным шагом, чем твёрдые, повышает точность.

Пример пошаговой интеграции:

const deltaTime = 1/60;
physicsWorld.stepSimulation(deltaTime, 10);
softBody.setTotalMass(softBodyMass, false);

Практические сценарии использования

  • Тканевые объекты: флаги, покрывала, одежда, реагирующие на падение предметов.
  • Мешковины и жидкости: грубое моделирование твёрдых гранул в мягкой оболочке.
  • Деформация при столкновении: мягкая поверхность реагирует на вес или движение твёрдого тела, создавая реалистичный визуальный эффект.

Взаимодействие с визуализацией

Для отображения симуляции важно синхронизировать позиции узлов мягкого тела с мешем в Three.js или другом рендерере. Пример обновления вершин:

const nodes = softBody.get_m_nodes();
for (let i = 0; i < nodes.size(); i++) {
    const node = nodes.at(i);
    const pos = node.get_m_x();
    mesh.geometry.attributes.position.setXYZ(i, pos.x(), pos.y(), pos.z());
}
mesh.geometry.attributes.position.needsUpdate = true;

Своевременная синхронизация обеспечивает плавное отображение деформаций, отражающих физическое взаимодействие с твёрдыми объектами.


Особенности производительности

  • Сложные мягкие тела с большим числом узлов требуют значительных ресурсов.
  • Оптимизация через уменьшение количества узлов, настройку iterations, отключение внутренних столкновений (CL_SS) при необходимости.
  • Использование уровней детализации для визуализации: простая сетка для расчёта физики и более детализированная для рендера.

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