btSoftRigidDynamicsWorld вместо btDiscreteDynamicsWorld

btSoftRigidDynamicsWorld — это расширение стандартного физического мира в Ammo.js, предназначенное для одновременной работы с твёрдыми и мягкими телами. В отличие от btDiscreteDynamicsWorld, которое оперирует только жёсткими телами, btSoftRigidDynamicsWorld интегрирует симуляцию мягких тел (soft bodies) с полной обработкой столкновений и взаимодействий с твёрдыми объектами.

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


Создание мира

Для создания мира с мягкими телами необходима особая последовательность инициализации:

const collisionConfiguration = new Ammo.btSoftBodyRigidBodyCollisionConfiguration();
const dispatcher = new Ammo.btCollisionDispatcher(collisionConfiguration);
const broadphase = new Ammo.btDbvtBroadphase();
const solver = new Ammo.btSequentialImpulseConstraintSolver();
const softBodySolver = new Ammo.btDefaultSoftBodySolver();

const dynamicsWorld = new Ammo.btSoftRigidDynamicsWorld(
    dispatcher,
    broadphase,
    solver,
    collisionConfiguration,
    softBodySolver
);

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

  • btSoftBodyRigidBodyCollisionConfiguration — настройка коллизий, поддерживающая мягкие тела.
  • btCollisionDispatcher — управляет обнаружением и обработкой столкновений.
  • btDbvtBroadphase — эффективный алгоритм широкого фазного обнаружения столкновений.
  • btSequentialImpulseConstraintSolver — решает ограничения между объектами.
  • btDefaultSoftBodySolver — специализированный solver для мягких тел, учитывающий внутренние силы деформации.

После создания мира важно установить гравитацию:

dynamicsWorld.setGravity(new Ammo.btVector3(0, -9.81, 0));
dynamicsWorld.getWorldInfo().set_m_gravity(new Ammo.btVector3(0, -9.81, 0));

getWorldInfo() возвращает объект btSoftBodyWorldInfo, который управляет параметрами мягких тел, включая гравитацию, аэродинамику и условия коллизий.


Добавление твёрдых тел

Добавление твёрдых тел в btSoftRigidDynamicsWorld аналогично btDiscreteDynamicsWorld:

const shape = new Ammo.btBoxShape(new Ammo.btVector3(1, 1, 1));
const mass = 1;
const localInertia = new Ammo.btVector3(0, 0, 0);
shape.calculateLocalInertia(mass, localInertia);

const transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin(new Ammo.btVector3(0, 10, 0));

const motionState = new Ammo.btDefaultMotionState(transform);
const rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, shape, localInertia);
const body = new Ammo.btRigidBody(rbInfo);

dynamicsWorld.addRigidBody(body);

Особенности:

  • Масса 0 создаёт статическое тело.
  • Твёрдые тела взаимодействуют с мягкими телами через стандартные коллизии.
  • Взаимодействие можно детально настраивать через группы и маски столкновений.

Создание мягких тел

Мягкие тела в Ammo.js представлены классом btSoftBody. Основные методы создания включают сетку узлов (nodes) или готовые формы, такие как ткань:

const softBodyHelpers = new Ammo.btSoftBodyHelpers();
const corner1 = new Ammo.btVector3(-5, 5, -5);
const corner2 = new Ammo.btVector3(5, 5, 5);
const resolution = 10;

const softBody = softBodyHelpers.CreatePatch(
    dynamicsWorld.getWorldInfo(),
    corner1,
    corner2,
    0, // fixed corners (0 = все подвижные)
    true // generate diagonals
);

Параметры и свойства мягких тел:

  • setTotalMass(mass, fromFaces) — распределяет массу по узлам.
  • get_m_nodes() — доступ к массиву узлов для прямого изменения позиции или скорости.
  • setVelocity() — установка начальной скорости мягкого тела.
  • setPose() — начальная конфигурация для «вытянутых» или «скрученных» форм.

Мягкие тела поддерживают:

  • Внутренние силы упругости (kLST, kAST)
  • Вязкие и аэродинамические силы (kDP, kDG)
  • Ограничения на колени, границы и привязку к точкам

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

btSoftRigidDynamicsWorld позволяет мягким телам реагировать на твёрдые объекты:

softBody.get_m_cfg().set_kDF(0.5); // damping
softBody.get_m_cfg().set_kDP(0.01); // pressure
softBody.get_m_cfg().set_kPR(250); // pose matching
softBody.get_m_cfg().set_kVC(0.9); // volume conservation

Важные моменты:

  • set_kDF контролирует внутреннее затухание, предотвращая чрезмерные колебания.
  • set_kDP регулирует давление внутри мягкого тела, влияя на его упругость.
  • Мягкие тела могут быть прикреплены к твёрдым через appendAnchor:
softBody.appendAnchor(nodeIndex, rigidBody, false, 1.0);

Обновление мира

Обновление физического мира происходит через метод stepSimulation:

const deltaTime = 1 / 60;
dynamicsWorld.stepSimulation(deltaTime, 10);

Параметры:

  • deltaTime — шаг времени.
  • maxSubSteps — максимальное число внутренних шагов для стабилизации симуляции.

Мягкие тела автоматически обновляют свои узлы. Для получения позиций можно использовать:

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();
}

Настройка WorldInfo для мягких тел

btSoftBodyWorldInfo хранит глобальные параметры для всех мягких тел:

  • m_gravity — вектор гравитации.
  • m_sparsesdf — оптимизация столкновений.
  • air_density, water_density — параметры среды для аэродинамики.
  • m_maxDisplacement — ограничение на деформацию узлов за шаг симуляции.

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


Особенности оптимизации

  • Использование btDbvtBroadphase ускоряет обнаружение столкновений для больших сцен.
  • Разделение solver’ов для мягких и твёрдых тел повышает стабильность симуляции.
  • Ограничение числа узлов в мягких телах снижает нагрузку на CPU.
  • Настройка maxSubSteps и fixedTimeStep позволяет балансировать точность и производительность.

btSoftRigidDynamicsWorld обеспечивает комплексное решение для симуляций, где требуется совместная работа твёрдых и мягких тел, с гибкой настройкой параметров коллизий, упругости и аэродинамики.