TransformControls: манипулятор объектов на сцене

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

Подключение и инициализация

Для использования TransformControls необходимо подключить соответствующий модуль из examples/jsm/controls/TransformControls.js:

import * as THREE from 'three';
import { TransformControls } from 'three/examples/jsm/controls/TransformControls.js';

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const scene = new THREE.Scene();
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

Создание самого TransformControls производится следующим образом:

const controls = new TransformControls(camera, renderer.domElement);
scene.add(controls);

Привязка к объекту

TransformControls работает с любым объектом наследующим THREE.Object3D, чаще всего с THREE.Mesh. Привязка осуществляется через метод attach:

const cube = new THREE.Mesh(
    new THREE.BoxGeometry(1, 1, 1),
    new THREE.MeshStandardMaterial({ color: 0x00ff00 })
);
scene.add(cube);

controls.attach(cube);

После этого манипулятор будет управлять кубом. Визуально появляются стрелки для перемещения, круги для вращения и кубики для масштабирования в зависимости от выбранного режима.

Режимы трансформации

TransformControls поддерживает три режима работы:

  • translate — перемещение объекта по осям X, Y, Z

    controls.setMode('translate');
  • rotate — вращение объекта вокруг осей

    controls.setMode('rotate');
  • scale — масштабирование объекта

    controls.setMode('scale');

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

Ограничения и осевые направления

TransformControls позволяет ограничивать движение объекта по определённой оси с помощью свойства axis:

controls.showX = true;
controls.showY = false;
controls.showZ = true;

Это удобно при работе с объектами, которые должны двигаться только в плоскости или вдоль одной оси. Также есть возможность задать мировые или локальные координаты через свойство space:

controls.setSpace('local'); // изменения в локальной системе координат
controls.setSpace('world'); // изменения в мировой системе координат

Интеграция с OrbitControls

При использовании TransformControls вместе с OrbitControls необходимо отключать управление камерой во время трансформации, чтобы не возникало конфликта:

controls.addEventListener('dragging-changed', function (event) {
    orbitControls.enabled = !event.value;
});

Событие dragging-changed срабатывает при начале и завершении перемещения объекта. Это обеспечивает плавную работу интерфейса и предотвращает случайное вращение камеры.

События и прослушка изменений

TransformControls генерирует события, которые позволяют отслеживать действия пользователя:

  • change — любое изменение трансформации объекта
  • mouseDown и mouseUp — начало и конец взаимодействия
  • objectChange — конкретное изменение привязанного объекта

Пример использования:

controls.addEventListener('objectChange', () => {
    console.log('Объект изменен:', cube.position, cube.rotation, cube.scale);
});

Это особенно важно для динамических сцен, где необходимо синхронизировать состояние объектов с логикой приложения или отправлять данные на сервер.

Взаимодействие с анимацией и рендерингом

Для корректной работы TransformControls необходимо вызывать renderer.render(scene, camera) в цикле анимации. Пример базового цикла:

function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
}
animate();

В случае, если сцена содержит другие анимации или динамические объекты, рекомендуется обновлять их состояния перед рендером и после обработки событий TransformControls.

Пользовательская настройка визуальных элементов

Визуальный стиль стрелок, кругов и кубиков можно настраивать через свойства материала:

controls.setSize(1.2); // масштаб визуального контроллера
controls.showX = true;
controls.showY = true;
controls.showZ = false;

Также можно изменять цвет и прозрачность элементов:

controls.children.forEach(child => {
    if (child.material) {
        child.material.opacity = 0.8;
        child.material.transparent = true;
    }
});

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

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

  • Использовать локальные координаты при работе с иерархическими объектами, чтобы изменения учитывали ориентацию родителя.
  • Отключать OrbitControls во время трансформаций для предотвращения конфликтов.
  • Прослушивать событие objectChange для синхронизации состояния объекта с остальной логикой приложения.
  • Ограничивать оси трансформации при необходимости точного позиционирования.
  • Настраивать визуальные элементы контроллера для улучшения пользовательского опыта на сложных сценах.

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