Basis.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. using System;
  2. using System.Runtime.InteropServices;
  3. #if REAL_T_IS_DOUBLE
  4. using real_t = System.Double;
  5. #else
  6. using real_t = System.Single;
  7. #endif
  8. namespace Godot
  9. {
  10. [StructLayout(LayoutKind.Sequential)]
  11. public struct Basis : IEquatable<Basis>
  12. {
  13. private static readonly Basis identity = new Basis
  14. (
  15. new Vector3(1f, 0f, 0f),
  16. new Vector3(0f, 1f, 0f),
  17. new Vector3(0f, 0f, 1f)
  18. );
  19. private static readonly Basis[] orthoBases = {
  20. new Basis(1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f),
  21. new Basis(0f, -1f, 0f, 1f, 0f, 0f, 0f, 0f, 1f),
  22. new Basis(-1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, 1f),
  23. new Basis(0f, 1f, 0f, -1f, 0f, 0f, 0f, 0f, 1f),
  24. new Basis(1f, 0f, 0f, 0f, 0f, -1f, 0f, 1f, 0f),
  25. new Basis(0f, 0f, 1f, 1f, 0f, 0f, 0f, 1f, 0f),
  26. new Basis(-1f, 0f, 0f, 0f, 0f, 1f, 0f, 1f, 0f),
  27. new Basis(0f, 0f, -1f, -1f, 0f, 0f, 0f, 1f, 0f),
  28. new Basis(1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, -1f),
  29. new Basis(0f, 1f, 0f, 1f, 0f, 0f, 0f, 0f, -1f),
  30. new Basis(-1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, -1f),
  31. new Basis(0f, -1f, 0f, -1f, 0f, 0f, 0f, 0f, -1f),
  32. new Basis(1f, 0f, 0f, 0f, 0f, 1f, 0f, -1f, 0f),
  33. new Basis(0f, 0f, -1f, 1f, 0f, 0f, 0f, -1f, 0f),
  34. new Basis(-1f, 0f, 0f, 0f, 0f, -1f, 0f, -1f, 0f),
  35. new Basis(0f, 0f, 1f, -1f, 0f, 0f, 0f, -1f, 0f),
  36. new Basis(0f, 0f, 1f, 0f, 1f, 0f, -1f, 0f, 0f),
  37. new Basis(0f, -1f, 0f, 0f, 0f, 1f, -1f, 0f, 0f),
  38. new Basis(0f, 0f, -1f, 0f, -1f, 0f, -1f, 0f, 0f),
  39. new Basis(0f, 1f, 0f, 0f, 0f, -1f, -1f, 0f, 0f),
  40. new Basis(0f, 0f, 1f, 0f, -1f, 0f, 1f, 0f, 0f),
  41. new Basis(0f, 1f, 0f, 0f, 0f, 1f, 1f, 0f, 0f),
  42. new Basis(0f, 0f, -1f, 0f, 1f, 0f, 1f, 0f, 0f),
  43. new Basis(0f, -1f, 0f, 0f, 0f, -1f, 1f, 0f, 0f)
  44. };
  45. public Vector3 x
  46. {
  47. get { return GetAxis(0); }
  48. set { SetAxis(0, value); }
  49. }
  50. public Vector3 y
  51. {
  52. get { return GetAxis(1); }
  53. set { SetAxis(1, value); }
  54. }
  55. public Vector3 z
  56. {
  57. get { return GetAxis(2); }
  58. set { SetAxis(2, value); }
  59. }
  60. private Vector3 _x;
  61. private Vector3 _y;
  62. private Vector3 _z;
  63. public static Basis Identity
  64. {
  65. get { return identity; }
  66. }
  67. public Vector3 Scale
  68. {
  69. get
  70. {
  71. return new Vector3
  72. (
  73. new Vector3(this[0, 0], this[1, 0], this[2, 0]).Length(),
  74. new Vector3(this[0, 1], this[1, 1], this[2, 1]).Length(),
  75. new Vector3(this[0, 2], this[1, 2], this[2, 2]).Length()
  76. );
  77. }
  78. }
  79. public Vector3 this[int index]
  80. {
  81. get
  82. {
  83. switch (index)
  84. {
  85. case 0:
  86. return _x;
  87. case 1:
  88. return _y;
  89. case 2:
  90. return _z;
  91. default:
  92. throw new IndexOutOfRangeException();
  93. }
  94. }
  95. set
  96. {
  97. switch (index)
  98. {
  99. case 0:
  100. _x = value;
  101. return;
  102. case 1:
  103. _y = value;
  104. return;
  105. case 2:
  106. _z = value;
  107. return;
  108. default:
  109. throw new IndexOutOfRangeException();
  110. }
  111. }
  112. }
  113. public real_t this[int index, int axis]
  114. {
  115. get
  116. {
  117. switch (index)
  118. {
  119. case 0:
  120. return _x[axis];
  121. case 1:
  122. return _y[axis];
  123. case 2:
  124. return _z[axis];
  125. default:
  126. throw new IndexOutOfRangeException();
  127. }
  128. }
  129. set
  130. {
  131. switch (index)
  132. {
  133. case 0:
  134. _x[axis] = value;
  135. return;
  136. case 1:
  137. _y[axis] = value;
  138. return;
  139. case 2:
  140. _z[axis] = value;
  141. return;
  142. default:
  143. throw new IndexOutOfRangeException();
  144. }
  145. }
  146. }
  147. internal static Basis CreateFromAxes(Vector3 xAxis, Vector3 yAxis, Vector3 zAxis)
  148. {
  149. return new Basis
  150. (
  151. new Vector3(xAxis.x, yAxis.x, zAxis.x),
  152. new Vector3(xAxis.y, yAxis.y, zAxis.y),
  153. new Vector3(xAxis.z, yAxis.z, zAxis.z)
  154. );
  155. }
  156. internal Quat RotationQuat()
  157. {
  158. Basis orthonormalizedBasis = Orthonormalized();
  159. real_t det = orthonormalizedBasis.Determinant();
  160. if (det < 0)
  161. {
  162. // Ensure that the determinant is 1, such that result is a proper rotation matrix which can be represented by Euler angles.
  163. orthonormalizedBasis = orthonormalizedBasis.Scaled(Vector3.NegOne);
  164. }
  165. return orthonormalizedBasis.Quat();
  166. }
  167. internal void SetQuantScale(Quat quat, Vector3 scale)
  168. {
  169. SetDiagonal(scale);
  170. Rotate(quat);
  171. }
  172. private void Rotate(Quat quat)
  173. {
  174. this *= new Basis(quat);
  175. }
  176. private void SetDiagonal(Vector3 diagonal)
  177. {
  178. _x = new Vector3(diagonal.x, 0, 0);
  179. _y = new Vector3(0, diagonal.y, 0);
  180. _z = new Vector3(0, 0, diagonal.z);
  181. }
  182. public real_t Determinant()
  183. {
  184. return this[0, 0] * (this[1, 1] * this[2, 2] - this[2, 1] * this[1, 2]) -
  185. this[1, 0] * (this[0, 1] * this[2, 2] - this[2, 1] * this[0, 2]) +
  186. this[2, 0] * (this[0, 1] * this[1, 2] - this[1, 1] * this[0, 2]);
  187. }
  188. public Vector3 GetAxis(int axis)
  189. {
  190. return new Vector3(this[0, axis], this[1, axis], this[2, axis]);
  191. }
  192. public void SetAxis(int axis, Vector3 value)
  193. {
  194. this[0, axis] = value.x;
  195. this[1, axis] = value.y;
  196. this[2, axis] = value.z;
  197. }
  198. public Vector3 GetEuler()
  199. {
  200. Basis m = Orthonormalized();
  201. Vector3 euler;
  202. euler.z = 0.0f;
  203. real_t mxy = m[1, 2];
  204. if (mxy < 1.0f)
  205. {
  206. if (mxy > -1.0f)
  207. {
  208. euler.x = Mathf.Asin(-mxy);
  209. euler.y = Mathf.Atan2(m[0, 2], m[2, 2]);
  210. euler.z = Mathf.Atan2(m[1, 0], m[1, 1]);
  211. }
  212. else
  213. {
  214. euler.x = Mathf.Pi * 0.5f;
  215. euler.y = -Mathf.Atan2(-m[0, 1], m[0, 0]);
  216. }
  217. }
  218. else
  219. {
  220. euler.x = -Mathf.Pi * 0.5f;
  221. euler.y = -Mathf.Atan2(-m[0, 1], m[0, 0]);
  222. }
  223. return euler;
  224. }
  225. public int GetOrthogonalIndex()
  226. {
  227. var orth = this;
  228. for (int i = 0; i < 3; i++)
  229. {
  230. for (int j = 0; j < 3; j++)
  231. {
  232. real_t v = orth[i, j];
  233. if (v > 0.5f)
  234. v = 1.0f;
  235. else if (v < -0.5f)
  236. v = -1.0f;
  237. else
  238. v = 0f;
  239. orth[i, j] = v;
  240. }
  241. }
  242. for (int i = 0; i < 24; i++)
  243. {
  244. if (orthoBases[i] == orth)
  245. return i;
  246. }
  247. return 0;
  248. }
  249. public Basis Inverse()
  250. {
  251. var inv = this;
  252. real_t[] co = {
  253. inv[1, 1] * inv[2, 2] - inv[1, 2] * inv[2, 1],
  254. inv[1, 2] * inv[2, 0] - inv[1, 0] * inv[2, 2],
  255. inv[1, 0] * inv[2, 1] - inv[1, 1] * inv[2, 0]
  256. };
  257. real_t det = inv[0, 0] * co[0] + inv[0, 1] * co[1] + inv[0, 2] * co[2];
  258. if (det == 0)
  259. {
  260. return new Basis
  261. (
  262. real_t.NaN, real_t.NaN, real_t.NaN,
  263. real_t.NaN, real_t.NaN, real_t.NaN,
  264. real_t.NaN, real_t.NaN, real_t.NaN
  265. );
  266. }
  267. real_t s = 1.0f / det;
  268. inv = new Basis
  269. (
  270. co[0] * s,
  271. inv[0, 2] * inv[2, 1] - inv[0, 1] * inv[2, 2] * s,
  272. inv[0, 1] * inv[1, 2] - inv[0, 2] * inv[1, 1] * s,
  273. co[1] * s,
  274. inv[0, 0] * inv[2, 2] - inv[0, 2] * inv[2, 0] * s,
  275. inv[0, 2] * inv[1, 0] - inv[0, 0] * inv[1, 2] * s,
  276. co[2] * s,
  277. inv[0, 1] * inv[2, 0] - inv[0, 0] * inv[2, 1] * s,
  278. inv[0, 0] * inv[1, 1] - inv[0, 1] * inv[1, 0] * s
  279. );
  280. return inv;
  281. }
  282. public Basis Orthonormalized()
  283. {
  284. Vector3 xAxis = GetAxis(0);
  285. Vector3 yAxis = GetAxis(1);
  286. Vector3 zAxis = GetAxis(2);
  287. xAxis.Normalize();
  288. yAxis = yAxis - xAxis * xAxis.Dot(yAxis);
  289. yAxis.Normalize();
  290. zAxis = zAxis - xAxis * xAxis.Dot(zAxis) - yAxis * yAxis.Dot(zAxis);
  291. zAxis.Normalize();
  292. return CreateFromAxes(xAxis, yAxis, zAxis);
  293. }
  294. public Basis Rotated(Vector3 axis, real_t phi)
  295. {
  296. return new Basis(axis, phi) * this;
  297. }
  298. public Basis Scaled(Vector3 scale)
  299. {
  300. var m = this;
  301. m[0, 0] *= scale.x;
  302. m[0, 1] *= scale.x;
  303. m[0, 2] *= scale.x;
  304. m[1, 0] *= scale.y;
  305. m[1, 1] *= scale.y;
  306. m[1, 2] *= scale.y;
  307. m[2, 0] *= scale.z;
  308. m[2, 1] *= scale.z;
  309. m[2, 2] *= scale.z;
  310. return m;
  311. }
  312. public real_t Tdotx(Vector3 with)
  313. {
  314. return this[0, 0] * with[0] + this[1, 0] * with[1] + this[2, 0] * with[2];
  315. }
  316. public real_t Tdoty(Vector3 with)
  317. {
  318. return this[0, 1] * with[0] + this[1, 1] * with[1] + this[2, 1] * with[2];
  319. }
  320. public real_t Tdotz(Vector3 with)
  321. {
  322. return this[0, 2] * with[0] + this[1, 2] * with[1] + this[2, 2] * with[2];
  323. }
  324. public Basis Transposed()
  325. {
  326. var tr = this;
  327. real_t temp = tr[0, 1];
  328. tr[0, 1] = tr[1, 0];
  329. tr[1, 0] = temp;
  330. temp = tr[0, 2];
  331. tr[0, 2] = tr[2, 0];
  332. tr[2, 0] = temp;
  333. temp = tr[1, 2];
  334. tr[1, 2] = tr[2, 1];
  335. tr[2, 1] = temp;
  336. return tr;
  337. }
  338. public Vector3 Xform(Vector3 v)
  339. {
  340. return new Vector3
  341. (
  342. this[0].Dot(v),
  343. this[1].Dot(v),
  344. this[2].Dot(v)
  345. );
  346. }
  347. public Vector3 XformInv(Vector3 v)
  348. {
  349. return new Vector3
  350. (
  351. this[0, 0] * v.x + this[1, 0] * v.y + this[2, 0] * v.z,
  352. this[0, 1] * v.x + this[1, 1] * v.y + this[2, 1] * v.z,
  353. this[0, 2] * v.x + this[1, 2] * v.y + this[2, 2] * v.z
  354. );
  355. }
  356. public Quat Quat()
  357. {
  358. real_t trace = _x[0] + _y[1] + _z[2];
  359. if (trace > 0.0f)
  360. {
  361. real_t s = Mathf.Sqrt(trace + 1.0f) * 2f;
  362. real_t inv_s = 1f / s;
  363. return new Quat(
  364. (_z[1] - _y[2]) * inv_s,
  365. (_x[2] - _z[0]) * inv_s,
  366. (_y[0] - _x[1]) * inv_s,
  367. s * 0.25f
  368. );
  369. }
  370. if (_x[0] > _y[1] && _x[0] > _z[2])
  371. {
  372. real_t s = Mathf.Sqrt(_x[0] - _y[1] - _z[2] + 1.0f) * 2f;
  373. real_t inv_s = 1f / s;
  374. return new Quat(
  375. s * 0.25f,
  376. (_x[1] + _y[0]) * inv_s,
  377. (_x[2] + _z[0]) * inv_s,
  378. (_z[1] - _y[2]) * inv_s
  379. );
  380. }
  381. if (_y[1] > _z[2])
  382. {
  383. real_t s = Mathf.Sqrt(-_x[0] + _y[1] - _z[2] + 1.0f) * 2f;
  384. real_t inv_s = 1f / s;
  385. return new Quat(
  386. (_x[1] + _y[0]) * inv_s,
  387. s * 0.25f,
  388. (_y[2] + _z[1]) * inv_s,
  389. (_x[2] - _z[0]) * inv_s
  390. );
  391. }
  392. else
  393. {
  394. real_t s = Mathf.Sqrt(-_x[0] - _y[1] + _z[2] + 1.0f) * 2f;
  395. real_t inv_s = 1f / s;
  396. return new Quat(
  397. (_x[2] + _z[0]) * inv_s,
  398. (_y[2] + _z[1]) * inv_s,
  399. s * 0.25f,
  400. (_y[0] - _x[1]) * inv_s
  401. );
  402. }
  403. }
  404. public Basis(Quat quat)
  405. {
  406. real_t s = 2.0f / quat.LengthSquared;
  407. real_t xs = quat.x * s;
  408. real_t ys = quat.y * s;
  409. real_t zs = quat.z * s;
  410. real_t wx = quat.w * xs;
  411. real_t wy = quat.w * ys;
  412. real_t wz = quat.w * zs;
  413. real_t xx = quat.x * xs;
  414. real_t xy = quat.x * ys;
  415. real_t xz = quat.x * zs;
  416. real_t yy = quat.y * ys;
  417. real_t yz = quat.y * zs;
  418. real_t zz = quat.z * zs;
  419. _x = new Vector3(1.0f - (yy + zz), xy - wz, xz + wy);
  420. _y = new Vector3(xy + wz, 1.0f - (xx + zz), yz - wx);
  421. _z = new Vector3(xz - wy, yz + wx, 1.0f - (xx + yy));
  422. }
  423. public Basis(Vector3 euler)
  424. {
  425. real_t c;
  426. real_t s;
  427. c = Mathf.Cos(euler.x);
  428. s = Mathf.Sin(euler.x);
  429. var xmat = new Basis(1, 0, 0, 0, c, -s, 0, s, c);
  430. c = Mathf.Cos(euler.y);
  431. s = Mathf.Sin(euler.y);
  432. var ymat = new Basis(c, 0, s, 0, 1, 0, -s, 0, c);
  433. c = Mathf.Cos(euler.z);
  434. s = Mathf.Sin(euler.z);
  435. var zmat = new Basis(c, -s, 0, s, c, 0, 0, 0, 1);
  436. this = ymat * xmat * zmat;
  437. }
  438. public Basis(Vector3 axis, real_t phi)
  439. {
  440. var axis_sq = new Vector3(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z);
  441. real_t cosine = Mathf.Cos(phi);
  442. real_t sine = Mathf.Sin(phi);
  443. _x = new Vector3
  444. (
  445. axis_sq.x + cosine * (1.0f - axis_sq.x),
  446. axis.x * axis.y * (1.0f - cosine) - axis.z * sine,
  447. axis.z * axis.x * (1.0f - cosine) + axis.y * sine
  448. );
  449. _y = new Vector3
  450. (
  451. axis.x * axis.y * (1.0f - cosine) + axis.z * sine,
  452. axis_sq.y + cosine * (1.0f - axis_sq.y),
  453. axis.y * axis.z * (1.0f - cosine) - axis.x * sine
  454. );
  455. _z = new Vector3
  456. (
  457. axis.z * axis.x * (1.0f - cosine) - axis.y * sine,
  458. axis.y * axis.z * (1.0f - cosine) + axis.x * sine,
  459. axis_sq.z + cosine * (1.0f - axis_sq.z)
  460. );
  461. }
  462. public Basis(Vector3 xAxis, Vector3 yAxis, Vector3 zAxis)
  463. {
  464. x = xAxis;
  465. y = yAxis;
  466. z = zAxis;
  467. }
  468. public Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz)
  469. {
  470. _x = new Vector3(xx, xy, xz);
  471. _y = new Vector3(yx, yy, yz);
  472. _z = new Vector3(zx, zy, zz);
  473. }
  474. public static Basis operator *(Basis left, Basis right)
  475. {
  476. return new Basis
  477. (
  478. right.Tdotx(left[0]), right.Tdoty(left[0]), right.Tdotz(left[0]),
  479. right.Tdotx(left[1]), right.Tdoty(left[1]), right.Tdotz(left[1]),
  480. right.Tdotx(left[2]), right.Tdoty(left[2]), right.Tdotz(left[2])
  481. );
  482. }
  483. public static bool operator ==(Basis left, Basis right)
  484. {
  485. return left.Equals(right);
  486. }
  487. public static bool operator !=(Basis left, Basis right)
  488. {
  489. return !left.Equals(right);
  490. }
  491. public override bool Equals(object obj)
  492. {
  493. if (obj is Basis)
  494. {
  495. return Equals((Basis)obj);
  496. }
  497. return false;
  498. }
  499. public bool Equals(Basis other)
  500. {
  501. return _x.Equals(other[0]) && _y.Equals(other[1]) && _z.Equals(other[2]);
  502. }
  503. public override int GetHashCode()
  504. {
  505. return _x.GetHashCode() ^ _y.GetHashCode() ^ _z.GetHashCode();
  506. }
  507. public override string ToString()
  508. {
  509. return String.Format("({0}, {1}, {2})", new object[]
  510. {
  511. _x.ToString(),
  512. _y.ToString(),
  513. _z.ToString()
  514. });
  515. }
  516. public string ToString(string format)
  517. {
  518. return String.Format("({0}, {1}, {2})", new object[]
  519. {
  520. _x.ToString(format),
  521. _y.ToString(format),
  522. _z.ToString(format)
  523. });
  524. }
  525. }
  526. }