texturemap.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /*
  2. * DoRayMe - a quick and dirty Raytracer
  3. * Texture Map header
  4. *
  5. * Created by Manoël Trapier
  6. * Copyright (c) 2020 986-Studio.
  7. *
  8. */
  9. #ifndef DORAYME_TEXTUREMAP_H
  10. #define DORAYME_TEXTUREMAP_H
  11. #include <math.h>
  12. #include <tuple.h>
  13. #include <uv_pattern.h>
  14. #include <colour.h>
  15. enum TextureMapType
  16. {
  17. SPHERICAL_MAP,
  18. PLANAR_MAP,
  19. CYLINDRICAL_MAP,
  20. };
  21. class TextureMap : public Pattern
  22. {
  23. private:
  24. TextureMapType type;
  25. UVPattern *pattern;
  26. public:
  27. TextureMap(TextureMapType type, UVPattern *pattern) : Pattern(Colour(0, 0, 0), Colour(0, 0, 0)),
  28. type(type), pattern(pattern) { };
  29. static void sphericalMap(Tuple point, double &u, double &v) {
  30. /* First compute the azimuthal angle
  31. * -π < theta <= π
  32. * angle increases clockwise as viewed from above,
  33. * which is opposite of what we want, but we'll fix it later.
  34. */
  35. double theta = atan2(point.x, point.z);
  36. /* vec is the vector pointing from the sphere's origin (the world origin)
  37. * to the point, which will also happen to be exactly equal to the sphere's
  38. * radius.
  39. */
  40. Tuple vec = Vector(point.x, point.y, point.z);
  41. double radius = vec.magnitude();
  42. /* Let's compute the polar angle
  43. * 0 <= phi <= π
  44. */
  45. double phi = acos(point.y / radius);
  46. /* -0.5 < raw_u <= 0.5 */
  47. double raw_u = theta / (2 * M_PI);
  48. /* 0 <= u < 1
  49. * here's also where we fix the direction of u. Subtract it from 1,
  50. * so that it increases counterclockwise as viewed from above.
  51. */
  52. u = 1 - (raw_u + 0.5);
  53. /* We want v to be 0 at the south pole of the sphere,
  54. * and 1 at the north pole, so we have to "flip it over"
  55. * by subtracting it from 1.
  56. */
  57. v = 1 - phi / M_PI;
  58. }
  59. static void planarMap(Tuple point, double &u, double &v) {
  60. u = modulo(point.x, 1.0);
  61. v = modulo(point.z, 1.0);
  62. }
  63. static void cylindricalMap(Tuple point, double &u, double &v) {
  64. /* Let's get the azimuthal angle, same as with the spherical mapping */
  65. double theta = atan2(point.x , point.z);
  66. double raw_u = theta / (2 * M_PI);
  67. u = 1 - (raw_u + 0.5);
  68. v = modulo(point.y, 1.0);
  69. }
  70. Colour patternAt(Tuple point)
  71. {
  72. double u,v;
  73. switch(this->type)
  74. {
  75. default:
  76. case SPHERICAL_MAP:
  77. this->sphericalMap(point, u, v);
  78. break;
  79. case PLANAR_MAP:
  80. this->planarMap(point, u, v);
  81. break;
  82. case CYLINDRICAL_MAP:
  83. this->cylindricalMap(point, u, v);
  84. break;
  85. }
  86. return this->pattern->uvPatternAt(u, v);
  87. }
  88. void dumpMe(FILE *fp) {
  89. fprintf(fp, "\"Type\": \"TextureMap\",\n");
  90. Pattern::dumpMe(fp);
  91. }
  92. };
  93. #endif /* DORAYME_TEXTUREMAP_H */