btStaticPlaneShape: бесконечная плоскость

btStaticPlaneShape — это специализированная форма коллизии в библиотеке Ammo.js, предназначенная для представления бесконечных плоскостей. Она используется для моделирования пола, стен или любых других поверхностей, которые не подвержены динамическим воздействиям и остаются статичными в симуляции. Ключевым преимуществом btStaticPlaneShape является высокая производительность, так как она не требует сложных вычислений столкновений с другими телами за пределами простой проверки проекции точек на плоскость.


Создание btStaticPlaneShape

Конструктор btStaticPlaneShape принимает два аргумента:

let planeShape = new Ammo.btStaticPlaneShape(new Ammo.btVector3(nx, ny, nz), constant);
  • btVector3(nx, ny, nz) — нормаль плоскости. Определяет направление, “в какую сторону” ориентирована плоскость. Вектор должен быть нормализован.
  • constant — смещение плоскости вдоль её нормали относительно начала координат. Плоскость будет находиться на расстоянии constant от точки (0,0,0) в направлении нормали.

Пример создания горизонтальной плоскости на уровне y = 0:

let groundShape = new Ammo.btStaticPlaneShape(new Ammo.btVector3(0, 1, 0), 0);

Здесь нормаль (0,1,0) указывает вверх по оси Y, а смещение равно нулю, что соответствует стандартному уровню пола.


Свойства btStaticPlaneShape

  1. Не динамическая: плоскость не реагирует на силы, импульсы или столкновения. Она всегда остаётся в фиксированном положении.
  2. Бесконечность: поверхность плоскости не имеет ограничений по размеру, что устраняет необходимость создавать огромные геометрии для пола.
  3. Оптимизация столкновений: столкновения вычисляются через проекцию точки объекта на плоскость, что минимизирует нагрузку на физический движок.

Использование btStaticPlaneShape в мире Ammo.js

Для добавления плоскости в физический мир необходимо создать rigid body с нулевой массой, так как масса определяет подвижность тела:

let groundMass = 0; 
let groundTransform = new Ammo.btTransform();
groundTransform.setIdentity();
groundTransform.setOrigin(new Ammo.btVector3(0, 0, 0));

let motionState = new Ammo.btDefaultMotionState(groundTransform);
let localInertia = new Ammo.btVector3(0, 0, 0);

let rbInfo = new Ammo.btRigidBodyConstructionInfo(groundMass, motionState, groundShape, localInertia);
let groundBody = new Ammo.btRigidBody(rbInfo);

physicsWorld.addRigidBody(groundBody);

Объяснение ключевых моментов:

  • Масса равна нулю делает тело статическим.
  • btDefaultMotionState управляет трансформацией объекта в мире.
  • localInertia для статических тел всегда равна нулю, так как вращательная динамика не применяется.
  • addRigidBody добавляет тело в физический мир для расчёта столкновений.

Взаимодействие с динамическими объектами

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

Пример падения сферы на плоскость:

let sphereShape = new Ammo.btSphereShape(1);
let sphereMass = 1;
let sphereTransform = new Ammo.btTransform();
sphereTransform.setIdentity();
sphereTransform.setOrigin(new Ammo.btVector3(0, 10, 0));

let sphereMotionState = new Ammo.btDefaultMotionState(sphereTransform);
let sphereInertia = new Ammo.btVector3(0, 0, 0);
sphereShape.calculateLocalInertia(sphereMass, sphereInertia);

let sphereRbInfo = new Ammo.btRigidBodyConstructionInfo(sphereMass, sphereMotionState, sphereShape, sphereInertia);
let sphereBody = new Ammo.btRigidBody(sphereRbInfo);

physicsWorld.addRigidBody(sphereBody);

В этом примере сфера падает под действием силы тяжести и корректно сталкивается с плоскостью, демонстрируя реалистичное поведение.


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

  • Нет поддержки наклонных коллизий для сложных рельефов: btStaticPlaneShape всегда плоская и бесконечная. Для рельефа или неровной поверхности следует использовать btBvhTriangleMeshShape или btHeightfieldTerrainShape.
  • Ограниченная визуализация: плоскость физически бесконечна, но визуально её необходимо представлять в виде плоской сетки или другой геометрии в рендере.
  • Только статическая геометрия: нельзя динамически изменять смещение или нормаль без пересоздания shape.

Методы btStaticPlaneShape

  • getPlaneConstant() — возвращает текущее смещение плоскости.
  • getPlaneNormal() — возвращает нормаль плоскости в виде btVector3.
  • setLocalScaling(vector) — позволяет масштабировать плоскость для визуализации, но физическая бесконечность сохраняется.

Пример получения нормали и смещения:

let normal = groundShape.getPlaneNormal();
let constant = groundShape.getPlaneConstant();
console.log(normal.x(), normal.y(), normal.z(), constant);

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

  • Использовать btStaticPlaneShape для полов, потолков и больших стен, где не требуется точная геометрическая детализация.
  • Для динамических платформ или наклонных поверхностей создавать отдельные rigid body с треугольной сеткой или другими collision shapes.
  • При симуляции большого количества объектов btStaticPlaneShape минимизирует нагрузку на движок и предотвращает артефакты проникновения через поверхность.

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