BaseRayPose.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. using System;
  2. using System.Collections.Generic;
  3. using Rokid.UXR.Native;
  4. using Rokid.UXR.Utility;
  5. using UnityEngine;
  6. using UnityEngine.EventSystems;
  7. namespace Rokid.UXR.Interaction
  8. {
  9. /// <summary>
  10. /// Base Ray Pose
  11. /// </summary>
  12. public abstract class BaseRayPose : MonoBehaviour
  13. {
  14. [Serializable]
  15. public class EditorParams
  16. {
  17. [Tooltip("是否使用鼠标模拟射线Rotate")]
  18. public bool useMouseRotate = true;
  19. [Tooltip("射线是否跟随相机,只在编辑器生效")]
  20. public bool followCameraInEditor = true;
  21. [Tooltip("相机空间下的局部坐标,只有在followCamera为真的情况下生效")]
  22. public Vector3 localPositionInCameraSpace = new Vector3(0, -0.1f, 0);
  23. public float maxDistanceInEditor = 10.0f;
  24. [HideInInspector]
  25. public float raycastDistance = -1.0f;
  26. public BaseRayCaster rayCaster;
  27. public static readonly RaycastHit[] hits = new RaycastHit[4];
  28. public readonly List<RaycastResult> sortedRaycastResults = new List<RaycastResult>();
  29. public Transform rayOrigin;
  30. }
  31. [SerializeField, Tooltip("编辑器模拟参数")]
  32. private EditorParams editorParams;
  33. private Transform hostTransform;
  34. protected virtual void Start()
  35. {
  36. if (editorParams.rayCaster == null)
  37. editorParams.rayCaster = GetComponent<BaseRayCaster>();
  38. hostTransform = editorParams.rayOrigin == null ? transform : editorParams.rayOrigin;
  39. }
  40. protected virtual void Update()
  41. {
  42. #if UNITY_EDITOR
  43. if (editorParams.useMouseRotate)
  44. {
  45. UpdateInEditor();
  46. }
  47. #endif
  48. }
  49. #if UNITY_EDITOR
  50. protected virtual void UpdateInEditor()
  51. {
  52. if (editorParams.followCameraInEditor)
  53. {
  54. hostTransform.position = MainCameraCache.mainCamera.transform.TransformPoint(editorParams.localPositionInCameraSpace);
  55. }
  56. if (editorParams.rayCaster != null)
  57. {
  58. Ray ray = MainCameraCache.mainCamera.ScreenPointToRay(Input.mousePosition);
  59. editorParams.rayCaster.Raycast(ray, Mathf.Infinity, editorParams.sortedRaycastResults);
  60. RaycastResult raycastResult = editorParams.rayCaster.FirstRaycastResult(editorParams.sortedRaycastResults);
  61. if (raycastResult.gameObject != null)
  62. {
  63. Vector3 targetPos = raycastResult.worldPosition;
  64. Vector3 toDirection = targetPos - hostTransform.position;
  65. hostTransform.localRotation = Quaternion.FromToRotation(Vector3.forward, toDirection);
  66. editorParams.raycastDistance = Mathf.Min(editorParams.maxDistanceInEditor, raycastResult.distance);
  67. }
  68. else if (editorParams.raycastDistance > 0.0f)
  69. {
  70. Vector3 targetPos = ray.origin + Mathf.Min(editorParams.maxDistanceInEditor, editorParams.raycastDistance) * ray.direction;
  71. Vector3 toDirection = targetPos - hostTransform.position;
  72. hostTransform.localRotation = Quaternion.FromToRotation(Vector3.forward, toDirection);
  73. }
  74. else
  75. {
  76. hostTransform.localRotation = Quaternion.identity;
  77. }
  78. }
  79. }
  80. #endif
  81. #region LimitInViewField
  82. protected Camera renderCamera;
  83. public Vector4 cursorSize;
  84. private Vector4 _halfFovTan = Vector4.zero;
  85. private Vector4 halfFovTan
  86. {
  87. get
  88. {
  89. if (_halfFovTan != Vector4.zero)
  90. {
  91. return _halfFovTan;
  92. }
  93. #if UNITY_EDITOR
  94. _halfFovTan.x = _halfFovTan.y = _halfFovTan.z = _halfFovTan.w = Mathf.Tan(renderCamera.fieldOfView / 2 * Mathf.Deg2Rad);
  95. return _halfFovTan;
  96. #endif
  97. float[] fov = new float[4];
  98. NativeInterface.NativeAPI.GetUnityEyeFrustumHalf(false, ref fov);
  99. if (fov[0] > 0 && fov[1] > 0 && fov[2] > 0 && fov[3] > 0)
  100. {
  101. _halfFovTan.x = Mathf.Tan(fov[0] * Mathf.Deg2Rad); // Left
  102. _halfFovTan.y = Mathf.Tan(fov[1] * Mathf.Deg2Rad); // Right
  103. _halfFovTan.z = Mathf.Tan(fov[2] * Mathf.Deg2Rad); // Top
  104. _halfFovTan.w = Mathf.Tan(fov[3] * Mathf.Deg2Rad); // Bottom
  105. return _halfFovTan;
  106. }
  107. return Vector4.zero;
  108. }
  109. }
  110. Vector4 GetCameraCorner(float dis)
  111. {
  112. Vector4 corner = Vector4.zero;
  113. corner.z = dis * halfFovTan.z; // Top
  114. corner.w = dis * halfFovTan.w; // Bottom
  115. #if UNITY_EDITOR
  116. corner.x = corner.y = corner.z * renderCamera.aspect;
  117. #else
  118. corner.x = dis * halfFovTan.x; // Left
  119. corner.y = dis * halfFovTan.y; // Right
  120. #endif
  121. return corner;
  122. }
  123. protected void LimitInViewField()
  124. {
  125. transform.position = renderCamera.transform.position;
  126. Vector3 pointPosition = transform.forward + transform.position;
  127. Vector3 pointInCamera = renderCamera.transform.InverseTransformPoint(pointPosition);
  128. //点在相机forward上的距离
  129. float dis = pointInCamera.z;
  130. if (dis < 0)
  131. {
  132. dis = -dis;
  133. pointInCamera.z = dis;
  134. }
  135. Vector4 corner = GetCameraCorner(dis);
  136. if (pointInCamera.x < -corner.x + cursorSize.x) // LEFT
  137. {
  138. pointInCamera.x = -corner.x + cursorSize.x;
  139. }
  140. else if (pointInCamera.x > corner.y - cursorSize.w) // Right
  141. {
  142. pointInCamera.x = corner.y - cursorSize.w;
  143. }
  144. if (pointInCamera.y > corner.z - cursorSize.y) // Top
  145. {
  146. pointInCamera.y = corner.z - cursorSize.y;
  147. }
  148. else if (pointInCamera.y < -corner.w + cursorSize.z) // Bottom
  149. {
  150. pointInCamera.y = -corner.w + cursorSize.z;
  151. }
  152. pointPosition = renderCamera.transform.TransformPoint(pointInCamera);
  153. transform.forward = pointPosition - transform.position;
  154. }
  155. #endregion
  156. }
  157. }