shape_test.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*
  2. * DoRayMe - a quick and dirty Raytracer
  3. * Shape unit tests
  4. *
  5. * Created by Manoël Trapier
  6. * Copyright (c) 2020 986-Studio.
  7. *
  8. */
  9. #include <shape.h>
  10. #include <testshape.h>
  11. #include <matrix.h>
  12. #include <group.h>
  13. #include <sphere.h>
  14. #include <transformation.h>
  15. #include <gtest/gtest.h>
  16. TEST(ShapeTest, The_default_transformation)
  17. {
  18. TestShape s = TestShape();
  19. ASSERT_EQ(s.transformMatrix, Matrix4().identity());
  20. }
  21. TEST(ShapeTest, Assigning_a_transformation)
  22. {
  23. TestShape s = TestShape();
  24. s.setTransform(translation(2, 3, 4));
  25. ASSERT_EQ(s.transformMatrix, translation(2, 3, 4));
  26. }
  27. TEST(ShapeTest, The_default_material)
  28. {
  29. TestShape s = TestShape();
  30. ASSERT_EQ(s.material, Material());
  31. }
  32. TEST(ShapeTest, Assigning_a_material)
  33. {
  34. TestShape s = TestShape();
  35. Material m = Material();
  36. m.ambient = 1;
  37. s.material = m;
  38. ASSERT_EQ(s.material, m);
  39. }
  40. TEST(ShapeTest, Intersecting_a_scaled_shape_with_a_ray)
  41. {
  42. Ray r = Ray(Point(0, 0, -5), Vector(0, 0, 1));
  43. TestShape s = TestShape();
  44. s.setTransform(scaling(2, 2, 2));
  45. Intersect xs; s.intersect(r, xs);
  46. ASSERT_EQ(s.localRay.origin, Point(0, 0, -2.5));
  47. ASSERT_EQ(s.localRay.direction, Vector(0, 0, 0.5));
  48. }
  49. TEST(ShapeTest, Intersecting_a_translated_shape_with_a_ray)
  50. {
  51. Ray r = Ray(Point(0, 0, -5), Vector(0, 0, 1));
  52. TestShape s = TestShape();
  53. s.setTransform(translation(5, 0, 0));
  54. Intersect xs; s.intersect(r, xs);
  55. ASSERT_EQ(s.localRay.origin, Point(-5, 0, -5));
  56. ASSERT_EQ(s.localRay.direction, Vector(0, 0, 1));
  57. }
  58. TEST(ShapeTest, Computing_the_normal_on_a_translated_shape)
  59. {
  60. TestShape s = TestShape();
  61. s.setTransform(translation(0, 1, 0));
  62. Tuple n = s.normalAt(Point(0, 1.70711, -0.70711));
  63. /* Temporary lower the precision */
  64. set_equal_precision(0.00001);
  65. ASSERT_EQ(n, Vector(0, 0.70711, -0.70711));
  66. set_equal_precision(FLT_EPSILON);
  67. }
  68. TEST(ShapeTest, Computing_the_normal_on_a_tranformed_shape)
  69. {
  70. TestShape s = TestShape();
  71. s.setTransform(scaling(1, 0.5, 1) * rotationZ(M_PI / 5));
  72. Tuple n = s.normalAt(Point(0, sqrt(2)/2, -sqrt(2)/2));
  73. /* Temporary lower the precision */
  74. set_equal_precision(0.00001);
  75. ASSERT_EQ(n, Vector(0, 0.97014, -0.24254));
  76. set_equal_precision(FLT_EPSILON);
  77. }
  78. TEST(ShapeTest, A_shape_has_a_parent_attribute)
  79. {
  80. TestShape s = TestShape();
  81. ASSERT_EQ(s.parent, nullptr);
  82. }
  83. TEST(ShapeTest, Converting_a_point_from_world_to_object_space)
  84. {
  85. Group g1 = Group();
  86. g1.setTransform(rotationY(M_PI / 2));
  87. Group g2 = Group();
  88. g2.setTransform(scaling(2, 2, 2));
  89. g1.addObject(&g2);
  90. Sphere s = Sphere();
  91. s.setTransform(translation(5, 0, 0));
  92. g2.addObject(&s);
  93. Tuple p = s.worldToObject(Point(-2, 0, -10));
  94. ASSERT_EQ(p, Point(0, 0, -1));
  95. }
  96. TEST(ShapeTest, Converting_a_normal_form_object_to_world_space)
  97. {
  98. Group g1 = Group();
  99. g1.setTransform(rotationY(M_PI / 2));
  100. Group g2 = Group();
  101. g2.setTransform(scaling(1, 2, 3));
  102. g1.addObject(&g2);
  103. Sphere s = Sphere();
  104. s.setTransform(translation(5, 0, 0));
  105. g2.addObject(&s);
  106. Tuple p = s.normalToWorld(Vector(sqrt(3)/3, sqrt(3)/3, sqrt(3)/3));
  107. /* Temporary lower the precision */
  108. set_equal_precision(0.0001);
  109. ASSERT_EQ(p, Vector(0.2857, 0.4286, -0.8571));
  110. set_equal_precision(FLT_EPSILON);
  111. }
  112. TEST(ShapeTest, Finding_the_normal_on_a_child_object)
  113. {
  114. Group g1 = Group();
  115. g1.setTransform(rotationY(M_PI / 2));
  116. Group g2 = Group();
  117. g2.setTransform(scaling(1, 2, 3));
  118. g1.addObject(&g2);
  119. Sphere s = Sphere();
  120. s.setTransform(translation(5, 0, 0));
  121. g2.addObject(&s);
  122. Tuple p = s.normalAt(Point(1.7321, 1.1547, -5.5774));
  123. /* Temporary lower the precision */
  124. set_equal_precision(0.0001);
  125. ASSERT_EQ(p, Vector(0.2857, 0.4286, -0.8571));
  126. set_equal_precision(FLT_EPSILON);
  127. }
  128. TEST(ShapeTest, Test_the_bouding_box_of_the_test_shape)
  129. {
  130. TestShape t = TestShape();
  131. BoundingBox b = BoundingBox(Point(-1, -1, -1), Point(1, 1, 1));
  132. BoundingBox res = t.getBounds();
  133. ASSERT_EQ(res.min, b.min);
  134. ASSERT_EQ(res.max, b.max);
  135. }
  136. TEST(ShapeTest, Test_the_bouding_box_of_the_scaled_shape)
  137. {
  138. TestShape t = TestShape();
  139. t.setTransform(scaling(3, 3, 3));
  140. BoundingBox b = BoundingBox(Point(-3, -3, -3), Point(3, 3, 3));
  141. BoundingBox res = t.getBounds();
  142. ASSERT_EQ(res.min, b.min);
  143. ASSERT_EQ(res.max, b.max);
  144. }
  145. TEST(ShapeTest, Test_the_bouding_box_of_the_translated_shape)
  146. {
  147. TestShape t = TestShape();
  148. t.setTransform(translation(10, 0, 0));
  149. BoundingBox b = BoundingBox(Point(9, -1, -1), Point(11, 1, 1));
  150. BoundingBox res = t.getBounds();
  151. ASSERT_EQ(res.min, b.min);
  152. ASSERT_EQ(res.max, b.max);
  153. }
  154. TEST(ShapeTest, A_lock_shape_can_t_have_transformation_changed)
  155. {
  156. TestShape t = TestShape();
  157. t.setTransform(translation(10, 0, 0));
  158. BoundingBox b = BoundingBox(Point(9, -1, -1), Point(11, 1, 1));
  159. BoundingBox res = t.getBounds();
  160. ASSERT_EQ(res.min, b.min);
  161. ASSERT_EQ(res.max, b.max);
  162. t.lock();
  163. t.setTransform(translation(-10, -10,-10));
  164. res = t.getBounds();
  165. ASSERT_EQ(res.min, b.min);
  166. ASSERT_EQ(res.max, b.max);
  167. }