pattern_test.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. /*
  2. * DoRayMe - a quick and dirty Raytracer
  3. * Pattern unit tests
  4. *
  5. * Created by Manoël Trapier
  6. * Copyright (c) 2020 986-Studio.
  7. *
  8. */
  9. #include <pattern.h>
  10. #include <strippattern.h>
  11. #include <gradientpattern.h>
  12. #include <ringpattern.h>
  13. #include <checkerspattern.h>
  14. #include <testpattern.h>
  15. #include <transformation.h>
  16. #include <colour.h>
  17. #include <sphere.h>
  18. #include <gtest/gtest.h>
  19. #include <material.h>
  20. #include <uv_pattern.h>
  21. #include <uv_checkers.h>
  22. #include <texturemap.h>
  23. #ifdef ENABLE_LUA_SUPPORT
  24. extern "C" {
  25. #include <lua.h>
  26. #include <lauxlib.h>
  27. #include <lualib.h>
  28. }
  29. #include <luapattern.h>
  30. #endif
  31. Colour black = Colour(0, 0, 0);
  32. Colour white = Colour(1, 1, 1);
  33. TEST(PatternTest, Creating_a_stripe_pattern)
  34. {
  35. StripPattern p = StripPattern(white, black);
  36. ASSERT_EQ(p.a, white);
  37. ASSERT_EQ(p.b, black);
  38. }
  39. TEST(PatternTest, A_strip_pattern_is_constant_in_y)
  40. {
  41. StripPattern p = StripPattern(white, black);
  42. ASSERT_EQ(p.patternAt(Point(0, 0, 0)), white);
  43. ASSERT_EQ(p.patternAt(Point(0, 1, 0)), white);
  44. ASSERT_EQ(p.patternAt(Point(0, 2, 0)), white);
  45. }
  46. TEST(PatternTest, A_strip_pattern_is_constant_in_z)
  47. {
  48. StripPattern p = StripPattern(white, black);
  49. ASSERT_EQ(p.patternAt(Point(0, 0, 0)), white);
  50. ASSERT_EQ(p.patternAt(Point(0, 0, 1)), white);
  51. ASSERT_EQ(p.patternAt(Point(0, 0, 2)), white);
  52. }
  53. TEST(PatternTest, A_strip_pattern_alternate_in_x)
  54. {
  55. StripPattern p = StripPattern(white, black);
  56. ASSERT_EQ(p.patternAt(Point(0, 0, 0)), white);
  57. ASSERT_EQ(p.patternAt(Point(0.9, 0, 0)), white);
  58. ASSERT_EQ(p.patternAt(Point(1, 0, 0)), black);
  59. ASSERT_EQ(p.patternAt(Point(-0.1, 0, 0)), black);
  60. ASSERT_EQ(p.patternAt(Point(-1, 0, 0)), black);
  61. ASSERT_EQ(p.patternAt(Point(-1.1, 0, 0)), white);
  62. }
  63. TEST(PatternTest, Lightning_with_a_pattern_applied)
  64. {
  65. Sphere s = Sphere();
  66. Material m;
  67. StripPattern p = StripPattern(white, black);
  68. m.pattern = &p;
  69. m.ambient = 1;
  70. m.diffuse = 0;
  71. m.specular = 0;
  72. Tuple eyev = Vector(0, 0, -1);
  73. Tuple normalv = Vector(0, 0, -1);
  74. Light light = Light(POINT_LIGHT, Point(0, 0, -10), Colour(1, 1, 1));
  75. Colour c1 = m.lighting(light, Point(0, 9, 0), eyev, normalv, &s, false);
  76. Colour c2 = m.lighting(light, Point(1, 1, 0), eyev, normalv, &s, false);
  77. ASSERT_EQ(c1, Colour(1, 1, 1));
  78. ASSERT_EQ(c2, Colour(0, 0, 0));
  79. }
  80. TEST(PatternTest, Stripe_with_an_object_transformation)
  81. {
  82. Sphere s = Sphere();
  83. s.setTransform(scaling(2, 2, 2));
  84. StripPattern pattern = StripPattern(white, black);
  85. Colour c = pattern.patternAtObject(&s, Point(1.5, 0, 0));
  86. ASSERT_EQ(c, white);
  87. }
  88. TEST(PatternTest, Stripe_with_a_pattern_transformation)
  89. {
  90. Sphere s = Sphere();
  91. StripPattern pattern = StripPattern(white, black);
  92. pattern.setTransform(scaling(2, 2, 2));
  93. Colour c = pattern.patternAtObject(&s, Point(1.5, 0, 0));
  94. ASSERT_EQ(c, white);
  95. }
  96. TEST(PatternTest, Stripe_with_both_an_object_and_a_pattern_transformation)
  97. {
  98. Sphere s = Sphere();
  99. s.setTransform(scaling(2, 2, 2));
  100. StripPattern pattern = StripPattern(white, black);
  101. pattern.setTransform(translation(0.5, 0, 0));
  102. Colour c = pattern.patternAtObject(&s, Point(2.5, 0, 0));
  103. ASSERT_EQ(c, white);
  104. }
  105. TEST(PatternTest, The_default_pattern_transformation)
  106. {
  107. TestPattern pattern = TestPattern();
  108. ASSERT_EQ(pattern.transformMatrix, Matrix4().identity());
  109. }
  110. TEST(PatternTest, Assigning_a_transformation)
  111. {
  112. TestPattern pattern = TestPattern();
  113. pattern.setTransform(translation(1, 2, 3));
  114. ASSERT_EQ(pattern.transformMatrix, translation(1, 2, 3));
  115. }
  116. TEST(PatternTest, A_pattern_with_an_object_transformation)
  117. {
  118. Sphere s = Sphere();
  119. s.setTransform(scaling(2, 2, 2));
  120. TestPattern pattern = TestPattern();
  121. Colour c = pattern.patternAtObject(&s, Point(2, 3, 4));
  122. ASSERT_EQ(c, Colour(1, 1.5, 2));
  123. }
  124. TEST(PatternTest, A_pattern_with_a_pattern_transformation)
  125. {
  126. Sphere s = Sphere();
  127. TestPattern pattern = TestPattern();
  128. pattern.setTransform(scaling(2, 2, 2));
  129. Colour c = pattern.patternAtObject(&s, Point(2, 3, 4));
  130. ASSERT_EQ(c, Colour(1, 1.5, 2));
  131. }
  132. TEST(PatternTest, A_pattern_with_an_object_and_a_pattern_transformation)
  133. {
  134. Sphere s = Sphere();
  135. s.setTransform(scaling(2, 2, 2));
  136. TestPattern pattern = TestPattern();
  137. pattern.setTransform(translation(0.5, 1, 1.5));
  138. Colour c = pattern.patternAtObject(&s, Point(2.5, 3, 3.5));
  139. ASSERT_EQ(c, Colour(0.75, 0.5, 0.25));
  140. }
  141. TEST(PatternTest, A_gradient_linearly_interpolates_betweens_colors)
  142. {
  143. GradientPattern pattern = GradientPattern(white, black);
  144. ASSERT_EQ(pattern.patternAt(Point(0.25, 0, 0)), Colour(0.75, 0.75, 0.75));
  145. ASSERT_EQ(pattern.patternAt(Point(0.5, 0, 0)), Colour(0.5, 0.5, 0.5));
  146. ASSERT_EQ(pattern.patternAt(Point(0.75, 0, 0)), Colour(0.25, 0.25, 0.25));
  147. }
  148. TEST(PatternTest, A_ring_should_extend_in_both_x_and_z)
  149. {
  150. RingPattern pattern = RingPattern(white, black);
  151. ASSERT_EQ(pattern.patternAt(Point(0, 0, 0)), white);
  152. ASSERT_EQ(pattern.patternAt(Point(1, 0, 0)), black);
  153. ASSERT_EQ(pattern.patternAt(Point(0, 0, 1)), black);
  154. /* 0.708 is just bit more than sqrt(2)/2 */
  155. ASSERT_EQ(pattern.patternAt(Point(0.708, 0, 0.708)), black);
  156. }
  157. TEST(PatternTest, Checkers_should_repeat_in_x)
  158. {
  159. CheckersPattern pattern = CheckersPattern(white, black);
  160. ASSERT_EQ(pattern.patternAt(Point(0, 0, 0)), white);
  161. ASSERT_EQ(pattern.patternAt(Point(0.99, 0, 0)), white);
  162. ASSERT_EQ(pattern.patternAt(Point(1.01, 0, 0)), black);
  163. }
  164. TEST(PatternTest, Checkers_should_repeat_in_y)
  165. {
  166. CheckersPattern pattern = CheckersPattern(white, black);
  167. ASSERT_EQ(pattern.patternAt(Point(0, 0, 0)), white);
  168. ASSERT_EQ(pattern.patternAt(Point(0, 0.99, 0)), white);
  169. ASSERT_EQ(pattern.patternAt(Point(0, 1.01, 0)), black);
  170. }
  171. TEST(PatternTest, Checkers_should_repeat_in_z)
  172. {
  173. CheckersPattern pattern = CheckersPattern(white, black);
  174. ASSERT_EQ(pattern.patternAt(Point(0, 0, 0)), white);
  175. ASSERT_EQ(pattern.patternAt(Point(0, 0, 0.99)), white);
  176. ASSERT_EQ(pattern.patternAt(Point(0, 0, 1.01)), black);
  177. }
  178. #ifdef ENABLE_LUA_SUPPORT
  179. TEST(PatternTest, Simple_test_of_a_lua_pattern)
  180. {
  181. int error;
  182. LuaPattern pattern = LuaPattern(white, black);
  183. lua_State *L = luaL_newstate();
  184. luaL_openlibs(L);
  185. pattern.setLua(L);
  186. pattern.setLuaFunctionName("pat");
  187. error = luaL_loadstring(L, "function pat(x, y, z, a, b)\n"
  188. " local v = math.floor(x) + math.floor(y) + math.floor(z)\n"
  189. " if (v % 2) == 0 then\n"
  190. " return a.r, a.g, a.b\n"
  191. " end\n"
  192. " return b.r, b.g, b.b\n"
  193. "end");
  194. if (error)
  195. {
  196. fprintf(stderr, "%s\n", lua_tostring(L, -1));
  197. lua_pop(L, 1); /* pop error message from the stack */
  198. }
  199. ASSERT_EQ(error, 0);
  200. error = lua_pcall(L, 0, 0, 0);
  201. if (error)
  202. {
  203. fprintf(stderr, "%s\n", lua_tostring(L, -1));
  204. lua_pop(L, 1); /* pop error message from the stack */
  205. }
  206. ASSERT_EQ(error, 0);
  207. ASSERT_EQ(pattern.patternAt(Point(0, 0, 0)), white);
  208. ASSERT_EQ(pattern.patternAt(Point(0, 0.99, 0)), white);
  209. ASSERT_EQ(pattern.patternAt(Point(0, 1.01, 0)), black);
  210. lua_close(L);
  211. }
  212. #endif
  213. TEST(PatternTest, Checkers_pattern_in_2D)
  214. {
  215. UVCheckers checkers = UVCheckers(2, 2, black, white);
  216. ASSERT_EQ(checkers.uvPatternAt(0.0, 0.0), black);
  217. ASSERT_EQ(checkers.uvPatternAt(0.5, 0.0), white);
  218. ASSERT_EQ(checkers.uvPatternAt(0.0, 0.5), white);
  219. ASSERT_EQ(checkers.uvPatternAt(0.5, 0.5), black);
  220. ASSERT_EQ(checkers.uvPatternAt(1.0, 1.0), black);
  221. }
  222. TEST(PatternTest, Using_a_spherical_mapping_on_a_3d_point)
  223. {
  224. Point testList[] = {
  225. Point( 0, 0, -1),
  226. Point( 1, 0, 0),
  227. Point( 0, 0, 1),
  228. Point(-1, 0, 0),
  229. Point( 0, 1, 0),
  230. Point( 0, -1, 0),
  231. Point(sqrt(2)/2, sqrt(2)/2, 0),
  232. };
  233. double testResults[][2] {
  234. {0.0, 0.5},
  235. {0.25, 0.5},
  236. {0.5, 0.5},
  237. {0.75, 0.5},
  238. {0.5, 1.0},
  239. {0.5, 0.0},
  240. {0.25, 0.75},
  241. };
  242. int testCount = sizeof(testList)/sizeof((testList)[0]);
  243. int i;
  244. TextureMap tm = TextureMap(SPHERICAL_MAP, nullptr);
  245. for(i = 0; i < testCount; i++)
  246. {
  247. double u, v;
  248. tm.sphericalMap(testList[i], u, v);
  249. ASSERT_TRUE(double_equal(u, testResults[i][0]));
  250. ASSERT_TRUE(double_equal(v, testResults[i][1]));
  251. }
  252. }
  253. TEST(PatternTest, Using_a_texture_map_with_a_spherical_map)
  254. {
  255. Point testList[] = {
  256. Point( 0.4315, 0.4670, 0.7719),
  257. Point( -0.9654, 0.2252, -0.0534),
  258. Point( 0.1039, 0.7090, 0.6975),
  259. Point( -0.4986, -0.7856, -0.3663),
  260. Point( -0.0317, -0.9395, 0.3411),
  261. Point( 0.4809, -0.7721, 0.4154),
  262. Point( 0.0285, -0.9612, -0.2745),
  263. Point( -0.5734, -0.2162, -0.7903),
  264. Point( 0.7688, -0.1470, 0.6223),
  265. Point( -0.7652, 0.2175, 0.6060),
  266. };
  267. Colour testResults[] {
  268. white,
  269. black,
  270. white,
  271. black,
  272. black,
  273. black,
  274. black,
  275. white,
  276. black,
  277. black,
  278. };
  279. int testCount = sizeof(testList)/sizeof((testList)[0]);
  280. int i;
  281. UVCheckers uvpat = UVCheckers(16, 8, black, white);
  282. TextureMap tm = TextureMap(SPHERICAL_MAP, &uvpat);
  283. for(i = 0; i < testCount; i++)
  284. {
  285. Colour ret = tm.patternAt(testList[i]);
  286. EXPECT_EQ(ret, testResults[i]);
  287. }
  288. }
  289. TEST(PatternTest, Using_a_planar_mapping_on_a_3d_point)
  290. {
  291. Point testList[] = {
  292. Point(0.25, 0.0, 0.5),
  293. Point(0.25, 0.0, -0.25),
  294. Point(0.25, 0.5, -0.25),
  295. Point(1.25, 0.0, 0.5),
  296. Point(0.25, 0.0, -1.75),
  297. Point(1.00, 0.0, -1.0),
  298. Point(0.00, 0.0, 0.0),
  299. };
  300. double testResults[][2] {
  301. {0.25, 0.50},
  302. {0.25, 0.75},
  303. {0.25, 0.75},
  304. {0.25, 0.50},
  305. {0.25, 0.25},
  306. {0.00, 0.00},
  307. {0.00, 0.00},
  308. };
  309. int testCount = sizeof(testList)/sizeof((testList)[0]);
  310. int i;
  311. TextureMap tm = TextureMap(PLANAR_MAP, nullptr);
  312. for(i = 0; i < testCount; i++)
  313. {
  314. double u, v;
  315. tm.planarMap(testList[i], u, v);
  316. ASSERT_TRUE(double_equal(u, testResults[i][0]));
  317. ASSERT_TRUE(double_equal(v, testResults[i][1]));
  318. }
  319. }
  320. TEST(PatternTest, Using_a_cylindrical_mapping_on_a_3d_point)
  321. {
  322. Point testList[] = {
  323. Point( 0.00000, 0.00, -1.00000),
  324. Point( 0.00000, 0.50, -1.00000),
  325. Point( 0.00000, 1.00, -1.00000),
  326. Point( 0.70711, 0.50, -0.70711),
  327. Point( 1.00000, 0.50, -0.00000),
  328. Point( 0.70711, 0.50, 0.70711),
  329. Point( 0.00000, -0.25, 1.00000),
  330. Point(-0.70711, 0.50, 0.70711),
  331. Point(-1.00000, 1.25, 0.00000),
  332. Point(-0.70711, 0.50, -0.70711),
  333. };
  334. double testResults[][2] {
  335. {0.000, 0.00},
  336. {0.000, 0.50},
  337. {0.000, 0.00},
  338. {0.125, 0.50},
  339. {0.250, 0.50},
  340. {0.375, 0.50},
  341. {0.500, 0.75},
  342. {0.625, 0.50},
  343. {0.750, 0.25},
  344. {0.875, 0.50},
  345. };
  346. int testCount = sizeof(testList)/sizeof((testList)[0]);
  347. int i;
  348. TextureMap tm = TextureMap(CYLINDRICAL_MAP, nullptr);
  349. for(i = 0; i < testCount; i++)
  350. {
  351. double u, v;
  352. tm.cylindricalMap(testList[i], u, v);
  353. ASSERT_TRUE(double_equal(u, testResults[i][0]));
  354. ASSERT_TRUE(double_equal(v, testResults[i][1]));
  355. }
  356. }