christmasball_render.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /*
  2. * DoRayMe - a quick and dirty Raytracer
  3. * Bonus scene - Christmas ball
  4. *
  5. * Created by Manoël Trapier
  6. * Copyright (c) 2020 986-Studio.
  7. *
  8. */
  9. #include <world.h>
  10. #include <light.h>
  11. #include <sphere.h>
  12. #include <plane.h>
  13. #include <cube.h>
  14. #include <cylinder.h>
  15. #include <material.h>
  16. #include <colour.h>
  17. #include <canvas.h>
  18. #include <camera.h>
  19. #include <group.h>
  20. #include <cone.h>
  21. #include <pattern.h>
  22. #include <strippattern.h>
  23. #include <gradientpattern.h>
  24. #include <checkerspattern.h>
  25. #include <ringpattern.h>
  26. #include <transformation.h>
  27. #include <triangle.h>
  28. #include <stdio.h>
  29. Shape *fir_branch()
  30. {
  31. Group *ret = new Group();
  32. double length = 2;
  33. double radius = 0.025;
  34. int segments = 20;
  35. int perSegment = 24;
  36. Cylinder *branch = new Cylinder();
  37. branch->minCap = 0;
  38. branch->maxCap = length;
  39. branch->isClosed = true;
  40. branch->setTransform(scaling(radius, 1, radius));
  41. branch->material.colour = Colour(0.5, 0.35, 0.26);
  42. branch->material.ambient = 0.2;
  43. branch->material.specular = 0;
  44. branch->material.diffuse = 0.6;
  45. branch->materialSet = true;
  46. ret->addObject(branch);
  47. double seq_size = length / (segments - 1);
  48. double theta = 2.1 * M_PI / perSegment;
  49. double maxLength = 20 * radius;
  50. int y, i;
  51. Triangle *needle;
  52. for(y = 0; y < segments; y++)
  53. {
  54. Group *subGroup = new Group();
  55. for(i = 0; i < perSegment; i++)
  56. {
  57. /* Each needle is a triangle */
  58. /* yBase is the y coordinate of the base of the triangle */
  59. double yBase = seq_size * y + frand() * seq_size;
  60. /* yTipe is the y coordinate of the tip of the triangle */
  61. double yTip = yBase - frand() * seq_size;
  62. /* yAndle is the angle (in radians) that the need shold be rotated
  63. * around the branch */
  64. double yAngle = i * theta + frand() * theta;
  65. /* How long is the needle? */
  66. double needleLenght = maxLength / 2 * (1 + frand());
  67. /* How much is the needle offset fomr the center of the branch? */
  68. double ofs = radius / 2;
  69. Point p1 = Point(ofs, yBase, ofs);
  70. Point p2 = Point(-ofs, yBase, ofs);
  71. Point p3 = Point(0, yTip, needleLenght);
  72. needle = new Triangle(p1, p2, p3);
  73. needle->setTransform(rotationY(yAngle));
  74. needle->material.colour = Colour(0.26, 0.36, 0.16);
  75. needle->material.specular = 0.1;
  76. needle->materialSet = true;
  77. subGroup->addObject(needle);
  78. }
  79. ret->addObject(subGroup);
  80. }
  81. return ret;
  82. }
  83. int main()
  84. {
  85. World w = World();
  86. printf("Preparing scene...\n");
  87. /* Add lights */
  88. Light light1 = Light(POINT_LIGHT, Point(-10, 10, -10), Colour(0.6, 0.6, 0.6));
  89. w.addLight(&light1);
  90. Sphere light1Sphere = Sphere();
  91. light1Sphere.dropShadow = false;
  92. light1Sphere.setTransform(translation(-10, 10, -10) * scaling(1.5, 1.5, 1.5));
  93. light1Sphere.material.colour = Colour(1, 1, 1);
  94. light1Sphere.material.ambient = 0.6;
  95. light1Sphere.material.diffuse = 0;
  96. light1Sphere.material.specular = 0;
  97. light1Sphere.materialSet = true;
  98. w.addObject(&light1Sphere);
  99. Light light2 = Light(POINT_LIGHT, Point(10, 10, -10), Colour(0.6, 0.6, 0.6));
  100. w.addLight(&light2);
  101. Sphere light2Sphere = Sphere();
  102. light2Sphere.dropShadow = false;
  103. light2Sphere.setTransform(translation(10, 10, -10) * scaling(1.5, 1.5, 1.5));
  104. light2Sphere.material.colour = Colour(1, 1, 1);
  105. light2Sphere.material.ambient = 0.6;
  106. light2Sphere.material.diffuse = 0;
  107. light2Sphere.material.specular = 0;
  108. light2Sphere.materialSet = true;
  109. w.addObject(&light2Sphere);
  110. Light light3 = Light(POINT_LIGHT, Point(-2, 1, -6), Colour(0.2, 0.1, 0.1));
  111. w.addLight(&light3);
  112. Sphere light3Sphere = Sphere();
  113. light3Sphere.dropShadow = false;
  114. light3Sphere.setTransform(translation(-2, 1, -6) * scaling(.4, .4, .4));
  115. light3Sphere.material.colour = Colour(1, 0.5, 0.5);
  116. light3Sphere.material.ambient = 0.6;
  117. light3Sphere.material.diffuse = 0;
  118. light3Sphere.material.specular = 0;
  119. light3Sphere.materialSet = true;
  120. w.addObject(&light3Sphere);
  121. Light light4 = Light(POINT_LIGHT, Point(-1, -2, -6), Colour(0.1, 0.2, 0.1));
  122. w.addLight(&light4);
  123. Sphere light4Sphere = Sphere();
  124. light4Sphere.dropShadow = false;
  125. light4Sphere.setTransform(translation(-1, -2, -6) * scaling(.4, .4, .4));
  126. light4Sphere.material.colour = Colour(0.5, 1, 0.5);
  127. light4Sphere.material.ambient = 0.6;
  128. light4Sphere.material.diffuse = 0;
  129. light4Sphere.material.specular = 0;
  130. light4Sphere.materialSet = true;
  131. w.addObject(&light4Sphere);
  132. Light light5 = Light(POINT_LIGHT, Point(3, -1, -6), Colour(0.2, 0.2, 0.2));
  133. w.addLight(&light5);
  134. Sphere light5Sphere = Sphere();
  135. light5Sphere.dropShadow = false;
  136. light5Sphere.setTransform(translation(3, -1, -6) * scaling(0.5, 0.5, 0.5));
  137. light5Sphere.material.colour = Colour(1, 1, 1);
  138. light5Sphere.material.ambient = 0.6;
  139. light5Sphere.material.diffuse = 0;
  140. light5Sphere.material.specular = 0;
  141. light5Sphere.materialSet = true;
  142. w.addObject(&light5Sphere);
  143. /* ----------------------------- */
  144. Sphere theBall = Sphere();
  145. theBall.material.colour = Colour(1, 0.25, 0.25);
  146. theBall.material.ambient = 0;
  147. theBall.material.specular = 0;
  148. theBall.material.diffuse = 0.5;
  149. theBall.material.reflective = 0.5;
  150. theBall.materialSet = true;
  151. w.addObject(&theBall);
  152. Cylinder crown = Cylinder();
  153. crown.minCap = 0;
  154. crown.maxCap = 1;
  155. crown.setTransform(rotationZ(-0.1) * translation(0, 0.9, 0) * scaling(0.2, 0.3, 0.2));
  156. crown.material.pattern = new CheckersPattern(Colour(1, 1, 1), Colour(0.94, 0.94, 0.94));
  157. crown.material.pattern->setTransform(scaling(0.2, 0.2, 0.2));
  158. crown.material.ambient = 0.02;
  159. crown.material.diffuse = 0.7;
  160. crown.material.specular = 0.8;
  161. crown.material.shininess = 20;
  162. crown.material.reflective = 0.05;
  163. crown.materialSet = true;
  164. w.addObject(&crown);
  165. /* ----------------------------- */
  166. Shape *s;
  167. s = fir_branch();
  168. s->setTransform(translation(-1, -1, 0) * rotationY(0.349) * rotationX(-1.5708) * translation(0, -0.5, 0));
  169. w.addObject(s);
  170. s = fir_branch();
  171. s->setTransform(translation(-1, 1, 0) * rotationY(0.349) * rotationX(-1.5708) * translation(0, -0.5, 0));
  172. w.addObject(s);
  173. s = fir_branch();
  174. s->setTransform(translation(1, -1, 0) * rotationY(-0.349) * rotationX(-1.5708) * translation(0, -0.5, 0));
  175. w.addObject(s);
  176. s = fir_branch();
  177. s->setTransform(translation(1, 1, 0) * rotationY(-0.349) * rotationX(-1.5708) * translation(0, -0.5, 0));
  178. w.addObject(s);
  179. s = fir_branch();
  180. s->setTransform(translation(0.2, -1.25, 0) * rotationY(-0.349) * rotationX(-1.5708) * translation(0, -0.5, 0));
  181. w.addObject(s);
  182. s = fir_branch();
  183. s->setTransform(translation(-0.2, -1.25, 0) * rotationY(0.349) * rotationX(-1.5708) * translation(0, -0.5, 0));
  184. w.addObject(s);
  185. s = fir_branch();
  186. s->setTransform(translation(-1.2, 0.1, 0) * rotationY(0.5236) * rotationX(0.087) * rotationX(-1.5708) * translation(0, -0.5, 0));
  187. w.addObject(s);
  188. s = fir_branch();
  189. s->setTransform(translation(-1.2, -0.35, 0.5) * rotationY(0.5236) * rotationX(-0.1745) * rotationX(-1.5708) * translation(0, -0.5, 0));
  190. w.addObject(s);
  191. s = fir_branch();
  192. s->setTransform(translation(-0.2, 1.5, 0.25) * rotationY(-0.5236) * rotationX(0.087) * rotationX(-1.5708) * translation(0, -0.5, 0));
  193. w.addObject(s);
  194. s = fir_branch();
  195. s->setTransform(translation(1.3, 0.4, 0) * rotationY(-0.5236) * rotationX(-0.087) * rotationX(-1.5708) * translation(0, -0.5, 0));
  196. w.addObject(s);
  197. s = fir_branch();
  198. s->setTransform(translation(1.5, -0.5, 0) * rotationY(-0.1754) * rotationX(0.087) * rotationX(-1.5708) * translation(0, -0.5, 0));
  199. w.addObject(s);
  200. /* ----------------------------- */
  201. /*
  202. FILE *fpOut = fopen("christmas_worlddump.json", "wt");
  203. if (fpOut)
  204. {
  205. w.dumpMe(fpOut);
  206. fclose(fpOut);
  207. }
  208. */
  209. /* ----------------------------- */
  210. /* Set the camera */
  211. Camera camera = Camera(40, 30, 1.047);
  212. camera.setTransform(viewTransform(Point(0, 0, -4),
  213. Point(0, 0, 0),
  214. Vector(0, 1, 0)));
  215. printf("And render!\n");
  216. /* Now render it */
  217. Canvas image = camera.render(w, 20);
  218. image.SaveAsPNG("christmasball.png");
  219. return 0;
  220. }