You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

351 lines
10 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net>
  5. // (c) 2013-2014 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
  6. // (c) 2013-2014 Guillaume Bittoun <guillaume.bittoun@gmail.com>
  7. // This program is free software; you can redistribute it and/or
  8. // modify it under the terms of the Do What The Fuck You Want To
  9. // Public License, Version 2, as published by Sam Hocevar. See
  10. // http://www.wtfpl.net/ for more details.
  11. //
  12. #include <lol/engine-internal.h>
  13. #include <lol/math/simplex_interpolator.h>
  14. #include <lolunit.h>
  15. namespace lol
  16. {
  17. template<int N, typename T = float>
  18. class test_interpolator : public simplex_interpolator<N, T>
  19. {
  20. public:
  21. test_interpolator() :
  22. simplex_interpolator<N, T>()
  23. {
  24. }
  25. test_interpolator(arraynd<N, T> const & samples) :
  26. simplex_interpolator<N, T>(samples)
  27. {
  28. }
  29. void DumpMatrix()
  30. {
  31. std::cout << std::endl;
  32. for (int i = 0; i < N; ++i)
  33. {
  34. for (int j = 0; j < N; ++j)
  35. {
  36. std::cout << this->m_base[i][j] << ", ";
  37. }
  38. std::cout << ";";
  39. }
  40. std::cout << std::endl;
  41. for (int i = 0; i < N; ++i)
  42. {
  43. for (int j = 0; j < N; ++j)
  44. {
  45. std::cout << this->m_base_inverse[i][j] << ", ";
  46. }
  47. std::cout << ";";
  48. }
  49. std::cout << std::endl;
  50. }
  51. void DumpMatrix(float result[N][N])
  52. {
  53. for (int i = 0; i < N; ++i)
  54. {
  55. for (int j = 0; j < N; ++j)
  56. {
  57. result[i][j] = this->m_base[i][j];
  58. }
  59. }
  60. }
  61. void DumpCheckInverse(float result[N][N])
  62. {
  63. for (int i = 0; i < N; ++i)
  64. for (int j = 0; j < N; ++j)
  65. result[i][j] = 0;
  66. for (int i = 0; i < N; ++i)
  67. {
  68. for (int j = 0; j < N; ++j)
  69. {
  70. for (int k = 0; k < N; ++k)
  71. {
  72. result[i][j] += this->m_base[i][k] * this->m_base_inverse[k][j];
  73. }
  74. }
  75. }
  76. }
  77. vec_t<int, N> GetIndexOrder(vec_t<float, N> const & decimal_point)
  78. {
  79. return simplex_interpolator<N, T>::GetIndexOrder(decimal_point);
  80. }
  81. };
  82. lolunit_declare_fixture(SimplexInterpolatorTest)
  83. {
  84. void SetUp() {}
  85. void TearDown() {}
  86. lolunit_declare_test(CompoundVariable)
  87. {
  88. test_interpolator<2, real> b({{ real(0) }});
  89. test_interpolator<2, vec2> c({{ vec2(0) }});
  90. }
  91. template<int N>
  92. void check_base_matrix()
  93. {
  94. test_interpolator<N> s;
  95. float result[N][N];
  96. s.DumpCheckInverse(result);
  97. // Check base matrix inverse
  98. for (int i = 0; i < N; ++i)
  99. {
  100. for (int j = 0; j < N; ++j)
  101. {
  102. if (i == j)
  103. lolunit_assert_doubles_equal(1, result[i][j], 1e-6);
  104. else
  105. lolunit_assert_doubles_equal(0, result[i][j], 1e-6);
  106. }
  107. }
  108. s.DumpMatrix(result);
  109. // Check base vectors’ norms
  110. for (int i = 0; i < N; ++i)
  111. {
  112. float norm = 0;
  113. for (int j = 0; j < N; ++j)
  114. {
  115. norm += result[i][j] * result[i][j];
  116. }
  117. lolunit_assert_doubles_equal(1, norm, 1e-6);
  118. }
  119. // Check result of sum of base vectors => must have norm = 1
  120. float vec_result[N];
  121. for (int i = 0; i < N; ++i)
  122. {
  123. vec_result[i] = 0;
  124. for (int j = 0; j < N; ++j)
  125. {
  126. vec_result[i] += result[i][j];
  127. }
  128. }
  129. float norm = 0;
  130. for (int i = 0 ; i < N ; ++i)
  131. {
  132. norm += vec_result[i] * vec_result[i];
  133. }
  134. lolunit_assert_doubles_equal(1, norm, 1e-6);
  135. }
  136. lolunit_declare_test(CoordinateMatrixTest)
  137. {
  138. check_base_matrix<1>();
  139. check_base_matrix<2>();
  140. check_base_matrix<3>();
  141. check_base_matrix<4>();
  142. check_base_matrix<5>();
  143. check_base_matrix<6>();
  144. check_base_matrix<7>();
  145. check_base_matrix<8>();
  146. check_base_matrix<9>();
  147. check_base_matrix<10>();
  148. }
  149. template<int N>
  150. void check_index_ordering()
  151. {
  152. static int gen = 12345678;
  153. test_interpolator<N> s;
  154. vec_t<float, N> vec_ref;
  155. for (int i = 0 ; i < N ; ++i)
  156. vec_ref[i] = (gen = gen * gen + gen);
  157. vec_t<int, N> result = s.GetIndexOrder(vec_ref);
  158. for (int i = 1 ; i < N ; ++i)
  159. lolunit_assert(vec_ref[result[i]] >= vec_ref[result[i-1]]);
  160. }
  161. lolunit_declare_test(IndexOrderTest)
  162. {
  163. for (int i = 1 ; i < 10 ; ++i)
  164. check_index_ordering<1>();
  165. for (int i = 1 ; i < 10 ; ++i)
  166. check_index_ordering<2>();
  167. for (int i = 1 ; i < 10 ; ++i)
  168. check_index_ordering<3>();
  169. for (int i = 1 ; i < 10 ; ++i)
  170. check_index_ordering<4>();
  171. for (int i = 1 ; i < 10 ; ++i)
  172. check_index_ordering<5>();
  173. for (int i = 1 ; i < 10 ; ++i)
  174. check_index_ordering<6>();
  175. for (int i = 1 ; i < 10 ; ++i)
  176. check_index_ordering<7>();
  177. for (int i = 1 ; i < 10 ; ++i)
  178. check_index_ordering<8>();
  179. for (int i = 1 ; i < 10 ; ++i)
  180. check_index_ordering<9>();
  181. for (int i = 1 ; i < 10 ; ++i)
  182. check_index_ordering<10>();
  183. }
  184. #if 0
  185. lolunit_declare_test(FloatGridPoints2D1x1)
  186. {
  187. simplex_interpolator<2> s({{1.f}});
  188. float val;
  189. val = s.Interp(GridPoint2D(-1, -1));
  190. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  191. val = s.Interp(GridPoint2D(0, -1));
  192. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  193. val = s.Interp(GridPoint2D(1, -1));
  194. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  195. val = s.Interp(GridPoint2D(-1, 0));
  196. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  197. val = s.Interp(GridPoint2D(0, 0));
  198. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  199. val = s.Interp(GridPoint2D(1, 0));
  200. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  201. val = s.Interp(GridPoint2D(-1, 1));
  202. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  203. val = s.Interp(GridPoint2D(0, 1));
  204. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  205. val = s.Interp(GridPoint2D(1, 1));
  206. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  207. }
  208. lolunit_declare_test(VectorGridPoints2D1x1)
  209. {
  210. simplex_interpolator<2, vec3> s({{vec3(1.f, 2.f, 3.f)}});
  211. vec3 val = s.Interp(GridPoint2D(-1, 0));
  212. lolunit_assert_doubles_equal(1.f, val.x, 1e-5f);
  213. lolunit_assert_doubles_equal(2.f, val.y, 1e-5f);
  214. lolunit_assert_doubles_equal(3.f, val.z, 1e-5f);
  215. }
  216. lolunit_declare_test(GridPoints2D2x2)
  217. {
  218. simplex_interpolator<2> s({{1.f, 1.f}, {1.f, 2.f}});
  219. float val;
  220. val = s.Interp(GridPoint2D(0, 0));
  221. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  222. val = s.Interp(GridPoint2D(1, 0));
  223. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  224. val = s.Interp(GridPoint2D(0, 1));
  225. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  226. val = s.Interp(GridPoint2D(1, 1));
  227. lolunit_assert_doubles_equal(2.f, val, 1e-5f);
  228. }
  229. lolunit_declare_test(MoreGridPoints2D2x2)
  230. {
  231. simplex_interpolator<2> s({{1.f, 1.f}, {1.f, 2.f}});
  232. float val;
  233. val = s.Interp(GridPoint2D(-1, -1));
  234. lolunit_assert_doubles_equal(2.f, val, 1e-5f);
  235. val = s.Interp(GridPoint2D(0, -1));
  236. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  237. val = s.Interp(GridPoint2D(1, -1));
  238. lolunit_assert_doubles_equal(2.f, val, 1e-5f);
  239. val = s.Interp(GridPoint2D(2, -1));
  240. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  241. val = s.Interp(GridPoint2D(2, 0));
  242. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  243. val = s.Interp(GridPoint2D(2, 1));
  244. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  245. val = s.Interp(GridPoint2D(2, 2));
  246. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  247. val = s.Interp(GridPoint2D(1, 2));
  248. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  249. val = s.Interp(GridPoint2D(0, 2));
  250. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  251. val = s.Interp(GridPoint2D(-1, 2));
  252. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  253. val = s.Interp(GridPoint2D(-1, 1));
  254. lolunit_assert_doubles_equal(2.f, val, 1e-5f);
  255. val = s.Interp(GridPoint2D(-1, 0));
  256. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  257. }
  258. lolunit_declare_test(GridPoints2D3x3)
  259. {
  260. simplex_interpolator<2> s({{1, 1, 2}, {1, 2, 2}, {2, 2, 2}});
  261. float val;
  262. val = s.Interp(GridPoint2D(0, 0));
  263. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  264. val = s.Interp(GridPoint2D(1, 0));
  265. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  266. val = s.Interp(GridPoint2D(0, 1));
  267. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  268. val = s.Interp(GridPoint2D(1, 1));
  269. lolunit_assert_doubles_equal(2.f, val, 1e-5f);
  270. }
  271. lolunit_declare_test(OtherPoints2D3x3)
  272. {
  273. simplex_interpolator<2> s({{1, 1, 2}, {1, 2, 2}, {2, 2, 2}});
  274. float val;
  275. /* 1/1 triangle edge */
  276. val = s.Interp(vec2(1.f, lol::sin(F_PI / 3)));
  277. lolunit_assert_doubles_equal(1.5f, val, 1e-5f);
  278. /* 1/1/1 triangle interior */
  279. val = s.Interp(vec2(0.5f, 0.5f));
  280. lolunit_assert_doubles_equal(1.f, val, 1e-5f);
  281. /* 1/1/2 triangle interior */
  282. val = s.Interp(vec2(0.f, 0.5f));
  283. lolunit_assert(val < 2.f);
  284. lolunit_assert(val > 1.f);
  285. /* Another 1/1/2 triangle interior */
  286. val = s.Interp(vec2(1.f, 0.5f));
  287. lolunit_assert(val < 2.f);
  288. lolunit_assert(val > 1.f);
  289. }
  290. private:
  291. vec2 GridPoint2D(int i, int j)
  292. {
  293. static vec2 vi(1.f, 0.f);
  294. static vec2 vj(lol::cos(F_PI / 3), lol::sin(F_PI / 3));
  295. return (float)i * vi + (float)j * vj;
  296. }
  297. #endif
  298. };
  299. }