btHeightfieldTerrainShape: ландшафт по карте высот

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

Создание объекта btHeightfieldTerrainShape

Конструктор класса имеет следующий основной синтаксис:

new Ammo.btHeightfieldTerrainShape(
    width,                // количество точек по X
    length,               // количество точек по Z
    heightData,           // массив высот или указатель на память
    heightScale,          // масштаб высот
    minHeight,            // минимальная высота
    maxHeight,            // максимальная высота
    upAxis,               // ось "вверх" (0=X, 1=Y, 2=Z)
    heightDataType,       // тип данных (обычно Ammo.PHY_FLOAT)
    flipQuadEdges         // переворот диагоналей квадов (true/false)
)

Ключевые параметры:

  • width и length определяют сетку точек, по которой строится рельеф. Это не физические единицы, а количество элементов сетки.
  • heightData может быть представлен как Float32Array, Int16Array или прямой указатель в памяти. Тип указывается через heightDataType.
  • heightScale позволяет масштабировать высоту каждой точки, что удобно для адаптации к игровым единицам.
  • upAxis определяет, какая ось является вертикальной. Для большинства игр это 1 (ось Y).
  • flipQuadEdges влияет на то, как будут строиться треугольники внутри квадов сетки, что может улучшать стабильность физики на крутых склонах.

Подготовка данных высот

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

const width = 128;
const length = 128;
const heightData = new Float32Array(width * length);

for (let z = 0; z < length; z++) {
    for (let x = 0; x < width; x++) {
        heightData[z * width + x] = Math.sin(x * 0.1) * Math.cos(z * 0.1) * 10;
    }
}
  • Массив хранит значения в строковом порядке (row-major): сначала все значения для первой строки по X, затем для второй и т.д.
  • Высоты могут быть отрицательными, но при этом minHeight и maxHeight должны корректно отражать диапазон значений, чтобы физика не «проваливалась».

Настройка масштаба и ориентации

  • heightScale позволяет увеличивать или уменьшать высоту рельефа без изменения исходного массива.
  • setLocalScaling используется для масштабирования сетки по горизонтали и вертикали:
terrainShape.setLocalScaling(new Ammo.btVector3(1, 1, 1));
  • upAxis выбирает ось, направленную вверх. Если ось Y (1), тогда рельеф растет вдоль Y, а плоскость XZ становится горизонтальной.

Создание физического тела для ландшафта

Рельеф обычно используется как статическое тело (STATIC), чтобы объекты могли взаимодействовать с ним без движения:

const mass = 0;
const localInertia = new Ammo.btVector3(0, 0, 0);
const motionState = new Ammo.btDefaultMotionState(
    new Ammo.btTransform(
        new Ammo.btQuaternion(0, 0, 0, 1),
        new Ammo.btVector3(0, 0, 0)
    )
);
const rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, terrainShape, localInertia);
const terrainBody = new Ammo.btRigidBody(rbInfo);
physicsWorld.addRigidBody(terrainBody);
  • Масса равна нулю для неподвижного рельефа.
  • localInertia не имеет значения, так как тело статическое.
  • btDefaultMotionState позволяет задать стартовую позицию и ориентацию ландшафта.

Оптимизация производительности

  • Размер сетки влияет на производительность: слишком много точек приводит к нагрузке на физический движок.
  • Использование flipQuadEdges = true улучшает стабильность при крутых склонах.
  • Для больших карт высот можно разбивать ландшафт на секции, создавая несколько btHeightfieldTerrainShape с частями карты.

Примеры применения

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

Важные особенности

  • Ландшафт создаётся как деформационная сетка, но не поддерживает деформации на лету. Изменение высот требует пересоздания btHeightfieldTerrainShape.
  • Высоты интерполируются внутри ячеек для точных столкновений.
  • Для оптимальной работы следует учитывать масштаб игры: маленькие единицы могут привести к нестабильности при расчётах физических столкновений.

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