pattern_test.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  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. #ifdef ENABLE_LUA_SUPPORT
  21. extern "C" {
  22. #include <lua.h>
  23. #include <lauxlib.h>
  24. #include <lualib.h>
  25. }
  26. #include <luapattern.h>
  27. #endif
  28. Colour black = Colour(0, 0, 0);
  29. Colour white = Colour(1, 1, 1);
  30. TEST(PatternTest, Creating_a_stripe_pattern)
  31. {
  32. StripPattern p = StripPattern(white, black);
  33. ASSERT_EQ(p.a, white);
  34. ASSERT_EQ(p.b, black);
  35. }
  36. TEST(PatternTest, A_strip_pattern_is_constant_in_y)
  37. {
  38. StripPattern p = StripPattern(white, black);
  39. ASSERT_EQ(p.patternAt(Point(0, 0, 0)), white);
  40. ASSERT_EQ(p.patternAt(Point(0, 1, 0)), white);
  41. ASSERT_EQ(p.patternAt(Point(0, 2, 0)), white);
  42. }
  43. TEST(PatternTest, A_strip_pattern_is_constant_in_z)
  44. {
  45. StripPattern p = StripPattern(white, black);
  46. ASSERT_EQ(p.patternAt(Point(0, 0, 0)), white);
  47. ASSERT_EQ(p.patternAt(Point(0, 0, 1)), white);
  48. ASSERT_EQ(p.patternAt(Point(0, 0, 2)), white);
  49. }
  50. TEST(PatternTest, A_strip_pattern_alternate_in_x)
  51. {
  52. StripPattern p = StripPattern(white, black);
  53. ASSERT_EQ(p.patternAt(Point(0, 0, 0)), white);
  54. ASSERT_EQ(p.patternAt(Point(0.9, 0, 0)), white);
  55. ASSERT_EQ(p.patternAt(Point(1, 0, 0)), black);
  56. ASSERT_EQ(p.patternAt(Point(-0.1, 0, 0)), black);
  57. ASSERT_EQ(p.patternAt(Point(-1, 0, 0)), black);
  58. ASSERT_EQ(p.patternAt(Point(-1.1, 0, 0)), white);
  59. }
  60. TEST(PatternTest, Lightning_with_a_pattern_applied)
  61. {
  62. Sphere s = Sphere();
  63. Material m;
  64. StripPattern p = StripPattern(white, black);
  65. m.pattern = &p;
  66. m.ambient = 1;
  67. m.diffuse = 0;
  68. m.specular = 0;
  69. Tuple eyev = Vector(0, 0, -1);
  70. Tuple normalv = Vector(0, 0, -1);
  71. Light light = Light(POINT_LIGHT, Point(0, 0, -10), Colour(1, 1, 1));
  72. Colour c1 = m.lighting(light, Point(0, 9, 0), eyev, normalv, &s, false);
  73. Colour c2 = m.lighting(light, Point(1, 1, 0), eyev, normalv, &s, false);
  74. ASSERT_EQ(c1, Colour(1, 1, 1));
  75. ASSERT_EQ(c2, Colour(0, 0, 0));
  76. }
  77. TEST(PatternTest, Stripe_with_an_object_transformation)
  78. {
  79. Sphere s = Sphere();
  80. s.setTransform(scaling(2, 2, 2));
  81. StripPattern pattern = StripPattern(white, black);
  82. Colour c = pattern.patternAtObject(&s, Point(1.5, 0, 0));
  83. ASSERT_EQ(c, white);
  84. }
  85. TEST(PatternTest, Stripe_with_a_pattern_transformation)
  86. {
  87. Sphere s = Sphere();
  88. StripPattern pattern = StripPattern(white, black);
  89. pattern.setTransform(scaling(2, 2, 2));
  90. Colour c = pattern.patternAtObject(&s, Point(1.5, 0, 0));
  91. ASSERT_EQ(c, white);
  92. }
  93. TEST(PatternTest, Stripe_with_both_an_object_and_a_pattern_transformation)
  94. {
  95. Sphere s = Sphere();
  96. s.setTransform(scaling(2, 2, 2));
  97. StripPattern pattern = StripPattern(white, black);
  98. pattern.setTransform(translation(0.5, 0, 0));
  99. Colour c = pattern.patternAtObject(&s, Point(2.5, 0, 0));
  100. ASSERT_EQ(c, white);
  101. }
  102. TEST(PatternTest, The_default_pattern_transformation)
  103. {
  104. TestPattern pattern = TestPattern();
  105. ASSERT_EQ(pattern.transformMatrix, Matrix4().identity());
  106. }
  107. TEST(PatternTest, Assigning_a_transformation)
  108. {
  109. TestPattern pattern = TestPattern();
  110. pattern.setTransform(translation(1, 2, 3));
  111. ASSERT_EQ(pattern.transformMatrix, translation(1, 2, 3));
  112. }
  113. TEST(PatternTest, A_pattern_with_an_object_transformation)
  114. {
  115. Sphere s = Sphere();
  116. s.setTransform(scaling(2, 2, 2));
  117. TestPattern pattern = TestPattern();
  118. Colour c = pattern.patternAtObject(&s, Point(2, 3, 4));
  119. ASSERT_EQ(c, Colour(1, 1.5, 2));
  120. }
  121. TEST(PatternTest, A_pattern_with_a_pattern_transformation)
  122. {
  123. Sphere s = Sphere();
  124. TestPattern pattern = TestPattern();
  125. pattern.setTransform(scaling(2, 2, 2));
  126. Colour c = pattern.patternAtObject(&s, Point(2, 3, 4));
  127. ASSERT_EQ(c, Colour(1, 1.5, 2));
  128. }
  129. TEST(PatternTest, A_pattern_with_an_object_and_a_pattern_transformation)
  130. {
  131. Sphere s = Sphere();
  132. s.setTransform(scaling(2, 2, 2));
  133. TestPattern pattern = TestPattern();
  134. pattern.setTransform(translation(0.5, 1, 1.5));
  135. Colour c = pattern.patternAtObject(&s, Point(2.5, 3, 3.5));
  136. ASSERT_EQ(c, Colour(0.75, 0.5, 0.25));
  137. }
  138. TEST(PatternTest, A_gradient_linearly_interpolates_betweens_colors)
  139. {
  140. GradientPattern pattern = GradientPattern(white, black);
  141. ASSERT_EQ(pattern.patternAt(Point(0.25, 0, 0)), Colour(0.75, 0.75, 0.75));
  142. ASSERT_EQ(pattern.patternAt(Point(0.5, 0, 0)), Colour(0.5, 0.5, 0.5));
  143. ASSERT_EQ(pattern.patternAt(Point(0.75, 0, 0)), Colour(0.25, 0.25, 0.25));
  144. }
  145. TEST(PatternTest, A_ring_should_extend_in_both_x_and_z)
  146. {
  147. RingPattern pattern = RingPattern(white, black);
  148. ASSERT_EQ(pattern.patternAt(Point(0, 0, 0)), white);
  149. ASSERT_EQ(pattern.patternAt(Point(1, 0, 0)), black);
  150. ASSERT_EQ(pattern.patternAt(Point(0, 0, 1)), black);
  151. /* 0.708 is just bit more than sqrt(2)/2 */
  152. ASSERT_EQ(pattern.patternAt(Point(0.708, 0, 0.708)), black);
  153. }
  154. TEST(PatternTest, Checkers_should_repeat_in_x)
  155. {
  156. CheckersPattern pattern = CheckersPattern(white, black);
  157. ASSERT_EQ(pattern.patternAt(Point(0, 0, 0)), white);
  158. ASSERT_EQ(pattern.patternAt(Point(0.99, 0, 0)), white);
  159. ASSERT_EQ(pattern.patternAt(Point(1.01, 0, 0)), black);
  160. }
  161. TEST(PatternTest, Checkers_should_repeat_in_y)
  162. {
  163. CheckersPattern pattern = CheckersPattern(white, black);
  164. ASSERT_EQ(pattern.patternAt(Point(0, 0, 0)), white);
  165. ASSERT_EQ(pattern.patternAt(Point(0, 0.99, 0)), white);
  166. ASSERT_EQ(pattern.patternAt(Point(0, 1.01, 0)), black);
  167. }
  168. TEST(PatternTest, Checkers_should_repeat_in_z)
  169. {
  170. CheckersPattern pattern = CheckersPattern(white, black);
  171. ASSERT_EQ(pattern.patternAt(Point(0, 0, 0)), white);
  172. ASSERT_EQ(pattern.patternAt(Point(0, 0, 0.99)), white);
  173. ASSERT_EQ(pattern.patternAt(Point(0, 0, 1.01)), black);
  174. }
  175. #ifdef ENABLE_LUA_SUPPORT
  176. TEST(PatternTest, Simple_test_of_a_lua_pattern)
  177. {
  178. int error;
  179. LuaPattern pattern = LuaPattern(white, black);
  180. lua_State *L = luaL_newstate();
  181. luaL_openlibs(L);
  182. pattern.setLua(L);
  183. pattern.setLuaFunctionName("pat");
  184. error = luaL_loadstring(L, "function pat(x, y, z, a, b)\n"
  185. " local v = math.floor(x) + math.floor(y) + math.floor(z)\n"
  186. " if (v % 2) == 0 then\n"
  187. " return a.r, a.g, a.b\n"
  188. " end\n"
  189. " return b.r, b.g, b.b\n"
  190. "end");
  191. if (error)
  192. {
  193. fprintf(stderr, "%s\n", lua_tostring(L, -1));
  194. lua_pop(L, 1); /* pop error message from the stack */
  195. }
  196. ASSERT_EQ(error, 0);
  197. error = lua_pcall(L, 0, 0, 0);
  198. if (error)
  199. {
  200. fprintf(stderr, "%s\n", lua_tostring(L, -1));
  201. lua_pop(L, 1); /* pop error message from the stack */
  202. }
  203. ASSERT_EQ(error, 0);
  204. ASSERT_EQ(pattern.patternAt(Point(0, 0, 0)), white);
  205. ASSERT_EQ(pattern.patternAt(Point(0, 0.99, 0)), white);
  206. ASSERT_EQ(pattern.patternAt(Point(0, 1.01, 0)), black);
  207. lua_close(L);
  208. }
  209. #endif