Cesium for Unity 1.15.2
Loading...
Searching...
No Matches
CesiumCameraController.cs
Go to the documentation of this file.
1using UnityEngine;
2using Unity.Mathematics;
3using System.Linq;
4
5
6#if ENABLE_INPUT_SYSTEM
7using UnityEngine.InputSystem;
8#if UNITY_IOS || UNITY_ANDROID
9using EnhancedTouch = UnityEngine.InputSystem.EnhancedTouch;
10#endif
11#endif
12
13namespace CesiumForUnity
14{
21 [RequireComponent(typeof(Camera))]
22 [DisallowMultipleComponent]
23 [AddComponentMenu("Cesium/Cesium Camera Controller")]
24 [IconAttribute("Packages/com.cesium.unity/Editor/Resources/Cesium-24x24.png")]
25 public class CesiumCameraController : MonoBehaviour
26 {
27 #region User-editable properties
28
29 [SerializeField]
30 private bool _enableMovement = true;
31
37 public bool enableMovement
38 {
39 get => this._enableMovement;
40 set
41 {
42 this._enableMovement = value;
43 this.ResetSpeed();
44 }
45 }
46
47 [SerializeField]
48 private bool _enableRotation = true;
49
54 public bool enableRotation
55 {
56 get => this._enableRotation;
57 set => this._enableRotation = value;
58 }
59
60 [SerializeField]
61 [Min(0.0f)]
62 private float _defaultMaximumSpeed = 100.0f;
63
69 {
70 get => this._defaultMaximumSpeed;
71 set => this._defaultMaximumSpeed = Mathf.Max(value, 0.0f);
72 }
73
74 [SerializeField]
75 private bool _enableDynamicSpeed = true;
76
83 {
84 get => this._enableDynamicSpeed;
85 set => this._enableDynamicSpeed = value;
86 }
87
88 [SerializeField]
89 [Min(0.0f)]
90 private float _dynamicSpeedMinHeight = 20.0f;
91
98 {
99 get => this._dynamicSpeedMinHeight;
100 set => this._dynamicSpeedMinHeight = Mathf.Max(value, 0.0f);
101 }
102
103 [SerializeField]
104 private bool _enableDynamicClippingPlanes = true;
105
112 {
113 get => this._enableDynamicClippingPlanes;
114 set => this._enableDynamicClippingPlanes = value;
115 }
116
117 [SerializeField]
118 [Min(0.0f)]
119 private float _dynamicClippingPlanesMinHeight = 10000.0f;
120
126 {
127 get => this._dynamicClippingPlanesMinHeight;
128 set => this._dynamicClippingPlanesMinHeight = Mathf.Max(value, 0.0f);
129 }
130
131#if ENABLE_INPUT_SYSTEM
132 [SerializeField]
133 private InputActionProperty _lookAction;
134
135 [SerializeField]
136 private InputActionProperty _moveAction;
137
138 [SerializeField]
139 private InputActionProperty _moveUpAction;
140
141 [SerializeField]
142 private InputActionProperty _speedChangeAction;
143
144 [SerializeField]
145 private InputActionProperty _speedResetAction;
146
147 [SerializeField]
148 private InputActionProperty _toggleDynamicSpeedAction;
149#endif
150
151 #endregion
152
153 #region Private variables
154
155 private Camera _camera;
156 private float _initialNearClipPlane;
157 private float _initialFarClipPlane;
158
159 private CharacterController _controller;
160 private CesiumGeoreference _georeference;
161 private CesiumGlobeAnchor _globeAnchor;
162
163 private Vector3 _velocity = Vector3.zero;
164 private float _lookSpeed = 10.0f;
165
166 // These numbers are borrowed from Cesium for Unreal.
167 private float _acceleration = 20000.0f;
168 private float _deceleration = 9999999959.0f;
169 private float _maxRaycastDistance = 1000 * 1000; // 1000 km;
170
171 private float _maxSpeed = 100.0f; // Maximum speed with the speed multiplier applied.
172 private float _maxSpeedPreMultiplier = 0.0f; // Max speed without the multiplier applied.
173 private AnimationCurve _maxSpeedCurve;
174
175 private float _speedMultiplier = 1.0f;
176 private float _speedMultiplierIncrement = 1.5f;
177
178 // If the near clip gets too large, Unity will throw errors. Keeping it
179 // at this value works fine even when the far clip plane gets large.
180 private float _maximumNearClipPlane = 1000.0f;
181 private float _maximumFarClipPlane = 500000000.0f;
182
183 // The maximum ratio that the far clip plane is allowed to be larger
184 // than the near clip plane. The near clip plane is set so that this
185 // ratio is never exceeded.
186 private float _maximumNearToFarRatio = 100000.0f;
187
188 #endregion
189
190 #region Input configuration
191
192#if ENABLE_INPUT_SYSTEM
193 private bool HasInputAction(InputActionProperty property)
194 {
195 return (property.action != null && property.action.bindings.Any()) || (property.reference != null);
196 }
197
198 void ConfigureInputs()
199 {
200#if UNITY_IOS || UNITY_ANDROID
201 EnhancedTouch.EnhancedTouchSupport.Enable();
202#endif
203 InputActionMap map = new InputActionMap("Cesium Camera Controller");
204
205 if (!HasInputAction(_lookAction))
206 {
207 InputAction newLookAction = map.AddAction("look", binding: "<Mouse>/delta");
208 newLookAction.AddBinding("<Gamepad>/rightStick").WithProcessor("scaleVector2(x=15, y=15)");
209 _lookAction = new InputActionProperty(newLookAction);
210 }
211
212 if (!HasInputAction(_moveAction))
213 {
214 InputAction newMoveAction = map.AddAction("move", binding: "<Gamepad>/leftStick");
215 newMoveAction.AddCompositeBinding("Dpad")
216 .With("Up", "<Keyboard>/w")
217 .With("Down", "<Keyboard>/s")
218 .With("Left", "<Keyboard>/a")
219 .With("Right", "<Keyboard>/d")
220 .With("Up", "<Keyboard>/upArrow")
221 .With("Down", "<Keyboard>/downArrow")
222 .With("Left", "<Keyboard>/leftArrow")
223 .With("Right", "<Keyboard>/rightArrow");
224 _moveAction = new InputActionProperty(newMoveAction);
225 }
226
227 if (!HasInputAction(_moveUpAction))
228 {
229 InputAction newMoveUpAction = map.AddAction("moveUp");
230 newMoveUpAction.AddCompositeBinding("Dpad")
231 .With("Up", "<Keyboard>/space")
232 .With("Down", "<Keyboard>/c")
233 .With("Up", "<Keyboard>/e")
234 .With("Down", "<Keyboard>/q")
235 .With("Up", "<Gamepad>/rightTrigger")
236 .With("Down", "<Gamepad>/leftTrigger");
237 _moveUpAction = new InputActionProperty(newMoveUpAction);
238 }
239
240 if (!HasInputAction(_speedChangeAction))
241 {
242 InputAction newSpeedChangeAction = map.AddAction("speedChange", binding: "<Mouse>/scroll");
243 newSpeedChangeAction.AddCompositeBinding("Dpad")
244 .With("Up", "<Gamepad>/rightShoulder")
245 .With("Down", "<Gamepad>/leftShoulder");
246 _speedChangeAction = new InputActionProperty(newSpeedChangeAction);
247 }
248
249 if (!HasInputAction(_speedResetAction))
250 {
251 InputAction newSpeedResetAction = map.AddAction("speedReset", binding: "<Mouse>/middleButton");
252 newSpeedResetAction.AddBinding("<Gamepad>/buttonNorth");
253 _speedResetAction = new InputActionProperty(newSpeedResetAction);
254 }
255
256 if (!HasInputAction(_toggleDynamicSpeedAction))
257 {
258 InputAction newToggleDynamicSpeedAction =
259 map.AddAction("toggleDynamicSpeed", binding: "<Keyboard>/g");
260 newToggleDynamicSpeedAction.AddBinding("<Gamepad>/buttonEast");
261 _toggleDynamicSpeedAction = new InputActionProperty(newToggleDynamicSpeedAction);
262 }
263
264 _moveAction.action.Enable();
265 _lookAction.action.Enable();
266 _moveUpAction.action.Enable();
267 _speedChangeAction.action.Enable();
268 _speedResetAction.action.Enable();
269 _toggleDynamicSpeedAction.action.Enable();
270 }
271#endif
272
273 #endregion
274
275 #region Initialization
276
277 private void InitializeCamera()
278 {
279 this._camera = this.gameObject.GetComponent<Camera>();
280 this._initialNearClipPlane = this._camera.nearClipPlane;
281 this._initialFarClipPlane = this._camera.farClipPlane;
282 }
283
284 private void InitializeController()
285 {
286 if (this._globeAnchor.GetComponent<CharacterController>() != null)
287 {
288 Debug.LogWarning(
289 "A CharacterController component was manually " +
290 "added to the CesiumGlobeAnchor's game object. " +
291 "This may interfere with the CesiumCameraController's movement.");
292
293 this._controller = this._globeAnchor.GetComponent<CharacterController>();
294 }
295 else
296 {
297 this._controller = this._globeAnchor.gameObject.AddComponent<CharacterController>();
298 this._controller.hideFlags = HideFlags.HideInInspector;
299 }
300
301 this._controller.radius = 1.0f;
302 this._controller.height = 1.0f;
303 this._controller.center = Vector3.zero;
304 this._controller.detectCollisions = true;
305 }
306
312 private void CreateMaxSpeedCurve()
313 {
314 // This creates a curve that is linear between the first two keys,
315 // then smoothly interpolated between the last two keys.
316 Keyframe[] keyframes = {
317 new Keyframe(0.0f, 4.0f),
318 new Keyframe(10000000.0f, 10000000.0f),
319 new Keyframe(13000000.0f, 2000000.0f)
320 };
321
322 keyframes[0].weightedMode = WeightedMode.Out;
323 keyframes[0].outTangent = keyframes[1].value / keyframes[0].value;
324 keyframes[0].outWeight = 0.0f;
325
326 keyframes[1].weightedMode = WeightedMode.In;
327 keyframes[1].inWeight = 0.0f;
328 keyframes[1].inTangent = keyframes[1].value / keyframes[0].value;
329 keyframes[1].outTangent = 0.0f;
330
331 keyframes[2].inTangent = 0.0f;
332
333 this._maxSpeedCurve = new AnimationCurve(keyframes);
334 this._maxSpeedCurve.preWrapMode = WrapMode.ClampForever;
335 this._maxSpeedCurve.postWrapMode = WrapMode.ClampForever;
336 }
337
338 void Awake()
339 {
340 this._georeference = this.gameObject.GetComponentInParent<CesiumGeoreference>();
341 if (this._georeference == null)
342 {
343 Debug.LogError(
344 "CesiumCameraController must be nested under a game object " +
345 "with a CesiumGeoreference.");
346 }
347
348 this._globeAnchor = this.gameObject.GetComponentInParent<CesiumGlobeAnchor>();
349 if (this._globeAnchor == null)
350 {
351 Debug.LogError("CesiumCameraController must have a CesiumGlobeAnchor " +
352 "attached to itself or a parent");
353 }
354
355 CesiumOriginShift originShift = this._globeAnchor.GetComponent<CesiumOriginShift>();
356 if (originShift == null)
357 {
358 Debug.LogError("CesiumCameraController expects a CesiumOriginShift " +
359 $"on {this._globeAnchor?.name}, none found");
360 }
361
362 this.InitializeCamera();
363 this.InitializeController();
364 this.CreateMaxSpeedCurve();
365
366#if ENABLE_INPUT_SYSTEM
367 this.ConfigureInputs();
368#endif
369 }
370
371#if UNITY_EDITOR
372 // Ensures required components are present in the editor.
373 private void Reset()
374 {
375 CesiumGlobeAnchor anchor = this.gameObject.GetComponentInParent<CesiumGlobeAnchor>();
376 if (anchor == null)
377 {
378 anchor = this.gameObject.AddComponent<CesiumGlobeAnchor>();
379 Debug.LogWarning("CesiumCameraController missing a CesiumGlobeAnchor - adding");
380 }
381
382 CesiumOriginShift origin = anchor.GetComponent<CesiumOriginShift>();
383 if (origin == null)
384 {
385 origin = anchor.gameObject.AddComponent<CesiumOriginShift>();
386 Debug.LogWarning("CesiumCameraController missing a CesiumOriginShift - adding");
387 }
388 }
389#endif
390
391 #endregion
392
393 #region Update
394
395 void FixedUpdate()
396 {
397 this.HandlePlayerInputs();
398
399 if (this._enableDynamicClippingPlanes)
400 {
401 this.UpdateClippingPlanes();
402 }
403 }
404
405 #endregion
406
407 #region Raycasting helpers
408
409 private bool RaycastTowardsEarthCenter(out float hitDistance)
410 {
411 if (this._georeference == null)
412 {
413 hitDistance = 0.0f;
414 return false;
415 }
416
417 double3 center =
418 this._georeference.TransformEarthCenteredEarthFixedPositionToUnity(new double3(0.0));
419
420 RaycastHit hitInfo;
421 if (Physics.Linecast(this.transform.position, (float3)center, out hitInfo))
422 {
423 hitDistance = Vector3.Distance(this.transform.position, hitInfo.point);
424 return true;
425 }
426
427 hitDistance = 0.0f;
428 return false;
429 }
430
431 private bool RaycastAlongForwardVector(float raycastDistance, out float hitDistance)
432 {
433 RaycastHit hitInfo;
434 if (Physics.Raycast(
435 this.transform.position,
436 this.transform.forward,
437 out hitInfo,
438 raycastDistance))
439 {
440 hitDistance = Vector3.Distance(this.transform.position, hitInfo.point);
441 return true;
442 }
443
444 hitDistance = 0.0f;
445 return false;
446 }
447
448 #endregion
449
450 #region Player movement
451
452 private void HandlePlayerInputs()
453 {
454#if ENABLE_INPUT_SYSTEM
455 Vector2 lookDelta;
456 Vector2 moveDelta;
457 lookDelta = _lookAction.action.ReadValue<Vector2>();
458 moveDelta = _moveAction.action.ReadValue<Vector2>();
459
460#if UNITY_IOS || UNITY_ANDROID
461 bool handledMove = false;
462 bool handledLook = false;
463
464 foreach(var touch in EnhancedTouch.Touch.activeTouches)
465 {
466 if(touch.startScreenPosition.x < Screen.width / 2)
467 {
468 if(!handledMove)
469 {
470 handledMove = true;
471 moveDelta = touch.screenPosition - touch.startScreenPosition;
472 }
473 }
474 else
475 {
476 if(!handledLook)
477 {
478 handledLook = true;
479 lookDelta = touch.delta;
480 }
481 }
482 }
483#endif
484
485 float inputRotateHorizontal = lookDelta.x;
486 float inputRotateVertical = lookDelta.y;
487
488 float inputForward = moveDelta.y;
489 float inputRight = moveDelta.x;
490
491 float inputUp = _moveUpAction.action.ReadValue<Vector2>().y;
492
493 float inputSpeedChange = _speedChangeAction.action.ReadValue<Vector2>().y;
494 bool inputSpeedReset = _speedResetAction.action.ReadValue<float>() > 0.5f;
495
496 bool toggleDynamicSpeed = _toggleDynamicSpeedAction.action.ReadValue<float>() > 0.5f;
497#else
498 float inputRotateHorizontal = Input.GetAxis("Mouse X");
499 float inputRotateVertical = Input.GetAxis("Mouse Y");
500
501 float inputForward = Input.GetAxis("Vertical");
502 float inputRight = Input.GetAxis("Horizontal");
503 float inputUp = 0.0f;
504
505 if (Input.GetKeyDown("q"))
506 {
507 inputUp -= 1.0f;
508 }
509
510 if (Input.GetKeyDown("e"))
511 {
512 inputUp += 1.0f;
513 }
514
515 float inputSpeedChange = Input.GetAxis("Mouse ScrollWheel");
516 bool inputSpeedReset =
517 Input.GetMouseButtonDown(2) || Input.GetKeyDown("joystick button 3");
518
519 bool toggleDynamicSpeed =
520 Input.GetKeyDown("g") || Input.GetKeyDown("joystick button 1");
521#endif
522
523 Vector3 movementInput = new Vector3(inputRight, inputUp, inputForward);
524
525 if (this._enableRotation)
526 {
527 this.Rotate(inputRotateHorizontal, inputRotateVertical);
528 }
529
530 if (toggleDynamicSpeed)
531 {
532 this._enableDynamicSpeed = !this._enableDynamicSpeed;
533 }
534
535 if (inputSpeedReset ||
536 (this._enableDynamicSpeed && movementInput == Vector3.zero))
537 {
538 this.ResetSpeedMultiplier();
539 }
540 else
541 {
542 this.HandleSpeedChange(inputSpeedChange);
543 }
544
545 if (this._enableMovement)
546 {
547 this.Move(movementInput);
548 }
549 }
550
551 private void HandleSpeedChange(float speedChangeInput)
552 {
553 if (this._enableDynamicSpeed)
554 {
555 this.UpdateDynamicSpeed();
556 }
557 else
558 {
559 this.SetMaxSpeed(this._defaultMaximumSpeed);
560 }
561
562 if (speedChangeInput != 0.0f)
563 {
564 if (speedChangeInput > 0.0f)
565 {
566 this._speedMultiplier *= this._speedMultiplierIncrement;
567 }
568 else
569 {
570 this._speedMultiplier /= this._speedMultiplierIncrement;
571 }
572
573 float max = this._enableDynamicSpeed ? 50.0f : 50000.0f;
574 this._speedMultiplier = Mathf.Clamp(this._speedMultiplier, 0.1f, max);
575 }
576 }
577
587 private void Rotate(float horizontalRotation, float verticalRotation)
588 {
589 if (horizontalRotation == 0.0f && verticalRotation == 0.0f)
590 {
591 return;
592 }
593
594 float valueX = verticalRotation * this._lookSpeed * Time.fixedDeltaTime;
595 float valueY = horizontalRotation * this._lookSpeed * Time.fixedDeltaTime;
596
597 // Rotation around the X-axis occurs counter-clockwise, so the look range
598 // maps to [270, 360] degrees for the upper quarter-sphere of motion, and
599 // [0, 90] degrees for the lower. Euler angles only work with positive values,
600 // so map the [0, 90] range to [360, 450] so the entire range is [270, 450].
601 // This makes it easy to clamp the values.
602 float rotationX = this.transform.localEulerAngles.x;
603 if (rotationX <= 90.0f)
604 {
605 rotationX += 360.0f;
606 }
607
608 float newRotationX = Mathf.Clamp(rotationX - valueX, 270.0f, 450.0f);
609 float newRotationY = this.transform.localEulerAngles.y + valueY;
610 this.transform.localRotation =
611 Quaternion.Euler(newRotationX, newRotationY, this.transform.localEulerAngles.z);
612 }
613
623 private void Move(Vector3 movementInput)
624 {
625 Vector3 inputDirection =
626 this.transform.right * movementInput.x + this.transform.forward * movementInput.z;
627
628 if (this._georeference != null)
629 {
630 double3 positionECEF = this._globeAnchor.positionGlobeFixed;
631 double3 upECEF = this._georeference.ellipsoid.GeodeticSurfaceNormal(positionECEF);
632 double3 upUnity =
633 this._georeference.TransformEarthCenteredEarthFixedDirectionToUnity(upECEF);
634
635 inputDirection = (float3)inputDirection + (float3)upUnity * movementInput.y;
636 }
637
638 if (inputDirection != Vector3.zero)
639 {
640 // If the controller was already moving, handle the direction change
641 // separately from the magnitude of the velocity.
642 if (this._velocity.magnitude > 0.0f)
643 {
644 Vector3 directionChange = inputDirection - this._velocity.normalized;
645 this._velocity +=
646 directionChange * this._velocity.magnitude * Time.fixedDeltaTime;
647 }
648
649 this._velocity += inputDirection * this._acceleration * Time.fixedDeltaTime;
650 this._velocity = Vector3.ClampMagnitude(this._velocity, this._maxSpeed);
651 }
652 else
653 {
654 // Decelerate
655 float speed = Mathf.Max(
656 this._velocity.magnitude - this._deceleration * Time.fixedDeltaTime,
657 0.0f);
658
659 this._velocity = Vector3.ClampMagnitude(this._velocity, speed);
660 }
661
662 if (this._velocity != Vector3.zero)
663 {
664 this._controller.Move(this._velocity * Time.fixedDeltaTime);
665
666 // Other controllers may disable detectTransformChanges to control their own
667 // movement, but the globe anchor should be synced even if detectTransformChanges
668 // is false.
669 if (!this._globeAnchor.detectTransformChanges)
670 {
671 this._globeAnchor.Sync();
672 }
673 }
674 }
675
676 #endregion
677
678 #region Dynamic speed computation
679
688 private bool GetDynamicSpeed(out bool overrideSpeed, out float newSpeed)
689 {
690 if (this._georeference == null)
691 {
692 overrideSpeed = false;
693 newSpeed = 0.0f;
694
695 return false;
696 }
697
698 float height, viewDistance;
699
700 // Raycast from the camera to the Earth's center and compute the distance.
701 // Ignore the result if the height is approximately 0.
702 if (!this.RaycastTowardsEarthCenter(out height) || height < 0.000001f)
703 {
704 overrideSpeed = false;
705 newSpeed = 0.0f;
706
707 return false;
708 }
709
710 // Also ignore the result if the speed will increase or decrease by too much at once.
711 // This can be an issue when 3D tiles are loaded/unloaded from the scene.
712 if (this._maxSpeedPreMultiplier > 0.5f)
713 {
714 float heightToMaxSpeedRatio = height / this._maxSpeedPreMultiplier;
715
716 // The asymmetry of these ratios is intentional. When traversing tilesets
717 // with many height differences (e.g. a city with tall buildings), flying over
718 // taller geometry will cause the camera to slow down suddenly, and sometimes
719 // cause it to stutter.
720 if (heightToMaxSpeedRatio > 1000.0f || heightToMaxSpeedRatio < 0.01f)
721 {
722 overrideSpeed = false;
723 newSpeed = 0.0f;
724
725 return false;
726 }
727 }
728
729 // Raycast along the camera's view (forward) vector.
730 float raycastDistance =
731 Mathf.Clamp(this._maxSpeed * 3.0f, 0.0f, this._maxRaycastDistance);
732
733 // If the raycast does not hit, then only override speed if the height
734 // is lower than the maximum threshold. Otherwise, if both raycasts hit,
735 // always override the speed.
736 if (!this.RaycastAlongForwardVector(raycastDistance, out viewDistance) ||
737 viewDistance < 0.000001f)
738 {
739 overrideSpeed = height <= this._dynamicSpeedMinHeight;
740 }
741 else
742 {
743 overrideSpeed = true;
744 }
745
746 // Set the speed to be the height of the camera from the Earth's center.
747 newSpeed = height;
748
749 return true;
750 }
751
752 private void ResetSpeedMultiplier()
753 {
754 this._speedMultiplier = 1.0f;
755 }
756
757 private void SetMaxSpeed(float speed)
758 {
759 float actualSpeed = this._maxSpeedCurve.Evaluate(speed);
760 this._maxSpeed = this._speedMultiplier * actualSpeed;
761 this._acceleration =
762 Mathf.Clamp(this._maxSpeed * 5.0f, 20000.0f, 10000000.0f);
763 }
764
765 private void UpdateDynamicSpeed()
766 {
767 bool overrideSpeed;
768 float newSpeed;
769 if (this.GetDynamicSpeed(out overrideSpeed, out newSpeed))
770 {
771 if (overrideSpeed || newSpeed >= this._maxSpeedPreMultiplier)
772 {
773 this._maxSpeedPreMultiplier = newSpeed;
774 }
775 }
776
777 this.SetMaxSpeed(this._maxSpeedPreMultiplier);
778 }
779
780 private void ResetSpeed()
781 {
782 this._maxSpeed = this._defaultMaximumSpeed;
783 this._maxSpeedPreMultiplier = 0.0f;
784 this.ResetSpeedMultiplier();
785 }
786
787 #endregion
788
789 #region Dynamic clipping plane adjustment
790
791 private void UpdateClippingPlanes()
792 {
793 if (this._camera == null)
794 {
795 return;
796 }
797
798 // Raycast from the camera to the Earth's center and compute the distance.
799 float height = 0.0f;
800 if (!this.RaycastTowardsEarthCenter(out height))
801 {
802 return;
803 }
804
805 float nearClipPlane = this._initialNearClipPlane;
806 float farClipPlane = this._initialFarClipPlane;
807
808 if (height >= this._dynamicClippingPlanesMinHeight)
809 {
810 farClipPlane = height + (float)(2.0 * this._georeference.ellipsoid.GetMaximumRadius());
811 farClipPlane = Mathf.Min(farClipPlane, this._maximumFarClipPlane);
812
813 float farClipRatio = farClipPlane / this._maximumNearToFarRatio;
814
815 if (farClipRatio > nearClipPlane)
816 {
817 nearClipPlane = Mathf.Min(farClipRatio, this._maximumNearClipPlane);
818 }
819 }
820
821 this._camera.nearClipPlane = nearClipPlane;
822 this._camera.farClipPlane = farClipPlane;
823 }
824
825 #endregion
826 }
827}
A camera controller that can easily move around and view the globe while maintaining a sensible orien...
float defaultMaximumSpeed
The maximum speed of this controller when dynamic speed is disabled.
bool enableDynamicClippingPlanes
Whether to dynamically adjust the camera's clipping planes so that the globe will not be clipped from...
bool enableDynamicSpeed
Whether to enable dynamic speed on this controller.
float dynamicClippingPlanesMinHeight
The height to start dynamically adjusting the camera's clipping planes.
float dynamicSpeedMinHeight
The minimum height where dynamic speed starts to take effect.
bool enableMovement
Whether movement is enabled on this controller.
bool enableRotation
Whether rotation is enabled on this controller.
double GetMaximumRadius()
Gets the maximum radius of the ellipsoid in any dimension.
partial double3 GeodeticSurfaceNormal(double3 ellipsoidCenteredEllipsoidFixed)
Computes the normal of the plane tangent to the surface of the ellipsoid at the provided Ellipsoid-Ce...
Controls how global geospatial coordinates are mapped to coordinates in the Unity scene.
double3 TransformEarthCenteredEarthFixedPositionToUnity(double3 earthCenteredEarthFixed)
Transform an Earth-Centered, Earth-Fixed position to Unity coordinates.
CesiumEllipsoid ellipsoid
The CesiumEllipsoid that is referenced.
double3 TransformEarthCenteredEarthFixedDirectionToUnity(double3 earthCenteredEarthFixedDirection)
Transform an Earth-Centered, Earth-Fixed direction to Unity coordinates.
Anchors this game object to the globe.
bool detectTransformChanges
Gets or sets whether to automatically detect changes in the game object's.
double3 positionGlobeFixed
Gets or sets the game object's position in the Earth-Centered, Earth-Fixed (ECEF) coordinates in mete...
void Sync()
Synchronizes the properties of this CesiumGlobeAnchor.