Cesium for Unity 1.15.2
Loading...
Searching...
No Matches
CesiumSubScene.cs
Go to the documentation of this file.
1using System;
2using Unity.Mathematics;
3using UnityEngine;
4
5namespace CesiumForUnity
6{
19 [ExecuteInEditMode]
20 [AddComponentMenu("Cesium/Cesium Sub Scene")]
21 [IconAttribute("Packages/com.cesium.unity/Editor/Resources/Cesium-24x24.png")]
22 public class CesiumSubScene : MonoBehaviour
23 {
24#if UNITY_EDITOR
25 // Caches the built-in sphere mesh across all CesiumSubScenes for use in OnDrawGizmos
26 private static Mesh _previewSphereMesh;
27#endif
28
29 [SerializeField]
30 private double _activationRadius = 1000;
31
39 public double activationRadius
40 {
41 get => this._activationRadius;
42 set
43 {
44 this._activationRadius = value;
45 }
46 }
47
48 [SerializeField]
49 private bool _showActivationRadius = true;
50
55 {
56 get => this._showActivationRadius;
57 set => this._showActivationRadius = value;
58 }
59
60 [SerializeField]
61 private CesiumGeoreferenceOriginAuthority _originAuthority =
62 CesiumGeoreferenceOriginAuthority.LongitudeLatitudeHeight;
63
69 {
70 get => this._originAuthority;
71 set
72 {
73 this._originAuthority = value;
74 this.UpdateOrigin();
75 }
76 }
77
78 [SerializeField]
79 private double _latitude = 39.736401;
80
87 public double latitude
88 {
89 get => this._latitude;
90 set
91 {
92 this._latitude = value;
93 this.originAuthority = CesiumGeoreferenceOriginAuthority.LongitudeLatitudeHeight;
94 }
95 }
96
97 [SerializeField]
98 private double _longitude = -105.25737;
99
106 public double longitude
107 {
108 get => this._longitude;
109 set
110 {
111 this._longitude = value;
112 this.originAuthority = CesiumGeoreferenceOriginAuthority.LongitudeLatitudeHeight;
113 }
114 }
115
116 [SerializeField]
117 private double _height = 2250.0;
118
127 public double height
128 {
129 get => this._height;
130 set
131 {
132 this._height = value;
133 this.originAuthority = CesiumGeoreferenceOriginAuthority.LongitudeLatitudeHeight;
134 }
135 }
136
137 [SerializeField]
138 private double _ecefX = 6378137.0;
139
146 public double ecefX
147 {
148 get => this._ecefX;
149 set
150 {
151 this._ecefX = value;
152 this.originAuthority = CesiumGeoreferenceOriginAuthority.EarthCenteredEarthFixed;
153 }
154 }
155
156 [SerializeField]
157 private double _ecefY = 0.0;
158
165 public double ecefY
166 {
167 get => this._ecefY;
168 set
169 {
170 this._ecefY = value;
171 this.originAuthority = CesiumGeoreferenceOriginAuthority.EarthCenteredEarthFixed;
172 }
173 }
174
175 [SerializeField]
176 private double _ecefZ = 0.0;
177
184 public double ecefZ
185 {
186 get => this._ecefZ;
187 set
188 {
189 this._ecefZ = value;
190 this.originAuthority = CesiumGeoreferenceOriginAuthority.EarthCenteredEarthFixed;
191 }
192 }
193
194 // The resolved georeference containing this globe anchor. This is just a cache
195 // of `GetComponentInParent<CesiumGeoreference>()`.
196 [NonSerialized]
197 internal CesiumGeoreference _parentGeoreference;
198
199#if UNITY_EDITOR
200 // The coordinates of the parent CesiumGeoreference before being changed by `UpdateOrigin`.
201 // This is used when adding a CesiumSubScene component to a GameObject. Since `OnEnable`
202 // runs before `Reset`, it will force the georeference to move to the default coordinates
203 // of CesiumSubScene, which is undesired. But there's no way to modify `OnEnable` to
204 // distinguish whether the subscene was just added or already existed in the scene.
205 // Instead, we need to store the georeference's previous values during `OnEnable`,
206 // so that we can move it back during `Reset`.
207 [NonSerialized]
208 private double3 _oldParentCoordinates = double3.zero;
209
210 [NonSerialized]
211 private CesiumGeoreferenceOriginAuthority _oldParentOriginAuthority;
212#endif
213
224 public void SetOriginEarthCenteredEarthFixed(double x, double y, double z)
225 {
226 this._ecefX = x;
227 this._ecefY = y;
228 this._ecefZ = z;
229 this.originAuthority = CesiumGeoreferenceOriginAuthority.EarthCenteredEarthFixed;
230 }
231
246 public void SetOriginLongitudeLatitudeHeight(double longitude, double latitude, double height)
247 {
248 this._longitude = longitude;
249 this._latitude = latitude;
250 this._height = height;
251 this.originAuthority = CesiumGeoreferenceOriginAuthority.LongitudeLatitudeHeight;
252 }
253
254 private void CopyParentCoordinates()
255 {
256 this._longitude = this._parentGeoreference.longitude;
257 this._latitude = this._parentGeoreference.latitude;
258 this._height = this._parentGeoreference.height;
259
260 this._ecefX = this._parentGeoreference.ecefX;
261 this._ecefY = this._parentGeoreference.ecefY;
262 this._ecefZ = this._parentGeoreference.ecefZ;
263 }
264
265 private void DetachFromParentIfNeeded()
266 {
267 if (this._parentGeoreference != null)
268 {
269 this._parentGeoreference.changed -= this.OnParentChanged;
270 this._parentGeoreference = null;
271 }
272 }
273
274 private void UpdateParentReference()
275 {
276 DetachFromParentIfNeeded();
277
278 this._parentGeoreference = this.GetComponentInParent<CesiumGeoreference>();
279
280 if (this._parentGeoreference != null)
281 {
282 this._parentGeoreference.Initialize();
283 this._parentGeoreference.changed += this.OnParentChanged;
284 }
285 }
286
292 private void OnValidate()
293 {
294 this.UpdateOrigin();
295 }
296
297#if UNITY_EDITOR
303 private void Reset()
304 {
305 this.UpdateParentReference();
306
307 // The default coordinates for the CesiumSubScene component should be the coordinates of its parent, if possible.
308 // This means adding the component as the child of an existing CesiumGeoreference won't reset the parent's coordinates.
309 if (this._parentGeoreference != null)
310 {
311 if (this._oldParentOriginAuthority == CesiumGeoreferenceOriginAuthority.EarthCenteredEarthFixed)
312 {
313 this._parentGeoreference.SetOriginEarthCenteredEarthFixed(this._oldParentCoordinates.x, this._oldParentCoordinates.y, this._oldParentCoordinates.z);
314 }
315 else
316 {
317 this._parentGeoreference.SetOriginLongitudeLatitudeHeight(this._oldParentCoordinates.x, this._oldParentCoordinates.y, this._oldParentCoordinates.z);
318 }
319
320 this.CopyParentCoordinates();
321 }
322 }
323#endif
324
325 private void OnEnable()
326 {
327 this.UpdateParentReference();
328
329 // If not under a georef, nothing to do
330 if (this._parentGeoreference == null)
331 throw new InvalidOperationException(
332 "CesiumSubScene is not nested inside a game object with a CesiumGeoreference.");
333
334 // When this sub-scene is enabled, all others are disabled.
335 CesiumSubScene[] subscenes = this._parentGeoreference.GetComponentsInChildren<CesiumSubScene>();
336 foreach (CesiumSubScene scene in subscenes)
337 {
338 if (scene == this)
339 continue;
340 scene.gameObject.SetActive(false);
341 }
342
343#if UNITY_EDITOR
344 // The parent's previous coordinates are saved here in case they have to be reverted in the editor during `Reset`
345 this._oldParentOriginAuthority = this._parentGeoreference.originAuthority;
346 if (this._oldParentOriginAuthority == CesiumGeoreferenceOriginAuthority.EarthCenteredEarthFixed)
347 {
348 this._oldParentCoordinates = new double3(this._parentGeoreference.ecefX, this._parentGeoreference.ecefY, this._parentGeoreference.ecefZ);
349 }
350 else
351 {
352 this._oldParentCoordinates = new double3(this._parentGeoreference.longitude, this._parentGeoreference.latitude, this._parentGeoreference.height);
353 }
354#endif
355
356 this.UpdateOrigin();
357 }
358
359 private void OnParentChanged()
360 {
361 if (!this.isActiveAndEnabled)
362 return;
363
364 this.UpdateParentReference();
365
366 // If not under a georef, nothing to do
367 if (this._parentGeoreference == null)
368 {
369 throw new InvalidOperationException(
370 "CesiumSubScene should have been nested inside a game object with a CesiumGeoreference.");
371 }
372
373 // Update our origin to our parent georef, maintain our origin authority,
374 // and copy both sets of reference coordinates. No need to calculate any of this again
375 this.CopyParentCoordinates();
376 }
377
378 private void OnDisable()
379 {
380 DetachFromParentIfNeeded();
381 }
382
383 private void OnDestroy()
384 {
385 DetachFromParentIfNeeded();
386 }
387
388 private void UpdateOtherCoordinates()
389 {
390 if(this._parentGeoreference == null)
391 {
392 this.UpdateParentReference();
393
394 if(this._parentGeoreference == null)
395 {
396 throw new InvalidOperationException("CesiumSubScene should have been nested inside a game object with a CesiumGeoreference.");
397 }
398 }
399
400 if (this._originAuthority == CesiumGeoreferenceOriginAuthority.LongitudeLatitudeHeight)
401 {
402 double3 ecef = this._parentGeoreference.ellipsoid.LongitudeLatitudeHeightToCenteredFixed(new double3(
403 this._longitude,
404 this._latitude,
405 this._height
406 ));
407
408 this._ecefX = ecef.x;
409 this._ecefY = ecef.y;
410 this._ecefZ = ecef.z;
411 }
412
413 if (this._originAuthority == CesiumGeoreferenceOriginAuthority.EarthCenteredEarthFixed)
414 {
415 double3 llh = this._parentGeoreference.ellipsoid.CenteredFixedToLongitudeLatitudeHeight(new double3(
416 this._ecefX,
417 this._ecefY,
418 this._ecefZ
419 ));
420
421 this._longitude = llh.x;
422 this._latitude = llh.y;
423 this._height = llh.z;
424 }
425 }
426
431 public void UpdateOrigin()
432 {
433 UpdateOtherCoordinates();
434
435 if (this.isActiveAndEnabled)
436 {
437 this.UpdateParentReference();
438
439 if (this._parentGeoreference == null)
440 throw new InvalidOperationException("CesiumSubScene is not nested inside a game object with a CesiumGeoreference.");
441
442 if (this.originAuthority == CesiumGeoreferenceOriginAuthority.EarthCenteredEarthFixed)
443 this._parentGeoreference.SetOriginEarthCenteredEarthFixed(
444 this._ecefX,
445 this._ecefY,
446 this._ecefZ);
447 else
448 this._parentGeoreference.SetOriginLongitudeLatitudeHeight(
449 this._longitude,
450 this._latitude,
451 this._height);
452 }
453 }
454
455#if UNITY_EDITOR
456 private void OnDrawGizmos()
457 {
458 if (this._showActivationRadius)
459 {
460 // Gizmos.DrawWireSphere only draws three wire circles representing the sphere's radii
461 // To do better, we need to fetch the built-in sphere mesh and use that
462 if (_previewSphereMesh == null)
463 {
464 _previewSphereMesh = Resources.GetBuiltinResource<Mesh>("Sphere.fbx");
465 }
466
467 Gizmos.color = Color.blue;
468 Gizmos.DrawWireMesh(_previewSphereMesh, this.transform.position, Quaternion.identity, (float3)new double3(this._activationRadius, this._activationRadius, this._activationRadius));
469 }
470 }
471#endif
472 }
473}
partial double3 LongitudeLatitudeHeightToCenteredFixed(double3 longitudeLatitudeHeight)
Convert longitude, latitude, and height to Ellipsoid-Centered, Ellipsoid-Fixed (ECEF) coordinates.
partial double3 CenteredFixedToLongitudeLatitudeHeight(double3 ellipsoidCenteredEllipsoidFixed)
Convert Ellipsoid-Centered, Ellipsoid-Fixed (ECEF) coordinates to longitude, latitude,...
Controls how global geospatial coordinates are mapped to coordinates in the Unity scene.
double ecefZ
The Earth-Centered, Earth-Fixed Z coordinate of the origin of the coordinate system,...
CesiumGeoreferenceOriginAuthority originAuthority
Identifies which set of coordinates authoritatively defines the origin of this georeference.
double ecefX
The Earth-Centered, Earth-Fixed X coordinate of the origin of the coordinate system,...
void SetOriginLongitudeLatitudeHeight(double longitude, double latitude, double height)
Sets the origin of the coordinate system to a particular longitude, latitude, and height.
double latitude
The latitude of the origin of the coordinate system, in degrees, in the range -90 to 90.
double ecefY
The Earth-Centered, Earth-Fixed Y coordinate of the origin of the coordinate system,...
void Initialize()
Initializes this georeference so that other objects may use it to locate the globe in the world.
CesiumEllipsoid ellipsoid
The CesiumEllipsoid that is referenced.
double longitude
The longitude of the origin of the coordinate system, in degrees, in the range -180 to 180.
double height
The height in the origin of the coordinate system, in meters above the ellipsoid.
void SetOriginEarthCenteredEarthFixed(double x, double y, double z)
Sets the origin of the coordinate system to particular ecefX, ecefY, ecefZ coordinates in the Earth-C...
A sub-scene with its own georeference origin.
double latitude
The latitude of the origin of the coordinate system, in degrees, in the range -90 to 90.
double longitude
The longitude of the origin of the coordinate system, in degrees, in the range -180 to 180.
void UpdateOrigin()
Recomputes the coordinate system based on an updated origin.
void SetOriginLongitudeLatitudeHeight(double longitude, double latitude, double height)
Sets the origin of the coordinate system to a particular longitude, latitude, and height.
double ecefY
The Earth-Centered, Earth-Fixed Y coordinate of the origin of the coordinate system,...
double height
The height in the origin of the coordinate system, in meters above the ellipsoid.
void SetOriginEarthCenteredEarthFixed(double x, double y, double z)
Sets the origin of the coordinate system to particular ecefX, ecefY, ecefZ coordinates in the Earth-C...
double ecefZ
The Earth-Centered, Earth-Fixed Z coordinate of the origin of the coordinate system,...
bool showActivationRadius
Whether to show the activation radius as a wireframe sphere in the Editor.
double ecefX
The Earth-Centered, Earth-Fixed X coordinate of the origin of the coordinate system,...
CesiumGeoreferenceOriginAuthority originAuthority
Identifies which set of coordinates authoritatively defines the origin of this sub-scene.
double activationRadius
The maximum distance at which to activate this sub-scene, in meters.
CesiumGeoreferenceOriginAuthority
Identifies the set of the coordinates that authoritatively define the origin of a CesiumGeoreference.