gtx_euler_angle.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. ///////////////////////////////////////////////////////////////////////////////////
  2. /// OpenGL Mathematics (glm.g-truc.net)
  3. ///
  4. /// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net)
  5. /// Permission is hereby granted, free of charge, to any person obtaining a copy
  6. /// of this software and associated documentation files (the "Software"), to deal
  7. /// in the Software without restriction, including without limitation the rights
  8. /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. /// copies of the Software, and to permit persons to whom the Software is
  10. /// furnished to do so, subject to the following conditions:
  11. ///
  12. /// The above copyright notice and this permission notice shall be included in
  13. /// all copies or substantial portions of the Software.
  14. ///
  15. /// Restrictions:
  16. /// By making use of the Software for military purposes, you choose to make
  17. /// a Bunny unhappy.
  18. ///
  19. /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. /// THE SOFTWARE.
  26. ///
  27. /// @file test/gtx/gtx_euler_angle.cpp
  28. /// @date 2013-10-25 / 2014-11-25
  29. /// @author Christophe Riccio
  30. ///////////////////////////////////////////////////////////////////////////////////
  31. // Code sample from Filippo Ramaciotti
  32. #include <glm/gtc/matrix_transform.hpp>
  33. #include <glm/gtc/epsilon.hpp>
  34. #include <glm/gtx/string_cast.hpp>
  35. #include <glm/gtx/euler_angles.hpp>
  36. #include <cstdio>
  37. namespace test_eulerAngleX
  38. {
  39. int test()
  40. {
  41. int Error = 0;
  42. float const Angle(glm::pi<float>() * 0.5f);
  43. glm::vec3 const X(1.0f, 0.0f, 0.0f);
  44. glm::vec4 const Y(0.0f, 1.0f, 0.0f, 1.0f);
  45. glm::vec4 const Y1 = glm::rotate(glm::mat4(1.0f), Angle, X) * Y;
  46. glm::vec4 const Y2 = glm::eulerAngleX(Angle) * Y;
  47. glm::vec4 const Y3 = glm::eulerAngleXY(Angle, 0.0f) * Y;
  48. glm::vec4 const Y4 = glm::eulerAngleYX(0.0f, Angle) * Y;
  49. glm::vec4 const Y5 = glm::eulerAngleXZ(Angle, 0.0f) * Y;
  50. glm::vec4 const Y6 = glm::eulerAngleZX(0.0f, Angle) * Y;
  51. glm::vec4 const Y7 = glm::eulerAngleYXZ(0.0f, Angle, 0.0f) * Y;
  52. Error += glm::all(glm::epsilonEqual(Y1, Y2, 0.00001f)) ? 0 : 1;
  53. Error += glm::all(glm::epsilonEqual(Y1, Y3, 0.00001f)) ? 0 : 1;
  54. Error += glm::all(glm::epsilonEqual(Y1, Y4, 0.00001f)) ? 0 : 1;
  55. Error += glm::all(glm::epsilonEqual(Y1, Y5, 0.00001f)) ? 0 : 1;
  56. Error += glm::all(glm::epsilonEqual(Y1, Y6, 0.00001f)) ? 0 : 1;
  57. Error += glm::all(glm::epsilonEqual(Y1, Y7, 0.00001f)) ? 0 : 1;
  58. glm::vec4 const Z(0.0f, 0.0f, 1.0f, 1.0f);
  59. glm::vec4 const Z1 = glm::rotate(glm::mat4(1.0f), Angle, X) * Z;
  60. glm::vec4 const Z2 = glm::eulerAngleX(Angle) * Z;
  61. glm::vec4 const Z3 = glm::eulerAngleXY(Angle, 0.0f) * Z;
  62. glm::vec4 const Z4 = glm::eulerAngleYX(0.0f, Angle) * Z;
  63. glm::vec4 const Z5 = glm::eulerAngleXZ(Angle, 0.0f) * Z;
  64. glm::vec4 const Z6 = glm::eulerAngleZX(0.0f, Angle) * Z;
  65. glm::vec4 const Z7 = glm::eulerAngleYXZ(0.0f, Angle, 0.0f) * Z;
  66. Error += glm::all(glm::epsilonEqual(Z1, Z2, 0.00001f)) ? 0 : 1;
  67. Error += glm::all(glm::epsilonEqual(Z1, Z3, 0.00001f)) ? 0 : 1;
  68. Error += glm::all(glm::epsilonEqual(Z1, Z4, 0.00001f)) ? 0 : 1;
  69. Error += glm::all(glm::epsilonEqual(Z1, Z5, 0.00001f)) ? 0 : 1;
  70. Error += glm::all(glm::epsilonEqual(Z1, Z6, 0.00001f)) ? 0 : 1;
  71. Error += glm::all(glm::epsilonEqual(Z1, Z7, 0.00001f)) ? 0 : 1;
  72. return Error;
  73. }
  74. }//namespace test_eulerAngleX
  75. namespace test_eulerAngleY
  76. {
  77. int test()
  78. {
  79. int Error = 0;
  80. float const Angle(glm::pi<float>() * 0.5f);
  81. glm::vec3 const Y(0.0f, 1.0f, 0.0f);
  82. glm::vec4 const X(1.0f, 0.0f, 0.0f, 1.0f);
  83. glm::vec4 const X1 = glm::rotate(glm::mat4(1.0f), Angle, Y) * X;
  84. glm::vec4 const X2 = glm::eulerAngleY(Angle) * X;
  85. glm::vec4 const X3 = glm::eulerAngleYX(Angle, 0.0f) * X;
  86. glm::vec4 const X4 = glm::eulerAngleXY(0.0f, Angle) * X;
  87. glm::vec4 const X5 = glm::eulerAngleYZ(Angle, 0.0f) * X;
  88. glm::vec4 const X6 = glm::eulerAngleZY(0.0f, Angle) * X;
  89. glm::vec4 const X7 = glm::eulerAngleYXZ(Angle, 0.0f, 0.0f) * X;
  90. Error += glm::all(glm::epsilonEqual(X1, X2, 0.00001f)) ? 0 : 1;
  91. Error += glm::all(glm::epsilonEqual(X1, X3, 0.00001f)) ? 0 : 1;
  92. Error += glm::all(glm::epsilonEqual(X1, X4, 0.00001f)) ? 0 : 1;
  93. Error += glm::all(glm::epsilonEqual(X1, X5, 0.00001f)) ? 0 : 1;
  94. Error += glm::all(glm::epsilonEqual(X1, X6, 0.00001f)) ? 0 : 1;
  95. Error += glm::all(glm::epsilonEqual(X1, X7, 0.00001f)) ? 0 : 1;
  96. glm::vec4 const Z(0.0f, 0.0f, 1.0f, 1.0f);
  97. glm::vec4 const Z1 = glm::eulerAngleY(Angle) * Z;
  98. glm::vec4 const Z2 = glm::rotate(glm::mat4(1.0f), Angle, Y) * Z;
  99. glm::vec4 const Z3 = glm::eulerAngleYX(Angle, 0.0f) * Z;
  100. glm::vec4 const Z4 = glm::eulerAngleXY(0.0f, Angle) * Z;
  101. glm::vec4 const Z5 = glm::eulerAngleYZ(Angle, 0.0f) * Z;
  102. glm::vec4 const Z6 = glm::eulerAngleZY(0.0f, Angle) * Z;
  103. glm::vec4 const Z7 = glm::eulerAngleYXZ(Angle, 0.0f, 0.0f) * Z;
  104. Error += glm::all(glm::epsilonEqual(Z1, Z2, 0.00001f)) ? 0 : 1;
  105. Error += glm::all(glm::epsilonEqual(Z1, Z3, 0.00001f)) ? 0 : 1;
  106. Error += glm::all(glm::epsilonEqual(Z1, Z4, 0.00001f)) ? 0 : 1;
  107. Error += glm::all(glm::epsilonEqual(Z1, Z5, 0.00001f)) ? 0 : 1;
  108. Error += glm::all(glm::epsilonEqual(Z1, Z6, 0.00001f)) ? 0 : 1;
  109. Error += glm::all(glm::epsilonEqual(Z1, Z7, 0.00001f)) ? 0 : 1;
  110. return Error;
  111. }
  112. }//namespace test_eulerAngleY
  113. namespace test_eulerAngleZ
  114. {
  115. int test()
  116. {
  117. int Error = 0;
  118. float const Angle(glm::pi<float>() * 0.5f);
  119. glm::vec3 const Z(0.0f, 0.0f, 1.0f);
  120. glm::vec4 const X(1.0f, 0.0f, 0.0f, 1.0f);
  121. glm::vec4 const X1 = glm::rotate(glm::mat4(1.0f), Angle, Z) * X;
  122. glm::vec4 const X2 = glm::eulerAngleZ(Angle) * X;
  123. glm::vec4 const X3 = glm::eulerAngleZX(Angle, 0.0f) * X;
  124. glm::vec4 const X4 = glm::eulerAngleXZ(0.0f, Angle) * X;
  125. glm::vec4 const X5 = glm::eulerAngleZY(Angle, 0.0f) * X;
  126. glm::vec4 const X6 = glm::eulerAngleYZ(0.0f, Angle) * X;
  127. glm::vec4 const X7 = glm::eulerAngleYXZ(0.0f, 0.0f, Angle) * X;
  128. Error += glm::all(glm::epsilonEqual(X1, X2, 0.00001f)) ? 0 : 1;
  129. Error += glm::all(glm::epsilonEqual(X1, X3, 0.00001f)) ? 0 : 1;
  130. Error += glm::all(glm::epsilonEqual(X1, X4, 0.00001f)) ? 0 : 1;
  131. Error += glm::all(glm::epsilonEqual(X1, X5, 0.00001f)) ? 0 : 1;
  132. Error += glm::all(glm::epsilonEqual(X1, X6, 0.00001f)) ? 0 : 1;
  133. Error += glm::all(glm::epsilonEqual(X1, X7, 0.00001f)) ? 0 : 1;
  134. glm::vec4 const Y(1.0f, 0.0f, 0.0f, 1.0f);
  135. glm::vec4 const Z1 = glm::rotate(glm::mat4(1.0f), Angle, Z) * Y;
  136. glm::vec4 const Z2 = glm::eulerAngleZ(Angle) * Y;
  137. glm::vec4 const Z3 = glm::eulerAngleZX(Angle, 0.0f) * Y;
  138. glm::vec4 const Z4 = glm::eulerAngleXZ(0.0f, Angle) * Y;
  139. glm::vec4 const Z5 = glm::eulerAngleZY(Angle, 0.0f) * Y;
  140. glm::vec4 const Z6 = glm::eulerAngleYZ(0.0f, Angle) * Y;
  141. glm::vec4 const Z7 = glm::eulerAngleYXZ(0.0f, 0.0f, Angle) * Y;
  142. Error += glm::all(glm::epsilonEqual(Z1, Z2, 0.00001f)) ? 0 : 1;
  143. Error += glm::all(glm::epsilonEqual(Z1, Z3, 0.00001f)) ? 0 : 1;
  144. Error += glm::all(glm::epsilonEqual(Z1, Z4, 0.00001f)) ? 0 : 1;
  145. Error += glm::all(glm::epsilonEqual(Z1, Z5, 0.00001f)) ? 0 : 1;
  146. Error += glm::all(glm::epsilonEqual(Z1, Z6, 0.00001f)) ? 0 : 1;
  147. Error += glm::all(glm::epsilonEqual(Z1, Z7, 0.00001f)) ? 0 : 1;
  148. return Error;
  149. }
  150. }//namespace test_eulerAngleZ
  151. namespace test_eulerAngleXY
  152. {
  153. int test()
  154. {
  155. int Error = 0;
  156. glm::vec4 const V(1.0f);
  157. float const AngleX(glm::pi<float>() * 0.5f);
  158. float const AngleY(glm::pi<float>() * 0.25f);
  159. glm::vec3 const axisX(1.0f, 0.0f, 0.0f);
  160. glm::vec3 const axisY(0.0f, 1.0f, 0.0f);
  161. glm::vec4 const V1 = (glm::rotate(glm::mat4(1.0f), AngleX, axisX) * glm::rotate(glm::mat4(1.0f), AngleY, axisY)) * V;
  162. glm::vec4 const V2 = glm::eulerAngleXY(AngleX, AngleY) * V;
  163. glm::vec4 const V3 = glm::eulerAngleX(AngleX) * glm::eulerAngleY(AngleY) * V;
  164. Error += glm::all(glm::epsilonEqual(V1, V2, 0.00001f)) ? 0 : 1;
  165. Error += glm::all(glm::epsilonEqual(V1, V3, 0.00001f)) ? 0 : 1;
  166. return Error;
  167. }
  168. }//namespace test_eulerAngleXY
  169. namespace test_eulerAngleYX
  170. {
  171. int test()
  172. {
  173. int Error = 0;
  174. glm::vec4 const V(1.0f);
  175. float const AngleX(glm::pi<float>() * 0.5f);
  176. float const AngleY(glm::pi<float>() * 0.25f);
  177. glm::vec3 const axisX(1.0f, 0.0f, 0.0f);
  178. glm::vec3 const axisY(0.0f, 1.0f, 0.0f);
  179. glm::vec4 const V1 = (glm::rotate(glm::mat4(1.0f), AngleY, axisY) * glm::rotate(glm::mat4(1.0f), AngleX, axisX)) * V;
  180. glm::vec4 const V2 = glm::eulerAngleYX(AngleY, AngleX) * V;
  181. glm::vec4 const V3 = glm::eulerAngleY(AngleY) * glm::eulerAngleX(AngleX) * V;
  182. Error += glm::all(glm::epsilonEqual(V1, V2, 0.00001f)) ? 0 : 1;
  183. Error += glm::all(glm::epsilonEqual(V1, V3, 0.00001f)) ? 0 : 1;
  184. return Error;
  185. }
  186. }//namespace test_eulerAngleYX
  187. namespace test_eulerAngleXZ
  188. {
  189. int test()
  190. {
  191. int Error = 0;
  192. glm::vec4 const V(1.0f);
  193. float const AngleX(glm::pi<float>() * 0.5f);
  194. float const AngleZ(glm::pi<float>() * 0.25f);
  195. glm::vec3 const axisX(1.0f, 0.0f, 0.0f);
  196. glm::vec3 const axisZ(0.0f, 0.0f, 1.0f);
  197. glm::vec4 const V1 = (glm::rotate(glm::mat4(1.0f), AngleX, axisX) * glm::rotate(glm::mat4(1.0f), AngleZ, axisZ)) * V;
  198. glm::vec4 const V2 = glm::eulerAngleXZ(AngleX, AngleZ) * V;
  199. glm::vec4 const V3 = glm::eulerAngleX(AngleX) * glm::eulerAngleZ(AngleZ) * V;
  200. Error += glm::all(glm::epsilonEqual(V1, V2, 0.00001f)) ? 0 : 1;
  201. Error += glm::all(glm::epsilonEqual(V1, V3, 0.00001f)) ? 0 : 1;
  202. return Error;
  203. }
  204. }//namespace test_eulerAngleXZ
  205. namespace test_eulerAngleZX
  206. {
  207. int test()
  208. {
  209. int Error = 0;
  210. glm::vec4 const V(1.0f);
  211. float const AngleX(glm::pi<float>() * 0.5f);
  212. float const AngleZ(glm::pi<float>() * 0.25f);
  213. glm::vec3 const axisX(1.0f, 0.0f, 0.0f);
  214. glm::vec3 const axisZ(0.0f, 0.0f, 1.0f);
  215. glm::vec4 const V1 = (glm::rotate(glm::mat4(1.0f), AngleZ, axisZ) * glm::rotate(glm::mat4(1.0f), AngleX, axisX)) * V;
  216. glm::vec4 const V2 = glm::eulerAngleZX(AngleZ, AngleX) * V;
  217. glm::vec4 const V3 = glm::eulerAngleZ(AngleZ) * glm::eulerAngleX(AngleX) * V;
  218. Error += glm::all(glm::epsilonEqual(V1, V2, 0.00001f)) ? 0 : 1;
  219. Error += glm::all(glm::epsilonEqual(V1, V3, 0.00001f)) ? 0 : 1;
  220. return Error;
  221. }
  222. }//namespace test_eulerAngleZX
  223. namespace test_eulerAngleYZ
  224. {
  225. int test()
  226. {
  227. int Error = 0;
  228. glm::vec4 const V(1.0f);
  229. float const AngleY(glm::pi<float>() * 0.5f);
  230. float const AngleZ(glm::pi<float>() * 0.25f);
  231. glm::vec3 const axisX(1.0f, 0.0f, 0.0f);
  232. glm::vec3 const axisY(0.0f, 1.0f, 0.0f);
  233. glm::vec3 const axisZ(0.0f, 0.0f, 1.0f);
  234. glm::vec4 const V1 = (glm::rotate(glm::mat4(1.0f), AngleY, axisY) * glm::rotate(glm::mat4(1.0f), AngleZ, axisZ)) * V;
  235. glm::vec4 const V2 = glm::eulerAngleYZ(AngleY, AngleZ) * V;
  236. glm::vec4 const V3 = glm::eulerAngleY(AngleY) * glm::eulerAngleZ(AngleZ) * V;
  237. Error += glm::all(glm::epsilonEqual(V1, V2, 0.00001f)) ? 0 : 1;
  238. Error += glm::all(glm::epsilonEqual(V1, V3, 0.00001f)) ? 0 : 1;
  239. return Error;
  240. }
  241. }//namespace test_eulerAngleYZ
  242. namespace test_eulerAngleZY
  243. {
  244. int test()
  245. {
  246. int Error = 0;
  247. glm::vec4 const V(1.0f);
  248. float const AngleY(glm::pi<float>() * 0.5f);
  249. float const AngleZ(glm::pi<float>() * 0.25f);
  250. glm::vec3 const axisX(1.0f, 0.0f, 0.0f);
  251. glm::vec3 const axisY(0.0f, 1.0f, 0.0f);
  252. glm::vec3 const axisZ(0.0f, 0.0f, 1.0f);
  253. glm::vec4 const V1 = (glm::rotate(glm::mat4(1.0f), AngleZ, axisZ) * glm::rotate(glm::mat4(1.0f), AngleY, axisY)) * V;
  254. glm::vec4 const V2 = glm::eulerAngleZY(AngleZ, AngleY) * V;
  255. glm::vec4 const V3 = glm::eulerAngleZ(AngleZ) * glm::eulerAngleY(AngleY) * V;
  256. Error += glm::all(glm::epsilonEqual(V1, V2, 0.00001f)) ? 0 : 1;
  257. Error += glm::all(glm::epsilonEqual(V1, V3, 0.00001f)) ? 0 : 1;
  258. return Error;
  259. }
  260. }//namespace test_eulerAngleZY
  261. namespace test_eulerAngleYXZ
  262. {
  263. int test()
  264. {
  265. glm::f32 first = 1.046f;
  266. glm::f32 second = 0.52f;
  267. glm::f32 third = -0.785f;
  268. glm::fmat4 rotationEuler = glm::eulerAngleYXZ(first, second, third);
  269. glm::fmat4 rotationInvertedY = glm::eulerAngleY(-1.f*first) * glm::eulerAngleX(second) * glm::eulerAngleZ(third);
  270. glm::fmat4 rotationDumb = glm::fmat4();
  271. rotationDumb = glm::rotate(rotationDumb, first, glm::fvec3(0,1,0));
  272. rotationDumb = glm::rotate(rotationDumb, second, glm::fvec3(1,0,0));
  273. rotationDumb = glm::rotate(rotationDumb, third, glm::fvec3(0,0,1));
  274. std::printf("%s\n", glm::to_string(glm::fmat3(rotationEuler)).c_str());
  275. std::printf("%s\n", glm::to_string(glm::fmat3(rotationDumb)).c_str());
  276. std::printf("%s\n", glm::to_string(glm::fmat3(rotationInvertedY)).c_str());
  277. std::printf("\nRESIDUAL\n");
  278. std::printf("%s\n", glm::to_string(glm::fmat3(rotationEuler-(rotationDumb))).c_str());
  279. std::printf("%s\n", glm::to_string(glm::fmat3(rotationEuler-(rotationInvertedY))).c_str());
  280. return 0;
  281. }
  282. }//namespace eulerAngleYXZ
  283. int main()
  284. {
  285. int Error = 0;
  286. Error += test_eulerAngleX::test();
  287. Error += test_eulerAngleY::test();
  288. Error += test_eulerAngleZ::test();
  289. Error += test_eulerAngleXY::test();
  290. Error += test_eulerAngleYX::test();
  291. Error += test_eulerAngleXZ::test();
  292. Error += test_eulerAngleZX::test();
  293. Error += test_eulerAngleYZ::test();
  294. Error += test_eulerAngleZY::test();
  295. Error += test_eulerAngleYXZ::test();
  296. return Error;
  297. }