В библиотеке Three.js геометрии являются объектами,
описывающими форму 3D-модели через вершины, грани, нормали и
UV-координаты. Иногда возникает необходимость создавать точные копии
существующих геометрий для многократного использования, не изменяя
исходный объект. Для этого используется метод
clone(), который создаёт глубокую копию
объекта геометрии, включая все её атрибуты.
const boxGeometry = new THREE.BoxGeometry(1, 1, 1);
const clonedGeometry = boxGeometry.clone();
Важный момент: клонированная геометрия полностью независима от
оригинала. Любые изменения в
clonedGeometry не повлияют на
boxGeometry.
Для поверхностного копирования, когда требуется лишь дублировать
ссылку на объект без копирования всех данных, используется
copy():
const copiedGeometry = new THREE.BufferGeometry().copy(boxGeometry);
Разница между clone() и copy() заключается
в том, что clone() создаёт новый объект с собственными
внутренними массивами данных, тогда как copy() позволяет
заменить содержимое уже существующего объекта.
Слияние геометрий используется для уменьшения количества отрисовываемых объектов и оптимизации производительности. Вместо рендеринга нескольких отдельных мешей можно объединить их в одну геометрию.
BufferGeometryUtils.mergeBufferGeometriesThree.js предоставляет утилиту
BufferGeometryUtils, включающую функцию
mergeBufferGeometries, которая принимает
массив геометрий и возвращает одну объединённую:
import { BufferGeometryUtils } from 'three/examples/jsm/utils/BufferGeometryUtils.js';
const sphere = new THREE.SphereGeometry(0.5, 16, 16);
const box = new THREE.BoxGeometry(1, 1, 1);
const merged = BufferGeometryUtils.mergeBufferGeometries([sphere, box], false);
Второй параметр (false) указывает, что индексы не должны
быть пересозданы для оптимизации. Если геометрии имеют общие атрибуты и
индексы, их можно объединять с true, чтобы избежать
дублирования вершин.
Особенности объединения:
BufferGeometry. Классические
Geometry больше не поддерживаются в
последних версиях Three.js.MeshFaceMaterial или используется массив
материалов.Перед объединением часто нужно преобразовать геометрии: переместить,
повернуть или масштабировать. Для этого используется метод
applyMatrix4(), позволяющий применить
матрицу преобразования к геометрии:
const translationMatrix = new THREE.Matrix4().makeTranslation(2, 0, 0);
box.applyMatrix4(translationMatrix);
const mergedWithTransform = BufferGeometryUtils.mergeBufferGeometries([sphere, box], false);
Каждая геометрия сохраняет свои координаты в глобальном пространстве перед слиянием. Это особенно важно при создании сцен с множеством объектов на разных позициях.
BufferGeometry хранит данные в виде атрибутов
(position, normal, uv и других).
При клонировании создаётся копия всех массивов, но при слиянии массивы
атрибутов необходимо правильно конкатенировать.
Пример ручного объединения двух геометрий с учётом атрибутов:
const geometry1 = new THREE.BoxGeometry(1, 1, 1);
const geometry2 = new THREE.SphereGeometry(0.5, 16, 16);
// Получение атрибутов
const pos1 = geometry1.attributes.position.array;
const pos2 = geometry2.attributes.position.array;
// Создание нового Float32Array
const mergedPos = new Float32Array(pos1.length + pos2.length);
mergedPos.set(pos1);
mergedPos.set(pos2, pos1.length);
// Создание новой геометрии
const mergedGeometry = new THREE.BufferGeometry();
mergedGeometry.setAttribute('position', new THREE.BufferAttribute(mergedPos, 3));
Этот способ позволяет полностью контролировать процесс объединения, добавлять или модифицировать дополнительные атрибуты (например, цвета или веса вершин).
Клонирование геометрии часто используется вместе с клонированием Mesh:
const mesh = new THREE.Mesh(boxGeometry, new THREE.MeshStandardMaterial({ color: 0xff0000 }));
const clonedMesh = mesh.clone();
clonedMesh.position.set(2, 0, 0);
scene.add(clonedMesh);
Метод clone() для Mesh не только
клонирует геометрию, но и материалы. При необходимости можно создать
отдельный материал для клона:
const clonedMesh = mesh.clone();
clonedMesh.material = mesh.material.clone();
Это гарантирует независимое управление визуальными свойствами каждого экземпляра.
InstancedMesh, что
эффективнее с точки зрения GPU, чем постоянное клонирование и слияние
геометрий.Создание большого ландшафта из блоков Используется слияние геометрий блоков в один объект для снижения количества draw calls.
Многократное использование одного объекта Клонирование позволяет создать копии одного меша с различными позициями и ориентациями.
Оптимизация статических сцен Несколько статичных элементов объединяются в одну геометрию, улучшая производительность WebGL.
Эти приёмы обеспечивают гибкость и эффективность при работе с 3D-сценами, особенно в проектах с большим количеством объектов.