gtx_euler_angle.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. // Code sample from Filippo Ramaciotti
  2. #include <glm/gtc/matrix_transform.hpp>
  3. #include <glm/gtc/epsilon.hpp>
  4. #include <glm/gtx/string_cast.hpp>
  5. #include <glm/gtx/euler_angles.hpp>
  6. #include <cstdio>
  7. namespace test_eulerAngleX
  8. {
  9. int test()
  10. {
  11. int Error = 0;
  12. float const Angle(glm::pi<float>() * 0.5f);
  13. glm::vec3 const X(1.0f, 0.0f, 0.0f);
  14. glm::vec4 const Y(0.0f, 1.0f, 0.0f, 1.0f);
  15. glm::vec4 const Y1 = glm::rotate(glm::mat4(1.0f), Angle, X) * Y;
  16. glm::vec4 const Y2 = glm::eulerAngleX(Angle) * Y;
  17. glm::vec4 const Y3 = glm::eulerAngleXY(Angle, 0.0f) * Y;
  18. glm::vec4 const Y4 = glm::eulerAngleYX(0.0f, Angle) * Y;
  19. glm::vec4 const Y5 = glm::eulerAngleXZ(Angle, 0.0f) * Y;
  20. glm::vec4 const Y6 = glm::eulerAngleZX(0.0f, Angle) * Y;
  21. glm::vec4 const Y7 = glm::eulerAngleYXZ(0.0f, Angle, 0.0f) * Y;
  22. Error += glm::all(glm::epsilonEqual(Y1, Y2, 0.00001f)) ? 0 : 1;
  23. Error += glm::all(glm::epsilonEqual(Y1, Y3, 0.00001f)) ? 0 : 1;
  24. Error += glm::all(glm::epsilonEqual(Y1, Y4, 0.00001f)) ? 0 : 1;
  25. Error += glm::all(glm::epsilonEqual(Y1, Y5, 0.00001f)) ? 0 : 1;
  26. Error += glm::all(glm::epsilonEqual(Y1, Y6, 0.00001f)) ? 0 : 1;
  27. Error += glm::all(glm::epsilonEqual(Y1, Y7, 0.00001f)) ? 0 : 1;
  28. glm::vec4 const Z(0.0f, 0.0f, 1.0f, 1.0f);
  29. glm::vec4 const Z1 = glm::rotate(glm::mat4(1.0f), Angle, X) * Z;
  30. glm::vec4 const Z2 = glm::eulerAngleX(Angle) * Z;
  31. glm::vec4 const Z3 = glm::eulerAngleXY(Angle, 0.0f) * Z;
  32. glm::vec4 const Z4 = glm::eulerAngleYX(0.0f, Angle) * Z;
  33. glm::vec4 const Z5 = glm::eulerAngleXZ(Angle, 0.0f) * Z;
  34. glm::vec4 const Z6 = glm::eulerAngleZX(0.0f, Angle) * Z;
  35. glm::vec4 const Z7 = glm::eulerAngleYXZ(0.0f, Angle, 0.0f) * Z;
  36. Error += glm::all(glm::epsilonEqual(Z1, Z2, 0.00001f)) ? 0 : 1;
  37. Error += glm::all(glm::epsilonEqual(Z1, Z3, 0.00001f)) ? 0 : 1;
  38. Error += glm::all(glm::epsilonEqual(Z1, Z4, 0.00001f)) ? 0 : 1;
  39. Error += glm::all(glm::epsilonEqual(Z1, Z5, 0.00001f)) ? 0 : 1;
  40. Error += glm::all(glm::epsilonEqual(Z1, Z6, 0.00001f)) ? 0 : 1;
  41. Error += glm::all(glm::epsilonEqual(Z1, Z7, 0.00001f)) ? 0 : 1;
  42. return Error;
  43. }
  44. }//namespace test_eulerAngleX
  45. namespace test_eulerAngleY
  46. {
  47. int test()
  48. {
  49. int Error = 0;
  50. float const Angle(glm::pi<float>() * 0.5f);
  51. glm::vec3 const Y(0.0f, 1.0f, 0.0f);
  52. glm::vec4 const X(1.0f, 0.0f, 0.0f, 1.0f);
  53. glm::vec4 const X1 = glm::rotate(glm::mat4(1.0f), Angle, Y) * X;
  54. glm::vec4 const X2 = glm::eulerAngleY(Angle) * X;
  55. glm::vec4 const X3 = glm::eulerAngleYX(Angle, 0.0f) * X;
  56. glm::vec4 const X4 = glm::eulerAngleXY(0.0f, Angle) * X;
  57. glm::vec4 const X5 = glm::eulerAngleYZ(Angle, 0.0f) * X;
  58. glm::vec4 const X6 = glm::eulerAngleZY(0.0f, Angle) * X;
  59. glm::vec4 const X7 = glm::eulerAngleYXZ(Angle, 0.0f, 0.0f) * X;
  60. Error += glm::all(glm::epsilonEqual(X1, X2, 0.00001f)) ? 0 : 1;
  61. Error += glm::all(glm::epsilonEqual(X1, X3, 0.00001f)) ? 0 : 1;
  62. Error += glm::all(glm::epsilonEqual(X1, X4, 0.00001f)) ? 0 : 1;
  63. Error += glm::all(glm::epsilonEqual(X1, X5, 0.00001f)) ? 0 : 1;
  64. Error += glm::all(glm::epsilonEqual(X1, X6, 0.00001f)) ? 0 : 1;
  65. Error += glm::all(glm::epsilonEqual(X1, X7, 0.00001f)) ? 0 : 1;
  66. glm::vec4 const Z(0.0f, 0.0f, 1.0f, 1.0f);
  67. glm::vec4 const Z1 = glm::eulerAngleY(Angle) * Z;
  68. glm::vec4 const Z2 = glm::rotate(glm::mat4(1.0f), Angle, Y) * Z;
  69. glm::vec4 const Z3 = glm::eulerAngleYX(Angle, 0.0f) * Z;
  70. glm::vec4 const Z4 = glm::eulerAngleXY(0.0f, Angle) * Z;
  71. glm::vec4 const Z5 = glm::eulerAngleYZ(Angle, 0.0f) * Z;
  72. glm::vec4 const Z6 = glm::eulerAngleZY(0.0f, Angle) * Z;
  73. glm::vec4 const Z7 = glm::eulerAngleYXZ(Angle, 0.0f, 0.0f) * Z;
  74. Error += glm::all(glm::epsilonEqual(Z1, Z2, 0.00001f)) ? 0 : 1;
  75. Error += glm::all(glm::epsilonEqual(Z1, Z3, 0.00001f)) ? 0 : 1;
  76. Error += glm::all(glm::epsilonEqual(Z1, Z4, 0.00001f)) ? 0 : 1;
  77. Error += glm::all(glm::epsilonEqual(Z1, Z5, 0.00001f)) ? 0 : 1;
  78. Error += glm::all(glm::epsilonEqual(Z1, Z6, 0.00001f)) ? 0 : 1;
  79. Error += glm::all(glm::epsilonEqual(Z1, Z7, 0.00001f)) ? 0 : 1;
  80. return Error;
  81. }
  82. }//namespace test_eulerAngleY
  83. namespace test_eulerAngleZ
  84. {
  85. int test()
  86. {
  87. int Error = 0;
  88. float const Angle(glm::pi<float>() * 0.5f);
  89. glm::vec3 const Z(0.0f, 0.0f, 1.0f);
  90. glm::vec4 const X(1.0f, 0.0f, 0.0f, 1.0f);
  91. glm::vec4 const X1 = glm::rotate(glm::mat4(1.0f), Angle, Z) * X;
  92. glm::vec4 const X2 = glm::eulerAngleZ(Angle) * X;
  93. glm::vec4 const X3 = glm::eulerAngleZX(Angle, 0.0f) * X;
  94. glm::vec4 const X4 = glm::eulerAngleXZ(0.0f, Angle) * X;
  95. glm::vec4 const X5 = glm::eulerAngleZY(Angle, 0.0f) * X;
  96. glm::vec4 const X6 = glm::eulerAngleYZ(0.0f, Angle) * X;
  97. glm::vec4 const X7 = glm::eulerAngleYXZ(0.0f, 0.0f, Angle) * X;
  98. Error += glm::all(glm::epsilonEqual(X1, X2, 0.00001f)) ? 0 : 1;
  99. Error += glm::all(glm::epsilonEqual(X1, X3, 0.00001f)) ? 0 : 1;
  100. Error += glm::all(glm::epsilonEqual(X1, X4, 0.00001f)) ? 0 : 1;
  101. Error += glm::all(glm::epsilonEqual(X1, X5, 0.00001f)) ? 0 : 1;
  102. Error += glm::all(glm::epsilonEqual(X1, X6, 0.00001f)) ? 0 : 1;
  103. Error += glm::all(glm::epsilonEqual(X1, X7, 0.00001f)) ? 0 : 1;
  104. glm::vec4 const Y(1.0f, 0.0f, 0.0f, 1.0f);
  105. glm::vec4 const Z1 = glm::rotate(glm::mat4(1.0f), Angle, Z) * Y;
  106. glm::vec4 const Z2 = glm::eulerAngleZ(Angle) * Y;
  107. glm::vec4 const Z3 = glm::eulerAngleZX(Angle, 0.0f) * Y;
  108. glm::vec4 const Z4 = glm::eulerAngleXZ(0.0f, Angle) * Y;
  109. glm::vec4 const Z5 = glm::eulerAngleZY(Angle, 0.0f) * Y;
  110. glm::vec4 const Z6 = glm::eulerAngleYZ(0.0f, Angle) * Y;
  111. glm::vec4 const Z7 = glm::eulerAngleYXZ(0.0f, 0.0f, Angle) * Y;
  112. Error += glm::all(glm::epsilonEqual(Z1, Z2, 0.00001f)) ? 0 : 1;
  113. Error += glm::all(glm::epsilonEqual(Z1, Z3, 0.00001f)) ? 0 : 1;
  114. Error += glm::all(glm::epsilonEqual(Z1, Z4, 0.00001f)) ? 0 : 1;
  115. Error += glm::all(glm::epsilonEqual(Z1, Z5, 0.00001f)) ? 0 : 1;
  116. Error += glm::all(glm::epsilonEqual(Z1, Z6, 0.00001f)) ? 0 : 1;
  117. Error += glm::all(glm::epsilonEqual(Z1, Z7, 0.00001f)) ? 0 : 1;
  118. return Error;
  119. }
  120. }//namespace test_eulerAngleZ
  121. namespace test_eulerAngleXY
  122. {
  123. int test()
  124. {
  125. int Error = 0;
  126. glm::vec4 const V(1.0f);
  127. float const AngleX(glm::pi<float>() * 0.5f);
  128. float const AngleY(glm::pi<float>() * 0.25f);
  129. glm::vec3 const axisX(1.0f, 0.0f, 0.0f);
  130. glm::vec3 const axisY(0.0f, 1.0f, 0.0f);
  131. glm::vec4 const V1 = (glm::rotate(glm::mat4(1.0f), AngleX, axisX) * glm::rotate(glm::mat4(1.0f), AngleY, axisY)) * V;
  132. glm::vec4 const V2 = glm::eulerAngleXY(AngleX, AngleY) * V;
  133. glm::vec4 const V3 = glm::eulerAngleX(AngleX) * glm::eulerAngleY(AngleY) * V;
  134. Error += glm::all(glm::epsilonEqual(V1, V2, 0.00001f)) ? 0 : 1;
  135. Error += glm::all(glm::epsilonEqual(V1, V3, 0.00001f)) ? 0 : 1;
  136. return Error;
  137. }
  138. }//namespace test_eulerAngleXY
  139. namespace test_eulerAngleYX
  140. {
  141. int test()
  142. {
  143. int Error = 0;
  144. glm::vec4 const V(1.0f);
  145. float const AngleX(glm::pi<float>() * 0.5f);
  146. float const AngleY(glm::pi<float>() * 0.25f);
  147. glm::vec3 const axisX(1.0f, 0.0f, 0.0f);
  148. glm::vec3 const axisY(0.0f, 1.0f, 0.0f);
  149. glm::vec4 const V1 = (glm::rotate(glm::mat4(1.0f), AngleY, axisY) * glm::rotate(glm::mat4(1.0f), AngleX, axisX)) * V;
  150. glm::vec4 const V2 = glm::eulerAngleYX(AngleY, AngleX) * V;
  151. glm::vec4 const V3 = glm::eulerAngleY(AngleY) * glm::eulerAngleX(AngleX) * V;
  152. Error += glm::all(glm::epsilonEqual(V1, V2, 0.00001f)) ? 0 : 1;
  153. Error += glm::all(glm::epsilonEqual(V1, V3, 0.00001f)) ? 0 : 1;
  154. return Error;
  155. }
  156. }//namespace test_eulerAngleYX
  157. namespace test_eulerAngleXZ
  158. {
  159. int test()
  160. {
  161. int Error = 0;
  162. glm::vec4 const V(1.0f);
  163. float const AngleX(glm::pi<float>() * 0.5f);
  164. float const AngleZ(glm::pi<float>() * 0.25f);
  165. glm::vec3 const axisX(1.0f, 0.0f, 0.0f);
  166. glm::vec3 const axisZ(0.0f, 0.0f, 1.0f);
  167. glm::vec4 const V1 = (glm::rotate(glm::mat4(1.0f), AngleX, axisX) * glm::rotate(glm::mat4(1.0f), AngleZ, axisZ)) * V;
  168. glm::vec4 const V2 = glm::eulerAngleXZ(AngleX, AngleZ) * V;
  169. glm::vec4 const V3 = glm::eulerAngleX(AngleX) * glm::eulerAngleZ(AngleZ) * V;
  170. Error += glm::all(glm::epsilonEqual(V1, V2, 0.00001f)) ? 0 : 1;
  171. Error += glm::all(glm::epsilonEqual(V1, V3, 0.00001f)) ? 0 : 1;
  172. return Error;
  173. }
  174. }//namespace test_eulerAngleXZ
  175. namespace test_eulerAngleZX
  176. {
  177. int test()
  178. {
  179. int Error = 0;
  180. glm::vec4 const V(1.0f);
  181. float const AngleX(glm::pi<float>() * 0.5f);
  182. float const AngleZ(glm::pi<float>() * 0.25f);
  183. glm::vec3 const axisX(1.0f, 0.0f, 0.0f);
  184. glm::vec3 const axisZ(0.0f, 0.0f, 1.0f);
  185. glm::vec4 const V1 = (glm::rotate(glm::mat4(1.0f), AngleZ, axisZ) * glm::rotate(glm::mat4(1.0f), AngleX, axisX)) * V;
  186. glm::vec4 const V2 = glm::eulerAngleZX(AngleZ, AngleX) * V;
  187. glm::vec4 const V3 = glm::eulerAngleZ(AngleZ) * glm::eulerAngleX(AngleX) * V;
  188. Error += glm::all(glm::epsilonEqual(V1, V2, 0.00001f)) ? 0 : 1;
  189. Error += glm::all(glm::epsilonEqual(V1, V3, 0.00001f)) ? 0 : 1;
  190. return Error;
  191. }
  192. }//namespace test_eulerAngleZX
  193. namespace test_eulerAngleYZ
  194. {
  195. int test()
  196. {
  197. int Error = 0;
  198. glm::vec4 const V(1.0f);
  199. float const AngleY(glm::pi<float>() * 0.5f);
  200. float const AngleZ(glm::pi<float>() * 0.25f);
  201. glm::vec3 const axisX(1.0f, 0.0f, 0.0f);
  202. glm::vec3 const axisY(0.0f, 1.0f, 0.0f);
  203. glm::vec3 const axisZ(0.0f, 0.0f, 1.0f);
  204. glm::vec4 const V1 = (glm::rotate(glm::mat4(1.0f), AngleY, axisY) * glm::rotate(glm::mat4(1.0f), AngleZ, axisZ)) * V;
  205. glm::vec4 const V2 = glm::eulerAngleYZ(AngleY, AngleZ) * V;
  206. glm::vec4 const V3 = glm::eulerAngleY(AngleY) * glm::eulerAngleZ(AngleZ) * V;
  207. Error += glm::all(glm::epsilonEqual(V1, V2, 0.00001f)) ? 0 : 1;
  208. Error += glm::all(glm::epsilonEqual(V1, V3, 0.00001f)) ? 0 : 1;
  209. return Error;
  210. }
  211. }//namespace test_eulerAngleYZ
  212. namespace test_eulerAngleZY
  213. {
  214. int test()
  215. {
  216. int Error = 0;
  217. glm::vec4 const V(1.0f);
  218. float const AngleY(glm::pi<float>() * 0.5f);
  219. float const AngleZ(glm::pi<float>() * 0.25f);
  220. glm::vec3 const axisX(1.0f, 0.0f, 0.0f);
  221. glm::vec3 const axisY(0.0f, 1.0f, 0.0f);
  222. glm::vec3 const axisZ(0.0f, 0.0f, 1.0f);
  223. glm::vec4 const V1 = (glm::rotate(glm::mat4(1.0f), AngleZ, axisZ) * glm::rotate(glm::mat4(1.0f), AngleY, axisY)) * V;
  224. glm::vec4 const V2 = glm::eulerAngleZY(AngleZ, AngleY) * V;
  225. glm::vec4 const V3 = glm::eulerAngleZ(AngleZ) * glm::eulerAngleY(AngleY) * V;
  226. Error += glm::all(glm::epsilonEqual(V1, V2, 0.00001f)) ? 0 : 1;
  227. Error += glm::all(glm::epsilonEqual(V1, V3, 0.00001f)) ? 0 : 1;
  228. return Error;
  229. }
  230. }//namespace test_eulerAngleZY
  231. namespace test_eulerAngleYXZ
  232. {
  233. int test()
  234. {
  235. glm::f32 first = 1.046f;
  236. glm::f32 second = 0.52f;
  237. glm::f32 third = -0.785f;
  238. glm::fmat4 rotationEuler = glm::eulerAngleYXZ(first, second, third);
  239. glm::fmat4 rotationInvertedY = glm::eulerAngleY(-1.f*first) * glm::eulerAngleX(second) * glm::eulerAngleZ(third);
  240. glm::fmat4 rotationDumb = glm::fmat4();
  241. rotationDumb = glm::rotate(rotationDumb, first, glm::fvec3(0,1,0));
  242. rotationDumb = glm::rotate(rotationDumb, second, glm::fvec3(1,0,0));
  243. rotationDumb = glm::rotate(rotationDumb, third, glm::fvec3(0,0,1));
  244. std::printf("%s\n", glm::to_string(glm::fmat3(rotationEuler)).c_str());
  245. std::printf("%s\n", glm::to_string(glm::fmat3(rotationDumb)).c_str());
  246. std::printf("%s\n", glm::to_string(glm::fmat3(rotationInvertedY)).c_str());
  247. std::printf("\nRESIDUAL\n");
  248. std::printf("%s\n", glm::to_string(glm::fmat3(rotationEuler-(rotationDumb))).c_str());
  249. std::printf("%s\n", glm::to_string(glm::fmat3(rotationEuler-(rotationInvertedY))).c_str());
  250. return 0;
  251. }
  252. }//namespace eulerAngleYXZ
  253. int main()
  254. {
  255. int Error = 0;
  256. Error += test_eulerAngleX::test();
  257. Error += test_eulerAngleY::test();
  258. Error += test_eulerAngleZ::test();
  259. Error += test_eulerAngleXY::test();
  260. Error += test_eulerAngleYX::test();
  261. Error += test_eulerAngleXZ::test();
  262. Error += test_eulerAngleZX::test();
  263. Error += test_eulerAngleYZ::test();
  264. Error += test_eulerAngleZY::test();
  265. Error += test_eulerAngleYXZ::test();
  266. return Error;
  267. }