В CesiumJS ориентация представляет собой совокупность параметров, определяющих, как камера или объект повернуты в пространстве относительно поверхности эллипсоида Земли. В отличие от классических 3D-движков, где сцена имеет локальную систему координат, здесь основой выступает геоцентрическая система координат (ECEF), а направление часто выражается через локальные системы East-North-Up (ENU).
Ориентация всегда рассматривается вместе с положением: точка задаёт позицию на глобусе, а ориентация определяет направление взгляда и поворот вокруг оси взгляда.
Камера в CesiumJS является полноценным математическим объектом, описываемым положением и ориентацией в мировом пространстве. Основные компоненты:
Эти три вектора формируют ортонормированный базис камеры, который определяет её ориентацию в пространстве.
Внутри движка ориентация камеры сводится к матрице поворота 3×3 или к кватерниону, обеспечивающему стабильную интерполяцию без артефактов вращения.
direction определяет, куда направлена камера. Это нормализованный вектор от камеры к точке наблюдения.
up задаёт вертикальную ось камеры и предотвращает «переворачивание» изображения.
right вычисляется как векторное произведение direction и up, обеспечивая ортогональность системы координат.
Эти три вектора взаимосвязаны: изменение одного автоматически требует пересчёта остальных для сохранения ортонормальности.
Наиболее практичный способ управления ориентацией — углы Heading, Pitch, Roll.
В CesiumJS используется система, привязанная к локальному горизонту точки наблюдения, что делает управление интуитивным при работе с земной поверхностью.
HeadingPitchRoll часто используется совместно с преобразованием в кватернион:
const hpr = new Cesium.HeadingPitchRoll(
Cesium.Math.toRadians(90),
Cesium.Math.toRadians(-20),
0
);
const orientation = Cesium.Transforms.headingPitchRollQuaternion(
position,
hpr
);
Метод setView задаёт мгновенное состояние камеры без
анимации. Он напрямую устанавливает позицию и ориентацию.
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(30, 50, 1000000),
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-45),
roll: 0
}
});
Особенность заключается в том, что ориентация применяется в контексте текущей системы координат камеры, без интерполяции.
Метод lookAt фиксирует камеру относительно заданной
точки в пространстве. Он полезен для привязки к объекту или
координате.
const target = Cesium.Cartesian3.fromDegrees(30, 50, 0);
viewer.camera.lookAt(
target,
new Cesium.HeadingPitchRange(
Cesium.Math.toRadians(0),
Cesium.Math.toRadians(-30),
500000
)
);
HeadingPitchRange задаёт угловое смещение и расстояние до цели.
flyTo добавляет интерполяцию движения камеры между
состояниями. Ориентация интерполируется плавно, включая поворот.
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(30, 50, 1000000),
orientation: {
heading: Cesium.Math.toRadians(120),
pitch: Cesium.Math.toRadians(-45),
roll: 0
}
});
Ориентация в CesiumJS тесно связана с преобразованиями между системами координат:
Transforms API обеспечивает переход между ними:
const enu = Cesium.Transforms.eastNorthUpToFixedFrame(position);
Эта матрица используется для преобразования локальной ориентации в глобальную.
Для сущностей и 3D-моделей ориентация часто задаётся через кватернионы, что исключает проблему гимбал-лока и обеспечивает плавные вращения.
const hpr = new Cesium.HeadingPitchRoll(
Cesium.Math.toRadians(45),
0,
0
);
entity.orientation = Cesium.Transforms.headingPitchRollQuaternion(
entity.position.getValue(Cesium.JulianDate.now()),
hpr
);
Кватернион в CesiumJS — это стандартный способ описания ориентации объектов в мировом пространстве.
Внутренне ориентация может быть представлена через Matrix3 или Matrix4:
Пример создания полной матрицы ориентации:
const modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(
position,
hpr
);
Эта матрица используется при рендеринге моделей, обеспечивая корректную ориентацию относительно поверхности Земли.
При работе с географическими объектами важна привязка ориентации к локальному горизонту. Например, «вперёд» для объекта на Земле не совпадает с глобальной осью Z.
CesiumJS использует касательную плоскость к эллипсоиду, формируя локальный базис:
Любая ориентация объектов преобразуется через этот базис.
Направление взгляда может задаваться напрямую через direction vector:
viewer.camera.direction = Cesium.Cartesian3.normalize(
new Cesium.Cartesian3(1, 0, -0.3),
new Cesium.Cartesian3()
);
Однако такой способ используется реже, поскольку нарушает интуитивную систему углов и требует ручного контроля up-вектора.
При переходах между состояниями камеры или объектов используется сферическая интерполяция (SLERP), особенно при работе с кватернионами. Это предотвращает резкие скачки вращения.
В случаях использования Euler-углов возможны артефакты при больших углах наклона, особенно около ±90° pitch.
Ориентация камеры и объектов в CesiumJS зависит от:
Неправильное сочетание heading/pitch без учёта roll может приводить к инверсии горизонта или неожиданному вращению сцены.
Часто входные данные приходят в виде GPS-направлений или азимутов. Их необходимо преобразовывать в heading:
Далее формируется HPR-структура и преобразуется в кватернион или матрицу трансформации.
Ориентация камеры и объектов в сцене вычисляется независимо, но визуально взаимосвязана. Камера может находиться в фиксированном положении, тогда как объекты вращаются в соответствии с модельными матрицами.
В сложных сценах используется синхронизация систем координат, чтобы избежать расхождений между локальной и глобальной ориентацией.