Three.js
April 29, 2022

Геометрия

Перед тем как начать:

В предыдущем уроке мы разобрались с тем, как работать с изменением размера экрана и полноэкранным режимом в three.js. Если ты это пропустил, то советую вернуться!

До сих пор для создания нашего куба мы использовали только класс BoxGeometry. В этом уроке мы познакомимся с другими геометриями, но сначала нам нужно понять, что такое геометрия на самом деле.

Что такое геометрия?

В Three.js , геометрия состоит из вершин (координаты точек в 3D-пространствах) и граней (треугольников, которые соединяют эти вершины для создания поверхности).

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

Мы можем хранить больше данных, чем положение вершин, например можно хранить еще UV координаты или нормали. Как вы увидите, позже мы узнаем о них больше.

Различные встроенные геометрии

Three.js имеет множество встроенных геометрий. Хотя вам не нужно точно знать, как создать экземпляр каждого из них, полезно знать, что они существуют.

Все встроенные геометрии, которые мы увидем, наследуются от класса BufferGeometry. Этот класс имеет множество встроенных методов, таких как translate(...), rotate(...), normalize() и т.д. Но мы не собираемся использовать их в этом уроке.

На большинстве страниц документации по геометрии есть примеры.

  • BoxGeometry Чтобы создать куб или параллелограмм
  • CircleGeometry Чтобы создать диск или кусок диска (что-то вроде кусочка торта)
  • PlaneGeometry Чтобы создать прямоугольную плоскость
  • ConeGeometry Чтобы создать конус или часть конуса
  • RingGeometry Чтобы создать плоское кольцо или часть плоского круга
  • TorusGeometry Чтобы создать кольцо, которое имеет толщину (как пончик) или часть кольца.
  • TetrahedronGeometry Чтобы создать сферу с 4 гранями (это не будет большой сферой, если вы не увеличите детали)
  • IcosahedronGeometry Чтобы создать сферу, состоящую из треугольников примерно одинакового размера
  • SphereGeometry Чтобы создать самый популярный тип сферы, грани которой выглядят как квадратики (квадратики - это просто комбинация двух треугольников).
  • ShapeGeometry Чтобы создать фигуру на основе контура
  • TubeGeometry Чтобы создать трубу, следующую по траектории
  • LatheGeometry Чтобы создать вазу или часть вазы
  • TextGeometry Чтобы создать 3D-текст. Вам нужно будет указать шрифт в формате typeface json.

Если вам нужна определенная геометрия, которая не поддерживается Three.js , вы можете создать свою собственную геометрию в JavaScript, или вы можете создать ее в 3D-программном обеспечении (например Blender) , экспортировать и импортировать в свой проект. Мы узнаем больше об этом немного позже.

Разберем Box получше

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

BoxGeometry имеет 6 параметров:

  • width: размер по оси x
  • height: размер по оси y
  • depth: размер по оси z
  • widthSegments: Сколько разбиений на оси x
  • heightSegments: Сколько разбиений на оси y
  • depthSegments: Сколько разбиений на оси z

Разбиения соответствуют тому, сколько треугольников должно составлять грань. По умолчанию это значение равно 1, что означает, что на каждой грани будет только 2 треугольника. Если вы установите деление на 2, то в итоге получите 8 треугольников на грань:

const geometry = new THREE.BoxGeometry(1, 1, 1, 2, 2, 2);

Как вы можете видеть, существует 8 треугольников по граням.

Хотя это не относится к кубу с плоской гранью, это становится более интересным при использовании SphereGeometry:

const geometry = new THREE.SphereGeometry(1, 16, 16);

Имейте в виду, что слишком много вершин и граней повлияет на производительность!

Создание собственного буфера геометрии

Иногда нам нужно создавать собственные геометрии. Если геометрия очень сложная или имеет точную форму, лучше создать ее в 3D-программном обеспечении (и мы рассмотрим это дальше), но если геометрия не слишком сложная, мы можем построить ее самостоятельно, используя BufferGeometry.

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

const geometry = new THREE.BufferGeometry();

Чтобы добавить вершины в BufferGeometry, вы должны начать с Float32Array.

Float32Array - это нативный типизированный JavaScript массив. Вы можете хранить только значения с плавающей точкой внутри, и длина этого массива фиксирована.

Чтобы создать Float32Array, вы можете указать его длину, а затем заполнить его позже:

const positionsArray = new Float32Array(9)

// Первая вершина
positionsArray[0] = 0;
positionsArray[1] = 0;
positionsArray[2] = 0;

// Вторая вершина
positionsArray[3] = 0;
positionsArray[4] = 1;
positionsArray[5] = 0;

// Третья вершина
positionsArray[6] = 1;
positionsArray[7] = 0;
positionsArray[8] = 0;

Или вы можете передать массив:

const positionsArray = new Float32Array([
    0, 0, 0, // Первая вершина
    0, 1, 0, // Вторая вершина
    1, 0, 0  // Третья вершина
]);

Как вы можете видеть, координаты вершин задаются линейно. Массив представляет собой одномерный массив, в котором вы указываете x, y и z первой вершины, за которыми следуют x, y и z второй вершины и так далее.

Прежде чем вы сможете отправить этот массив в BufferGeometry, вы должны преобразовать его в BufferAttribute.

Первый параметр соответствует вашему типизированному массиву, а второй параметр соответствует тому, сколько значений составляет один атрибут вершины. Как мы видели ранее, чтобы прочитать этот массив, мы должны перейти 3 на 3, потому что позиция вершины состоит из 3 значений (x, y и z):

const positionsAttribute = new THREE.BufferAttribute(positionsArray, 3);

Затем мы можем добавить этот атрибут в наш BufferGeometry, используя метод setAttribute(...). Первый параметр - это имя этого атрибута, а второй параметр - значение:

geometry.setAttribute('position', positionsAttribute);

Мы выбрали "position" в качестве названия, потому что внутренние шейдеры Three.js будут искать это значение для позиционирования вершин. Подробнее об этом мы поговорим в уроке про шейдеры.

Грани будут автоматически созданы в соответствии с порядком расположения вершин.

Все вместе:

//  Создаем пустой BufferGeometry
const geometry = new THREE.BufferGeometry();

// Создаем Float32Array, который содержит координаты вершин
const positionsArray = new Float32Array([
    0, 0, 0, // Первая вершина
    0, 1, 0, // Вторая вершина
    1, 0, 0  // Третья вершина
]);

//Создаем атрибут и называем его 'position'
const positionsAttribute = new THREE.BufferAttribute(positionsArray, 3);
geometry.setAttribute('position', positionsAttribute);

Вот что у нас получилось:

Мы также можем создать кучу случайных треугольников:

const geometry = new THREE.BufferGeometry();

// Создаем 50 треугольников (450 значений)
const count = 50;
const positionsArray = new Float32Array(count * 3 * 3);
for (let i = 0; i < count * 3 * 3; i++) {
    positionsArray[i] = (Math.random() - 0.5) * 4;
}

const positionsAttribute = new THREE.BufferAttribute(positionsArray, 3);
geometry.setAttribute('position', positionsAttribute);

Единственной трудностью может быть часть count * 3 * 3, но это довольно просто объяснить: нам нужно 50 треугольников. Каждый треугольник состоит из 3 вершин, и каждая вершина состоит из 3 значений (x, y и z).

На этом сегодня все, надеюсь вам это было полезно!

🤖 Чтобы не пропустить новые уроки подпишись на телеграм канал!

🚀 Код для данного урока вы можете найти тут.

Дебаг приложения ->