В Three.js сцена представлена объектом THREE.Scene, который служит корневым контейнером для всех визуальных элементов: камер, источников света, моделей, мешей и вспомогательных объектов. Каждый объект сцены является экземпляром класса THREE.Object3D или его наследников, таких как THREE.Mesh, THREE.Group, THREE.Camera, THREE.Light.
Ключевая особенность — дерево объектов: каждый объект может иметь произвольное количество дочерних объектов, формируя иерархическую структуру. Эта иерархия позволяет удобно управлять группами объектов, трансформациями и анимацией.
const scene = new THREE.Scene();
const group = new THREE.Group();
const mesh = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshStandardMaterial({ color: 0xff0000 })
);
group.add(mesh);
scene.add(group);
В этом примере mesh является дочерним объектом
group, а group — дочерним объектом
scene. Любые преобразования, применённые к
group, автоматически влияют на все её дочерние объекты.
Каждый объект в дереве имеет свойства position, rotation, scale, которые определяют его положение, ориентацию и масштаб относительно родителя. Эти свойства формируют локальную систему координат объекта.
Если объект не имеет родителя, его трансформации считаются глобальными относительно сцены. Если объект вложен, глобальное положение вычисляется с учётом всех родителей:
mesh.position.set(1, 0, 0);
group.position.set(2, 0, 0);
scene.add(group);
// Глобальная позиция mesh = (1+2, 0, 0) = (3, 0, 0)
Трансформации наследуются и при вращении: вращение родителя вращает все дочерние объекты вместе с ним.
add() и remove() — основные методы для построения и изменения иерархии:
group.add(mesh); // Добавление дочернего объекта
group.remove(mesh); // Удаление объекта из группы
Метод attach() позволяет перенести объект из одного родителя к другому с сохранением глобальной позиции:
scene.add(mesh);
group.attach(mesh); // mesh теперь дочерний объект group, позиция не изменится
Свойство children хранит массив всех дочерних объектов объекта:
console.log(group.children); // [mesh]
Свойство parent указывает на родительский объект:
console.log(mesh.parent === group); // true
THREE.Group — удобный способ объединять несколько объектов для совместных трансформаций или управления логикой. Группы могут содержать как меши, так и другие группы, создавая сложные иерархические структуры.
const solarSystem = new THREE.Group();
const earthOrbit = new THREE.Group();
const earth = new THREE.Mesh(
new THREE.SphereGeometry(1, 32, 32),
new THREE.MeshStandardMaterial({ color: 0x0000ff })
);
earthOrbit.add(earth);
solarSystem.add(earthOrbit);
scene.add(solarSystem);
В этом примере вращение earthOrbit вокруг своей оси
моделирует орбитальное движение Земли, не затрагивая положение других
планет. Такой подход позволяет легко создавать сложные механизмы и
симуляции.
Three.js предоставляет методы для рекурсивного обхода:
scene.traverse((obj) => {
console.log(obj.type, obj.name);
});
Эти методы позволяют реализовать выбор объектов, управление анимацией и обработку событий.
Методы localToWorld(vector) и worldToLocal(vector) преобразуют координаты объекта между локальной системой и системой сцены:
const localPos = new THREE.Vector3(1, 0, 0);
const globalPos = mesh.localToWorld(localPos.clone());
const convertedBack = mesh.worldToLocal(globalPos.clone());
console.log(convertedBack); // (1, 0, 0)
Эти функции особенно полезны для расчёта коллизий, физики и точного позиционирования объектов в сложных иерархиях.
Каждому объекту можно задать уникальное имя через свойство name:
mesh.name = "cube1";
const found = scene.getObjectByName("cube1");
Каждый объект также имеет уникальный идентификатор id, присваиваемый автоматически, что облегчает управление сценой при динамическом создании множества объектов.
Глубокая и сложная иерархия может влиять на производительность: обновление матриц, расчёт глобальных координат и рендеринг затрачивают больше ресурсов. Для оптимизации:
Свет и камеры также являются объектами сцены и поддерживают иерархию:
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
const light = new THREE.PointLight(0xffffff, 1);
const cameraHolder = new THREE.Group();
cameraHolder.add(camera);
cameraHolder.add(light);
scene.add(cameraHolder);
Перемещение или вращение cameraHolder одновременно
изменяет положение камеры и источника света, что упрощает настройку
сложных сцен.
Эта организация объектов и их связей позволяет строить сцены любой сложности, управлять трансформациями, анимацией и взаимодействием между объектами на высоком уровне.