Полёты камеры

Камера в CesiumJS представляет собой математическую модель наблюдателя в трёхмерном пространстве, определяющую положение, ориентацию и параметры проекции. Она тесно связана с глобусом и сценой, формируя единый контекст визуализации геопространственных данных.

Основные компоненты камеры:

  • Позиция (position) — координаты камеры в мировой системе координат (Cartesian3)
  • Ориентация (orientation) — направление взгляда, задаваемое кватернионом или Heading/Pitch/Roll
  • Фрустум (frustum) — параметры перспективной или ортографической проекции
  • Контроллер сцены — интерфейс взаимодействия с Viewer.scene.camera

Ключевая особенность камеры CesiumJS заключается в том, что она оперирует не только локальными координатами сцены, но и геодезическими системами, обеспечивая корректную работу с глобусом WGS84.


Механизм полёта камеры

Полёт камеры — это интерполяция состояния камеры во времени между начальной и конечной позицией с заданной траекторией движения. В CesiumJS этот процесс реализован через методы камеры Viewer и Camera.

Основные свойства полёта:

  • интерполяция позиции (linear или spline)
  • интерполяция ориентации
  • управление длительностью анимации
  • применение easing-функций
  • возможность прерывания и цепочки полётов

Метод flyTo и базовая анимация

Ключевой метод:

viewer.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(37.6173, 55.7558, 10000),
    duration: 3.0
});

Параметр destination

destination определяет конечную точку камеры:

  • Cartesian3 — мировые координаты
  • Cartographic conversion через fromDegrees
  • возможность задания высоты над эллипсоидом

Параметр duration

Определяет длительность анимации в секундах:

  • малые значения (1–2 сек) — резкие переходы
  • средние (3–6 сек) — стандартные кинематографические пролёты
  • большие (10+ сек) — навигационные обзоры

Параметр orientation

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

orientation: {
    heading: Cesium.Math.toRadians(90),
    pitch: Cesium.Math.toRadians(-30),
    roll: 0.0
}
  • heading — поворот по азимуту
  • pitch — наклон вверх/вниз
  • roll — крен камеры

FlyTo с bounding sphere

Метод используется для автоматического охвата объекта в сцене.

viewer.camera.flyToBoundingSphere(boundingSphere, {
    duration: 2.5
});

BoundingSphere вычисляется на основе геометрии:

  • набор точек модели
  • объекты Cesium3DTiles
  • entities и primitives

Алгоритм работы:

  1. вычисление центра сферы
  2. определение радиуса охвата
  3. расчёт оптимальной дистанции камеры
  4. установка угла обзора

Управление траекторией полёта

complete callback

viewer.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(10, 10, 5000),
    complete: function () {
        viewer.camera.flyTo({
            destination: Cesium.Cartesian3.fromDegrees(20, 20, 5000)
        });
    }
});

Цепочки полётов строятся через callback-и, позволяя формировать сценарии навигации.


Easing-функции и характер движения

CesiumJS поддерживает кастомизацию ускорения движения камеры через easingFunction.

Пример:

easingFunction: Cesium.EasingFunction.CUBIC_IN_OUT

Основные типы:

  • LINEAR_NONE — равномерное движение
  • QUADRATIC_IN/OUT — ускорение или замедление
  • CUBIC_IN_OUT — плавный кинематографический переход
  • EXPONENTIAL — резкие ускорения

Поведение траектории определяется функцией времени t ∈ [0, 1], влияющей на интерполяцию позиции.


flyToOffset и локальные смещения

Метод flyToOffset позволяет выполнять полёт относительно текущей ориентации объекта:

viewer.camera.flyToBoundingSphere(boundingSphere, {
    offset: new Cesium.HeadingPitchRange(
        Cesium.Math.toRadians(0),
        Cesium.Math.toRadians(-45),
        2000
    )
});

HeadingPitchRange

  • heading — поворот вокруг вертикальной оси
  • pitch — угол наклона
  • range — дистанция до цели

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


Полёт к геометрическим примитивам

Для сложных сцен используется комбинированный подход:

  • вычисление boundingVolume
  • нормализация координат
  • корректировка высоты камеры

Пример:

const boundingSphere = tileset.boundingSphere;

viewer.camera.flyToBoundingSphere(boundingSphere, {
    duration: 4.0,
    offset: new Cesium.HeadingPitchRange(0, -0.5, boundingSphere.radius * 2)
});

Прямое управление камерой без анимации

Помимо flyTo, существует мгновенное позиционирование:

viewer.camera.setView({
    destination: Cesium.Cartesian3.fromDegrees(30, 50, 10000),
    orientation: {
        heading: 0,
        pitch: -0.5,
        roll: 0
    }
});

Отличие:

  • setView — мгновенная установка состояния
  • flyTo — интерполированная анимация

Математика интерполяции камеры

Траектория движения камеры строится на интерполяции:

Линейная интерполяция позиции

[ P(t) = (1 - t)P_0 + tP_1]

Интерполяция ориентации

Используется сферическая интерполяция кватернионов (SLERP):

[ Q(t) = Q_0 + Q_1]

Где θ — угол между кватернионами.


Камера и глобальная система координат

CesiumJS работает в системе Earth-Centered Earth-Fixed (ECEF):

  • начало координат — центр Земли
  • оси фиксированы относительно планеты
  • координаты Cartesian3 являются основой всех вычислений

При полётах происходит трансформация:

  • Cartographic → Cartesian3
  • локальные offset → ECEF смещения
  • ориентация → кватернионы в мировом пространстве

Ограничения и особенности поведения

Поведение камеры зависит от:

  • уровня детализации terrain (Cesium Terrain)
  • наличия 3D Tiles
  • масштаба сцены
  • текущей высоты камеры

При малых высотах:

  • усиливается влияние кривизны Земли
  • увеличивается чувствительность pitch
  • изменяется скорость визуального смещения

Прерывание и управление полётом

Любая анимация камеры может быть остановлена:

viewer.camera.cancelFlight();

Особенности:

  • мгновенная остановка интерполяции
  • сохранение текущего состояния камеры
  • возможность нового flyTo сразу после cancel

Типовые сценарии использования полётов камеры

Навигация по точкам интереса

  • последовательный flyTo
  • фиксированная длительность переходов
  • одинаковый pitch для стабильности визуального восприятия

Облёт 3D-моделей

  • использование boundingSphere
  • динамическое вычисление range
  • орбитальные offset-параметры

Панорамирование карты

  • низкий pitch (приближение к горизонту)
  • увеличенная дистанция камеры
  • плавное easing движение

Композиция сложных маршрутов камеры

Сложные сценарии формируются через последовательные анимации:

  • цепочка flyTo
  • комбинирование setView и flyTo
  • динамическая корректировка destination на лету

При этом каждый следующий этап может зависеть от текущей позиции камеры, вычисляемой через viewer.camera.positionWC и orientation.