gl_mat.cc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. #include "catch.hpp"
  2. #include "gl_mat.hh"
  3. using namespace gl;
  4. // Test approximations.
  5. static bool approxEq(const mat4& x, const mat4&y)
  6. {
  7. return norm2_2(x - y) < 1.0e-3f;
  8. }
  9. // Extra matrix types used in this test.
  10. using imat2 = matMxN<2, 2, int>;
  11. using imat3 = matMxN<3, 3, int>;
  12. using imat4 = matMxN<4, 4, int>;
  13. using mat32 = matMxN<3, 2, float>;
  14. using mat23 = matMxN<2, 3, float>;
  15. // It's useful to test both integer and float variants because the
  16. // former are implemented in plain C++ and (only) the latter have SSE
  17. // optimizations.
  18. TEST_CASE("gl_mat: constructors")
  19. {
  20. SECTION("default constructor") {
  21. mat2 m2;
  22. CHECK(m2[0] == vec2(1, 0));
  23. CHECK(m2[1] == vec2(0, 1));
  24. imat2 i2;
  25. CHECK(i2[0] == ivec2(1, 0));
  26. CHECK(i2[1] == ivec2(0, 1));
  27. mat3 m3;
  28. CHECK(m3[0] == vec3(1, 0, 0));
  29. CHECK(m3[1] == vec3(0, 1, 0));
  30. CHECK(m3[2] == vec3(0, 0, 1));
  31. imat3 i3;
  32. CHECK(i3[0] == ivec3(1, 0, 0));
  33. CHECK(i3[1] == ivec3(0, 1, 0));
  34. CHECK(i3[2] == ivec3(0, 0, 1));
  35. mat4 m4;
  36. CHECK(m4[0] == vec4(1, 0, 0, 0));
  37. CHECK(m4[1] == vec4(0, 1, 0, 0));
  38. CHECK(m4[2] == vec4(0, 0, 1, 0));
  39. CHECK(m4[3] == vec4(0, 0, 0, 1));
  40. imat4 i4;
  41. CHECK(i4[0] == ivec4(1, 0, 0, 0));
  42. CHECK(i4[1] == ivec4(0, 1, 0, 0));
  43. CHECK(i4[2] == ivec4(0, 0, 1, 0));
  44. CHECK(i4[3] == ivec4(0, 0, 0, 1));
  45. mat32 m32;
  46. CHECK(m32[0] == vec3(1, 0, 0));
  47. CHECK(m32[1] == vec3(0, 1, 0));
  48. mat23 m23;
  49. CHECK(m23[0] == vec2(1, 0));
  50. CHECK(m23[1] == vec2(0, 1));
  51. CHECK(m23[2] == vec2(0, 0));
  52. }
  53. SECTION("diagonal constructor") {
  54. mat2 m2(vec2(2, 3));
  55. CHECK(m2[0] == vec2(2, 0));
  56. CHECK(m2[1] == vec2(0, 3));
  57. imat2 i2(ivec2(2, 3));
  58. CHECK(i2[0] == ivec2(2, 0));
  59. CHECK(i2[1] == ivec2(0, 3));
  60. mat3 m3(vec3(2, 3, 4));
  61. CHECK(m3[0] == vec3(2, 0, 0));
  62. CHECK(m3[1] == vec3(0, 3, 0));
  63. CHECK(m3[2] == vec3(0, 0, 4));
  64. imat3 i3(ivec3(2, 3, 4));
  65. CHECK(i3[0] == ivec3(2, 0, 0));
  66. CHECK(i3[1] == ivec3(0, 3, 0));
  67. CHECK(i3[2] == ivec3(0, 0, 4));
  68. mat4 m4(vec4(2, 3, 4, 5));
  69. CHECK(m4[0] == vec4(2, 0, 0, 0));
  70. CHECK(m4[1] == vec4(0, 3, 0, 0));
  71. CHECK(m4[2] == vec4(0, 0, 4, 0));
  72. CHECK(m4[3] == vec4(0, 0, 0, 5));
  73. imat4 i4(ivec4(2, 3, 4, 5));
  74. CHECK(i4[0] == ivec4(2, 0, 0, 0));
  75. CHECK(i4[1] == ivec4(0, 3, 0, 0));
  76. CHECK(i4[2] == ivec4(0, 0, 4, 0));
  77. CHECK(i4[3] == ivec4(0, 0, 0, 5));
  78. mat32 m32(vec2(2, 3));
  79. CHECK(m32[0] == vec3(2, 0, 0));
  80. CHECK(m32[1] == vec3(0, 3, 0));
  81. mat23 m23(vec2(2, 3));
  82. CHECK(m23[0] == vec2(2, 0));
  83. CHECK(m23[1] == vec2(0, 3));
  84. CHECK(m23[2] == vec2(0, 0));
  85. }
  86. SECTION("construct from columns") {
  87. mat2 m2(vec2(2, 3), vec2(4, 5));
  88. CHECK(m2[0] == vec2(2, 3));
  89. CHECK(m2[1] == vec2(4, 5));
  90. imat2 i2(ivec2(2, 3), ivec2(4, 5));
  91. CHECK(i2[0] == ivec2(2, 3));
  92. CHECK(i2[1] == ivec2(4, 5));
  93. mat3 m3(vec3(2, 3, 4), vec3(5, 6, 7), vec3(8, 9, 1));
  94. CHECK(m3[0] == vec3(2, 3, 4));
  95. CHECK(m3[1] == vec3(5, 6, 7));
  96. CHECK(m3[2] == vec3(8, 9, 1));
  97. imat3 i3(ivec3(2, 3, 4), ivec3(5, 6, 7), ivec3(8, 9, 1));
  98. CHECK(i3[0] == ivec3(2, 3, 4));
  99. CHECK(i3[1] == ivec3(5, 6, 7));
  100. CHECK(i3[2] == ivec3(8, 9, 1));
  101. mat4 m4(vec4(2, 3, 4, 5), vec4(3, 4, 5, 6), vec4(4, 5, 6, 7), vec4(5, 6, 7, 8));
  102. CHECK(m4[0] == vec4(2, 3, 4, 5));
  103. CHECK(m4[1] == vec4(3, 4, 5, 6));
  104. CHECK(m4[2] == vec4(4, 5, 6, 7));
  105. CHECK(m4[3] == vec4(5, 6, 7, 8));
  106. imat4 i4(ivec4(2, 3, 4, 5), ivec4(3, 4, 5, 6), ivec4(4, 5, 6, 7), ivec4(5, 6, 7, 8));
  107. CHECK(i4[0] == ivec4(2, 3, 4, 5));
  108. CHECK(i4[1] == ivec4(3, 4, 5, 6));
  109. CHECK(i4[2] == ivec4(4, 5, 6, 7));
  110. CHECK(i4[3] == ivec4(5, 6, 7, 8));
  111. mat32 m32(vec3(2, 3, 4), vec3(5, 6, 7));
  112. CHECK(m32[0] == vec3(2, 3, 4));
  113. CHECK(m32[1] == vec3(5, 6, 7));
  114. mat23 m23(vec2(2, 3), vec2(4, 5), vec2(6, 7));
  115. CHECK(m23[0] == vec2(2, 3));
  116. CHECK(m23[1] == vec2(4, 5));
  117. CHECK(m23[2] == vec2(6, 7));
  118. }
  119. }
  120. TEST_CASE("gl_mat: modify columns or elements")
  121. {
  122. mat2 m2(vec2(2, 3));
  123. m2[1] = vec2(8, 9); m2[0][1] = 7;
  124. CHECK(m2[0] == vec2(2, 7));
  125. CHECK(m2[1] == vec2(8, 9));
  126. imat2 i2(ivec2(2, 3));
  127. i2[0] = ivec2(8, 9); i2[1][1] = 7;
  128. CHECK(i2[0] == ivec2(8, 9));
  129. CHECK(i2[1] == ivec2(0, 7));
  130. mat3 m3(vec3(2, 3, 4));
  131. m3[1] = vec3(7, 8, 9); m3[0][1] = 6;
  132. CHECK(m3[0] == vec3(2, 6, 0));
  133. CHECK(m3[1] == vec3(7, 8, 9));
  134. CHECK(m3[2] == vec3(0, 0, 4));
  135. imat3 i3(ivec3(2, 3, 4));
  136. i3[0] = ivec3(7, 8, 9); i3[2][0] = 6;
  137. CHECK(i3[0] == ivec3(7, 8, 9));
  138. CHECK(i3[1] == ivec3(0, 3, 0));
  139. CHECK(i3[2] == ivec3(6, 0, 4));
  140. mat4 m4(vec4(2, 3, 4, 5));
  141. m4[3] = vec4(6, 7, 8, 9); m4[1][1] = 1;
  142. CHECK(m4[0] == vec4(2, 0, 0, 0));
  143. CHECK(m4[1] == vec4(0, 1, 0, 0));
  144. CHECK(m4[2] == vec4(0, 0, 4, 0));
  145. CHECK(m4[3] == vec4(6, 7, 8, 9));
  146. imat4 i4(ivec4(2, 3, 4, 5));
  147. i4[1] = ivec4(6, 7, 8, 9); i4[2][3] = 1;
  148. CHECK(i4[0] == ivec4(2, 0, 0, 0));
  149. CHECK(i4[1] == ivec4(6, 7, 8, 9));
  150. CHECK(i4[2] == ivec4(0, 0, 4, 1));
  151. CHECK(i4[3] == ivec4(0, 0, 0, 5));
  152. mat32 m32(vec2(2, 3));
  153. m32[0] = vec3(7, 8, 9); m32[1][0] = 6;
  154. CHECK(m32[0] == vec3(7, 8, 9));
  155. CHECK(m32[1] == vec3(6, 3, 0));
  156. mat23 m23(vec2(2, 3));
  157. m23[1] = vec2(8, 9); m23[1][0] = 7;
  158. CHECK(m23[0] == vec2(2, 0));
  159. CHECK(m23[1] == vec2(7, 9));
  160. CHECK(m23[2] == vec2(0, 0));
  161. }
  162. TEST_CASE("gl_mat: (in)equality")
  163. {
  164. mat3 m3(vec3(1, 2, 3), vec3(4, 5, 6), vec3(7, 8, 9));
  165. mat3 n3(vec3(1, 0, 3), vec3(4, 5, 6), vec3(7, 8, 9));
  166. mat3 o3(vec3(1, 2, 3), vec3(4, 5, 0), vec3(7, 8, 9));
  167. mat3 p3(vec3(1, 2, 3), vec3(4, 5, 6), vec3(7, 0, 9));
  168. CHECK(m3 == m3);
  169. CHECK(m3 != n3);
  170. CHECK(m3 != o3);
  171. CHECK(m3 != p3);
  172. imat3 i3(ivec3(1, 2, 3), ivec3(4, 5, 6), ivec3(7, 8, 9));
  173. imat3 j3(ivec3(1, 2, 3), ivec3(4, 5, 6), ivec3(7, 0, 9));
  174. imat3 k3(ivec3(1, 2, 3), ivec3(4, 5, 0), ivec3(7, 8, 9));
  175. imat3 l3(ivec3(0, 2, 3), ivec3(4, 5, 6), ivec3(7, 8, 9));
  176. CHECK(i3 == i3);
  177. CHECK(i3 != j3);
  178. CHECK(i3 != k3);
  179. CHECK(i3 != l3);
  180. mat4 m4(vec4(1, 2, 3, 4), vec4(3, 4, 5, 6), vec4(5, 6, 7, 8), vec4(7, 8, 9, 0));
  181. mat4 n4(vec4(1, 2, 0, 4), vec4(3, 4, 5, 6), vec4(5, 6, 7, 8), vec4(7, 8, 9, 0));
  182. mat4 o4(vec4(1, 2, 3, 4), vec4(0, 4, 5, 6), vec4(5, 6, 7, 8), vec4(7, 8, 9, 0));
  183. mat4 p4(vec4(1, 2, 3, 4), vec4(3, 4, 5, 6), vec4(5, 0, 7, 8), vec4(7, 8, 9, 0));
  184. mat4 q4(vec4(1, 2, 3, 4), vec4(3, 4, 5, 6), vec4(5, 6, 7, 8), vec4(7, 8, 9, 1));
  185. CHECK(m4 == m4);
  186. CHECK(m4 != n4);
  187. CHECK(m4 != o4);
  188. CHECK(m4 != p4);
  189. CHECK(m4 != q4);
  190. imat4 i4(ivec4(1, 2, 3, 4), ivec4(3, 4, 5, 6), ivec4(5, 6, 7, 8), ivec4(7, 8, 9, 0));
  191. imat4 j4(ivec4(1, 0, 3, 4), ivec4(3, 4, 5, 6), ivec4(5, 6, 7, 8), ivec4(7, 8, 9, 0));
  192. imat4 k4(ivec4(1, 2, 3, 4), ivec4(3, 4, 0, 6), ivec4(5, 6, 7, 8), ivec4(7, 8, 9, 0));
  193. imat4 l4(ivec4(1, 2, 3, 4), ivec4(3, 4, 5, 6), ivec4(5, 6, 7, 0), ivec4(7, 8, 9, 0));
  194. imat4 h4(ivec4(1, 2, 3, 4), ivec4(3, 4, 5, 6), ivec4(5, 6, 7, 8), ivec4(0, 8, 9, 0));
  195. CHECK(i4 == i4);
  196. CHECK(i4 != j4);
  197. CHECK(i4 != k4);
  198. CHECK(i4 != l4);
  199. CHECK(i4 != h4);
  200. mat32 m32(vec3(2, 3, 4), vec3(5, 6, 7));
  201. mat32 n32(vec3(2, 3, 0), vec3(5, 6, 7));
  202. mat32 o32(vec3(2, 3, 4), vec3(0, 6, 7));
  203. CHECK(m32 == m32);
  204. CHECK(m32 != n32);
  205. CHECK(m32 != o32);
  206. mat23 m23(vec2(2, 3), vec2(4, 5), vec2(6, 7));
  207. mat23 n23(vec2(0, 3), vec2(4, 5), vec2(6, 7));
  208. mat23 o23(vec2(2, 3), vec2(4, 0), vec2(6, 7));
  209. mat23 p23(vec2(2, 3), vec2(4, 5), vec2(0, 7));
  210. CHECK(m23 == m23);
  211. CHECK(m23 != n23);
  212. CHECK(m23 != o23);
  213. CHECK(m23 != p23);
  214. }
  215. TEST_CASE("gl_mat: copy constructor, assignment")
  216. {
  217. SECTION("mat2") {
  218. mat2 m(vec2(2, 3));
  219. mat2 n(m); CHECK(n == m);
  220. m[1][0] = 9; CHECK(n != m);
  221. n = m; CHECK(n == m);
  222. }
  223. SECTION("imat2") {
  224. imat2 m(ivec2(2, 3));
  225. imat2 n(m); CHECK(n == m);
  226. m[0][1] = 9; CHECK(n != m);
  227. n = m; CHECK(n == m);
  228. }
  229. SECTION("mat3") {
  230. mat3 m(vec3(3, 4, 5));
  231. mat3 n(m); CHECK(n == m);
  232. m[2][1] = 8; CHECK(n != m);
  233. n = m; CHECK(n == m);
  234. }
  235. SECTION("imat3") {
  236. imat3 m(ivec3(3, 4, 5));
  237. imat3 n(m); CHECK(n == m);
  238. m[1][2] = 8; CHECK(n != m);
  239. n = m; CHECK(n == m);
  240. }
  241. SECTION("mat4") {
  242. mat4 m(vec4(4, 5, 6, 7));
  243. mat4 n(m); CHECK(n == m);
  244. m[3][1] = 2; CHECK(n != m);
  245. n = m; CHECK(n == m);
  246. }
  247. SECTION("imat3") {
  248. imat4 m(ivec4(4, 5, 6, 7));
  249. imat4 n(m); CHECK(n == m);
  250. m[0][1] = 1; CHECK(n != m);
  251. n = m; CHECK(n == m);
  252. }
  253. }
  254. TEST_CASE("gl_mat: construct from larger matrix")
  255. {
  256. mat4 m4(vec4(1, 2, 3, 4), vec4(4, 5, 6, 7), vec4(7, 8, 9, 1), vec4(1, 0, 0, 0));
  257. mat3 m3(vec3(1, 2, 3), vec3(4, 5, 6), vec3(7, 8, 9));
  258. mat2 m2(vec2(1, 2), vec2(4, 5));
  259. CHECK(mat3(m4) == m3);
  260. CHECK(mat2(m4) == m2);
  261. CHECK(mat2(m3) == m2);
  262. imat4 i4(ivec4(1, 2, 3, 4), ivec4(4, 5, 6, 7), ivec4(7, 8, 9, 1), ivec4(1, 0, 0, 0));
  263. imat3 i3(ivec3(1, 2, 3), ivec3(4, 5, 6), ivec3(7, 8, 9));
  264. imat2 i2(ivec2(1, 2), ivec2(4, 5));
  265. CHECK(imat3(i4) == i3);
  266. CHECK(imat2(i4) == i2);
  267. CHECK(imat2(i3) == i2);
  268. CHECK(mat32(m4) == mat32(vec3(1, 2, 3), vec3(4, 5, 6)));
  269. CHECK(mat32(m3) == mat32(vec3(1, 2, 3), vec3(4, 5, 6)));
  270. CHECK(mat23(m4) == mat23(vec2(1, 2), vec2(4, 5), vec2(7, 8)));
  271. CHECK(mat23(m3) == mat23(vec2(1, 2), vec2(4, 5), vec2(7, 8)));
  272. }
  273. TEST_CASE("gl_mat: addition, subtraction, negation")
  274. {
  275. mat3 m3(vec3(1, 2, 3), vec3(4, 5, 6), vec3(7, 8, 9));
  276. mat3 n3(vec3(2, 4, 6), vec3(1, 3, 5), vec3(7, 8, 9));
  277. mat3 o3 = m3 + n3;
  278. mat3 p3 = m3 - n3;
  279. CHECK(o3 == mat3(vec3( 3, 6, 9), vec3(5, 8, 11), vec3(14, 16, 18)));
  280. CHECK(p3 == mat3(vec3(-1, -2, -3), vec3(3, 2, 1), vec3( 0, 0, 0)));
  281. p3 += n3;
  282. o3 -= n3;
  283. CHECK(o3 == m3);
  284. CHECK(p3 == m3);
  285. CHECK(-m3 == mat3(vec3(-1, -2, -3), vec3(-4, -5, -6), vec3(-7, -8, -9)));
  286. imat3 i3(ivec3(6, 3, 0), ivec3(2, 4, 6), ivec3(3, 4, 5));
  287. imat3 j3(ivec3(1, 2, 3), ivec3(4, 0, 4), ivec3(0, 1, 1));
  288. imat3 k3 = i3 + j3;
  289. imat3 l3 = i3 - j3;
  290. CHECK(k3 == imat3(ivec3(7, 5, 3), ivec3( 6, 4, 10), ivec3(3, 5, 6)));
  291. CHECK(l3 == imat3(ivec3(5, 1, -3), ivec3(-2, 4, 2), ivec3(3, 3, 4)));
  292. l3 += j3;
  293. k3 -= j3;
  294. CHECK(k3 == i3);
  295. CHECK(l3 == i3);
  296. CHECK(-i3 == imat3(ivec3(-6, -3, -0), ivec3(-2, -4, -6), ivec3(-3, -4, -5)));
  297. mat4 m4(vec4(1, 2, 3, 4), vec4(4, 5, 6, 7), vec4(7, 8, 9, 1), vec4(1, 0, 0, 0));
  298. mat4 n4(vec4(2, 4, 6, 8), vec4(1, 3, 5, 7), vec4(7, 8, 9, 2), vec4(0, 0, 0, 1));
  299. mat4 o4 = m4 + n4;
  300. mat4 p4 = m4 - n4;
  301. CHECK(o4 == mat4(vec4( 3, 6, 9, 12), vec4(5, 8, 11, 14), vec4(14, 16, 18, 3), vec4(1, 0, 0, 1)));
  302. CHECK(p4 == mat4(vec4(-1, -2, -3, -4), vec4(3, 2, 1, 0), vec4( 0, 0, 0, -1), vec4(1, 0, 0, -1)));
  303. p4 += n4;
  304. o4 -= n4;
  305. CHECK(o4 == m4);
  306. CHECK(p4 == m4);
  307. CHECK(-m4 == mat4(vec4(-1, -2, -3, -4), vec4(-4, -5, -6, -7), vec4(-7, -8, -9, -1), vec4(-1, 0, 0, 0)));
  308. imat4 i4(ivec4(0, 1, 2, 3), ivec4(4, 3, 2, 1), ivec4(1, 1, 1, 1), ivec4(5, 5, 4, 4));
  309. imat4 j4(ivec4(2, 3, 4, 5), ivec4(1, 1, 2, 2), ivec4(0, 0, 1, 2), ivec4(1, 2, 2, 0));
  310. imat4 k4 = i4 + j4;
  311. imat4 l4 = i4 - j4;
  312. CHECK(k4 == imat4(ivec4( 2, 4, 6, 8), ivec4(5, 4, 4, 3), ivec4(1, 1, 2, 3), ivec4(6, 7, 6, 4)));
  313. CHECK(l4 == imat4(ivec4(-2, -2, -2, -2), ivec4(3, 2, 0, -1), ivec4(1, 1, 0, -1), ivec4(4, 3, 2, 4)));
  314. l4 += j4;
  315. k4 -= j4;
  316. CHECK(k4 == i4);
  317. CHECK(l4 == i4);
  318. CHECK(-i4 == imat4(ivec4(0, -1, -2, -3), ivec4(-4, -3, -2, -1), ivec4(-1, -1, -1, -1), ivec4(-5, -5, -4, -4)));
  319. mat32 m32(vec3(3, 4, 5), vec3(4, 2, 0));
  320. mat32 n32(vec3(1, 1, 2), vec3(4, 4, 3));
  321. mat32 o32 = m32 + n32;
  322. mat32 p32 = m32 - n32;
  323. CHECK(o32 == mat32(vec3(4, 5, 7), vec3(8, 6, 3)));
  324. CHECK(p32 == mat32(vec3(2, 3, 3), vec3(0, -2, -3)));
  325. p32 += n32;
  326. o32 -= n32;
  327. CHECK(o32 == m32);
  328. CHECK(p32 == m32);
  329. CHECK(-m32 == mat32(vec3(-3, -4, -5), vec3(-4, -2, 0)));
  330. }
  331. TEST_CASE("gl_mat: matrix * scalar")
  332. {
  333. mat3 m3(vec3(1, 2, 3), vec3(4, 5, 6), vec3( 7, 8, 9));
  334. mat3 n3(vec3(2, 4, 6), vec3(8, 10, 12), vec3(14, 16, 18));
  335. CHECK((2.0f * m3) == n3);
  336. CHECK((m3 * 2.0f) == n3);
  337. m3 *= 2.0f;
  338. CHECK(m3 == n3);
  339. imat3 i3(ivec3(2, 1, 0), ivec3(-1, 5, 3), ivec3( 7, 0, -3));
  340. imat3 j3(ivec3(4, 2, 0), ivec3(-2, 10, 6), ivec3(14, 0, -6));
  341. CHECK((2 * i3) == j3);
  342. CHECK((i3 * 2) == j3);
  343. i3 *= 2;
  344. CHECK(i3 == j3);
  345. mat4 m4(vec4(1, 2, 3, 4), vec4(4, 5, 6, 7), vec4( 7, 8, 9, 10), vec4(0, 0, -1, -2));
  346. mat4 n4(vec4(2, 4, 6, 8), vec4(8, 10, 12, 14), vec4(14, 16, 18, 20), vec4(0, 0, -2, -4));
  347. CHECK((2.0f * m4) == n4);
  348. CHECK((m4 * 2.0f) == n4);
  349. m4 *= 2.0f;
  350. CHECK(m4 == n4);
  351. imat4 i4(ivec4(0, 1, 2, 3), ivec4(1, 0, 0, 2), ivec4(3, 2, 1, 0), ivec4(0, 0, -1, -2));
  352. imat4 j4(ivec4(0, 3, 6, 9), ivec4(3, 0, 0, 6), ivec4(9, 6, 3, 0), ivec4(0, 0, -3, -6));
  353. CHECK((3 * i4) == j4);
  354. CHECK((i4 * 3) == j4);
  355. i4 *= 3;
  356. CHECK(i4 == j4);
  357. mat32 m32(vec3( 3, 4, 5), vec3( 4, 2, 0));
  358. mat32 n32(vec3(-6, -8, -10), vec3(-8, -4, 0));
  359. CHECK((-2.0f * m32) == n32);
  360. CHECK((m32 * -2.0f) == n32);
  361. m32 *= -2.0f;
  362. CHECK(m32 == n32);
  363. }
  364. TEST_CASE("gl_mat: matrix * column-vector")
  365. {
  366. mat3 m3(vec3(1, 2, 3), vec3(4, 5, 6), vec3(7, 8, 9));
  367. CHECK((m3 * vec3(1, 0, 0)) == vec3( 1, 2, 3));
  368. CHECK((m3 * vec3(0, 2, 0)) == vec3( 8, 10, 12));
  369. CHECK((m3 * vec3(0, 0, 3)) == vec3(21, 24, 27));
  370. CHECK((m3 * vec3(1, 2, 3)) == vec3(30, 36, 42));
  371. imat3 i3(ivec3(0, -2, 1), ivec3(1, -1, 0), ivec3(-1, -2, 1));
  372. CHECK((i3 * ivec3(-1, 0, 0)) == ivec3( 0, 2, -1));
  373. CHECK((i3 * ivec3( 0, 0, 0)) == ivec3( 0, 0, 0));
  374. CHECK((i3 * ivec3( 0, 0, 3)) == ivec3(-3, -6, 3));
  375. CHECK((i3 * ivec3(-1, 0, 3)) == ivec3(-3, -4, 2));
  376. mat4 m4(vec4(1, 2, 3, 4), vec4(4, 5, 6, 7), vec4(7, 8, 9, 1), vec4(0, 1, 0, -1));
  377. CHECK((m4 * vec4(1, 0, 0, 0)) == vec4( 1, 2, 3, 4));
  378. CHECK((m4 * vec4(0, 2, 0, 0)) == vec4( 8, 10, 12, 14));
  379. CHECK((m4 * vec4(0, 0, 3, 0)) == vec4(21, 24, 27, 3));
  380. CHECK((m4 * vec4(0, 0, 0, 4)) == vec4( 0, 4, 0, -4));
  381. CHECK((m4 * vec4(1, 2, 3, 4)) == vec4(30, 40, 42, 17));
  382. imat4 i4(ivec4(-1, 2, 0, -3), ivec4(0, 1, 2, -1), ivec4(0, 1, 1, 0), ivec4(-1, 1, 0, -1));
  383. CHECK((i4 * ivec4(-1, 0, 0, 0)) == ivec4( 1, -2, 0, 3));
  384. CHECK((i4 * ivec4( 0, 2, 0, 0)) == ivec4( 0, 2, 4, -2));
  385. CHECK((i4 * ivec4( 0, 0, -2, 0)) == ivec4( 0, -2, -2, 0));
  386. CHECK((i4 * ivec4( 0, 0, 0, 1)) == ivec4(-1, 1, 0, -1));
  387. CHECK((i4 * ivec4(-1, 2, -2, 1)) == ivec4( 0, -1, 2, 0));
  388. mat32 m32(vec3(3, 4, 5), vec3(4, 2, 0));
  389. CHECK((m32 * vec2(2, 3)) == vec3(18, 14, 10));
  390. mat23 m23(vec2(3, 4), vec2(1, 5), vec2(4, 2));
  391. CHECK((m23 * vec3(1, 2, 3)) == vec2(17, 20));
  392. }
  393. TEST_CASE("gl_mat: matrix * matrix")
  394. {
  395. mat3 m3(vec3(1, -1, 1), vec3(2, 0, -1), vec3(0, 1, 1));
  396. mat3 n3(vec3(1, 1, -1), vec3(0, -2, 1), vec3(1, 0, 1));
  397. mat3 o3(vec3(0, -1, 2), vec3(1, 2, -2), vec3(0, 2, 1));
  398. CHECK((m3 * n3) == mat3(vec3(3, -2, -1), vec3(-4, 1, 3), vec3(1, 0, 2)));
  399. CHECK((n3 * o3) == mat3(vec3(2, 2, 1), vec3(-1, -3, -1), vec3(1, -4, 3)));
  400. CHECK(((m3 * n3) * o3) == (m3 * (n3 * o3)));
  401. imat3 i3(ivec3( 1, 1, 1), ivec3(-2, 0, -1), ivec3(0, -1, 1));
  402. imat3 j3(ivec3(-1, 0, -1), ivec3( 1, -2, 1), ivec3(1, -1, 1));
  403. CHECK((i3 * j3) == imat3(ivec3(-1, 0, -2), ivec3(5, 0, 4), ivec3(3, 0, 3)));
  404. mat4 m4(vec4(1, -1, 1, 0), vec4(2, 0, -1, 1), vec4(0, 1, 1, -1), vec4(2, 0, 1, -1));
  405. mat4 n4(vec4(1, 1, -1, 1), vec4(0, -2, 1, 0), vec4(1, 0, 1, -1), vec4(0, 1, 2, -2));
  406. CHECK((m4 * n4) == mat4(vec4(5, -2, 0, 1), vec4(-4, 1, 3, -3), vec4(-1, 0, 1, 0), vec4(-2, 2, -1, 1)));
  407. CHECK((n4 * m4) == mat4(vec4(2, 3, -1, 0), vec4( 1, 3, -1, 1), vec4( 1, -3, 0, 1), vec4( 3, 1, -3, 3)));
  408. imat4 i4(ivec4(1, -1, 1, 2), ivec4(2, -1, -1, 1), ivec4(2, 1, 1, -1), ivec4( 2, -1, 1, -1));
  409. imat4 j4(ivec4(1, 1, -1, 1), ivec4(2, -2, 1, -1), ivec4(1, -2, 1, -1), ivec4(-1, 1, 2, -2));
  410. CHECK((i4 * j4) == imat4(ivec4(3, -4, 0, 3), ivec4(-2, 2, 4, 2), ivec4(-3, 3, 3, 0), ivec4(1, 4, -2, -1)));
  411. mat32 m32(vec3(1, 2, -1), vec3(-1, -1, 2));
  412. mat23 m23(vec2(1, -2), vec2(2, -1), vec2(1, -1));
  413. CHECK((m32 * m23) == mat3(vec3(3, 4, -5), vec3(3, 5, -4), vec3(2, 3, -3)));
  414. CHECK((m23 * m32) == mat2(vec2(4, -3), vec2(-1, 1)));
  415. CHECK((m3 * m32) == mat32(vec3(5, -2, -2), vec3(-3, 3, 2)));
  416. CHECK((m23 * m3 ) == mat23(vec2(0, -2), vec2(1, -3), vec2(3, -2)));
  417. }
  418. TEST_CASE("gl_mat: transpose")
  419. {
  420. mat3 m3(vec3(1, -1, 1), vec3(2, 0, -1), vec3(0, 1, 1));
  421. CHECK(transpose(m3) == mat3(vec3(1, 2, 0), vec3(-1, 0, 1), vec3(1, -1, 1)));
  422. imat3 i3(ivec3(1, 1, 1), ivec3(-2, 0, -1), ivec3(0, -1, 1));
  423. CHECK(transpose(i3) == imat3(ivec3(1, -2, 0), ivec3(1, 0, -1), ivec3(1, -1, 1)));
  424. mat4 m4(vec4(1, -1, 1, 0), vec4(2, 0, -1, 1), vec4(0, 1, 1, -1), vec4(2, 0, 1, -1));
  425. CHECK(transpose(m4) == mat4(vec4(1, 2, 0, 2), vec4(-1, 0, 1, 0), vec4(1, -1, 1, 1), vec4(0, 1, -1, -1)));
  426. imat4 i4(ivec4(1, -1, 1, 2), ivec4(2, -1, -1, 1), ivec4(2, 1, 1, -1), ivec4(2, -1, 1, -1));
  427. CHECK(transpose(i4) == imat4(ivec4(1, 2, 2, 2), ivec4(-1, -1, 1, -1), ivec4(1, -1, 1, 1), ivec4(2, 1, -1, -1)));
  428. mat32 m32(vec3(1, 2, 3), vec3(4, 5, 6));
  429. mat23 m23(vec2(1, 4), vec2(2, 5), vec2(3, 6));
  430. CHECK(transpose(m32) == m23);
  431. CHECK(transpose(m23) == m32);
  432. }
  433. TEST_CASE("gl_mat: determinant, inverse")
  434. {
  435. mat2 m2(vec2(1, -1), vec2(0, 1));
  436. CHECK(determinant(m2) == 1.0f);
  437. mat2 i2 = inverse(m2);
  438. CHECK(determinant(i2) == 1.0f);
  439. CHECK(i2 == mat2(vec2(1, 1), vec2(0, 1)));
  440. CHECK(m2 * i2 == mat2());
  441. CHECK(i2 * m2 == mat2());
  442. mat3 m3(vec3(1, 0, -1), vec3(0, 1, 0), vec3(1, -1, 1));
  443. CHECK(determinant(m3) == 2.0f);
  444. mat3 i3 = inverse(m3);
  445. CHECK(determinant(i3) == 0.5f);
  446. CHECK(i3 == mat3(vec3(0.5f, 0.5f, 0.5f), vec3(0, 1, 0), vec3(-0.5f, 0.5f, 0.5f)));
  447. CHECK(m3 * i3 == mat3());
  448. CHECK(i3 * m3 == mat3());
  449. mat4 m4(vec4(0, 1, 1, 0), vec4(-1, 0, 1, 0), vec4(1, 1, 0, -1), vec4(0, 1, 0, 0));
  450. CHECK(determinant(m4) == -1.0f);
  451. mat4 i4 = inverse(m4);
  452. CHECK(approxEq(i4, mat4(vec4(1, -1, 0, -1), vec4(0, 0, 0, 1), vec4(1, 0, 0, -1), vec4(1, -1, -1, 0))));
  453. CHECK(approxEq(m4 * i4, mat4()));
  454. CHECK(approxEq(i4 * m4, mat4()));
  455. }
  456. TEST_CASE("gl_mat: norm-2 squared")
  457. {
  458. mat3 m3(vec3(1, -1, 1), vec3(2, 0, -1), vec3(0, 1, 1));
  459. CHECK(norm2_2(m3) == 10);
  460. imat3 i3(ivec3(1, 2, 1), ivec3(-2, 3, -1), ivec3(2, 1, 4));
  461. CHECK(norm2_2(i3) == 41);
  462. mat4 m4(vec4(1, -1, 1, 2), vec4(2, 0, -1, 1), vec4(0, 1, 1, 0), vec4(0, 1, 1, 3));
  463. CHECK(norm2_2(m4) == 26);
  464. imat4 i4(ivec4(1, 2, 1, -3), ivec4(-2, 3, -1, 0), ivec4(2, 1, 4, -2), ivec4(0, 2, 2, 2));
  465. CHECK(norm2_2(i4) == 66);
  466. mat32 m32(vec3(1, 2, -1), vec3(-1, -1, 2));
  467. mat23 m23(vec2(1, -1), vec2(2, -1), vec2(-1, 2));
  468. CHECK(norm2_2(m32) == norm2_2(m23));
  469. }
  470. #if 0
  471. // The following functions are not part of the actual test. They get compiled,
  472. // but never executed. I used them to (manually) inspect the quality of the
  473. // generated code. Only for mat4, because the code was only optimized for that
  474. // type.
  475. void test_constr(mat4& A)
  476. {
  477. A = mat4();
  478. }
  479. void test_constr(const vec4& x, mat4& A)
  480. {
  481. A = mat4(x);
  482. }
  483. void test_constr(const vec4& x, const vec4& y, const vec4& z, const vec4& w, mat4& A)
  484. {
  485. A = mat4(x, y, z, w);
  486. }
  487. void test_constr(const mat4& A, mat3& B)
  488. {
  489. B = mat3(A);
  490. }
  491. void test_change0(const vec4& x, mat4& A)
  492. {
  493. A[0] = x;
  494. }
  495. void test_change2(const vec4& x, mat4& A)
  496. {
  497. A[2] = x;
  498. }
  499. void test_extr0(const mat4& A, vec4& x)
  500. {
  501. x = A[0];
  502. }
  503. void test_extr2(const mat4& A, vec4& x)
  504. {
  505. x = A[2];
  506. }
  507. bool test_equal(const mat4& A, const mat4& B)
  508. {
  509. return A == B;
  510. }
  511. bool test_not_equal(const mat4& A, const mat4& B)
  512. {
  513. return A != B;
  514. }
  515. void test_add(const mat4& A, const mat4& B, mat4& C)
  516. {
  517. C = A + B;
  518. }
  519. void test_add(const mat4& A, mat4& B)
  520. {
  521. B += A;
  522. }
  523. void test_sub(const mat4& A, const mat4& B, mat4& C)
  524. {
  525. C = A - B;
  526. }
  527. void test_negate(const mat4& A, mat4& B)
  528. {
  529. B = -A;
  530. }
  531. void test_mul(float x, const mat4& A, mat4& B)
  532. {
  533. B = x * A;
  534. }
  535. void test_mul(const mat4& A, const vec4& x, vec4& y)
  536. {
  537. y = A * x;
  538. }
  539. void test_mul(const mat4& A, const mat4& B, mat4& C)
  540. {
  541. C = A * B;
  542. }
  543. void test_transpose(const mat4& A, mat4& B)
  544. {
  545. B = transpose(A);
  546. }
  547. void test_determinant(const mat4& A, float& x)
  548. {
  549. x = determinant(A);
  550. }
  551. void test_inverse(const mat4& A, mat4& B)
  552. {
  553. B = inverse(A);
  554. }
  555. void test_norm(const mat4& A, float& x)
  556. {
  557. x = norm2_2(A);
  558. }
  559. #endif