WorldTracker_GPS.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.Runtime.InteropServices;
  5. using System.Linq;
  6. using UnityEngine;
  7. using UnityEngine.Events;
  8. #if ENABLE_INPUT_SYSTEM
  9. using UnityEngine.InputSystem;
  10. #endif
  11. namespace Imagine.WebAR
  12. {
  13. [System.Serializable]
  14. public class GeolocationSettings{
  15. [SerializeField] public float activationRadius = 50;
  16. [SerializeField] public float pinRadius = 5;
  17. [HideInInspector] public List<GPSPin> gpsPins;
  18. [SerializeField] public UnityEvent<GPSData> OnGPSPositionUpdated;
  19. [SerializeField] public UnityEvent<GPSPin> OnGPSPinInRange;
  20. [SerializeField] public UnityEvent<GPSPin> OnGPSPinOutOfRange;
  21. [SerializeField] public UnityEvent OnAllGPSPinsOutOfRange;
  22. [SerializeField] public UnityEvent<GPSPin> OnEnterGPSPin;
  23. [SerializeField] public UnityEvent<GPSPin> OnExitGPSPin;
  24. // [Space]
  25. // [SerializeField] public double testLatitude;
  26. // [SerializeField] public double testLongitude;
  27. }
  28. public class GPSData{
  29. public double accuracy, altitude, altitudeAccuracy, heading, latitude, longitude, speed, distanceFromOrigin, alpha;
  30. }
  31. public partial class WorldTracker
  32. {
  33. [DllImport("__Internal")] private static extern void WebGLGetGPSPosition();
  34. [DllImport("__Internal")] private static extern void WebGLSubscribeToGPSPositionUpdates();
  35. [DllImport("__Internal")] private static extern void WebGLUnsubscribeToGPSPositionUpdates();
  36. [SerializeField] public bool useGeolocation = false;
  37. [SerializeField] public GeolocationSettings geolocationSettings;
  38. public GPSData cameraPosData;
  39. private bool noPinsInRange = true;
  40. public void StartGPS(){
  41. if(useGeolocation){
  42. geolocationSettings.gpsPins = FindObjectsOfType<GPSPin>().ToList();
  43. Debug.Log("Found gps pins - " + geolocationSettings.gpsPins.Count);
  44. #if UNITY_WEBGL && !UNITY_EDITOR
  45. WebGLSubscribeToGPSPositionUpdates();
  46. #endif
  47. }
  48. #if UNITY_EDITOR
  49. OnGPSPosition("0,0,0,0," + debugStartLat + "," + debugStartLon + ",0,0");
  50. #endif
  51. }
  52. float gpsTestoffsetX = 0;
  53. float gpsTestoffsetZ = 0;
  54. [SerializeField] double debugStartLat = -27.516158;
  55. [SerializeField] double debugStartLon = 153.269033;
  56. public void OnDestroyGPS(){
  57. if(useGeolocation){
  58. #if !UNITY_EDITOR && UNITY_WEBGL
  59. WebGLUnsubscribeToGPSPositionUpdates();
  60. #endif
  61. }
  62. }
  63. public void OnGPSPosition(string data){
  64. data = data.Replace("null","0").Replace("NaN","0");
  65. // Debug.Log(data);
  66. var vals = data.Split(new string[]{","}, System.StringSplitOptions.RemoveEmptyEntries);
  67. cameraPosData = new GPSData{
  68. // accuracy = double.Parse(vals[0], CultureInfo.InvariantCulture),
  69. altitude = double.Parse(vals[1], CultureInfo.InvariantCulture),
  70. // altitudeAccuracy = double.Parse(vals[2], CultureInfo.InvariantCulture),
  71. // heading = double.Parse(vals[3], CultureInfo.InvariantCulture),
  72. latitude = double.Parse(vals[4], CultureInfo.InvariantCulture),
  73. longitude = double.Parse(vals[5], CultureInfo.InvariantCulture),
  74. // speed = double.Parse(vals[6], CultureInfo.InvariantCulture),
  75. // alpha = double.Parse(vals[7], CultureInfo.InvariantCulture)
  76. };
  77. var nearbyPinCount = 0;
  78. foreach (var pin in geolocationSettings.gpsPins){
  79. //reposition GPS objects based on new coordinates
  80. var pos = pin.ConvertGPSToCartesian(
  81. cameraPosData.latitude,
  82. cameraPosData.longitude,
  83. pin.altitude
  84. );
  85. pin.targetPos = pos;
  86. var distance = Vector3.Distance(trackerCamera.transform.position, pin.transform.position);
  87. // Debug.Log(pin.transform.name + " is " + distance + " m away");
  88. //Debug.Log(pin.name + " " + distance + " " + pin.inRange);
  89. if( distance > geolocationSettings.activationRadius && pin.inRange)
  90. {
  91. pin.inRange = false;
  92. Debug.Log("Pin " + pin.id + " out of range!");
  93. pin.transform.gameObject.SetActive(false);
  94. geolocationSettings.OnGPSPinOutOfRange?.Invoke(pin);
  95. }
  96. else if(distance <= geolocationSettings.activationRadius)
  97. {
  98. nearbyPinCount++;
  99. if(!pin.inRange){
  100. pin.inRange = true;
  101. Debug.Log("Pin " + pin.id + " in range!");
  102. pin.transform.gameObject.SetActive(true);
  103. geolocationSettings.OnGPSPinInRange?.Invoke(pin);
  104. }
  105. }
  106. }
  107. // Debug.Log("nearbyPins = " + nearbyPinCount);
  108. if(!noPinsInRange && nearbyPinCount <= 0){
  109. Debug.Log("No pins in range!");
  110. geolocationSettings.OnAllGPSPinsOutOfRange?.Invoke();
  111. }
  112. noPinsInRange = (nearbyPinCount <= 0);
  113. geolocationSettings.OnGPSPositionUpdated.Invoke(cameraPosData);
  114. }
  115. public void OnGPSPositionError(string error){
  116. Debug.LogError(error);
  117. }
  118. public void UpdateGPS(){
  119. if(useGeolocation){
  120. float lerpSpeed = 2.5f;
  121. foreach(var pin in geolocationSettings.gpsPins){
  122. pin.transform.position = Vector3.Lerp(pin.transform.position, pin.targetPos, Time.deltaTime * lerpSpeed);
  123. var distance = Vector3.Distance(pin.transform.position, trackerCamera.transform.position);
  124. if(distance <= geolocationSettings.pinRadius && !pin.entered){
  125. pin.entered = true;
  126. geolocationSettings.OnEnterGPSPin?.Invoke(pin);
  127. }
  128. else if (distance > geolocationSettings.pinRadius && pin.entered){
  129. pin.entered = false;
  130. geolocationSettings.OnExitGPSPin?.Invoke(pin);
  131. }
  132. }
  133. }
  134. }
  135. void Update_DebugGeolocation(){
  136. float sensitivity = 0.0002f;
  137. #if ENABLE_INPUT_SYSTEM
  138. var moveRight = Keyboard.current != null && Keyboard.current.dKey.isPressed ? 1 : 0;
  139. var moveLeft = Keyboard.current != null && Keyboard.current.aKey.isPressed ? -1 : 0;
  140. var moveFwd = Keyboard.current != null && Keyboard.current.wKey.isPressed ? 1 : 0;
  141. var moveBack = Keyboard.current != null && Keyboard.current.sKey.isPressed ? -1 : 0;
  142. gpsTestoffsetZ += (moveRight + moveLeft) * sensitivity * Time.deltaTime;
  143. gpsTestoffsetX += (moveFwd + moveBack) * sensitivity * Time.deltaTime;
  144. #else
  145. gpsTestoffsetZ += Input.GetAxis("Horizontal") * sensitivity * Time.deltaTime;
  146. gpsTestoffsetX += Input.GetAxis("Vertical") * sensitivity * Time.deltaTime;
  147. #endif
  148. var lat = debugStartLat + gpsTestoffsetX;
  149. var lon = debugStartLon + gpsTestoffsetZ;
  150. OnGPSPosition("0,0,0,0," + lat.ToString(CultureInfo.InvariantCulture) + "," + lon.ToString(CultureInfo.InvariantCulture) + ",0,0");
  151. }
  152. }
  153. }