Масштабирование форм через setLocalScaling

В физическом движке Ammo.js, основанном на Bullet Physics, ключевым элементом при работе с объектами является форма коллизии (btCollisionShape). Масштабирование формы позволяет изменять её размер без необходимости пересоздавать сам объект. Это особенно полезно при динамическом изменении размеров игровых объектов или симуляции анимационных эффектов.

Основы setLocalScaling

Метод setLocalScaling применяется к экземплярам класса btCollisionShape. Он принимает объект типа btVector3, задающий масштаб по осям X, Y и Z:

shape.setLocalScaling(new Ammo.btVector3(scaleX, scaleY, scaleZ));
  • scaleX, scaleY, scaleZ — коэффициенты масштабирования вдоль соответствующих осей.
  • Значение 1 сохраняет исходный размер.
  • Значение меньше 1 уменьшает объект, больше 1 — увеличивает.

Масштабирование напрямую влияет на вычисление столкновений, физические границы объекта и генерацию контактных точек. Изменение масштаба после добавления объекта в мир (btDiscreteDynamicsWorld) автоматически обновляет физическую симуляцию без пересоздания rigid body, если форма поддерживает динамическое масштабирование.

Масштабирование различных типов форм

Разные формы коллизии ведут себя по-разному при масштабировании:

  1. Примитивные формы

    • btBoxShape, btSphereShape, btCylinderShape поддерживают масштабирование напрямую.

    • Пример для куба:

      let boxShape = new Ammo.btBoxShape(new Ammo.btVector3(1, 1, 1));
      boxShape.setLocalScaling(new Ammo.btVector3(2, 0.5, 1.5));

      Куб увеличится в два раза по X, уменьшится вдвое по Y и увеличится на 50% по Z.

  2. Составные формы (btCompoundShape)

    • Масштабирование влияет на все дочерние формы.

    • При использовании btCompoundShape рекомендуется применять масштаб к корневой форме:

      let compound = new Ammo.btCompoundShape();
      compound.addChildShape(transform, childShape);
      compound.setLocalScaling(new Ammo.btVector3(1.5, 1.5, 1.5));
  3. Сложные меши (btBvhTriangleMeshShape)

    • Поддержка масштабирования ограничена, так как форма основана на фиксированном триангулярном меше.
    • Для масштабирования часто используют btScaledBvhTriangleMeshShape, который оборачивает оригинальный меш с указанным масштабом.

Влияние на физику

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

let mass = 2; // кг
let localInertia = new Ammo.btVector3(0, 0, 0);
shape.calculateLocalInertia(mass, localInertia);

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

Примеры динамического масштабирования

  1. Анимация увеличения объекта

    let scale = 1;
    function animate() {
        scale += 0.01;
        boxShape.setLocalScaling(new Ammo.btVector3(scale, scale, scale));
        requestAnimationFrame(animate);
    }
    animate();
  2. Реакция на столкновение Масштабирование можно использовать для имитации деформаций при ударе:

    function onCollision() {
        let currentScale = boxShape.getLocalScaling();
        boxShape.setLocalScaling(new Ammo.btVector3(
            currentScale.x() * 0.9,
            currentScale.y() * 0.9,
            currentScale.z() * 0.9
        ));
    }

Ограничения и особенности

  • Некоторые формы, например btConvexHullShape, после масштабирования требуют пересоздания BVH (Bounding Volume Hierarchy) для корректной обработки столкновений.
  • Масштабирование не влияет на визуальный меш в рендеринге; необходимо синхронизировать визуальный объект с коллизионной формой вручную.
  • Масштабирование нельзя использовать для нулевых или отрицательных значений: это приведет к некорректной симуляции.

Рекомендации по использованию

  • Для динамических объектов предпочтительно использовать примитивные формы (btBoxShape, btSphereShape) для стабильного масштабирования.
  • Для статических сложных мешей использовать btScaledBvhTriangleMeshShape.
  • Всегда пересчитывать локальную инерцию после изменения масштаба для сохранения реалистичной динамики.
  • Хранить отдельный вектор текущего масштаба для управления анимациями и эффектами деформации.

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