Browse Source

Add cylindrical mapping!

Godzil 4 years ago
parent
commit
7209244f48

+ 4 - 1
README.md

@@ -87,4 +87,7 @@ Spherical mapping:
 ![Spherical mapping](output/uvmap_checkeredsphere.png)
 
 Planar mapping:
-![Planar mapping](output/uvmap_checkeredplane.png)
+![Planar mapping](output/uvmap_checkeredplane.png)
+
+Cylindrical mapping:
+![Cylindrical mapping](output/uvmap_checkeredcylinder.png)

BIN
output/uvmap_checkeredcylinder.png


+ 15 - 2
source/pattern/texturemap.h

@@ -67,8 +67,17 @@ public:
     }
 
     static void planarMap(Tuple point, double &u, double &v) {
-        u = fmod(point.x, 1);
-        v = fmod(point.z, 1);
+        u = modulo(point.x, 1.0);
+        v = modulo(point.z, 1.0);
+    }
+
+    static void cylindricalMap(Tuple point, double &u, double &v) {
+        /* Let's get the azimuthal angle, same as with the spherical mapping */
+        double theta = atan2(point.x , point.z);
+        double raw_u = theta / (2 * M_PI);
+
+        u = 1 - (raw_u + 0.5);
+        v = modulo(point.y, 1.0);
     }
 
     Colour patternAt(Tuple point)
@@ -83,6 +92,10 @@ public:
         case PLANAR_MAP:
             this->planarMap(point, u, v);
             break;
+
+        case CYLINDRICAL_MAP:
+            this->cylindricalMap(point, u, v);
+            break;
         }
 
         return this->pattern->uvPatternAt(u, v);

+ 4 - 0
tests/CMakeLists.txt

@@ -80,6 +80,9 @@ target_sources(uvmap_checkeredsphere PRIVATE uvmap_checkeredsphere.cpp)
 add_executable(uvmap_checkeredplane)
 target_sources(uvmap_checkeredplane PRIVATE uvmap_checkeredplane.cpp)
 
+add_executable(uvmap_checkeredcylinder)
+target_sources(uvmap_checkeredcylinder PRIVATE uvmap_checkeredcylinder.cpp)
+
 add_test(NAME Chapter05_Test COMMAND $<TARGET_FILE:ch5_test>)
 add_test(NAME Chapter06_Test COMMAND $<TARGET_FILE:ch6_test>)
 add_test(NAME Chapter07_Test COMMAND $<TARGET_FILE:ch7_test>)
@@ -95,6 +98,7 @@ add_test(NAME Chapter14_Test COMMAND $<TARGET_FILE:ch14_test>)
 add_test(NAME AreaLight_Test COMMAND $<TARGET_FILE:arealight_test>)
 add_test(NAME UVMap_CheckeredSphere COMMAND $<TARGET_FILE:uvmap_checkeredsphere>)
 add_test(NAME UVMap_CheckeredPlane COMMAND $<TARGET_FILE:uvmap_checkeredplane>)
+add_test(NAME UVMap_CheckeredCylinder COMMAND $<TARGET_FILE:uvmap_checkeredcylinder>)
 add_test(NAME Test_Rendering COMMAND $<TARGET_FILE:test_render>)
 add_test(NAME Triangle_RenderTest COMMAND $<TARGET_FILE:triangle_rendertest>)
 add_test(NAME ChristmasBall_Rendering COMMAND $<TARGET_FILE:christmasball_render>)

+ 42 - 0
tests/pattern_test.cpp

@@ -387,4 +387,46 @@ TEST(PatternTest, Using_a_planar_mapping_on_a_3d_point)
         ASSERT_TRUE(double_equal(u, testResults[i][0]));
         ASSERT_TRUE(double_equal(v, testResults[i][1]));
     }
+}
+
+TEST(PatternTest, Using_a_cylindrical_mapping_on_a_3d_point)
+{
+    Point testList[] = {
+            Point( 0.00000,  0.00, -1.00000),
+            Point( 0.00000,  0.50, -1.00000),
+            Point( 0.00000,  1.00, -1.00000),
+            Point( 0.70711,  0.50, -0.70711),
+            Point( 1.00000,  0.50, -0.00000),
+            Point( 0.70711,  0.50,  0.70711),
+            Point( 0.00000, -0.25,  1.00000),
+            Point(-0.70711,  0.50,  0.70711),
+            Point(-1.00000,  1.25,  0.00000),
+            Point(-0.70711,  0.50, -0.70711),
+    };
+
+    double testResults[][2] {
+            {0.000, 0.00},
+            {0.000, 0.50},
+            {0.000, 0.00},
+            {0.125, 0.50},
+            {0.250, 0.50},
+            {0.375, 0.50},
+            {0.500, 0.75},
+            {0.625, 0.50},
+            {0.750, 0.25},
+            {0.875, 0.50},
+    };
+
+    int testCount = sizeof(testList)/sizeof((testList)[0]);
+    int i;
+
+    TextureMap tm = TextureMap(CYLINDRICAL_MAP, nullptr);
+
+    for(i = 0; i < testCount; i++)
+    {
+        double u, v;
+        tm.cylindricalMap(testList[i], u, v);
+        ASSERT_TRUE(double_equal(u, testResults[i][0]));
+        ASSERT_TRUE(double_equal(v, testResults[i][1]));
+    }
 }

+ 58 - 0
tests/uvmap_checkeredcylinder.cpp

@@ -0,0 +1,58 @@
+/*
+ *  DoRayMe - a quick and dirty Raytracer
+ *  Render test for chapter 10
+ *
+ *  Created by Manoël Trapier
+ *  Copyright (c) 2020 986-Studio.
+ *
+ */
+#include <world.h>
+#include <light.h>
+#include <sphere.h>
+#include <plane.h>
+#include <cylinder.h>
+#include <material.h>
+#include <colour.h>
+#include <canvas.h>
+#include <camera.h>
+
+#include <pattern.h>
+#include <texturemap.h>
+#include <uv_checkers.h>
+
+#include <transformation.h>
+
+int main()
+{
+    World w = World();
+
+    Light light = Light(POINT_LIGHT, Point(-10, 10, -10), Colour(1, 1, 1));
+    w.addLight(&light);
+
+    Cylinder sp = Cylinder();
+    sp.minCap = 0;
+    sp.maxCap = 1;
+    sp.setTransform(scaling(1, 3.1415, 1) * translation(0, -0.5, 0));
+    UVCheckers checkers = UVCheckers(16, 8, Colour(0, 0.5, 0), Colour(1, 1, 1));
+    TextureMap tm = TextureMap(CYLINDRICAL_MAP, &checkers);
+    sp.material.pattern = &tm;
+    sp.material.ambient = 0.1;
+    sp.material.specular = 0.6;
+    sp.material.shininess = 15;
+    sp.material.diffuse = 0.8;
+
+    w.addObject(&sp);
+
+    /* Set the camera */
+    Camera camera = Camera(400, 400, 0.5);
+    camera.setTransform(viewTransform(Point(0, 0, -10),
+                                      Point(0, 0, 0),
+                                      Vector(0, 1, 0)));
+
+    /* Now render it */
+    Canvas image = camera.render(w);
+
+    image.SaveAsPNG("uvmap_checkeredcylinder.png");
+
+    return 0;
+}