SW 중심대학 OSS GIT 서버 박건태, 이승준, 고기완, 이준호 새로운 배포
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

236 lines
9.1 KiB

4 years ago
  1. using System;
  2. using System.Collections.Generic;
  3. using Unity.Collections;
  4. using UnityEngine.XR.ARSubsystems;
  5. namespace UnityEngine.XR.ARFoundation
  6. {
  7. /// <summary>
  8. /// Manages an <c>XRRaycastSubsystem</c>, exposing raycast functionality in ARFoundation. Use this component
  9. /// to raycast against trackables (i.e., detected features in the physical environment) when they do not have
  10. /// a presence in the Physics world.
  11. /// </summary>
  12. [DisallowMultipleComponent]
  13. [RequireComponent(typeof(ARSessionOrigin))]
  14. [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@3.0/api/UnityEngine.XR.ARFoundation.ARRaycastManager.html")]
  15. public sealed class ARRaycastManager : SubsystemLifecycleManager<XRRaycastSubsystem, XRRaycastSubsystemDescriptor>
  16. {
  17. /// <summary>
  18. /// Cast a ray from a point in screen space against trackables, i.e., detected features such as planes.
  19. /// </summary>
  20. /// <param name="screenPoint">The point, in device screen pixels, from which to cast.</param>
  21. /// <param name="hitResults">Contents are replaced with the raycast results, if successful.</param>
  22. /// <param name="trackableTypes">(Optional) The types of trackables to cast against.</param>
  23. /// <returns>True if the raycast hit a trackable in the <paramref name="trackableTypes"/></returns>
  24. public bool Raycast(
  25. Vector2 screenPoint,
  26. List<ARRaycastHit> hitResults,
  27. TrackableType trackableTypes = TrackableType.All)
  28. {
  29. if (subsystem == null)
  30. return false;
  31. if (hitResults == null)
  32. throw new ArgumentNullException("hitResults");
  33. var nativeHits = m_RaycastViewportDelegate(screenPoint, trackableTypes, Allocator.Temp);
  34. var originTransform = m_SessionOrigin.camera != null ? m_SessionOrigin.camera.transform : m_SessionOrigin.trackablesParent;
  35. return TransformAndDisposeNativeHitResults(nativeHits, hitResults, originTransform.position);
  36. }
  37. /// <summary>
  38. /// Cast a <c>Ray</c> against trackables, i.e., detected features such as planes.
  39. /// </summary>
  40. /// <param name="ray">The <c>Ray</c>, in Unity world space, to cast.</param>
  41. /// <param name="hitResults">Contents are replaced with the raycast results, if successful.</param>
  42. /// <param name="trackableTypes">(Optional) The types of trackables to cast against.</param>
  43. /// <returns>True if the raycast hit a trackable in the <paramref name="trackableTypes"/></returns>
  44. public bool Raycast(
  45. Ray ray,
  46. List<ARRaycastHit> hitResults,
  47. TrackableType trackableTypes = TrackableType.All)
  48. {
  49. if (subsystem == null)
  50. return false;
  51. if (hitResults == null)
  52. throw new ArgumentNullException("hitResults");
  53. var sessionSpaceRay = m_SessionOrigin.trackablesParent.InverseTransformRay(ray);
  54. var nativeHits = m_RaycastRayDelegate(sessionSpaceRay, trackableTypes, Allocator.Temp);
  55. return TransformAndDisposeNativeHitResults(nativeHits, hitResults, ray.origin);
  56. }
  57. static void TransformAndSortRaycastResults(
  58. Transform transform,
  59. NativeArray<XRRaycastHit> nativeHits,
  60. List<ARRaycastHit> managedHits,
  61. Vector3 rayOrigin)
  62. {
  63. foreach (var nativeHit in nativeHits)
  64. {
  65. float distanceInWorldSpace = (nativeHit.pose.position - rayOrigin).magnitude;
  66. managedHits.Add(new ARRaycastHit(nativeHit, distanceInWorldSpace, transform));
  67. }
  68. }
  69. /// <summary>
  70. /// Allows AR managers to register themselves as a raycaster.
  71. /// Raycasters be used as a fallback method if the AR platform does
  72. /// not support raycasting using arbitrary <c>Ray</c>s.
  73. /// </summary>
  74. /// <param name="raycaster">A raycaster implementing the IRaycast interface.</param>
  75. internal void RegisterRaycaster(IRaycaster raycaster)
  76. {
  77. ConstructIfNecessary();
  78. if (!m_Raycasters.Contains(raycaster))
  79. m_Raycasters.Add(raycaster);
  80. }
  81. /// <summary>
  82. /// Unregisters a raycaster previously registered with <see cref="RegisterRaycaster(IRaycaster)"/>.
  83. /// </summary>
  84. /// <param name="raycaster">A raycaster to use in the fallback case.</param>
  85. internal void UnregisterRaycaster(IRaycaster raycaster)
  86. {
  87. if (m_Raycasters != null)
  88. m_Raycasters.Remove(raycaster);
  89. }
  90. protected override void OnAfterStart()
  91. {
  92. if (subsystem.SubsystemDescriptor.supportsViewportBasedRaycast)
  93. {
  94. m_RaycastViewportDelegate = RaycastViewport;
  95. }
  96. else
  97. {
  98. m_RaycastViewportDelegate = RaycastViewportAsRay;
  99. }
  100. if (subsystem.SubsystemDescriptor.supportsWorldBasedRaycast)
  101. {
  102. m_RaycastRayDelegate = RaycastRay;
  103. }
  104. else
  105. {
  106. m_RaycastRayDelegate = RaycastFallback;
  107. }
  108. var raycasters = GetComponents(typeof(IRaycaster));
  109. foreach (var raycaster in raycasters)
  110. RegisterRaycaster((IRaycaster)raycaster);
  111. }
  112. NativeArray<XRRaycastHit> RaycastViewportAsRay(
  113. Vector2 screenPoint,
  114. TrackableType trackableTypeMask,
  115. Allocator allocator)
  116. {
  117. if (m_SessionOrigin.camera == null)
  118. return new NativeArray<XRRaycastHit>(0, allocator);
  119. var worldSpaceRay = m_SessionOrigin.camera.ScreenPointToRay(screenPoint);
  120. var sessionSpaceRay = m_SessionOrigin.trackablesParent.InverseTransformRay(worldSpaceRay);
  121. return m_RaycastRayDelegate(sessionSpaceRay, trackableTypeMask, allocator);
  122. }
  123. NativeArray<XRRaycastHit> RaycastViewport(
  124. Vector2 screenPoint,
  125. TrackableType trackableTypeMask,
  126. Allocator allocator)
  127. {
  128. screenPoint.x = Mathf.Clamp01(screenPoint.x / Screen.width);
  129. screenPoint.y = Mathf.Clamp01(screenPoint.y / Screen.height);
  130. return subsystem.Raycast(screenPoint, trackableTypeMask, allocator);
  131. }
  132. NativeArray<XRRaycastHit> RaycastRay(
  133. Ray ray,
  134. TrackableType trackableTypeMask,
  135. Allocator allocator)
  136. {
  137. return subsystem.Raycast(ray, trackableTypeMask, allocator);
  138. }
  139. static int RaycastHitComparer(ARRaycastHit lhs, ARRaycastHit rhs)
  140. {
  141. return lhs.CompareTo(rhs);
  142. }
  143. NativeArray<XRRaycastHit> RaycastFallback(
  144. Ray ray,
  145. TrackableType trackableTypeMask,
  146. Allocator allocator)
  147. {
  148. s_NativeRaycastHits.Clear();
  149. int count = 0;
  150. foreach (var raycaster in m_Raycasters)
  151. {
  152. var hits = raycaster.Raycast(ray, trackableTypeMask, Allocator.Temp);
  153. if (hits.IsCreated)
  154. {
  155. s_NativeRaycastHits.Add(hits);
  156. count += hits.Length;
  157. }
  158. }
  159. var allHits = new NativeArray<XRRaycastHit>(count, allocator);
  160. int dstIndex = 0;
  161. foreach (var hitArray in s_NativeRaycastHits)
  162. {
  163. NativeArray<XRRaycastHit>.Copy(hitArray, 0, allHits, dstIndex, hitArray.Length);
  164. hitArray.Dispose();
  165. dstIndex += hitArray.Length;
  166. }
  167. return allHits;
  168. }
  169. bool TransformAndDisposeNativeHitResults(
  170. NativeArray<XRRaycastHit> nativeHits,
  171. List<ARRaycastHit> managedHits,
  172. Vector3 rayOrigin)
  173. {
  174. managedHits.Clear();
  175. if (!nativeHits.IsCreated)
  176. return false;
  177. try
  178. {
  179. // Results are in "trackables space", so transform results back into world space
  180. TransformAndSortRaycastResults(m_SessionOrigin.trackablesParent, nativeHits, managedHits, rayOrigin);
  181. managedHits.Sort(s_RaycastHitComparer);
  182. return managedHits.Count > 0;
  183. }
  184. finally
  185. {
  186. nativeHits.Dispose();
  187. }
  188. }
  189. void ConstructIfNecessary()
  190. {
  191. if (m_Raycasters == null)
  192. m_Raycasters = new List<IRaycaster>();
  193. }
  194. void Awake()
  195. {
  196. m_SessionOrigin = GetComponent<ARSessionOrigin>();
  197. ConstructIfNecessary();
  198. }
  199. static Comparison<ARRaycastHit> s_RaycastHitComparer = RaycastHitComparer;
  200. static List<NativeArray<XRRaycastHit>> s_NativeRaycastHits = new List<NativeArray<XRRaycastHit>>();
  201. ARSessionOrigin m_SessionOrigin;
  202. Func<Vector2, TrackableType, Allocator, NativeArray<XRRaycastHit>> m_RaycastViewportDelegate;
  203. Func<Ray, TrackableType, Allocator, NativeArray<XRRaycastHit>> m_RaycastRayDelegate;
  204. List<IRaycaster> m_Raycasters;
  205. }
  206. }