diff --git a/CHANGES.md b/CHANGES.md
index 18b1dead..a4350270 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -9,6 +9,7 @@
##### Additions :tada:
- Editor builds for macOS now target macOS 10.15+. Previously, macOS 12.7+ was required.
+- Added `originPlacement` property to `CesiumGeoreference` to toggle between "Cartographic Origin" and "True Origin" reference modes. Whereas "Cartographic Origin" is the default for georeferenced tilesets, "True Origin" may be used for non-georeferenced tilesets centered at the origin.
##### Fixes :wrench:
diff --git a/Editor/CesiumGeoreferenceEditor.cs b/Editor/CesiumGeoreferenceEditor.cs
index 1b259dc1..644e21a7 100644
--- a/Editor/CesiumGeoreferenceEditor.cs
+++ b/Editor/CesiumGeoreferenceEditor.cs
@@ -8,6 +8,19 @@ public class CesiumGeoreferenceEditor : Editor
{
private CesiumGeoreference _georeference;
+ private SerializedProperty _originPlacement;
+
+ // Converts the SerializedProperty's value to the CesiumGeoreferenceOriginPlacement
+ // enum it corresponds to, for convenience.
+ internal CesiumGeoreferenceOriginPlacement originPlacement
+ {
+ get
+ {
+ return (CesiumGeoreferenceOriginPlacement)
+ this._originPlacement.enumValueIndex;
+ }
+ }
+
private SerializedProperty _originAuthority;
// Converts the SerializedProperty's value to the CesiumGeoreferenceOriginAuthority
@@ -37,6 +50,8 @@ private void OnEnable()
this._georeference = (CesiumGeoreference)this.target;
this._ellipsoidOverride = this.serializedObject.FindProperty("_ellipsoidOverride");
+ this._originPlacement =
+ this.serializedObject.FindProperty("_originPlacement");
this._originAuthority =
this.serializedObject.FindProperty("_originAuthority");
@@ -58,15 +73,16 @@ public override void OnInspectorGUI()
DrawInspectorButtons();
EditorGUILayout.Space(5);
- this.DrawEllipsoidOverrideProperty();
- EditorGUILayout.Space(5);
- this.DrawScaleProperty();
- EditorGUILayout.Space(5);
+ this.DrawOriginPlacementProperty();
this.DrawOriginAuthorityProperty();
EditorGUILayout.Space(5);
this.DrawLongitudeLatitudeHeightProperties();
EditorGUILayout.Space(5);
this.DrawEarthCenteredEarthFixedProperties();
+ EditorGUILayout.Space(5);
+ this.DrawScaleProperty();
+ EditorGUILayout.Space(5);
+ this.DrawEllipsoidOverrideProperty();
this.serializedObject.ApplyModifiedProperties();
}
@@ -93,23 +109,48 @@ private void DrawInspectorButtons()
CesiumEditorUtility.PlaceGeoreferenceAtCameraPosition(this._georeference);
}
+ EditorGUI.BeginDisabledGroup(
+ this.originPlacement != CesiumGeoreferenceOriginPlacement.CartographicOrigin);
GUIContent createSubSceneContent = new GUIContent(
"Create Sub-Scene Here",
"Creates a child GameObject with a \"CesiumSubScene\" component whose origin " +
"is set to the camera's current location. A \"CesiumSubScene\" describes a " +
"corresponding world location that can be jumped to, and only one sub-scene " +
- "can be worked on in the editor at a time.");
+ "can be worked on in the editor at a time." +
+ "\n\n" +
+ "This is disabled when \"Origin Placement\" is set to \"True Origin\".");
if (GUILayout.Button("Create Sub-Scene Here"))
{
CesiumEditorUtility.CreateSubScene(this._georeference);
}
+ EditorGUI.EndDisabledGroup();
+
GUILayout.EndHorizontal();
EditorGUI.EndDisabledGroup();
}
+ private void DrawOriginPlacementProperty()
+ {
+ GUIContent originPlacementContent = new GUIContent(
+ "Origin Placement",
+ "The placement of this GameObject's origin (0,0,0) within the tileset." +
+ "\n\n" +
+ "3D Tiles tilesets often use Earth-centered, Earth-fixed coordinates, such that " +
+ "the tileset content is in a small bounding volume 6-7 million meters " +
+ "(the radius of the Earth) away from the coordinate system origin. This property " +
+ "allows an alternative position, other than the tileset's true origin, to be " +
+ "treated as the origin for the purpose of this GameObject. Using this property will " +
+ "preserve vertex precision (and thus avoid jittering) much better than setting the " +
+ "GameObject's Transform property.");
+ EditorGUILayout.PropertyField(this._originPlacement, originPlacementContent);
+ }
+
private void DrawEllipsoidOverrideProperty()
{
+ EditorGUI.BeginDisabledGroup(
+ this.originPlacement != CesiumGeoreferenceOriginPlacement.CartographicOrigin);
+
GUIContent ellipsoidOverrideContent = new GUIContent(
"Ellipsoid Override",
"The ellipsoid definition to use for this tileset. If this is left blank, " +
@@ -117,11 +158,13 @@ private void DrawEllipsoidOverrideProperty()
"doesn't list an ellipsoid to use.");
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(this._ellipsoidOverride, ellipsoidOverrideContent);
- if(EditorGUI.EndChangeCheck())
+ if (EditorGUI.EndChangeCheck())
{
this.serializedObject.ApplyModifiedProperties();
this._georeference.ReloadEllipsoid();
}
+
+ EditorGUI.EndDisabledGroup();
}
private void DrawScaleProperty()
@@ -137,17 +180,24 @@ private void DrawScaleProperty()
private void DrawOriginAuthorityProperty()
{
+ EditorGUI.BeginDisabledGroup(
+ this.originPlacement != CesiumGeoreferenceOriginPlacement.CartographicOrigin);
+
GUIContent originAuthorityContent = new GUIContent(
"Origin Authority",
"The set of coordinates that authoritatively define the origin of " +
"this georeference.");
EditorGUILayout.PropertyField(this._originAuthority, originAuthorityContent);
+
+ EditorGUI.EndDisabledGroup();
}
private void DrawLongitudeLatitudeHeightProperties()
{
+ CesiumGeoreferenceOriginPlacement placement = this.originPlacement;
CesiumGeoreferenceOriginAuthority authority = this.originAuthority;
EditorGUI.BeginDisabledGroup(
+ placement != CesiumGeoreferenceOriginPlacement.CartographicOrigin ||
authority != CesiumGeoreferenceOriginAuthority.LongitudeLatitudeHeight);
GUILayout.Label(
@@ -187,8 +237,10 @@ private void DrawLongitudeLatitudeHeightProperties()
private void DrawEarthCenteredEarthFixedProperties()
{
+ CesiumGeoreferenceOriginPlacement placement = this.originPlacement;
CesiumGeoreferenceOriginAuthority authority = this.originAuthority;
EditorGUI.BeginDisabledGroup(
+ placement != CesiumGeoreferenceOriginPlacement.CartographicOrigin ||
authority != CesiumGeoreferenceOriginAuthority.EarthCenteredEarthFixed);
GUILayout.Label(
diff --git a/Runtime/CesiumGeoreference.cs b/Runtime/CesiumGeoreference.cs
index d07d5146..dc7e898d 100644
--- a/Runtime/CesiumGeoreference.cs
+++ b/Runtime/CesiumGeoreference.cs
@@ -6,6 +6,30 @@
namespace CesiumForUnity
{
+ ///
+ /// An enumeration of the possible strategies for placing the origin of a .
+ ///
+ public enum CesiumGeoreferenceOriginPlacement
+ {
+ ///
+ /// Use the tileset's true origin as the GameObject's origin.
+ ///
+ ///
+ /// For georeferenced tilesets, this usually means the GameObject's origin will be
+ /// at the center of the Earth, which is not recommended. For a non-georeferenced
+ /// tileset, however, such as a detailed building with a local origin, putting the
+ /// GameObject's origin at the same location as the tileset's origin can be useful.
+ ///
+ TrueOrigin,
+ ///
+ /// Use a custom position within the tileset as the GameObject's origin. The
+ /// position is expressed as cartographic coordinates determined by the
+ /// , and that position within
+ /// the tileset will be at coordinate (0,0,0) in the GameObject's coordinate system.
+ ///
+ CartographicOrigin
+ }
+
///
/// Identifies the set of the coordinates that authoritatively define
/// the origin of a .
@@ -68,6 +92,9 @@ public partial class CesiumGeoreference : MonoBehaviour
[SerializeField]
private CesiumEllipsoid _ellipsoidOverride = null;
+ [SerializeField]
+ private CesiumGeoreferenceOriginPlacement _originPlacement = CesiumGeoreferenceOriginPlacement.CartographicOrigin;
+
[SerializeField]
private CesiumGeoreferenceOriginAuthority _originAuthority = CesiumGeoreferenceOriginAuthority.LongitudeLatitudeHeight;
@@ -113,26 +140,55 @@ public partial class CesiumGeoreference : MonoBehaviour
#endregion
+ ///
+ /// The placement of this GameObject's origin (coordinate 0,0,0) within the tileset.
+ ///
+ ///
+ /// 3D Tiles tilesets often use Earth-centered, Earth-fixed coordinates, such
+ /// that the tileset content is in a small bounding volume 6-7 million meters
+ /// (the radius of the Earth) away from the coordinate system origin. This
+ /// property allows an alternative position, other than the tileset's true
+ /// origin, to be treated as the origin for the purpose of this GameObject. Using
+ /// this property will preserve vertex precision (and thus avoid jittering)
+ /// much better than setting the GameObject's Transform property.
+ ///
+ public CesiumGeoreferenceOriginPlacement originPlacement
+ {
+ get => this._originPlacement;
+ set
+ {
+ this._originPlacement = value;
+ this.MoveOrigin();
+ }
+ }
+
///
/// Identifies which set of coordinates authoritatively defines the origin
/// of this georeference.
///
+ ///
+ /// Setting this property changes the accordingly.
+ ///
public CesiumGeoreferenceOriginAuthority originAuthority
{
get => this._originAuthority;
set
{
this._originAuthority = value;
- this.MoveOrigin();
+ this.originPlacement = CesiumGeoreferenceOriginPlacement.CartographicOrigin;
}
}
///
/// The latitude of the origin of the coordinate system, in degrees, in the range -90 to 90.
- /// This property is ignored unless is
+ ///
+ ///
+ /// This property only takes effect if is set to
+ /// and
+ /// is set to
/// .
/// Setting this property changes the accordingly.
- ///
+ ///
public double latitude
{
get => this._latitude;
@@ -145,10 +201,14 @@ public double latitude
///
/// The longitude of the origin of the coordinate system, in degrees, in the range -180 to 180.
- /// This property is ignored unless is
+ ///
+ ///
+ /// This property only takes effect if is set to
+ /// and
+ /// is set to
/// .
/// Setting this property changes the accordingly.
- ///
+ ///
public double longitude
{
get => this._longitude;
@@ -162,11 +222,15 @@ public double longitude
///
/// The height in the origin of the coordinate system, in meters above the ellipsoid. Do not
/// confuse this with a geoid height or height above mean sea level, which can be tens of
- /// meters higher or lower depending on where in the world the object is located. This
- /// property is ignored unless is
+ /// meters higher or lower depending on where in the world the object is located.
+ ///
+ ///
+ /// This property only takes effect if is set to
+ /// and
+ /// is set to
/// .
/// Setting this property changes the accordingly.
- ///
+ ///
public double height
{
get => this._height;
@@ -179,10 +243,14 @@ public double height
///
/// The Earth-Centered, Earth-Fixed X coordinate of the origin of the coordinate system, in meters.
- /// This property is ignored unless is
+ ///
+ ///
+ /// This property only takes effect if is set to
+ /// and
+ /// is set to
/// .
/// Setting this property changes the accordingly.
- ///
+ ///
public double ecefX
{
get => this._ecefX;
@@ -195,10 +263,14 @@ public double ecefX
///
/// The Earth-Centered, Earth-Fixed Y coordinate of the origin of the coordinate system, in meters.
- /// This property is ignored unless is
+ ///
+ ///
+ /// This property only takes effect if is set to
+ /// and
+ /// is set to
/// .
/// Setting this property changes the accordingly.
- ///
+ ///
public double ecefY
{
get => this._ecefY;
@@ -211,10 +283,14 @@ public double ecefY
///
/// The Earth-Centered, Earth-Fixed Z coordinate of the origin of the coordinate system, in meters.
- /// This property is ignored unless is
+ ///
+ ///
+ /// This property only takes effect if is set to
+ /// and
+ /// is set to
/// .
/// Setting this property changes the accordingly.
- ///
+ ///
public double ecefZ
{
get => this._ecefZ;
@@ -227,10 +303,12 @@ public double ecefZ
///
/// The scale of the globe in the Unity world. If this value is 0.5, for example, one
- /// meter on the globe occupies half a meter in the Unity world. The globe can also
- /// be scaled by modifying the georeference's Transform, but setting this property instead
- /// will do a better job of preserving precision.
+ /// meter on the globe occupies half a meter in the Unity world.
///
+ ///
+ /// The globe can also be scaled by modifying the georeference's Transform, but setting
+ /// this property instead will do a better job of preserving precision.
+ ///
public double scale
{
get => this._scale;
@@ -259,6 +337,9 @@ public double4x4 ecefToLocalMatrix
}
}
+ ///
+ /// The that is referenced.
+ ///
public CesiumEllipsoid ellipsoid
{
get
@@ -391,7 +472,7 @@ public void ReloadEllipsoid()
this.UpdateOtherCoordinates();
Cesium3DTileset[] tilesets = GetComponentsInChildren();
- foreach(var tileset in tilesets)
+ foreach (var tileset in tilesets)
{
tileset.RecreateTileset();
}
diff --git a/Runtime/ConfigureReinterop.cs b/Runtime/ConfigureReinterop.cs
index c674fbc0..a5e26ab5 100644
--- a/Runtime/ConfigureReinterop.cs
+++ b/Runtime/ConfigureReinterop.cs
@@ -393,6 +393,7 @@ public void ExposeToCPP()
georeference.ecefX = georeference.ecefX;
georeference.ecefY = georeference.ecefY;
georeference.ecefZ = georeference.ecefZ;
+ georeference.originPlacement = georeference.originPlacement;
georeference.originAuthority = georeference.originAuthority;
georeference.scale = georeference.scale;
double4x4 ecefToLocal = georeference.ecefToLocalMatrix;
diff --git a/native~/Runtime/src/CesiumGeoreferenceImpl.cpp b/native~/Runtime/src/CesiumGeoreferenceImpl.cpp
index 192fb80e..bc069dfa 100644
--- a/native~/Runtime/src/CesiumGeoreferenceImpl.cpp
+++ b/native~/Runtime/src/CesiumGeoreferenceImpl.cpp
@@ -8,6 +8,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -24,6 +25,21 @@ namespace {
LocalHorizontalCoordinateSystem createCoordinateSystem(
const DotNet::CesiumForUnity::CesiumGeoreference& georeference) {
+ double scale = 1.0 / georeference.scale();
+ if (georeference.originPlacement() ==
+ DotNet::CesiumForUnity::CesiumGeoreferenceOriginPlacement::TrueOrigin) {
+ // In True Origin mode, we want a coordinate system that:
+ // 1. Is at the origin,
+ // 2. Converts from Y-up to Z-up, and
+ // 3. Uses the georeference's scale
+ glm::dmat4 localToEcef(
+ glm::dvec4(scale, 0.0, 0.0, 0.0),
+ glm::dvec4(0.0, 0.0, scale, 0.0),
+ glm::dvec4(0.0, -scale, 0.0, 0.0),
+ glm::dvec4(0.0, 0.0, 0.0, 1.0));
+ return LocalHorizontalCoordinateSystem(localToEcef);
+ }
+
if (georeference.originAuthority() ==
DotNet::CesiumForUnity::CesiumGeoreferenceOriginAuthority::
LongitudeLatitudeHeight) {
@@ -35,7 +51,7 @@ LocalHorizontalCoordinateSystem createCoordinateSystem(
LocalDirection::East,
LocalDirection::Up,
LocalDirection::North,
- 1.0 / georeference.scale(),
+ scale,
georeference.ellipsoid().NativeImplementation().GetEllipsoid());
} else {
return LocalHorizontalCoordinateSystem(
@@ -46,7 +62,7 @@ LocalHorizontalCoordinateSystem createCoordinateSystem(
LocalDirection::East,
LocalDirection::Up,
LocalDirection::North,
- 1.0 / georeference.scale(),
+ scale,
georeference.ellipsoid().NativeImplementation().GetEllipsoid());
}
}