Программное управление камерой

В Three.js камеры определяют точку зрения, с которой сцена проецируется на экран. Основные типы камер: PerspectiveCamera и OrthographicCamera.

  • PerspectiveCamera имитирует перспективу человеческого глаза. Её параметры:

    • fov — угол обзора в градусах.
    • aspect — соотношение сторон (ширина/высота рендера).
    • near и far — ближняя и дальняя плоскости отсечения. Объекты вне этих границ не рендерятся.
  • OrthographicCamera создаёт параллельную проекцию. Параметры:

    • left, right, top, bottom — границы видимой области.
    • near и far — плоскости отсечения.
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 5, 10);

Управление положением и ориентацией камеры

Камера имеет свойства position и rotation, а также методы для направления взгляда:

  • camera.position.set(x, y, z) — установка координат.
  • camera.lookAt(x, y, z) — ориентация камеры на точку в мировых координатах.
  • camera.rotation — можно изменять напрямую через Euler-углы, но рекомендуется использовать lookAt для упрощения.
camera.position.set(10, 5, 10);
camera.lookAt(new THREE.Vector3(0, 0, 0));

Для динамического перемещения удобно использовать векторы направления:

const direction = new THREE.Vector3();
camera.getWorldDirection(direction);
camera.position.add(direction.multiplyScalar(0.1));

Камерные контроллеры

Three.js включает утилиты для удобного управления камерой:

  • OrbitControls — вращение вокруг цели, зум и панорамирование.
  • TrackballControls — более свободное вращение, чувствительное к скорости движения мыши.
  • FlyControls — имитация полёта через сцену.
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true; // плавность движения
controls.dampingFactor = 0.05;
controls.target.set(0, 0, 0);

Параметры контроллеров позволяют:

  • Ограничивать минимальное и максимальное расстояние до цели (minDistance, maxDistance).
  • Ограничивать вертикальные углы вращения (maxPolarAngle, minPolarAngle).
  • Включать/выключать возможность зума и панорамирования.

Анимация камеры

Для создания плавного движения камеры используют Tweening или собственные функции обновления в animate():

function animate() {
    requestAnimationFrame(animate);

    camera.position.x += 0.05; // плавное движение по оси X
    camera.lookAt(scene.position);

    renderer.render(scene, camera);
}

Для сложных траекторий применяют кривые CatmullRomCurve3:

const path = new THREE.CatmullRomCurve3([
    new THREE.Vector3(0, 2, 10),
    new THREE.Vector3(10, 5, 0),
    new THREE.Vector3(0, 2, -10),
]);

let t = 0;
function animatePath() {
    requestAnimationFrame(animatePath);

    t += 0.001;
    if(t > 1) t = 0;
    camera.position.copy(path.getPointAt(t));
    camera.lookAt(new THREE.Vector3(0, 0, 0));

    renderer.render(scene, camera);
}

Взаимодействие с пользователем

Камеру можно управлять через события мыши и клавиатуры:

  • mousemove — вращение.
  • wheel — масштабирование.
  • keydown — движение по сцене.
window.addEventListener('keydown', (event) => {
    switch(event.key) {
        case 'w': camera.position.z -= 0.1; break;
        case 's': camera.position.z += 0.1; break;
        case 'a': camera.position.x -= 0.1; break;
        case 'd': camera.position.x += 0.1; break;
    }
});

Связь камеры с объектами сцены

Камеру можно привязать к объекту для создания эффектов «следования за объектом»:

const target = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshBasicMaterial({color: 0xff0000}));
scene.add(target);

function animateFollow() {
    requestAnimationFrame(animateFollow);

    camera.position.lerp(new THREE.Vector3(target.position.x + 5, target.position.y + 2, target.position.z + 5), 0.05);
    camera.lookAt(target.position);

    renderer.render(scene, camera);
}

Использование lerp обеспечивает плавное приближение к цели, создавая естественный эффект слежения.

Камера и рендеринг

Любые изменения камеры требуют повторного вызова рендера. При изменении размера окна важно обновлять соотношение сторон и матрицу проекции:

window.addEventListener('resize', () => {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
});

updateProjectionMatrix() обязательна после изменения параметров камеры, иначе перспективные и ортографические проекции будут некорректны.

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