242 lines
8.3 KiB
C++
242 lines
8.3 KiB
C++
// Copyright 2020-2024 CesiumGS, Inc. and Contributors
|
|
|
|
#pragma once
|
|
|
|
#include "CesiumGeospatial/Ellipsoid.h"
|
|
#include "CesiumGeospatial/LocalHorizontalCoordinateSystem.h"
|
|
#include "HAL/Platform.h"
|
|
#include "Math/Matrix.h"
|
|
#include <glm/fwd.hpp>
|
|
#include <glm/vec3.hpp>
|
|
|
|
/**
|
|
* @brief A lightweight structure to encapsulate coordinate transforms.
|
|
*
|
|
* It encapsulates the conversions between...
|
|
* - Earth-Centered, Earth-Fixed (ECEF) coordinates
|
|
* - Georeferenced coordinates (Latitude/Longitude/Height)
|
|
* - Unreal coordinates (relative to the unreal world origin)
|
|
*
|
|
*/
|
|
class CESIUMRUNTIME_API GeoTransforms {
|
|
|
|
public:
|
|
/**
|
|
* @brief Creates a new instance.
|
|
*/
|
|
GeoTransforms();
|
|
|
|
/**
|
|
* @brief Creates a new instance.
|
|
*
|
|
* The center position is the position of the origin of the
|
|
* local coordinate system that is established by this instance.
|
|
*
|
|
* @param ellipsoid The ellipsoid to use for the georeferenced coordinates
|
|
* @param center The center position.
|
|
* @param scale The scale factor of the globe in the Unreal world.
|
|
*/
|
|
GeoTransforms(
|
|
const CesiumGeospatial::Ellipsoid& ellipsoid,
|
|
const glm::dvec3& center,
|
|
double scale);
|
|
|
|
/**
|
|
* @brief Set the center position of this instance
|
|
*
|
|
* The center position is the position of the origin of the
|
|
* local coordinate system that is established by this instance.
|
|
*
|
|
* @param center The center position.
|
|
*/
|
|
void setCenter(const glm::dvec3& center) noexcept;
|
|
|
|
/**
|
|
* @brief Set the ellipsoid of this instance
|
|
*
|
|
* @param ellipsoid The ellipsoid
|
|
*/
|
|
void setEllipsoid(const CesiumGeospatial::Ellipsoid& ellipsoid) noexcept;
|
|
|
|
/**
|
|
* Transforms the given longitude in degrees (x), latitude in
|
|
* degrees (y), and height in meters (z) into Earth-Centered, Earth-Fixed
|
|
* (ECEF) coordinates.
|
|
*/
|
|
glm::dvec3 TransformLongitudeLatitudeHeightToEcef(
|
|
const glm::dvec3& LongitudeLatitudeHeight) const noexcept;
|
|
|
|
/**
|
|
* Transforms the given Earth-Centered, Earth-Fixed (ECEF) coordinates into
|
|
* longitude in degrees (x), latitude in degrees (y), and height in
|
|
* meters (z).
|
|
*/
|
|
glm::dvec3
|
|
TransformEcefToLongitudeLatitudeHeight(const glm::dvec3& Ecef) const noexcept;
|
|
|
|
/**
|
|
* Transforms the given longitude in degrees (x), latitude in
|
|
* degrees (y), and height in meters (z) into Unreal world coordinates
|
|
* (relative to the floating origin).
|
|
*/
|
|
glm::dvec3 TransformLongitudeLatitudeHeightToUnreal(
|
|
const glm::dvec3& origin,
|
|
const glm::dvec3& LongitudeLatitudeHeight) const noexcept;
|
|
|
|
/**
|
|
* Transforms Unreal world coordinates (relative to the floating origin) into
|
|
* longitude in degrees (x), latitude in degrees (y), and height in
|
|
* meters (z).
|
|
*/
|
|
glm::dvec3 TransformUnrealToLongitudeLatitudeHeight(
|
|
const glm::dvec3& origin,
|
|
const glm::dvec3& Ue) const noexcept;
|
|
|
|
/**
|
|
* Transforms the given point from Earth-Centered, Earth-Fixed (ECEF) into
|
|
* Unreal world coordinates (relative to the floating origin).
|
|
*/
|
|
glm::dvec3 TransformEcefToUnreal(
|
|
const glm::dvec3& origin,
|
|
const glm::dvec3& Ecef) const noexcept;
|
|
|
|
/**
|
|
* Transforms the given point from Unreal world coordinates (relative to the
|
|
* floating origin) to Earth-Centered, Earth-Fixed (ECEF).
|
|
*/
|
|
glm::dvec3 TransformUnrealToEcef(
|
|
const glm::dvec3& origin,
|
|
const glm::dvec3& Ue) const noexcept;
|
|
|
|
/**
|
|
* Transforms a rotator from Unreal world to East-South-Up at the given
|
|
* Unreal relative world location (relative to the floating origin).
|
|
*/
|
|
glm::dquat TransformRotatorUnrealToEastSouthUp(
|
|
const glm::dvec3& origin,
|
|
const glm::dquat& UeRotator,
|
|
const glm::dvec3& UeLocation) const noexcept;
|
|
|
|
/**
|
|
* Transforms a rotator from East-South-Up to Unreal world at the given
|
|
* Unreal world location (relative to the floating origin).
|
|
*/
|
|
glm::dquat TransformRotatorEastSouthUpToUnreal(
|
|
const glm::dvec3& origin,
|
|
const glm::dquat& EnuRotator,
|
|
const glm::dvec3& UeLocation) const noexcept;
|
|
|
|
/**
|
|
* Computes the rotation matrix from the local East-South-Up to Unreal at the
|
|
* specified Unreal world location (relative to the floating
|
|
* origin). The returned transformation works in Unreal's left-handed
|
|
* coordinate system.
|
|
*/
|
|
glm::dmat4 ComputeEastSouthUpToUnreal(
|
|
const glm::dvec3& origin,
|
|
const glm::dvec3& Ue) const noexcept;
|
|
|
|
/**
|
|
* Computes the rotation matrix from the local East-North-Up to
|
|
* Earth-Centered, Earth-Fixed (ECEF) at the specified ECEF location.
|
|
*/
|
|
glm::dmat3 ComputeEastNorthUpToEcef(const glm::dvec3& Ecef) const noexcept;
|
|
|
|
/*
|
|
* GEOREFERENCE TRANSFORMS
|
|
*/
|
|
|
|
/**
|
|
* @brief Gets the transformation from the _absolute_ "Unreal World" reference
|
|
* frame to the "Ellipsoid-centered" reference frame (i.e. ECEF).
|
|
*
|
|
* Gets a matrix that transforms coordinates from the absolute "Unreal World"
|
|
* reference frame (with respect to the absolute world origin, not the
|
|
* floating origin) to the "Ellipsoid-centered" reference frame (which is
|
|
* usually Earth-centered, Earth-fixed). See {@link reference-frames.md}.
|
|
*/
|
|
const glm::dmat4&
|
|
GetAbsoluteUnrealWorldToEllipsoidCenteredTransform() const noexcept {
|
|
return this->_coordinateSystem.getLocalToEcefTransformation();
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the transformation from the "Ellipsoid-centered" reference
|
|
* frame (i.e. ECEF) to the absolute "Unreal World" reference frame.
|
|
*
|
|
* Gets a matrix that transforms coordinates from the "Ellipsoid-centered"
|
|
* reference frame (which is usually Earth-centered, Earth-fixed) to the
|
|
* absolute "Unreal world" reference frame (with respect to the absolute world
|
|
* origin, not the floating origin). See {@link reference-frames.md}.
|
|
*/
|
|
const glm::dmat4&
|
|
GetEllipsoidCenteredToAbsoluteUnrealWorldTransform() const noexcept {
|
|
return this->_coordinateSystem.getEcefToLocalTransformation();
|
|
}
|
|
|
|
/**
|
|
* @brief Computes the normal of the plane tangent to the surface of the
|
|
* ellipsoid that is used by this instance, at the provided position.
|
|
*
|
|
* @param position The cartesian position for which to to determine the
|
|
* surface normal.
|
|
* @return The normal.
|
|
*/
|
|
glm::dvec3 ComputeGeodeticSurfaceNormal(const glm::dvec3& position) const {
|
|
return _ellipsoid.geodeticSurfaceNormal(position);
|
|
}
|
|
|
|
/**
|
|
* Computes the rotation in ellipsoid surface normal between an old position
|
|
* and a new position. This rotation is expressed in terms of Unreal world
|
|
* coordinates, and can be used to maintain an object's orientation relative
|
|
* to the local horizontal as it moves over the globe.
|
|
*
|
|
* @param oldPosition The old ECEF position that the object moved from.
|
|
* @param newPosition The new ECEF position that the object moved to.
|
|
* @return The rotation from the ellipsoid surface normal at the old position
|
|
* to the ellipsoid surface normal at the new position.
|
|
*/
|
|
glm::dquat ComputeSurfaceNormalRotation(
|
|
const glm::dvec3& oldPosition,
|
|
const glm::dvec3& newPosition) const;
|
|
|
|
/**
|
|
* Computes the rotation in ellipsoid surface normal between an old position
|
|
* and a new position. This rotation is expressed in terms of Unreal world
|
|
* coordinates, and can be used to maintain an object's orientation relative
|
|
* to the local horizontal as it moves over the globe.
|
|
*
|
|
* @param oldPosition The old ECEF position that the object moved from.
|
|
* @param newPosition The new ECEF position that the object moved to.
|
|
* @return The rotation from the ellipsoid surface normal at the old position
|
|
* to the ellipsoid surface normal at the new position.
|
|
*/
|
|
glm::dquat ComputeSurfaceNormalRotationUnreal(
|
|
const glm::dvec3& oldPosition,
|
|
const glm::dvec3& newPosition) const;
|
|
|
|
const FMatrix& GetEllipsoidCenteredToAbsoluteUnrealWorldMatrix() const {
|
|
return this->_ecefToUnreal;
|
|
}
|
|
const FMatrix& GetAbsoluteUnrealWorldToEllipsoidCenteredMatrix() const {
|
|
return this->_unrealToEcef;
|
|
}
|
|
|
|
private:
|
|
/**
|
|
* Update the derived state (i.e. the local horizontal coordinate system) when
|
|
* either the center or the ellipsoid has changed.
|
|
*/
|
|
void updateTransforms() noexcept;
|
|
|
|
CesiumGeospatial::LocalHorizontalCoordinateSystem _coordinateSystem;
|
|
|
|
// Modifiable state
|
|
CesiumGeospatial::Ellipsoid _ellipsoid;
|
|
glm::dvec3 _center;
|
|
double _scale;
|
|
FMatrix _ecefToUnreal;
|
|
FMatrix _unrealToEcef;
|
|
};
|