BabylonQuaternion.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. using System;
  2. namespace BabylonExport.Entities
  3. {
  4. public class BabylonQuaternion
  5. {
  6. public float X { get; set; }
  7. public float Y { get; set; }
  8. public float Z { get; set; }
  9. public float W { get; set; }
  10. public BabylonQuaternion() { }
  11. /**
  12. * Creates a new Quaternion from the passed floats.
  13. */
  14. public BabylonQuaternion(float x, float y, float z, float w)
  15. {
  16. this.X = x;
  17. this.Y = y;
  18. this.Z = z;
  19. this.W = w;
  20. }
  21. public float[] ToArray()
  22. {
  23. return new [] {X, Y, Z, W};
  24. }
  25. /**
  26. * Copy / pasted from babylon
  27. */
  28. public BabylonVector3 toEulerAngles()
  29. {
  30. var result = new BabylonVector3();
  31. var qz = this.Z;
  32. var qx = this.X;
  33. var qy = this.Y;
  34. var qw = this.W;
  35. var sqw = qw * qw;
  36. var sqz = qz * qz;
  37. var sqx = qx * qx;
  38. var sqy = qy * qy;
  39. var zAxisY = qy * qz - qx * qw;
  40. var limit = .4999999;
  41. if (zAxisY< -limit) {
  42. result.Y = (float) (2 * Math.Atan2(qy, qw));
  43. result.X = (float) Math.PI / 2;
  44. result.Z = 0;
  45. } else if (zAxisY > limit) {
  46. result.Y = (float) (2 * Math.Atan2(qy, qw));
  47. result.X = (float) -Math.PI / 2;
  48. result.Z = 0;
  49. } else {
  50. result.Z = (float)Math.Atan2(2.0 * (qx* qy + qz* qw), (-sqz - sqx + sqy + sqw));
  51. result.X = (float)Math.Asin(-2.0 * (qz* qy - qx* qw));
  52. result.Y = (float)Math.Atan2(2.0 * (qz* qx + qy* qw), (sqz - sqx - sqy + sqw));
  53. }
  54. return result;
  55. }
  56. public override string ToString()
  57. {
  58. return "{ X=" + X + ", Y=" + Y + ", Z=" + Z + ", W=" + W + " }";
  59. }
  60. /**
  61. * Updates the passed quaternion "result" with the passed rotation matrix values.
  62. */
  63. public static void FromRotationMatrixToRef(BabylonMatrix matrix, BabylonQuaternion result) {
  64. var data = matrix.m;
  65. float m11 = data[0], m12 = data[4], m13 = data[8];
  66. float m21 = data[1], m22 = data[5], m23 = data[9];
  67. float m31 = data[2], m32 = data[6], m33 = data[10];
  68. var trace = m11 + m22 + m33;
  69. float s;
  70. if (trace > 0) {
  71. s = (float) (0.5 / Math.Sqrt(trace + 1.0));
  72. result.W = 0.25f / s;
  73. result.X = (m32 - m23) * s;
  74. result.Y = (m13 - m31) * s;
  75. result.Z = (m21 - m12) * s;
  76. } else if (m11 > m22 && m11 > m33) {
  77. s = (float)(2.0 * Math.Sqrt(1.0 + m11 - m22 - m33));
  78. result.W = (m32 - m23) / s;
  79. result.X = 0.25f * s;
  80. result.Y = (m12 + m21) / s;
  81. result.Z = (m13 + m31) / s;
  82. } else if (m22 > m33) {
  83. s = (float)(2.0 * Math.Sqrt(1.0 + m22 - m11 - m33));
  84. result.W = (m13 - m31) / s;
  85. result.X = (m12 + m21) / s;
  86. result.Y = 0.25f * s;
  87. result.Z = (m23 + m32) / s;
  88. } else {
  89. s = (float)(2.0 * Math.Sqrt(1.0 + m33 - m11 - m22));
  90. result.W = (m21 - m12) / s;
  91. result.X = (m13 + m31) / s;
  92. result.Y = (m23 + m32) / s;
  93. result.Z = 0.25f * s;
  94. }
  95. }
  96. /**
  97. * Updates the passed rotation matrix with the current Quaternion values.
  98. * Returns the current Quaternion.
  99. */
  100. public BabylonQuaternion toRotationMatrix(BabylonMatrix result) {
  101. var xx = this.X * this.X;
  102. var yy = this.Y * this.Y;
  103. var zz = this.Z * this.Z;
  104. var xy = this.X * this.Y;
  105. var zw = this.Z * this.W;
  106. var zx = this.Z * this.X;
  107. var yw = this.Y * this.W;
  108. var yz = this.Y * this.Z;
  109. var xw = this.X * this.W;
  110. result.m[0] = 1.0f - (2.0f * (yy + zz));
  111. result.m[1] = 2.0f * (xy + zw);
  112. result.m[2] = 2.0f * (zx - yw);
  113. result.m[3] = 0;
  114. result.m[4] = 2.0f * (xy - zw);
  115. result.m[5] = 1.0f - (2.0f * (zz + xx));
  116. result.m[6] = 2.0f * (yz + xw);
  117. result.m[7] = 0;
  118. result.m[8] = 2.0f * (zx + yw);
  119. result.m[9] = 2.0f * (yz - xw);
  120. result.m[10] = 1.0f - (2.0f * (yy + xx));
  121. result.m[11] = 0;
  122. result.m[12] = 0;
  123. result.m[13] = 0;
  124. result.m[14] = 0;
  125. result.m[15] = 1.0f;
  126. return this;
  127. }
  128. /**
  129. * Retuns a new Quaternion set from the starting index of the passed array.
  130. */
  131. public static BabylonQuaternion FromArray(float[] array, int offset = 0)
  132. {
  133. return new BabylonQuaternion(array[offset], array[offset + 1], array[offset + 2], array[offset + 3]);
  134. }
  135. }
  136. }