PikaMath_Quaternion.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. #include "PikaMath_Quaternion.h"
  2. #include "PikaStdData_List.h"
  3. #include "math.h"
  4. void PikaMath_Quaternion___init__(PikaObj* self) {
  5. obj_setFloat(self, "x", 0.0);
  6. obj_setFloat(self, "y", 0.0);
  7. obj_setFloat(self, "z", 0.0);
  8. obj_setFloat(self, "w", 1.0);
  9. }
  10. void PikaMath_Quaternion_set(PikaObj* self,
  11. pika_float x,
  12. pika_float y,
  13. pika_float z,
  14. pika_float w) {
  15. obj_setFloat(self, "x", x);
  16. obj_setFloat(self, "y", y);
  17. obj_setFloat(self, "z", z);
  18. obj_setFloat(self, "w", w);
  19. }
  20. pika_float PikaMath_Quaternion_get(PikaObj* self, int key) {
  21. if (key == 0) {
  22. return obj_getFloat(self, "x");
  23. }
  24. if (key == 1) {
  25. return obj_getFloat(self, "y");
  26. }
  27. if (key == 2) {
  28. return obj_getFloat(self, "z");
  29. }
  30. if (key == 3) {
  31. return obj_getFloat(self, "w");
  32. } else {
  33. obj_setErrorCode(self, 1);
  34. return 0.0;
  35. }
  36. }
  37. void PikaMath_Quaternion_add(PikaObj* self, PikaObj* quat) {
  38. float x_ = obj_getFloat(quat, "x");
  39. float y_ = obj_getFloat(quat, "y");
  40. float z_ = obj_getFloat(quat, "z");
  41. float w_ = obj_getFloat(quat, "w");
  42. float x = obj_getFloat(self, "x");
  43. float y = obj_getFloat(self, "y");
  44. float z = obj_getFloat(self, "z");
  45. float w = obj_getFloat(self, "w");
  46. float x_sum = x + x_;
  47. float y_sum = y + y_;
  48. float z_sum = z + z_;
  49. float w_sum = w + w_;
  50. obj_setFloat(self, "x", x_sum);
  51. obj_setFloat(self, "y", y_sum);
  52. obj_setFloat(self, "z", z_sum);
  53. obj_setFloat(self, "w", w_sum);
  54. }
  55. void PikaMath_Quaternion_sub(PikaObj* self, PikaObj* quat) {
  56. float x_ = obj_getFloat(quat, "x");
  57. float y_ = obj_getFloat(quat, "y");
  58. float z_ = obj_getFloat(quat, "z");
  59. float w_ = obj_getFloat(quat, "w");
  60. float x = obj_getFloat(self, "x");
  61. float y = obj_getFloat(self, "y");
  62. float z = obj_getFloat(self, "z");
  63. float w = obj_getFloat(self, "w");
  64. float x_sub = x - x_;
  65. float y_sub = y - y_;
  66. float z_sub = z - z_;
  67. float w_sub = w - w_;
  68. obj_setFloat(self, "x", x_sub);
  69. obj_setFloat(self, "y", y_sub);
  70. obj_setFloat(self, "z", z_sub);
  71. obj_setFloat(self, "w", w_sub);
  72. }
  73. void PikaMath_Quaternion_mul(PikaObj* self, PikaObj* quat) {
  74. float x_ = obj_getFloat(quat, "x");
  75. float y_ = obj_getFloat(quat, "y");
  76. float z_ = obj_getFloat(quat, "z");
  77. float w_ = obj_getFloat(quat, "w");
  78. float x = obj_getFloat(self, "x");
  79. float y = obj_getFloat(self, "y");
  80. float z = obj_getFloat(self, "z");
  81. float w = obj_getFloat(self, "w");
  82. float x_mul = w * x_ + x * w_ - y * z_ + z * y_;
  83. float y_mul = w * y_ + y * w_ + x * z_ - z * x_;
  84. float z_mul = w * z_ + z * w_ - x * y_ + y * x_;
  85. float w_mul = w * w_ - x * x_ - y * y_ - z * z_;
  86. obj_setFloat(self, "x", x_mul);
  87. obj_setFloat(self, "y", y_mul);
  88. obj_setFloat(self, "z", z_mul);
  89. obj_setFloat(self, "w", w_mul);
  90. }
  91. pika_float PikaMath_Quaternion_magnituded(PikaObj* self) {
  92. float magnituded = PikaMath_Quaternion_magnitudedsquare(self);
  93. return pow(magnituded, 0.5);
  94. }
  95. pika_float PikaMath_Quaternion_magnitudedsquare(PikaObj* self) {
  96. float x = obj_getFloat(self, "x");
  97. float y = obj_getFloat(self, "y");
  98. float z = obj_getFloat(self, "z");
  99. float w = obj_getFloat(self, "w");
  100. float magnitudedsquare = pow(x, 2) + pow(y, 2) + pow(z, 2) + pow(w, 2);
  101. return magnitudedsquare;
  102. }
  103. void PikaMath_Quaternion_reverse(PikaObj* self) {
  104. float x = obj_getFloat(self, "x");
  105. float y = obj_getFloat(self, "y");
  106. float z = obj_getFloat(self, "z");
  107. float w = obj_getFloat(self, "w");
  108. obj_setFloat(self, "x", -x);
  109. obj_setFloat(self, "y", -y);
  110. obj_setFloat(self, "z", -z);
  111. obj_setFloat(self, "w", w);
  112. }
  113. void PikaMath_Quaternion_inverse(PikaObj* self) {
  114. float x = obj_getFloat(self, "x");
  115. float y = obj_getFloat(self, "y");
  116. float z = obj_getFloat(self, "z");
  117. float w = obj_getFloat(self, "w");
  118. float mag = PikaMath_Quaternion_magnitudedsquare(self);
  119. if (mag > 0.0001) {
  120. obj_setFloat(self, "x", -x / mag);
  121. obj_setFloat(self, "y", -y / mag);
  122. obj_setFloat(self, "z", -z / mag);
  123. obj_setFloat(self, "w", w / mag);
  124. } else {
  125. obj_setFloat(self, "x", 0.0);
  126. obj_setFloat(self, "y", 0.0);
  127. obj_setFloat(self, "z", 0.0);
  128. obj_setFloat(self, "w", 1.0);
  129. }
  130. }
  131. void PikaMath_Quaternion_crossproduct(PikaObj* self, PikaObj* quat) {
  132. float x_ = obj_getFloat(quat, "x");
  133. float y_ = obj_getFloat(quat, "y");
  134. float z_ = obj_getFloat(quat, "z");
  135. float x = obj_getFloat(self, "x");
  136. float y = obj_getFloat(self, "y");
  137. float z = obj_getFloat(self, "z");
  138. float x_cross = y * z_ - z * y_;
  139. float y_cross = z * x_ - x * z_;
  140. float z_cross = x * y_ - y * x_;
  141. obj_setFloat(self, "x", x_cross);
  142. obj_setFloat(self, "y", y_cross);
  143. obj_setFloat(self, "z", z_cross);
  144. obj_setFloat(self, "w", 0.0);
  145. }
  146. pika_float PikaMath_Quaternion_dot(PikaObj* self, PikaObj* quat) {
  147. float x_ = obj_getFloat(quat, "x");
  148. float y_ = obj_getFloat(quat, "y");
  149. float z_ = obj_getFloat(quat, "z");
  150. float w_ = obj_getFloat(quat, "w");
  151. float x = obj_getFloat(self, "x");
  152. float y = obj_getFloat(self, "y");
  153. float z = obj_getFloat(self, "z");
  154. float w = obj_getFloat(self, "w");
  155. return (x_ * x + y_ * y + z_ * z + w_ * w);
  156. }
  157. void PikaMath_Quaternion_normalize(PikaObj* self) {
  158. float x = obj_getFloat(self, "x");
  159. float y = obj_getFloat(self, "y");
  160. float z = obj_getFloat(self, "z");
  161. float w = obj_getFloat(self, "w");
  162. float mag = PikaMath_Quaternion_magnituded(self);
  163. if (mag > 0.0001) {
  164. obj_setFloat(self, "x", x / mag);
  165. obj_setFloat(self, "y", y / mag);
  166. obj_setFloat(self, "z", z / mag);
  167. obj_setFloat(self, "w", w / mag);
  168. } else {
  169. obj_setFloat(self, "x", 0.0);
  170. obj_setFloat(self, "y", 0.0);
  171. obj_setFloat(self, "z", 0.0);
  172. obj_setFloat(self, "w", 1.0);
  173. }
  174. }
  175. int PikaMath_Quaternion_isnormalize(PikaObj* self) {
  176. float mag = PikaMath_Quaternion_magnituded(self);
  177. if (1.0 == mag) {
  178. return 1;
  179. } else {
  180. return 0;
  181. }
  182. }
  183. #define PI_DIV_180 (0.017453292519943296)
  184. #define DegToRad(x) ((x)*PI_DIV_180)
  185. void PikaMath_Quaternion_fromEuler(PikaObj* self,
  186. pika_float yaw,
  187. pika_float pitch,
  188. pika_float roll,
  189. int mode) {
  190. if (mode) {
  191. pitch = DegToRad(pitch);
  192. roll = DegToRad(roll);
  193. yaw = DegToRad(yaw);
  194. }
  195. float sinp = sin(pitch / 2);
  196. float siny = sin(yaw / 2);
  197. float sinr = sin(roll / 2);
  198. float cosp = cos(pitch / 2);
  199. float cosy = cos(yaw / 2);
  200. float cosr = cos(roll / 2);
  201. float x = sinr * cosp * cosy - cosr * sinp * siny;
  202. float y = cosr * sinp * cosy + sinr * cosp * siny;
  203. float z = cosr * cosp * siny - sinr * sinp * cosy;
  204. float w = cosr * cosp * cosy + sinr * sinp * siny;
  205. obj_setFloat(self, "x", x);
  206. obj_setFloat(self, "y", y);
  207. obj_setFloat(self, "z", z);
  208. obj_setFloat(self, "w", w);
  209. }
  210. PikaObj* PikaMath_Quaternion_toEuler(PikaObj* self) {
  211. float x = obj_getFloat(self, "x");
  212. float y = obj_getFloat(self, "y");
  213. float z = obj_getFloat(self, "z");
  214. float w = obj_getFloat(self, "w");
  215. float roll = atan2(2 * (w * x + y * z), 1 - 2 * (x * x + y * y));
  216. float pitch = asin(2 * (w * y - z * x));
  217. float yaw = atan2(2 * (w * z + x * y), 1 - 2 * (y * y + z * z));
  218. float rpy[3] = {roll, pitch, yaw};
  219. PikaObj* list = newNormalObj(New_PikaStdData_List);
  220. PikaStdData_List___init__(list);
  221. for (int i = 0; i < 3; i++) {
  222. Arg* token_arg = arg_newFloat(rpy[i]);
  223. PikaStdData_List_append(list, token_arg);
  224. arg_deinit(token_arg);
  225. }
  226. return list;
  227. }