Доступ к объекту Three.js через el.object3D

В A-Frame каждая сущность (<a-entity>) представляет собой обёртку над объектом Three.js. Основной способ взаимодействия с низкоуровневыми объектами сцены Three.js осуществляется через свойство object3D. Оно позволяет напрямую манипулировать геометрией, материалами, позициями, поворотами и другими свойствами объектов 3D-графики.


Структура object3D

Каждый элемент A-Frame содержит несколько ключевых объектов Three.js в object3D:

  • object3D – основной объект типа THREE.Object3D, представляющий сущность.

  • object3DMap – объект, хранящий разные версии визуальных представлений:

    • mesh – геометрия с материалами (THREE.Mesh) для рендеринга.
    • collision – объект для физического взаимодействия, если подключены системы физики.
    • camera – объект камеры (THREE.Camera), если элемент является камерой.
    • light – объект освещения (THREE.Light), если элемент — источник света.

Пример доступа к основному мешу:

const entity = document.querySelector('#myBox');
const mesh = entity.object3DMap.mesh;
mesh.position.set(1, 2, 3);
mesh.rotation.y = Math.PI / 4;

Если object3DMap.mesh отсутствует (например, объект ещё не создан), можно использовать общий объект object3D, который всегда присутствует:

entity.object3D.position.set(0, 1, -5);

Модификация позиции, поворота и масштаба

object3D использует стандартные методы Three.js:

  • Позиция: object3D.position.set(x, y, z) или object3D.position.x += 1.
  • Поворот: object3D.rotation.set(x, y, z) в радианах.
  • Масштаб: object3D.scale.set(sx, sy, sz).

Пример динамического изменения позиции с анимацией:

AFRAME.registerComponent('move-up', {
  tick: function (time, timeDelta) {
    this.el.object3D.position.y += 0.001 * timeDelta;
  }
});

Работа с материалами и геометрией

Через object3DMap.mesh.material можно менять цвет, текстуру, прозрачность:

const mesh = document.querySelector('#mySphere').object3DMap.mesh;
mesh.material.color.set(0xff0000);
mesh.material.transparent = true;
mesh.material.opacity = 0.5;

Изменение геометрии требует создания нового объекта THREE.Geometry или THREE.BufferGeometry:

const mesh = document.querySelector('#myBox').object3DMap.mesh;
mesh.geometry = new THREE.BoxGeometry(2, 2, 2);

Добавление дочерних объектов

Через object3D можно создавать сложные иерархии:

const parent = document.querySelector('#parentEntity');
const child = new THREE.Mesh(
  new THREE.BoxGeometry(1, 1, 1),
  new THREE.MeshStandardMaterial({ color: 0x00ff00 })
);
parent.object3D.add(child);

Дочерние объекты наследуют позицию, поворот и масштаб родителя.


Доступ к физике и коллизиям

Если используется физический движок (например, aframe-physics-system), object3D позволяет синхронизировать визуальное представление с физикой:

const entity = document.querySelector('#dynamicBox');
const body = entity.body; // физическое тело, созданное движком
entity.object3D.position.copy(body.position);
entity.object3D.quaternion.copy(body.quaternion);

Реакция на события через object3D

Можно отслеживать изменения или анимацию объектов:

entity.object3D.traverse((obj) => {
  if (obj.isMesh) {
    obj.material.color.set(Math.random() * 0xffffff);
  }
});

Метод traverse проходит по всем потомкам объекта, включая вложенные меши, камеры и светильники.


Синхронизация с компонентами A-Frame

При использовании компонентов A-Frame часто удобнее обновлять object3D напрямую, чтобы добиться сложных эффектов, недоступных стандартным компонентам:

  • Анимация мешей с использованием THREE.AnimationMixer.
  • Динамическое добавление или удаление частей модели.
  • Реализация кастомных шейдеров через material.onBeforeCompile.

Пример применения кастомного шейдера:

const mesh = document.querySelector('#myPlane').object3DMap.mesh;
mesh.material.onBeforeComp ile = function (shader) {
  shader.fragmentShader = shader.fragmentShader.replace(
    '#include <dithering_fragment>',
    'gl_FragColor.rgb *= 0.5;'
  );
};

Практические рекомендации

  • object3D всегда доступен, даже если меш ещё не создан. Для визуальных изменений лучше проверять наличие object3DMap.mesh.
  • Любые изменения свойств Three.js лучше выполнять после события model-loaded для моделей GLTF.
  • Использование traverse удобно для массового изменения дочерних мешей.
  • Для сложных анимаций или динамических эффектов прямой доступ к object3D предоставляет полную свободу, позволяя сочетать возможности Three.js с удобной сценографией A-Frame.