Basis.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  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. public real_t Determinant()
  157. {
  158. return this[0, 0] * (this[1, 1] * this[2, 2] - this[2, 1] * this[1, 2]) -
  159. this[1, 0] * (this[0, 1] * this[2, 2] - this[2, 1] * this[0, 2]) +
  160. this[2, 0] * (this[0, 1] * this[1, 2] - this[1, 1] * this[0, 2]);
  161. }
  162. public Vector3 GetAxis(int axis)
  163. {
  164. return new Vector3(this[0, axis], this[1, axis], this[2, axis]);
  165. }
  166. public void SetAxis(int axis, Vector3 value)
  167. {
  168. this[0, axis] = value.x;
  169. this[1, axis] = value.y;
  170. this[2, axis] = value.z;
  171. }
  172. public Vector3 GetEuler()
  173. {
  174. Basis m = Orthonormalized();
  175. Vector3 euler;
  176. euler.z = 0.0f;
  177. real_t mxy = m[1, 2];
  178. if (mxy < 1.0f)
  179. {
  180. if (mxy > -1.0f)
  181. {
  182. euler.x = Mathf.Asin(-mxy);
  183. euler.y = Mathf.Atan2(m[0, 2], m[2, 2]);
  184. euler.z = Mathf.Atan2(m[1, 0], m[1, 1]);
  185. }
  186. else
  187. {
  188. euler.x = Mathf.Pi * 0.5f;
  189. euler.y = -Mathf.Atan2(-m[0, 1], m[0, 0]);
  190. }
  191. }
  192. else
  193. {
  194. euler.x = -Mathf.Pi * 0.5f;
  195. euler.y = -Mathf.Atan2(-m[0, 1], m[0, 0]);
  196. }
  197. return euler;
  198. }
  199. public int GetOrthogonalIndex()
  200. {
  201. var orth = this;
  202. for (int i = 0; i < 3; i++)
  203. {
  204. for (int j = 0; j < 3; j++)
  205. {
  206. real_t v = orth[i, j];
  207. if (v > 0.5f)
  208. v = 1.0f;
  209. else if (v < -0.5f)
  210. v = -1.0f;
  211. else
  212. v = 0f;
  213. orth[i, j] = v;
  214. }
  215. }
  216. for (int i = 0; i < 24; i++)
  217. {
  218. if (orthoBases[i] == orth)
  219. return i;
  220. }
  221. return 0;
  222. }
  223. public Basis Inverse()
  224. {
  225. var inv = this;
  226. real_t[] co = {
  227. inv[1, 1] * inv[2, 2] - inv[1, 2] * inv[2, 1],
  228. inv[1, 2] * inv[2, 0] - inv[1, 0] * inv[2, 2],
  229. inv[1, 0] * inv[2, 1] - inv[1, 1] * inv[2, 0]
  230. };
  231. real_t det = inv[0, 0] * co[0] + inv[0, 1] * co[1] + inv[0, 2] * co[2];
  232. if (det == 0)
  233. {
  234. return new Basis
  235. (
  236. real_t.NaN, real_t.NaN, real_t.NaN,
  237. real_t.NaN, real_t.NaN, real_t.NaN,
  238. real_t.NaN, real_t.NaN, real_t.NaN
  239. );
  240. }
  241. real_t s = 1.0f / det;
  242. inv = new Basis
  243. (
  244. co[0] * s,
  245. inv[0, 2] * inv[2, 1] - inv[0, 1] * inv[2, 2] * s,
  246. inv[0, 1] * inv[1, 2] - inv[0, 2] * inv[1, 1] * s,
  247. co[1] * s,
  248. inv[0, 0] * inv[2, 2] - inv[0, 2] * inv[2, 0] * s,
  249. inv[0, 2] * inv[1, 0] - inv[0, 0] * inv[1, 2] * s,
  250. co[2] * s,
  251. inv[0, 1] * inv[2, 0] - inv[0, 0] * inv[2, 1] * s,
  252. inv[0, 0] * inv[1, 1] - inv[0, 1] * inv[1, 0] * s
  253. );
  254. return inv;
  255. }
  256. public Basis Orthonormalized()
  257. {
  258. Vector3 xAxis = GetAxis(0);
  259. Vector3 yAxis = GetAxis(1);
  260. Vector3 zAxis = GetAxis(2);
  261. xAxis.Normalize();
  262. yAxis = yAxis - xAxis * xAxis.Dot(yAxis);
  263. yAxis.Normalize();
  264. zAxis = zAxis - xAxis * xAxis.Dot(zAxis) - yAxis * yAxis.Dot(zAxis);
  265. zAxis.Normalize();
  266. return CreateFromAxes(xAxis, yAxis, zAxis);
  267. }
  268. public Basis Rotated(Vector3 axis, real_t phi)
  269. {
  270. return new Basis(axis, phi) * this;
  271. }
  272. public Basis Scaled(Vector3 scale)
  273. {
  274. var m = this;
  275. m[0, 0] *= scale.x;
  276. m[0, 1] *= scale.x;
  277. m[0, 2] *= scale.x;
  278. m[1, 0] *= scale.y;
  279. m[1, 1] *= scale.y;
  280. m[1, 2] *= scale.y;
  281. m[2, 0] *= scale.z;
  282. m[2, 1] *= scale.z;
  283. m[2, 2] *= scale.z;
  284. return m;
  285. }
  286. public real_t Tdotx(Vector3 with)
  287. {
  288. return this[0, 0] * with[0] + this[1, 0] * with[1] + this[2, 0] * with[2];
  289. }
  290. public real_t Tdoty(Vector3 with)
  291. {
  292. return this[0, 1] * with[0] + this[1, 1] * with[1] + this[2, 1] * with[2];
  293. }
  294. public real_t Tdotz(Vector3 with)
  295. {
  296. return this[0, 2] * with[0] + this[1, 2] * with[1] + this[2, 2] * with[2];
  297. }
  298. public Basis Transposed()
  299. {
  300. var tr = this;
  301. real_t temp = tr[0, 1];
  302. tr[0, 1] = tr[1, 0];
  303. tr[1, 0] = temp;
  304. temp = tr[0, 2];
  305. tr[0, 2] = tr[2, 0];
  306. tr[2, 0] = temp;
  307. temp = tr[1, 2];
  308. tr[1, 2] = tr[2, 1];
  309. tr[2, 1] = temp;
  310. return tr;
  311. }
  312. public Vector3 Xform(Vector3 v)
  313. {
  314. return new Vector3
  315. (
  316. this[0].Dot(v),
  317. this[1].Dot(v),
  318. this[2].Dot(v)
  319. );
  320. }
  321. public Vector3 XformInv(Vector3 v)
  322. {
  323. return new Vector3
  324. (
  325. this[0, 0] * v.x + this[1, 0] * v.y + this[2, 0] * v.z,
  326. this[0, 1] * v.x + this[1, 1] * v.y + this[2, 1] * v.z,
  327. this[0, 2] * v.x + this[1, 2] * v.y + this[2, 2] * v.z
  328. );
  329. }
  330. public Quat Quat() {
  331. real_t trace = _x[0] + _y[1] + _z[2];
  332. if (trace > 0.0f) {
  333. real_t s = Mathf.Sqrt(trace + 1.0f) * 2f;
  334. real_t inv_s = 1f / s;
  335. return new Quat(
  336. (_z[1] - _y[2]) * inv_s,
  337. (_x[2] - _z[0]) * inv_s,
  338. (_y[0] - _x[1]) * inv_s,
  339. s * 0.25f
  340. );
  341. }
  342. if (_x[0] > _y[1] && _x[0] > _z[2]) {
  343. real_t s = Mathf.Sqrt(_x[0] - _y[1] - _z[2] + 1.0f) * 2f;
  344. real_t inv_s = 1f / s;
  345. return new Quat(
  346. s * 0.25f,
  347. (_x[1] + _y[0]) * inv_s,
  348. (_x[2] + _z[0]) * inv_s,
  349. (_z[1] - _y[2]) * inv_s
  350. );
  351. }
  352. if (_y[1] > _z[2]) {
  353. real_t s = Mathf.Sqrt(-_x[0] + _y[1] - _z[2] + 1.0f) * 2f;
  354. real_t inv_s = 1f / s;
  355. return new Quat(
  356. (_x[1] + _y[0]) * inv_s,
  357. s * 0.25f,
  358. (_y[2] + _z[1]) * inv_s,
  359. (_x[2] - _z[0]) * inv_s
  360. );
  361. } else {
  362. real_t s = Mathf.Sqrt(-_x[0] - _y[1] + _z[2] + 1.0f) * 2f;
  363. real_t inv_s = 1f / s;
  364. return new Quat(
  365. (_x[2] + _z[0]) * inv_s,
  366. (_y[2] + _z[1]) * inv_s,
  367. s * 0.25f,
  368. (_y[0] - _x[1]) * inv_s
  369. );
  370. }
  371. }
  372. public Basis(Quat quat)
  373. {
  374. real_t s = 2.0f / quat.LengthSquared();
  375. real_t xs = quat.x * s;
  376. real_t ys = quat.y * s;
  377. real_t zs = quat.z * s;
  378. real_t wx = quat.w * xs;
  379. real_t wy = quat.w * ys;
  380. real_t wz = quat.w * zs;
  381. real_t xx = quat.x * xs;
  382. real_t xy = quat.x * ys;
  383. real_t xz = quat.x * zs;
  384. real_t yy = quat.y * ys;
  385. real_t yz = quat.y * zs;
  386. real_t zz = quat.z * zs;
  387. _x = new Vector3(1.0f - (yy + zz), xy - wz, xz + wy);
  388. _y = new Vector3(xy + wz, 1.0f - (xx + zz), yz - wx);
  389. _z = new Vector3(xz - wy, yz + wx, 1.0f - (xx + yy));
  390. }
  391. public Basis(Vector3 euler)
  392. {
  393. real_t c;
  394. real_t s;
  395. c = Mathf.Cos(euler.x);
  396. s = Mathf.Sin(euler.x);
  397. var xmat = new Basis(1, 0, 0, 0, c, -s, 0, s, c);
  398. c = Mathf.Cos(euler.y);
  399. s = Mathf.Sin(euler.y);
  400. var ymat = new Basis(c, 0, s, 0, 1, 0, -s, 0, c);
  401. c = Mathf.Cos(euler.z);
  402. s = Mathf.Sin(euler.z);
  403. var zmat = new Basis(c, -s, 0, s, c, 0, 0, 0, 1);
  404. this = ymat * xmat * zmat;
  405. }
  406. public Basis(Vector3 axis, real_t phi)
  407. {
  408. var axis_sq = new Vector3(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z);
  409. real_t cosine = Mathf.Cos( phi);
  410. real_t sine = Mathf.Sin( phi);
  411. _x = new Vector3
  412. (
  413. axis_sq.x + cosine * (1.0f - axis_sq.x),
  414. axis.x * axis.y * (1.0f - cosine) - axis.z * sine,
  415. axis.z * axis.x * (1.0f - cosine) + axis.y * sine
  416. );
  417. _y = new Vector3
  418. (
  419. axis.x * axis.y * (1.0f - cosine) + axis.z * sine,
  420. axis_sq.y + cosine * (1.0f - axis_sq.y),
  421. axis.y * axis.z * (1.0f - cosine) - axis.x * sine
  422. );
  423. _z = new Vector3
  424. (
  425. axis.z * axis.x * (1.0f - cosine) - axis.y * sine,
  426. axis.y * axis.z * (1.0f - cosine) + axis.x * sine,
  427. axis_sq.z + cosine * (1.0f - axis_sq.z)
  428. );
  429. }
  430. public Basis(Vector3 xAxis, Vector3 yAxis, Vector3 zAxis)
  431. {
  432. _x = xAxis;
  433. _y = yAxis;
  434. _z = zAxis;
  435. }
  436. 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)
  437. {
  438. _x = new Vector3(xx, xy, xz);
  439. _y = new Vector3(yx, yy, yz);
  440. _z = new Vector3(zx, zy, zz);
  441. }
  442. public static Basis operator *(Basis left, Basis right)
  443. {
  444. return new Basis
  445. (
  446. right.Tdotx(left[0]), right.Tdoty(left[0]), right.Tdotz(left[0]),
  447. right.Tdotx(left[1]), right.Tdoty(left[1]), right.Tdotz(left[1]),
  448. right.Tdotx(left[2]), right.Tdoty(left[2]), right.Tdotz(left[2])
  449. );
  450. }
  451. public static bool operator ==(Basis left, Basis right)
  452. {
  453. return left.Equals(right);
  454. }
  455. public static bool operator !=(Basis left, Basis right)
  456. {
  457. return !left.Equals(right);
  458. }
  459. public override bool Equals(object obj)
  460. {
  461. if (obj is Basis)
  462. {
  463. return Equals((Basis)obj);
  464. }
  465. return false;
  466. }
  467. public bool Equals(Basis other)
  468. {
  469. return _x.Equals(other[0]) && _y.Equals(other[1]) && _z.Equals(other[2]);
  470. }
  471. public override int GetHashCode()
  472. {
  473. return _x.GetHashCode() ^ _y.GetHashCode() ^ _z.GetHashCode();
  474. }
  475. public override string ToString()
  476. {
  477. return String.Format("({0}, {1}, {2})", new object[]
  478. {
  479. _x.ToString(),
  480. _y.ToString(),
  481. _z.ToString()
  482. });
  483. }
  484. public string ToString(string format)
  485. {
  486. return String.Format("({0}, {1}, {2})", new object[]
  487. {
  488. _x.ToString(format),
  489. _y.ToString(format),
  490. _z.ToString(format)
  491. });
  492. }
  493. }
  494. }