ConvexPolyhedron: создание из произвольной геометрии

ConvexPolyhedron — это одна из ключевых форм в физическом движке Cannon.js, предназначенная для представления выпуклых многогранников. Она позволяет моделировать объекты сложной формы, сохраняя высокую производительность при столкновениях. Использование этой формы особенно полезно, когда стандартные геометрии (Box, Sphere, Cylinder) не подходят для точного физического представления объекта.


Основные компоненты ConvexPolyhedron

Для создания ConvexPolyhedron необходимы три базовые структуры:

  1. Вершины (vertices) Представляют собой массив объектов CANNON.Vec3, где каждая вершина задаёт координаты точки в локальной системе объекта. Пример структуры:
const vertices = [
    new CANNON.Vec3(1, 1, 1),
    new CANNON.Vec3(-1, 1, 1),
    new CANNON.Vec3(-1, -1, 1),
    new CANNON.Vec3(1, -1, 1),
    new CANNON.Vec3(1, 1, -1),
    new CANNON.Vec3(-1, 1, -1),
    new CANNON.Vec3(-1, -1, -1),
    new CANNON.Vec3(1, -1, -1)
];
  1. Грани (faces) Грани задаются массивом массивов, где каждый внутренний массив содержит индексы вершин, формирующих грань. Порядок индексов должен быть по часовой стрелке относительно наружной нормали. Пример для куба:
const faces = [
    [0, 1, 2, 3],
    [4, 5, 6, 7],
    [0, 3, 7, 4],
    [1, 2, 6, 5],
    [0, 1, 5, 4],
    [3, 2, 6, 7]
];
  1. Нормали (optional) Cannon.js может автоматически рассчитывать нормали граней, но для оптимизации и точного контроля столкновений рекомендуется явно задавать нормали как массив CANNON.Vec3, направленных наружу:
const normals = [
    new CANNON.Vec3(0, 0, 1),
    new CANNON.Vec3(0, 0, -1),
    new CANNON.Vec3(-1, 0, 0),
    new CANNON.Vec3(1, 0, 0),
    new CANNON.Vec3(0, 1, 0),
    new CANNON.Vec3(0, -1, 0)
];

Создание ConvexPolyhedron

Для инициализации объекта используется конструктор CANNON.ConvexPolyhedron, принимающий вершины, грани и необязательные нормали:

const convexShape = new CANNON.ConvexPolyhedron({
    vertices: vertices,
    faces: faces,
    normals: normals
});

Особенности и требования:

  • Все вершины должны быть уникальными и образовывать выпуклую оболочку. Если включить внутрь форму с вогнутыми углами, столкновения могут работать некорректно.
  • Порядок вершин в гранях критичен. Нарушение порядка может привести к неправильным нормалям и физическим ошибкам.
  • Форма автоматически вычисляет центроид, который используется как точка приложения массы и инерции.

Интеграция с телами (Body)

Созданную форму можно добавить в тело CANNON.Body для включения в симуляцию:

const body = new CANNON.Body({
    mass: 5,
    position: new CANNON.Vec3(0, 10, 0)
});

body.addShape(convexShape);
world.addBody(body);

Рекомендации по массе и физическим свойствам:

  • Масса должна соответствовать предполагаемой плотности объекта. Для очень сложных многогранников с большим количеством граней рекомендуется корректировать массу вручную.
  • Для динамических объектов важно правильно рассчитать инерцию, что Cannon.js делает автоматически для ConvexPolyhedron.

Создание из произвольной геометрии

ConvexPolyhedron позволяет преобразовать произвольные трехмерные модели, например экспортированные из Blender или Three.js, в физические объекты:

  1. Извлечение вершин и индексов:
const geometry = new THREE.BoxGeometry(2, 2, 2);
const vertices = geometry.attributes.position.array;
const faces = [];
for (let i = 0; i < geometry.index.count; i += 3) {
    faces.push([
        geometry.index.array[i],
        geometry.index.array[i + 1],
        geometry.index.array[i + 2]
    ]);
}
  1. Преобразование в Vec3:
const cannonVertices = [];
for (let i = 0; i < vertices.length; i += 3) {
    cannonVertices.push(new CANNON.Vec3(vertices[i], vertices[i + 1], vertices[i + 2]));
}
  1. Инициализация ConvexPolyhedron:
const convexShape = new CANNON.ConvexPolyhedron({
    vertices: cannonVertices,
    faces: faces
});

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


Оптимизация и практические советы

  • Для моделей с очень большим числом граней рекомендуется предварительно упрощать геометрию, чтобы не перегружать движок.
  • Для сложных форм, где вычисление нормалей вручную затруднительно, можно использовать библиотеку QuickHull для генерации выпуклой оболочки и нормалей.
  • Конструктор ConvexPolyhedron поддерживает updateNormals() и computeEdges(), что позволяет корректно пересчитывать параметры при изменении вершин на лету.

Работа с столкновениями

  • ConvexPolyhedron корректно работает с другими формами Cannon.js, включая Box, Sphere, Plane и Compound.
  • Точность столкновений зависит от выпуклости и ориентации граней. В сложных моделях рекомендуется проверять симуляцию на пересечения и глубину проникновения.
  • Для динамических объектов с вращением необходимо учитывать момент инерции, который вычисляется автоматически на основе вершин, но может быть корректирован вручную для оптимизации поведения.

ConvexPolyhedron открывает широкие возможности для точного моделирования физики объектов любой формы, объединяя гибкость произвольной геометрии с высокой производительностью движка Cannon.js. Его интеграция с динамическими телами и возможность создавать формы из внешних 3D-моделей делают его незаменимым инструментом для продвинутой физической симуляции.