Continue working on Cube mapping
This commit is contained in:
@@ -19,6 +19,7 @@ enum TextureMapType
|
||||
SPHERICAL_MAP,
|
||||
PLANAR_MAP,
|
||||
CYLINDRICAL_MAP,
|
||||
CUBIC_MAP
|
||||
};
|
||||
|
||||
class TextureMap : public Pattern
|
||||
@@ -26,6 +27,7 @@ class TextureMap : public Pattern
|
||||
private:
|
||||
TextureMapType type;
|
||||
UVPattern *pattern;
|
||||
UVPattern *frontPat, *leftPat, *rightPat, *backPat, *upPat, *downPat;
|
||||
public:
|
||||
TextureMap(TextureMapType type, UVPattern *pattern) : Pattern(Colour(0, 0, 0), Colour(0, 0, 0)),
|
||||
type(type), pattern(pattern) { };
|
||||
@@ -80,25 +82,112 @@ public:
|
||||
v = modulo(point.y, 1.0);
|
||||
}
|
||||
|
||||
enum CubeFaces {
|
||||
CUBE_LEFT,
|
||||
CUBE_RIGHT,
|
||||
CUBE_FRONT,
|
||||
CUBE_BACK,
|
||||
CUBE_UP,
|
||||
CUBE_DOWN,
|
||||
};
|
||||
|
||||
static CubeFaces faceFromPoint(Tuple point) {
|
||||
double abs_x = fabs(point.x);
|
||||
double abs_y = fabs(point.y);
|
||||
double abs_z = fabs(point.z);
|
||||
|
||||
double coord = max3(abs_x, abs_y, abs_z);
|
||||
|
||||
if (coord == point.x) { return CUBE_RIGHT; }
|
||||
if (coord == -point.x) { return CUBE_LEFT; }
|
||||
if (coord == point.y) { return CUBE_UP; }
|
||||
if (coord == -point.y) { return CUBE_DOWN; }
|
||||
if (coord == point.z) { return CUBE_FRONT; }
|
||||
|
||||
return CUBE_BACK;
|
||||
}
|
||||
|
||||
static void cubeUBFront(Tuple point, double &u, double &v) {
|
||||
u = modulo(point.x + 1, 2.0) / 2.0;
|
||||
v = modulo(point.y + 1, 2.0) / 2.0;
|
||||
}
|
||||
|
||||
static void cubeUBBack(Tuple point, double &u, double &v) {
|
||||
u = modulo(1 - point.x, 2.0) / 2.0;
|
||||
v = modulo(point.y + 1, 2.0) / 2.0;
|
||||
}
|
||||
|
||||
static void cubeUBLeft(Tuple point, double &u, double &v) {
|
||||
u = modulo(point.z + 1, 2.0) / 2.0;
|
||||
v = modulo(point.y + 1, 2.0) / 2.0;
|
||||
}
|
||||
|
||||
static void cubeUBRight(Tuple point, double &u, double &v) {
|
||||
u = modulo(1 - point.z, 2.0) / 2.0;
|
||||
v = modulo(point.y + 1, 2.0) / 2.0;
|
||||
}
|
||||
|
||||
static void cubeUBUp(Tuple point, double &u, double &v) {
|
||||
u = modulo(point.x + 1, 2.0) / 2.0;
|
||||
v = modulo(1 - point.z, 2.0) / 2.0;
|
||||
}
|
||||
|
||||
static void cubeUBDown(Tuple point, double &u, double &v) {
|
||||
u = modulo(point.x + 1, 2.0) / 2.0;
|
||||
v = modulo(point.z + 1, 2.0) / 2.0;
|
||||
}
|
||||
|
||||
void setCubePattern(UVPattern *front, UVPattern *left, UVPattern *right,
|
||||
UVPattern *back, UVPattern *up, UVPattern *down)
|
||||
{
|
||||
this->frontPat = front;
|
||||
this->leftPat = left;
|
||||
this->rightPat = right;
|
||||
this->backPat = back;
|
||||
this->upPat = up;
|
||||
this->downPat = down;
|
||||
}
|
||||
|
||||
Colour patternAt(Tuple point)
|
||||
{
|
||||
double u,v;
|
||||
switch(this->type)
|
||||
if (this->type == CUBIC_MAP)
|
||||
{
|
||||
default:
|
||||
case SPHERICAL_MAP:
|
||||
this->sphericalMap(point, u, v);
|
||||
break;
|
||||
case PLANAR_MAP:
|
||||
this->planarMap(point, u, v);
|
||||
break;
|
||||
CubeFaces face = this->faceFromPoint(point);
|
||||
UVPattern *facePat;
|
||||
double u, v;
|
||||
switch(face)
|
||||
{
|
||||
default:
|
||||
case CUBE_LEFT: facePat = this->leftPat; this->cubeUBLeft(point, u, v); break;
|
||||
case CUBE_RIGHT: facePat = this->rightPat; this->cubeUBRight(point, u, v); break;
|
||||
case CUBE_FRONT: facePat = this->frontPat; this->cubeUBFront(point, u, v); break;
|
||||
case CUBE_BACK: facePat = this->backPat; this->cubeUBBack(point, u, v); break;
|
||||
case CUBE_UP: facePat = this->upPat; this->cubeUBUp(point, u, v); break;
|
||||
case CUBE_DOWN: facePat = this->downPat; this->cubeUBDown(point, u, v); break;
|
||||
}
|
||||
|
||||
case CYLINDRICAL_MAP:
|
||||
this->cylindricalMap(point, u, v);
|
||||
break;
|
||||
return facePat->uvPatternAt(u, v);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (this->type)
|
||||
{
|
||||
default:
|
||||
case SPHERICAL_MAP:
|
||||
this->sphericalMap(point, u, v);
|
||||
break;
|
||||
case PLANAR_MAP:
|
||||
this->planarMap(point, u, v);
|
||||
break;
|
||||
|
||||
return this->pattern->uvPatternAt(u, v);
|
||||
case CYLINDRICAL_MAP:
|
||||
this->cylindricalMap(point, u, v);
|
||||
break;
|
||||
}
|
||||
|
||||
return this->pattern->uvPatternAt(u, v);
|
||||
}
|
||||
}
|
||||
|
||||
void dumpMe(FILE *fp) {
|
||||
|
||||
@@ -83,6 +83,9 @@ target_sources(uvmap_checkeredplane PRIVATE uvmap_checkeredplane.cpp)
|
||||
add_executable(uvmap_checkeredcylinder)
|
||||
target_sources(uvmap_checkeredcylinder PRIVATE uvmap_checkeredcylinder.cpp)
|
||||
|
||||
add_executable(uvmap_checkeredcube)
|
||||
target_sources(uvmap_checkeredcube PRIVATE uvmap_checkeredcube.cpp)
|
||||
|
||||
add_executable(uvmap_aligncheckplane)
|
||||
target_sources(uvmap_aligncheckplane PRIVATE uvmap_aligncheckplane.cpp)
|
||||
|
||||
@@ -103,6 +106,7 @@ 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 UVMap_AlignCheckPlane COMMAND $<TARGET_FILE:uvmap_aligncheckplane>)
|
||||
add_test(NAME UVMap_CheckeredCube COMMAND $<TARGET_FILE:uvmap_checkeredcube>)
|
||||
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>)
|
||||
|
||||
@@ -467,3 +467,241 @@ TEST(PatternTest, Layout_of_the_align_check_pattern)
|
||||
ASSERT_EQ(ret, testResults[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(PatternTest, Identifying_the_face_of_a_cube_from_a_point)
|
||||
{
|
||||
Point testList[] = {
|
||||
Point(-1, 0.5, -0.25),
|
||||
Point(1.1, -0.75, 0.8),
|
||||
Point(0.1, 0.6, 0.9),
|
||||
Point(-0.7, 0, -2),
|
||||
Point(0.5, 1, 0.9),
|
||||
Point(-0.2, -1.3, 1.1),
|
||||
};
|
||||
|
||||
TextureMap::CubeFaces testResults[] {
|
||||
TextureMap::CUBE_LEFT,
|
||||
TextureMap::CUBE_RIGHT,
|
||||
TextureMap::CUBE_FRONT,
|
||||
TextureMap::CUBE_BACK,
|
||||
TextureMap::CUBE_UP,
|
||||
TextureMap::CUBE_DOWN,
|
||||
};
|
||||
|
||||
int testCount = sizeof(testList)/sizeof((testList)[0]);
|
||||
int i;
|
||||
|
||||
TextureMap tm = TextureMap(CUBIC_MAP, nullptr);
|
||||
|
||||
for(i = 0; i < testCount; i++)
|
||||
{
|
||||
TextureMap::CubeFaces face = tm.faceFromPoint(testList[i]);
|
||||
ASSERT_EQ(face, testResults[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(PatternTest, UV_mapping_the_front_face_of_a_cube)
|
||||
{
|
||||
Point testList[] = {
|
||||
Point(-0.5, 0.5, 1),
|
||||
Point(0.5, -0.5, 1),
|
||||
};
|
||||
|
||||
double testResults[][2] {
|
||||
{0.25, 0.75},
|
||||
{0.75, 0.25},
|
||||
};
|
||||
|
||||
int testCount = sizeof(testList)/sizeof((testList)[0]);
|
||||
int i;
|
||||
|
||||
TextureMap tm = TextureMap(CUBIC_MAP, nullptr);
|
||||
|
||||
for(i = 0; i < testCount; i++)
|
||||
{
|
||||
double u, v;
|
||||
tm.cubeUBFront(testList[i], u, v);
|
||||
ASSERT_TRUE(double_equal(u, testResults[i][0]));
|
||||
ASSERT_TRUE(double_equal(v, testResults[i][1]));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(PatternTest, UV_mapping_the_back_face_of_a_cube)
|
||||
{
|
||||
Point testList[] = {
|
||||
Point(0.5, 0.5, -1),
|
||||
Point(-0.5, -0.5, -1),
|
||||
};
|
||||
|
||||
double testResults[][2] {
|
||||
{0.25, 0.75},
|
||||
{0.75, 0.25},
|
||||
};
|
||||
|
||||
int testCount = sizeof(testList)/sizeof((testList)[0]);
|
||||
int i;
|
||||
|
||||
TextureMap tm = TextureMap(CUBIC_MAP, nullptr);
|
||||
|
||||
for(i = 0; i < testCount; i++)
|
||||
{
|
||||
double u, v;
|
||||
tm.cubeUBBack(testList[i], u, v);
|
||||
ASSERT_TRUE(double_equal(u, testResults[i][0]));
|
||||
ASSERT_TRUE(double_equal(v, testResults[i][1]));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(PatternTest, UV_mapping_the_left_face_of_a_cube)
|
||||
{
|
||||
Point testList[] = {
|
||||
Point(-1, 0.5, -0.5),
|
||||
Point(-1, -0.5, 0.5),
|
||||
};
|
||||
|
||||
double testResults[][2] {
|
||||
{0.25, 0.75},
|
||||
{0.75, 0.25},
|
||||
};
|
||||
|
||||
int testCount = sizeof(testList)/sizeof((testList)[0]);
|
||||
int i;
|
||||
|
||||
TextureMap tm = TextureMap(CUBIC_MAP, nullptr);
|
||||
|
||||
for(i = 0; i < testCount; i++)
|
||||
{
|
||||
double u, v;
|
||||
tm.cubeUBLeft(testList[i], u, v);
|
||||
ASSERT_TRUE(double_equal(u, testResults[i][0]));
|
||||
ASSERT_TRUE(double_equal(v, testResults[i][1]));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(PatternTest, UV_mapping_the_right_face_of_a_cube)
|
||||
{
|
||||
Point testList[] = {
|
||||
Point(1, 0.5, 0.5),
|
||||
Point(1, -0.5, -0.5),
|
||||
};
|
||||
|
||||
double testResults[][2] {
|
||||
{0.25, 0.75},
|
||||
{0.75, 0.25},
|
||||
};
|
||||
|
||||
int testCount = sizeof(testList)/sizeof((testList)[0]);
|
||||
int i;
|
||||
|
||||
TextureMap tm = TextureMap(CUBIC_MAP, nullptr);
|
||||
|
||||
for(i = 0; i < testCount; i++)
|
||||
{
|
||||
double u, v;
|
||||
tm.cubeUBRight(testList[i], u, v);
|
||||
ASSERT_TRUE(double_equal(u, testResults[i][0]));
|
||||
ASSERT_TRUE(double_equal(v, testResults[i][1]));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(PatternTest, UV_mapping_the_up_face_of_a_cube)
|
||||
{
|
||||
Point testList[] = {
|
||||
Point(-0.5, 1, -0.5),
|
||||
Point(0.5, 1, 0.5),
|
||||
};
|
||||
|
||||
double testResults[][2] {
|
||||
{0.25, 0.75},
|
||||
{0.75, 0.25},
|
||||
};
|
||||
|
||||
int testCount = sizeof(testList)/sizeof((testList)[0]);
|
||||
int i;
|
||||
|
||||
TextureMap tm = TextureMap(CUBIC_MAP, nullptr);
|
||||
|
||||
for(i = 0; i < testCount; i++)
|
||||
{
|
||||
double u, v;
|
||||
tm.cubeUBUp(testList[i], u, v);
|
||||
ASSERT_TRUE(double_equal(u, testResults[i][0]));
|
||||
ASSERT_TRUE(double_equal(v, testResults[i][1]));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(PatternTest, UV_mapping_the_down_face_of_a_cube)
|
||||
{
|
||||
Point testList[] = {
|
||||
Point(-0.5, -1, 0.5),
|
||||
Point(0.5, -1, -0.5),
|
||||
};
|
||||
|
||||
double testResults[][2] {
|
||||
{0.25, 0.75},
|
||||
{0.75, 0.25},
|
||||
};
|
||||
|
||||
int testCount = sizeof(testList)/sizeof((testList)[0]);
|
||||
int i;
|
||||
|
||||
TextureMap tm = TextureMap(CUBIC_MAP, nullptr);
|
||||
|
||||
for(i = 0; i < testCount; i++)
|
||||
{
|
||||
double u, v;
|
||||
tm.cubeUBDown(testList[i], u, v);
|
||||
ASSERT_TRUE(double_equal(u, testResults[i][0]));
|
||||
ASSERT_TRUE(double_equal(v, testResults[i][1]));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(PatternTest, Finding_the_colours_on_a_mapped_cube)
|
||||
{
|
||||
Colour red = Colour(1, 0, 0);
|
||||
Colour yellow = Colour(1, 1, 0);
|
||||
Colour brown = Colour(1, 0.5, 0);
|
||||
Colour green = Colour(0, 1, 0);
|
||||
Colour cyan = Colour(0, 1, 1);
|
||||
Colour blue = Colour(0, 0, 1);
|
||||
Colour purple = Colour(1, 0, 1);
|
||||
Colour white = Colour(1, 1, 1);
|
||||
|
||||
UVAlignCheck left = UVAlignCheck(yellow, cyan, red, blue, brown);
|
||||
UVAlignCheck front = UVAlignCheck(cyan, red, yellow, brown, green);
|
||||
UVAlignCheck right = UVAlignCheck(red, yellow, purple, green, white);
|
||||
UVAlignCheck back = UVAlignCheck(green, purple, cyan, white, blue);
|
||||
UVAlignCheck up = UVAlignCheck(brown, cyan, purple, red, yellow);
|
||||
UVAlignCheck down = UVAlignCheck(purple, brown, green, blue, white);
|
||||
|
||||
TextureMap tm = TextureMap(CUBIC_MAP, nullptr);
|
||||
tm.setCubePattern(&front, &left, &right, &back, &up, &down);
|
||||
|
||||
Point testList[] = {
|
||||
Point(-1, 0, 0), Point(-1, 0.9, -0.9), Point(-1, 0.9, 0.9), Point(-1, -0.9, -0.9), Point(-1, -0.9, 0.9), /* left */
|
||||
Point(0, 0, 1), Point(-0.9, 0.9, 1), Point(0.9, 0.9, 1), Point(-0.9, -0.9, 1), Point(0.9, -0.9, 1), /* front */
|
||||
Point(1, 0, 0), Point(1, 0.9, 0.9), Point(1, 0.9, -0.9), Point(1, -0.9, 0.9), Point(1, -0.9, -0.9), /* right */
|
||||
Point(0, 0, -1), Point(0.9, 0.9, -1), Point(-0.9, 0.9, -1), Point(0.9, -0.9, -1), Point(-0.9, -0.9, -1), /* back */
|
||||
Point(0, 1, 0), Point(-0.9, 1, -0.9), Point(0.9, 1, -0.9), Point(-0.9, 1, 0.9), Point(0.9, 1, 0.9), /* up */
|
||||
Point(0, -1, 0), Point(-0.9, -1, 0.9), Point(0.9, -1, 0.9), Point(-0.9, -1, -0.9), Point(0.9, -1, -0.9), /* down */
|
||||
};
|
||||
|
||||
Colour testResults[] {
|
||||
yellow, cyan, red, blue, brown, /* left */
|
||||
cyan, red, yellow, brown, green, /* front */
|
||||
red, yellow, purple, green, white, /* right */
|
||||
green, purple, cyan, white, blue, /* back */
|
||||
brown, cyan, purple, red, yellow, /* up */
|
||||
purple, brown, green, blue, white, /* down */
|
||||
};
|
||||
|
||||
int testCount = sizeof(testList)/sizeof((testList)[0]);
|
||||
int i;
|
||||
|
||||
for(i = 0; i < testCount; i++)
|
||||
{
|
||||
Colour ret = tm.patternAt(testList[i]);
|
||||
ASSERT_EQ(ret, testResults[i]);
|
||||
}
|
||||
|
||||
}
|
||||
111
tests/uvmap_checkeredcube.cpp
Normal file
111
tests/uvmap_checkeredcube.cpp
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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 <cube.h>
|
||||
#include <material.h>
|
||||
#include <colour.h>
|
||||
#include <canvas.h>
|
||||
#include <camera.h>
|
||||
|
||||
#include <pattern.h>
|
||||
#include <texturemap.h>
|
||||
#include <uv_aligncheck.h>
|
||||
|
||||
#include <transformation.h>
|
||||
|
||||
Colour red = Colour(1, 0, 0);
|
||||
Colour yellow = Colour(1, 1, 0);
|
||||
Colour brown = Colour(1, 0.5, 0);
|
||||
Colour green = Colour(0, 1, 0);
|
||||
Colour cyan = Colour(0, 1, 1);
|
||||
Colour blue = Colour(0, 0, 1);
|
||||
Colour purple = Colour(1, 0, 1);
|
||||
Colour white = Colour(1, 1, 1);
|
||||
|
||||
UVAlignCheck left = UVAlignCheck(yellow, cyan, red, blue, brown);
|
||||
UVAlignCheck front = UVAlignCheck(cyan, red, yellow, brown, green);
|
||||
UVAlignCheck right = UVAlignCheck(red, yellow, purple, green, white);
|
||||
UVAlignCheck back = UVAlignCheck(green, purple, cyan, white, blue);
|
||||
UVAlignCheck up = UVAlignCheck(brown, cyan, purple, red, yellow);
|
||||
UVAlignCheck down = UVAlignCheck(purple, brown, green, blue, white);
|
||||
|
||||
Shape *MappedCube()
|
||||
{
|
||||
Cube *ret = new Cube();
|
||||
TextureMap *tm = new TextureMap(CUBIC_MAP, nullptr);
|
||||
tm->setCubePattern(&front, &left, &right, &back, &up, &down);
|
||||
ret->material.pattern = tm;
|
||||
ret->material.ambient = 0.2;
|
||||
ret->material.specular = 0;
|
||||
ret->material.diffuse = 0.8;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
World w = World();
|
||||
|
||||
Light light1 = Light(POINT_LIGHT, Point(0, 100, -100), Colour(0.25, 0.25, 0.25));
|
||||
w.addLight(&light1);
|
||||
Light light2 = Light(POINT_LIGHT, Point(0, -100, -100), Colour(0.25, 0.25, 0.25));
|
||||
w.addLight(&light2);
|
||||
Light light3 = Light(POINT_LIGHT, Point(-100, 0, -100), Colour(0.25, 0.25, 0.25));
|
||||
w.addLight(&light3);
|
||||
Light light4 = Light(POINT_LIGHT, Point(100, 0, -100), Colour(0.25, 0.25, 0.25));
|
||||
w.addLight(&light4);
|
||||
|
||||
Shape *s;
|
||||
|
||||
s = MappedCube();
|
||||
s->setTransform(translation(-6, 2, 0) * rotationX(0.7854) * rotationY(0.7854));
|
||||
w.addObject(s);
|
||||
|
||||
s = MappedCube();
|
||||
s->setTransform(translation(-2, 2, 0) * rotationX(0.7854) * rotationY(2.3562));
|
||||
w.addObject(s);
|
||||
|
||||
s = MappedCube();
|
||||
s->setTransform(translation(2, 2, 0) * rotationX(0.7854) * rotationY(3.927));
|
||||
w.addObject(s);
|
||||
|
||||
s = MappedCube();
|
||||
s->setTransform(translation(6, 2, 0) * rotationX(0.7854) * rotationY(5.4978));
|
||||
w.addObject(s);
|
||||
|
||||
s = MappedCube();
|
||||
s->setTransform(translation(-6, -2, 0) * rotationX(-0.7854) * rotationY(0.7854));
|
||||
w.addObject(s);
|
||||
|
||||
s = MappedCube();
|
||||
s->setTransform(translation(-2, -2, 0) * rotationX(-0.7854) * rotationY(2.3562));
|
||||
w.addObject(s);
|
||||
|
||||
s = MappedCube();
|
||||
s->setTransform(translation(2, -2, 0) * rotationX(-0.7854) * rotationY(3.927));
|
||||
w.addObject(s);
|
||||
|
||||
s = MappedCube();
|
||||
s->setTransform(translation(6, -2, 0) * rotationX(-0.7854) * rotationY(5.4978));
|
||||
w.addObject(s);
|
||||
|
||||
/* Set the camera */
|
||||
Camera camera = Camera(800, 400, 0.8);
|
||||
camera.setTransform(viewTransform(Point(0, 0, -20),
|
||||
Point(0, 0, 0),
|
||||
Vector(0, 1, 0)));
|
||||
|
||||
/* Now render it */
|
||||
Canvas image = camera.render(w);
|
||||
|
||||
image.SaveAsPNG("uvmap_checkeredcube.png");
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user