Rokid_Utils_Math.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.IO;
  4. namespace Rokid.UXR.Utility
  5. {
  6. public static partial class Utils
  7. {
  8. public class Event
  9. {
  10. public delegate void Handler(params object[] args);
  11. public static void Listen(string message, Handler action)
  12. {
  13. var actions = listeners[message] as Handler;
  14. if (actions != null)
  15. {
  16. listeners[message] = actions + action;
  17. }
  18. else
  19. {
  20. listeners[message] = action;
  21. }
  22. }
  23. public static void Remove(string message, Handler action)
  24. {
  25. var actions = listeners[message] as Handler;
  26. if (actions != null)
  27. {
  28. listeners[message] = actions - action;
  29. }
  30. }
  31. public static void Send(string message, params object[] args)
  32. {
  33. var actions = listeners[message] as Handler;
  34. if (actions != null)
  35. {
  36. actions(args);
  37. }
  38. }
  39. private static Hashtable listeners = new Hashtable();
  40. }
  41. /// <summary>
  42. /// Smooths from source to goal, provided lerptime and a deltaTime.
  43. /// </summary>
  44. /// <param name="source">Current value</param>
  45. /// <param name="goal">"goal" value which will be lerped to</param>
  46. /// <param name="lerpTime">Smoothing/lerp amount. Smoothing of 0 means no smoothing, and max value means no change at all.</param>
  47. /// <param name="deltaTime">Delta time. Usually would be set to Time.deltaTime</param>
  48. /// <returns>Smoothed value</returns>
  49. public static Vector3 SmoothTo(Vector3 source, Vector3 goal, float lerpTime, float deltaTime)
  50. {
  51. return Vector3.Lerp(source, goal, (lerpTime == 0f) ? 1f : 1f - Mathf.Pow(lerpTime, deltaTime));
  52. }
  53. /// <summary>
  54. /// Smooths from source to goal, provided slerptime and a deltaTime.
  55. /// </summary>
  56. /// <param name="source">Current value</param>
  57. /// <param name="goal">"goal" value which will be lerped to</param>
  58. /// <param name="slerpTime">Smoothing/lerp amount. Smoothing of 0 means no smoothing, and max value means no change at all.</param>
  59. /// <param name="deltaTime">Delta time. Usually would be set to Time.deltaTime</param>
  60. /// <returns>Smoothed value</returns>
  61. public static Quaternion SmoothTo(Quaternion source, Quaternion goal, float slerpTime, float deltaTime)
  62. {
  63. return Quaternion.Slerp(source, goal, (slerpTime == 0f) ? 1f : 1f - Mathf.Pow(slerpTime, deltaTime));
  64. }
  65. public static bool IsValid(Vector3 vector)
  66. {
  67. return (float.IsNaN(vector.x) == false && float.IsNaN(vector.y) == false && float.IsNaN(vector.z) == false);
  68. }
  69. public static bool IsValid(Quaternion rotation)
  70. {
  71. return (float.IsNaN(rotation.x) == false && float.IsNaN(rotation.y) == false && float.IsNaN(rotation.z) == false && float.IsNaN(rotation.w) == false) &&
  72. (rotation.x != 0 || rotation.y != 0 || rotation.z != 0 || rotation.w != 0);
  73. }
  74. // this version does not clamp [0..1]
  75. public static Quaternion Slerp(Quaternion A, Quaternion B, float t)
  76. {
  77. var cosom = Mathf.Clamp(A.x * B.x + A.y * B.y + A.z * B.z + A.w * B.w, -1.0f, 1.0f);
  78. if (cosom < 0.0f)
  79. {
  80. B = new Quaternion(-B.x, -B.y, -B.z, -B.w);
  81. cosom = -cosom;
  82. }
  83. float sclp, sclq;
  84. if ((1.0f - cosom) > 0.0001f)
  85. {
  86. var omega = Mathf.Acos(cosom);
  87. var sinom = Mathf.Sin(omega);
  88. sclp = Mathf.Sin((1.0f - t) * omega) / sinom;
  89. sclq = Mathf.Sin(t * omega) / sinom;
  90. }
  91. else
  92. {
  93. // "from" and "to" very close, so do linear interp
  94. sclp = 1.0f - t;
  95. sclq = t;
  96. }
  97. return new Quaternion(
  98. sclp * A.x + sclq * B.x,
  99. sclp * A.y + sclq * B.y,
  100. sclp * A.z + sclq * B.z,
  101. sclp * A.w + sclq * B.w);
  102. }
  103. public static Vector3 Lerp(Vector3 A, Vector3 B, float t)
  104. {
  105. return new Vector3(
  106. Lerp(A.x, B.x, t),
  107. Lerp(A.y, B.y, t),
  108. Lerp(A.z, B.z, t));
  109. }
  110. public static float Lerp(float A, float B, float t)
  111. {
  112. return A + (B - A) * t;
  113. }
  114. public static double Lerp(double A, double B, double t)
  115. {
  116. return A + (B - A) * t;
  117. }
  118. public static float InverseLerp(Vector3 A, Vector3 B, Vector3 result)
  119. {
  120. return Vector3.Dot(result - A, B - A);
  121. }
  122. public static float InverseLerp(float A, float B, float result)
  123. {
  124. return (result - A) / (B - A);
  125. }
  126. public static double InverseLerp(double A, double B, double result)
  127. {
  128. return (result - A) / (B - A);
  129. }
  130. public static float Saturate(float A)
  131. {
  132. return (A < 0) ? 0 : (A > 1) ? 1 : A;
  133. }
  134. public static Vector2 Saturate(Vector2 A)
  135. {
  136. return new Vector2(Saturate(A.x), Saturate(A.y));
  137. }
  138. public static float Abs(float A)
  139. {
  140. return (A < 0) ? -A : A;
  141. }
  142. public static Vector2 Abs(Vector2 A)
  143. {
  144. return new Vector2(Abs(A.x), Abs(A.y));
  145. }
  146. private static float _copysign(float sizeval, float signval)
  147. {
  148. return Mathf.Sign(signval) == 1 ? Mathf.Abs(sizeval) : -Mathf.Abs(sizeval);
  149. }
  150. public static Quaternion GetRotation(this Matrix4x4 matrix)
  151. {
  152. Quaternion q = new Quaternion();
  153. q.w = Mathf.Sqrt(Mathf.Max(0, 1 + matrix.m00 + matrix.m11 + matrix.m22)) / 2;
  154. q.x = Mathf.Sqrt(Mathf.Max(0, 1 + matrix.m00 - matrix.m11 - matrix.m22)) / 2;
  155. q.y = Mathf.Sqrt(Mathf.Max(0, 1 - matrix.m00 + matrix.m11 - matrix.m22)) / 2;
  156. q.z = Mathf.Sqrt(Mathf.Max(0, 1 - matrix.m00 - matrix.m11 + matrix.m22)) / 2;
  157. q.x = _copysign(q.x, matrix.m21 - matrix.m12);
  158. q.y = _copysign(q.y, matrix.m02 - matrix.m20);
  159. q.z = _copysign(q.z, matrix.m10 - matrix.m01);
  160. return q;
  161. }
  162. public static Vector3 GetPosition(this Matrix4x4 matrix)
  163. {
  164. var x = matrix.m03;
  165. var y = matrix.m13;
  166. var z = matrix.m23;
  167. return new Vector3(x, y, z);
  168. }
  169. public static Vector3 GetScale(this Matrix4x4 m)
  170. {
  171. var x = Mathf.Sqrt(m.m00 * m.m00 + m.m01 * m.m01 + m.m02 * m.m02);
  172. var y = Mathf.Sqrt(m.m10 * m.m10 + m.m11 * m.m11 + m.m12 * m.m12);
  173. var z = Mathf.Sqrt(m.m20 * m.m20 + m.m21 * m.m21 + m.m22 * m.m22);
  174. return new Vector3(x, y, z);
  175. }
  176. public static float GetLossyScale(Transform t)
  177. {
  178. return t.lossyScale.x;
  179. }
  180. private const string secretKey = "foobar";
  181. public static string GetBadMD5Hash(string usedString)
  182. {
  183. byte[] bytes = System.Text.Encoding.UTF8.GetBytes(usedString + secretKey);
  184. return GetBadMD5Hash(bytes);
  185. }
  186. public static string GetBadMD5Hash(byte[] bytes)
  187. {
  188. System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
  189. byte[] hash = md5.ComputeHash(bytes);
  190. System.Text.StringBuilder sb = new System.Text.StringBuilder();
  191. for (int i = 0; i < hash.Length; i++)
  192. {
  193. sb.Append(hash[i].ToString("x2"));
  194. }
  195. return sb.ToString();
  196. }
  197. public static string GetBadMD5HashFromFile(string filePath)
  198. {
  199. if (File.Exists(filePath) == false)
  200. return null;
  201. string data = File.ReadAllText(filePath);
  202. return GetBadMD5Hash(data + secretKey);
  203. }
  204. public static string SanitizePath(string path, bool allowLeadingSlash = true)
  205. {
  206. if (path.Contains("\\\\"))
  207. path = path.Replace("\\\\", "\\");
  208. if (path.Contains("//"))
  209. path = path.Replace("//", "/");
  210. if (allowLeadingSlash == false)
  211. {
  212. if (path[0] == '/' || path[0] == '\\')
  213. path = path.Substring(1);
  214. }
  215. return path;
  216. }
  217. public static System.Type FindType(string typeName)
  218. {
  219. var type = System.Type.GetType(typeName);
  220. if (type != null) return type;
  221. foreach (var a in System.AppDomain.CurrentDomain.GetAssemblies())
  222. {
  223. type = a.GetType(typeName);
  224. if (type != null)
  225. return type;
  226. }
  227. return null;
  228. }
  229. [System.Serializable]
  230. public struct RigidTransform
  231. {
  232. public Vector3 pos;
  233. public Quaternion rot;
  234. public static RigidTransform identity
  235. {
  236. get { return new RigidTransform(Vector3.zero, Quaternion.identity); }
  237. }
  238. public static RigidTransform FromLocal(Transform t)
  239. {
  240. return new RigidTransform(t.localPosition, t.localRotation);
  241. }
  242. public RigidTransform(Vector3 pos, Quaternion rot)
  243. {
  244. this.pos = pos;
  245. this.rot = rot;
  246. }
  247. public RigidTransform(Transform t)
  248. {
  249. this.pos = t.position;
  250. this.rot = t.rotation;
  251. }
  252. public RigidTransform(Transform from, Transform to)
  253. {
  254. var inv = Quaternion.Inverse(from.rotation);
  255. rot = inv * to.rotation;
  256. pos = inv * (to.position - from.position);
  257. }
  258. public RigidTransform(HmdMatrix34_t pose)
  259. {
  260. var m = Matrix4x4.identity;
  261. m[0, 0] = pose.m0;
  262. m[0, 1] = pose.m1;
  263. m[0, 2] = -pose.m2;
  264. m[0, 3] = pose.m3;
  265. m[1, 0] = pose.m4;
  266. m[1, 1] = pose.m5;
  267. m[1, 2] = -pose.m6;
  268. m[1, 3] = pose.m7;
  269. m[2, 0] = -pose.m8;
  270. m[2, 1] = -pose.m9;
  271. m[2, 2] = pose.m10;
  272. m[2, 3] = -pose.m11;
  273. this.pos = m.GetPosition();
  274. this.rot = m.GetRotation();
  275. }
  276. public RigidTransform(HmdMatrix44_t pose)
  277. {
  278. var m = Matrix4x4.identity;
  279. m[0, 0] = pose.m0;
  280. m[0, 1] = pose.m1;
  281. m[0, 2] = -pose.m2;
  282. m[0, 3] = pose.m3;
  283. m[1, 0] = pose.m4;
  284. m[1, 1] = pose.m5;
  285. m[1, 2] = -pose.m6;
  286. m[1, 3] = pose.m7;
  287. m[2, 0] = -pose.m8;
  288. m[2, 1] = -pose.m9;
  289. m[2, 2] = pose.m10;
  290. m[2, 3] = -pose.m11;
  291. m[3, 0] = pose.m12;
  292. m[3, 1] = pose.m13;
  293. m[3, 2] = -pose.m14;
  294. m[3, 3] = pose.m15;
  295. this.pos = m.GetPosition();
  296. this.rot = m.GetRotation();
  297. }
  298. public HmdMatrix44_t ToHmdMatrix44()
  299. {
  300. var m = Matrix4x4.TRS(pos, rot, Vector3.one);
  301. var pose = new HmdMatrix44_t();
  302. pose.m0 = m[0, 0];
  303. pose.m1 = m[0, 1];
  304. pose.m2 = -m[0, 2];
  305. pose.m3 = m[0, 3];
  306. pose.m4 = m[1, 0];
  307. pose.m5 = m[1, 1];
  308. pose.m6 = -m[1, 2];
  309. pose.m7 = m[1, 3];
  310. pose.m8 = -m[2, 0];
  311. pose.m9 = -m[2, 1];
  312. pose.m10 = m[2, 2];
  313. pose.m11 = -m[2, 3];
  314. pose.m12 = m[3, 0];
  315. pose.m13 = m[3, 1];
  316. pose.m14 = -m[3, 2];
  317. pose.m15 = m[3, 3];
  318. return pose;
  319. }
  320. public HmdMatrix34_t ToHmdMatrix34()
  321. {
  322. var m = Matrix4x4.TRS(pos, rot, Vector3.one);
  323. var pose = new HmdMatrix34_t();
  324. pose.m0 = m[0, 0];
  325. pose.m1 = m[0, 1];
  326. pose.m2 = -m[0, 2];
  327. pose.m3 = m[0, 3];
  328. pose.m4 = m[1, 0];
  329. pose.m5 = m[1, 1];
  330. pose.m6 = -m[1, 2];
  331. pose.m7 = m[1, 3];
  332. pose.m8 = -m[2, 0];
  333. pose.m9 = -m[2, 1];
  334. pose.m10 = m[2, 2];
  335. pose.m11 = -m[2, 3];
  336. return pose;
  337. }
  338. public override bool Equals(object o)
  339. {
  340. if (o is RigidTransform)
  341. {
  342. RigidTransform t = (RigidTransform)o;
  343. return pos == t.pos && rot == t.rot;
  344. }
  345. return false;
  346. }
  347. public override int GetHashCode()
  348. {
  349. return pos.GetHashCode() ^ rot.GetHashCode();
  350. }
  351. public static bool operator ==(RigidTransform a, RigidTransform b)
  352. {
  353. return a.pos == b.pos && a.rot == b.rot;
  354. }
  355. public static bool operator !=(RigidTransform a, RigidTransform b)
  356. {
  357. return a.pos != b.pos || a.rot != b.rot;
  358. }
  359. public static RigidTransform operator *(RigidTransform a, RigidTransform b)
  360. {
  361. return new RigidTransform
  362. {
  363. rot = a.rot * b.rot,
  364. pos = a.pos + a.rot * b.pos
  365. };
  366. }
  367. public void Inverse()
  368. {
  369. rot = Quaternion.Inverse(rot);
  370. pos = -(rot * pos);
  371. }
  372. public RigidTransform GetInverse()
  373. {
  374. var t = new RigidTransform(pos, rot);
  375. t.Inverse();
  376. return t;
  377. }
  378. public void Multiply(RigidTransform a, RigidTransform b)
  379. {
  380. rot = a.rot * b.rot;
  381. pos = a.pos + a.rot * b.pos;
  382. }
  383. public Vector3 InverseTransformPoint(Vector3 point)
  384. {
  385. return Quaternion.Inverse(rot) * (point - pos);
  386. }
  387. public Vector3 TransformPoint(Vector3 point)
  388. {
  389. return pos + (rot * point);
  390. }
  391. public static Vector3 operator *(RigidTransform t, Vector3 v)
  392. {
  393. return t.TransformPoint(v);
  394. }
  395. public static RigidTransform Interpolate(RigidTransform a, RigidTransform b, float t)
  396. {
  397. return new RigidTransform(Vector3.Lerp(a.pos, b.pos, t), Quaternion.Slerp(a.rot, b.rot, t));
  398. }
  399. public void Interpolate(RigidTransform to, float t)
  400. {
  401. pos = Utils.Lerp(pos, to.pos, t);
  402. rot = Utils.Slerp(rot, to.rot, t);
  403. }
  404. }
  405. }
  406. public struct HmdMatrix44_t
  407. {
  408. public float m0;
  409. public float m1;
  410. public float m2;
  411. public float m3;
  412. public float m4;
  413. public float m5;
  414. public float m6;
  415. public float m7;
  416. public float m8;
  417. public float m9;
  418. public float m10;
  419. public float m11;
  420. public float m12;
  421. public float m13;
  422. public float m14;
  423. public float m15;
  424. }
  425. public struct HmdMatrix34_t
  426. {
  427. public float m0;
  428. public float m1;
  429. public float m2;
  430. public float m3;
  431. public float m4;
  432. public float m5;
  433. public float m6;
  434. public float m7;
  435. public float m8;
  436. public float m9;
  437. public float m10;
  438. public float m11;
  439. public Vector3 GetPosition()
  440. {
  441. return new Vector3(m3, m7, 0f - m11);
  442. }
  443. public bool IsRotationValid()
  444. {
  445. if (m2 != 0f || m6 != 0f || m10 != 0f)
  446. {
  447. if (m1 == 0f && m5 == 0f)
  448. {
  449. return m9 != 0f;
  450. }
  451. return true;
  452. }
  453. return false;
  454. }
  455. public Quaternion GetRotation()
  456. {
  457. if (IsRotationValid())
  458. {
  459. float w = Mathf.Sqrt(Mathf.Max(0f, 1f + m0 + m5 + m10)) / 2f;
  460. float sizeval = Mathf.Sqrt(Mathf.Max(0f, 1f + m0 - m5 - m10)) / 2f;
  461. float sizeval2 = Mathf.Sqrt(Mathf.Max(0f, 1f - m0 + m5 - m10)) / 2f;
  462. float sizeval3 = Mathf.Sqrt(Mathf.Max(0f, 1f - m0 - m5 + m10)) / 2f;
  463. _copysign(ref sizeval, 0f - m9 - (0f - m6));
  464. _copysign(ref sizeval2, 0f - m2 - (0f - m8));
  465. _copysign(ref sizeval3, m4 - m1);
  466. return new Quaternion(sizeval, sizeval2, sizeval3, w);
  467. }
  468. return Quaternion.identity;
  469. }
  470. private static void _copysign(ref float sizeval, float signval)
  471. {
  472. if (signval > 0f != sizeval > 0f)
  473. {
  474. sizeval = 0f - sizeval;
  475. }
  476. }
  477. }
  478. }