Rokid_Utils_Componet.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. using UnityEngine;
  2. using UnityEngine.UI;
  3. using System;
  4. using Rokid.UXR.Native;
  5. namespace Rokid.UXR.Utility
  6. {
  7. public static partial class Utils
  8. {
  9. /// <summary>
  10. /// ClearChild
  11. /// </summary>
  12. /// <param name="transform"></param>
  13. public static void ClearTransformChild(Transform transform)
  14. {
  15. for (int i = transform.childCount - 1; i >= 0; i--)
  16. {
  17. GameObject.Destroy(transform.GetChild(i).gameObject);
  18. }
  19. }
  20. /// <summary>
  21. /// Retrieve angular measurement describing how large a sphere or circle appears from a given point of view.
  22. /// Takes an angle (at given point of view) and a distance and returns the actual diameter of the object.
  23. /// </summary>
  24. public static float ScaleFromAngularSizeAndDistance(float angle, float distance)
  25. {
  26. float scale = 1.5f * distance * Mathf.Tan(angle * Mathf.Deg2Rad * 0.5f);
  27. return scale;
  28. }
  29. public static float GetYawAngleFromDirection(Vector3 direction)
  30. {
  31. float yaw = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg;//所给方向与世界坐标系的z轴夹角(yaw angle,偏航角)
  32. return yaw;
  33. }
  34. public static float GetPitchAngleFromDirection(Vector3 direction)
  35. {
  36. float pitch = Mathf.Atan2(direction.y, direction.z) * Mathf.Rad2Deg;
  37. return pitch;
  38. }
  39. public static float GetRollAngleFromDirection(Vector3 direction)
  40. {
  41. float roll = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
  42. return roll;
  43. }
  44. public static void LogFuncTimeStamp(Action func, string tag)
  45. {
  46. double beginTime = GetTimeStamp();
  47. func?.Invoke();
  48. double endTime = GetTimeStamp();
  49. RKLog.Debug($"{tag}:" + (endTime - beginTime));
  50. }
  51. public static double GetTimeStamp()
  52. {
  53. TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);
  54. return ts.TotalMilliseconds;
  55. }
  56. public static long GetSystemStartupTimeStamp()
  57. {
  58. return (DateTime.Now.AddMilliseconds(-Environment.TickCount)).Ticks;
  59. }
  60. public static bool GetWorldPointInRectangle(RectTransform rect, Ray ray, out Vector3 worldPoint)
  61. {
  62. worldPoint = Vector2.zero;
  63. Plane plane = new Plane(rect.rotation * Vector3.back, rect.position);
  64. float enter = 0f;
  65. float num = Vector3.Dot(Vector3.Normalize(rect.position - ray.origin), plane.normal);
  66. if (num != 0f && !plane.Raycast(ray, out enter))
  67. {
  68. return false;
  69. }
  70. worldPoint = ray.GetPoint(enter);
  71. return true;
  72. }
  73. public static bool GetWorldPointInRectangle(Graphic rect, Ray ray, out Vector3 worldPoint)
  74. {
  75. worldPoint = Vector2.zero;
  76. Plane plane = new Plane(rect.transform.rotation * Vector3.back, rect.transform.position);
  77. float enter = 0f;
  78. float num = Vector3.Dot(Vector3.Normalize(rect.transform.position - ray.origin), plane.normal);
  79. if (num != 0f && !plane.Raycast(ray, out enter))
  80. {
  81. return false;
  82. }
  83. worldPoint = ray.GetPoint(enter);
  84. return true;
  85. }
  86. public static bool IsAndroidPlatfrom()
  87. {
  88. return Application.platform == RuntimePlatform.Android;
  89. }
  90. public static bool IsUnityEditor()
  91. {
  92. #if UNITY_EDITOR
  93. return true;
  94. #else
  95. return false;
  96. #endif
  97. }
  98. public static bool InCameraView(Vector3 point, Camera camera)
  99. {
  100. var v = camera.WorldToViewportPoint(point);
  101. if (v.x > 0.8f || v.y > 0.8f || v.z < 0.1f)
  102. {
  103. return false;
  104. }
  105. return true;
  106. }
  107. private static bool useLeftEyeFov = true;
  108. private static Vector4 halfFovTan = Vector4.zero;
  109. public static Vector4 HalfFovTan
  110. {
  111. get
  112. {
  113. if (halfFovTan.x != 0)
  114. return halfFovTan;
  115. if (Utils.IsUnityEditor())
  116. {
  117. Camera cam = MainCameraCache.mainCamera;
  118. float aspectRatio = cam.aspect;
  119. float verticalFOV = cam.fieldOfView;
  120. float horizontalFOV = 2f * Mathf.Atan(Mathf.Tan(verticalFOV * Mathf.Deg2Rad / 2f) * aspectRatio) * Mathf.Rad2Deg;
  121. halfFovTan.x = halfFovTan.y = Mathf.Tan(horizontalFOV / 2 * Mathf.Deg2Rad);
  122. halfFovTan.z = halfFovTan.w = Mathf.Tan(verticalFOV / 2 * Mathf.Deg2Rad);
  123. }
  124. else
  125. {
  126. float[] fov = new float[4];
  127. NativeInterface.NativeAPI.GetUnityEyeFrustumHalf(!useLeftEyeFov, ref fov);
  128. if (fov[0] > 0 && fov[1] > 0 && fov[2] > 0 && fov[3] > 0)
  129. {
  130. halfFovTan.x = Mathf.Tan(fov[0] * Mathf.Deg2Rad); // Left
  131. halfFovTan.y = Mathf.Tan(fov[1] * Mathf.Deg2Rad); // Right
  132. halfFovTan.z = Mathf.Tan(fov[2] * Mathf.Deg2Rad); // Top
  133. halfFovTan.w = Mathf.Tan(fov[3] * Mathf.Deg2Rad); // Bottom
  134. }
  135. }
  136. return halfFovTan;
  137. }
  138. }
  139. public static Vector3[] GetCameraCorners(float dis, bool useLeftEyeFov = true)
  140. {
  141. Vector3[] corners = new Vector3[4];
  142. Vector3 center = GetCameraCenter(dis);
  143. Utils.useLeftEyeFov = useLeftEyeFov;
  144. // Vector4 corner = Vector4.zero;
  145. // corner.x = dis * HalfFovTan.x; // Left
  146. // corner.y = -dis * HalfFovTan.y; // Right
  147. // corner.z = dis * HalfFovTan.z; // Top
  148. // corner.w = -dis * HalfFovTan.w; // Bottom
  149. corners[0] = center + new Vector3(-dis * HalfFovTan.x, dis * HalfFovTan.z); // leftTop
  150. corners[1] = center + new Vector3(dis * HalfFovTan.y, dis * HalfFovTan.z);// rightTop
  151. corners[2] = center + new Vector3(-dis * HalfFovTan.x, -dis * HalfFovTan.w); //leftBottom
  152. corners[3] = center + new Vector3(dis * HalfFovTan.y, -dis * HalfFovTan.w); //rightBottom
  153. return corners;
  154. }
  155. public static Vector3 GetCameraCenter(float distance)
  156. {
  157. Vector4 halffovtan = Utils.HalfFovTan;
  158. Vector2 pivot = new Vector2(halffovtan.y / (halffovtan.x + halffovtan.y), (halffovtan.z) / (halffovtan.z + halffovtan.w));
  159. Vector3 center = MainCameraCache.mainCamera.ViewportToWorldPoint(new Vector3(pivot.x, pivot.y, distance));
  160. if (Utils.IsAndroidPlatfrom())
  161. {
  162. //运行时相机 fov!=渲染 fov
  163. center.y *= (NativeInterface.NativeAPI.GetVFov(true) / MainCameraCache.mainCamera.fieldOfView);
  164. }
  165. RKLog.KeyInfo($"====Utils==== GetCameraCenter halffovtan:{halffovtan},nativefov:{NativeInterface.NativeAPI.GetVFov(true)} mainCameraFov:{MainCameraCache.mainCamera.fieldOfView},pivot:{pivot},MainCameraProjectionMatrix:{MainCameraCache.mainCamera.projectionMatrix},distance:{distance},center:{center}");
  166. return center;
  167. }
  168. // 获得分辨率,当选择 Free Aspect 直接返回相机的像素宽和高
  169. public static Vector2 GetScreenPixelDimensions()
  170. {
  171. Vector2 dimensions = new Vector2(MainCameraCache.mainCamera.pixelWidth, MainCameraCache.mainCamera.pixelHeight);
  172. #if UNITY_EDITOR
  173. // 获取编辑器 GameView 的分辨率
  174. float gameViewPixelWidth = 0, gameViewPixelHeight = 0;
  175. float gameViewAspect = 0;
  176. if (Editor__GetGameViewSize(out gameViewPixelWidth, out gameViewPixelHeight, out gameViewAspect))
  177. {
  178. if (gameViewPixelWidth != 0 && gameViewPixelHeight != 0)
  179. {
  180. dimensions.x = gameViewPixelWidth;
  181. dimensions.y = gameViewPixelHeight;
  182. }
  183. }
  184. #endif
  185. return dimensions;
  186. }
  187. #if UNITY_EDITOR
  188. static bool Editor__getGameViewSizeError = false;
  189. public static bool Editor__gameViewReflectionError = false;
  190. // 尝试获取 GameView 的分辨率
  191. // 当正确获取到 GameView 的分辨率时,返回 true
  192. public static bool Editor__GetGameViewSize(out float width, out float height, out float aspect)
  193. {
  194. try
  195. {
  196. Editor__gameViewReflectionError = false;
  197. System.Type gameViewType = System.Type.GetType("UnityEditor.GameView,UnityEditor");
  198. System.Reflection.MethodInfo GetMainGameView = gameViewType.GetMethod("GetMainGameView", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);
  199. object mainGameViewInst = GetMainGameView.Invoke(null, null);
  200. if (mainGameViewInst == null)
  201. {
  202. width = height = aspect = 0;
  203. return false;
  204. }
  205. System.Reflection.FieldInfo s_viewModeResolutions = gameViewType.GetField("s_viewModeResolutions", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);
  206. if (s_viewModeResolutions == null)
  207. {
  208. System.Reflection.PropertyInfo currentGameViewSize = gameViewType.GetProperty("currentGameViewSize", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);
  209. object gameViewSize = currentGameViewSize.GetValue(mainGameViewInst, null);
  210. System.Type gameViewSizeType = gameViewSize.GetType();
  211. int gvWidth = (int)gameViewSizeType.GetProperty("width").GetValue(gameViewSize, null);
  212. int gvHeight = (int)gameViewSizeType.GetProperty("height").GetValue(gameViewSize, null);
  213. int gvSizeType = (int)gameViewSizeType.GetProperty("sizeType").GetValue(gameViewSize, null);
  214. if (gvWidth == 0 || gvHeight == 0)
  215. {
  216. width = height = aspect = 0;
  217. return false;
  218. }
  219. else if (gvSizeType == 0)
  220. {
  221. width = height = 0;
  222. aspect = (float)gvWidth / (float)gvHeight;
  223. return true;
  224. }
  225. else
  226. {
  227. width = gvWidth; height = gvHeight;
  228. aspect = (float)gvWidth / (float)gvHeight;
  229. return true;
  230. }
  231. }
  232. else
  233. {
  234. Vector2[] viewModeResolutions = (Vector2[])s_viewModeResolutions.GetValue(null);
  235. float[] viewModeAspects = (float[])gameViewType.GetField("s_viewModeAspects", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic).GetValue(null);
  236. string[] viewModeStrings = (string[])gameViewType.GetField("s_viewModeAspectStrings", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic).GetValue(null);
  237. if (mainGameViewInst != null
  238. && viewModeStrings != null
  239. && viewModeResolutions != null && viewModeAspects != null)
  240. {
  241. int aspectRatio = (int)gameViewType.GetField("m_AspectRatio", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic).GetValue(mainGameViewInst);
  242. string thisViewModeString = viewModeStrings[aspectRatio];
  243. if (thisViewModeString.Contains("Standalone"))
  244. {
  245. width = UnityEditor.PlayerSettings.defaultScreenWidth; height = UnityEditor.PlayerSettings.defaultScreenHeight;
  246. aspect = width / height;
  247. }
  248. else if (thisViewModeString.Contains("Web"))
  249. {
  250. width = UnityEditor.PlayerSettings.defaultWebScreenWidth; height = UnityEditor.PlayerSettings.defaultWebScreenHeight;
  251. aspect = width / height;
  252. }
  253. else
  254. {
  255. width = viewModeResolutions[aspectRatio].x; height = viewModeResolutions[aspectRatio].y;
  256. aspect = viewModeAspects[aspectRatio];
  257. // this is an error state
  258. if (width == 0 && height == 0 && aspect == 0)
  259. {
  260. return false;
  261. }
  262. }
  263. return true;
  264. }
  265. }
  266. }
  267. catch (System.Exception e)
  268. {
  269. if (Editor__getGameViewSizeError == false)
  270. {
  271. Debug.LogError("GameCamera.GetGameViewSize - has a Unity update broken this?\nThis is not a fatal error !\n" + e.ToString());
  272. Editor__getGameViewSizeError = true;
  273. }
  274. Editor__gameViewReflectionError = true;
  275. }
  276. width = height = aspect = 0;
  277. return false;
  278. }
  279. #endif
  280. }
  281. }