Smooth triangles! And support for them in the OBJ File parser.
Also add an interesting tea party scene!
This commit is contained in:
@@ -6,9 +6,12 @@ DoRayMe
|
|||||||
A Quick and dirty raytracer.
|
A Quick and dirty raytracer.
|
||||||
|
|
||||||
|
|
||||||
This raytracer is made following the book "[The Ray Tracer Challenge](https://pragprog.com/book/jbtracer/the-ray-tracer-challenge)" by Jamis Buck.
|
This raytracer is made following the book
|
||||||
|
"[The Ray Tracer Challenge](https://pragprog.com/book/jbtracer/the-ray-tracer-challenge)" by Jamis Buck.
|
||||||
|
|
||||||
It is writen in C++ with no STL and use [LodePNG](https://github.com/lvandeve/lodepng) to output PNG file.
|
It is writen in C++ with no STL and use [LodePNG](https://github.com/lvandeve/lodepng) to output PNG file and use them
|
||||||
|
as texture, also use [NanoJPEG](https://keyj.emphy.de/nanojpeg/) to use jpeg file as texture, and can use use
|
||||||
|
[Lua 5.3](https://www.lua.org/) for 3D pattern definition and more to come on the Lua side later..
|
||||||
|
|
||||||
|
|
||||||
Examples outputs
|
Examples outputs
|
||||||
@@ -65,6 +68,8 @@ Bonus:
|
|||||||
**From Chapter 14 - Groups & Bounding boxes:**
|
**From Chapter 14 - Groups & Bounding boxes:**
|
||||||

|

|
||||||
|
|
||||||
|
**From Chapter 15 - Triangles, Wavefrom OBJ files - Smooth trianges:**
|
||||||
|

|
||||||
|
|
||||||
**Bonus (from the forum):**
|
**Bonus (from the forum):**
|
||||||
|
|
||||||
|
|||||||
274
external/teapot-lowtri.obj
vendored
Normal file
274
external/teapot-lowtri.obj
vendored
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
#
|
||||||
|
# object Teapot001
|
||||||
|
#
|
||||||
|
|
||||||
|
v 7.0000 0.0000 12.0000
|
||||||
|
v 4.9700 -4.9700 12.0000
|
||||||
|
v 4.9811 -4.9811 12.4922
|
||||||
|
v 7.0156 0.0000 12.4922
|
||||||
|
v 5.3250 -5.3250 12.0000
|
||||||
|
v 7.5000 0.0000 12.0000
|
||||||
|
v 0.0000 -7.0000 12.0000
|
||||||
|
v 0.0000 -7.0156 12.4922
|
||||||
|
v 0.0000 -7.5000 12.0000
|
||||||
|
v -5.1387 -4.9700 12.0000
|
||||||
|
v -5.0022 -4.9811 12.4922
|
||||||
|
v -5.3250 -5.3250 12.0000
|
||||||
|
v -7.0000 0.0000 12.0000
|
||||||
|
v -7.0156 0.0000 12.4922
|
||||||
|
v -7.5000 0.0000 12.0000
|
||||||
|
v -4.9700 4.9700 12.0000
|
||||||
|
v -4.9811 4.9811 12.4922
|
||||||
|
v -5.3250 5.3250 12.0000
|
||||||
|
v 0.0000 7.0000 12.0000
|
||||||
|
v 0.0000 7.0156 12.4922
|
||||||
|
v 0.0000 7.5000 12.0000
|
||||||
|
v 4.9700 4.9700 12.0000
|
||||||
|
v 4.9811 4.9811 12.4922
|
||||||
|
v 5.3250 5.3250 12.0000
|
||||||
|
v 6.5453 -6.5453 8.1094
|
||||||
|
v 9.2188 0.0000 8.1094
|
||||||
|
v 7.1000 -7.1000 4.5000
|
||||||
|
v 10.0000 0.0000 4.5000
|
||||||
|
v 0.0000 -9.2188 8.1094
|
||||||
|
v 0.0000 -10.0000 4.5000
|
||||||
|
v -6.5453 -6.5453 8.1094
|
||||||
|
v -7.1000 -7.1000 4.5000
|
||||||
|
v -9.2188 0.0000 8.1094
|
||||||
|
v -10.0000 0.0000 4.5000
|
||||||
|
v -6.5453 6.5453 8.1094
|
||||||
|
v -7.1000 7.1000 4.5000
|
||||||
|
v 0.0000 9.2188 8.1094
|
||||||
|
v 0.0000 10.0000 4.5000
|
||||||
|
v 6.5453 6.5453 8.1094
|
||||||
|
v 7.1000 7.1000 4.5000
|
||||||
|
v 6.2125 -6.2125 1.9219
|
||||||
|
v 8.7500 0.0000 1.9219
|
||||||
|
v 5.3250 -5.3250 0.7500
|
||||||
|
v 7.5000 0.0000 0.7500
|
||||||
|
v 0.0000 -8.7500 1.9219
|
||||||
|
v 0.0000 -7.5000 0.7500
|
||||||
|
v -6.2125 -6.2125 1.9219
|
||||||
|
v -5.3250 -5.3250 0.7500
|
||||||
|
v -8.7500 0.0000 1.9219
|
||||||
|
v -7.5000 0.0000 0.7500
|
||||||
|
v -6.2125 6.2125 1.9219
|
||||||
|
v -5.3250 5.3250 0.7500
|
||||||
|
v 0.0000 8.7500 1.9219
|
||||||
|
v 0.0000 7.5000 0.7500
|
||||||
|
v 6.2125 6.2125 1.9219
|
||||||
|
v 5.3250 5.3250 0.7500
|
||||||
|
v 4.5595 -4.5595 0.2344
|
||||||
|
v 6.4219 0.0000 0.2344
|
||||||
|
v 0.0000 0.0000 0.0000
|
||||||
|
v 0.0000 -6.4219 0.2344
|
||||||
|
v -4.5595 -4.5595 0.2344
|
||||||
|
v -6.4219 0.0000 0.2344
|
||||||
|
v -4.5595 4.5595 0.2344
|
||||||
|
v 0.0000 6.4219 0.2344
|
||||||
|
v 4.5595 4.5595 0.2344
|
||||||
|
v -8.0000 0.0000 10.1250
|
||||||
|
v -7.7500 -1.1250 10.6875
|
||||||
|
v -12.5938 -1.1250 10.4766
|
||||||
|
v -12.0625 0.0000 9.9844
|
||||||
|
v -14.2500 -1.1250 9.0000
|
||||||
|
v -13.5000 0.0000 9.0000
|
||||||
|
v -7.5000 0.0000 11.2500
|
||||||
|
v -13.1250 0.0000 10.9688
|
||||||
|
v -15.0000 0.0000 9.0000
|
||||||
|
v -7.7500 1.1250 10.6875
|
||||||
|
v -12.5938 1.1250 10.4766
|
||||||
|
v -14.2500 1.1250 9.0000
|
||||||
|
v -13.1719 -1.1250 6.2695
|
||||||
|
v -12.6875 0.0000 6.7500
|
||||||
|
v -9.7500 -1.1250 3.7500
|
||||||
|
v -13.6563 0.0000 5.7891
|
||||||
|
v -9.5000 0.0000 3.0000
|
||||||
|
v -13.1719 1.1250 6.2695
|
||||||
|
v -9.7500 1.1250 3.7500
|
||||||
|
v 8.5000 0.0000 7.1250
|
||||||
|
v 8.5000 -2.4750 5.0625
|
||||||
|
v 12.6875 -1.7062 8.1094
|
||||||
|
v 11.9375 0.0000 9.0000
|
||||||
|
v 15.0000 -0.9375 12.0000
|
||||||
|
v 13.5000 0.0000 12.0000
|
||||||
|
v 8.5000 0.0000 3.0000
|
||||||
|
v 13.4375 0.0000 7.2187
|
||||||
|
v 16.5000 0.0000 12.0000
|
||||||
|
v 8.5000 2.4750 5.0625
|
||||||
|
v 12.6875 1.7062 8.1094
|
||||||
|
v 15.0000 0.9375 12.0000
|
||||||
|
v 15.6328 -0.7500 12.3340
|
||||||
|
v 14.1250 0.0000 12.2813
|
||||||
|
v 15.0000 -0.5625 12.0000
|
||||||
|
v 14.0000 0.0000 12.0000
|
||||||
|
v 17.1406 0.0000 12.3867
|
||||||
|
v 16.0000 0.0000 12.0000
|
||||||
|
v 15.6328 0.7500 12.3340
|
||||||
|
v 15.0000 0.5625 12.0000
|
||||||
|
v 1.1552 -1.1552 14.9063
|
||||||
|
v 1.6250 0.0000 14.9063
|
||||||
|
v 0.0000 0.0000 15.7500
|
||||||
|
v 0.7100 -0.7100 13.5000
|
||||||
|
v 1.0000 0.0000 13.5000
|
||||||
|
v 0.0000 -1.6250 14.9063
|
||||||
|
v 0.0000 -1.0000 13.5000
|
||||||
|
v -1.1552 -1.1552 14.9063
|
||||||
|
v -0.7100 -0.7100 13.5000
|
||||||
|
v -1.6250 0.0000 14.9063
|
||||||
|
v -1.0000 0.0000 13.5000
|
||||||
|
v -1.1552 1.1552 14.9063
|
||||||
|
v -0.7100 0.7100 13.5000
|
||||||
|
v 0.0000 1.6250 14.9063
|
||||||
|
v 0.0000 1.0000 13.5000
|
||||||
|
v 1.1552 1.1552 14.9063
|
||||||
|
v 0.7100 0.7100 13.5000
|
||||||
|
v 2.9288 -2.9288 12.7500
|
||||||
|
v 4.1250 0.0000 12.7500
|
||||||
|
v 4.6150 -4.6150 12.0000
|
||||||
|
v 6.5000 0.0000 12.0000
|
||||||
|
v 0.0000 -4.1250 12.7500
|
||||||
|
v 0.0000 -6.5000 12.0000
|
||||||
|
v -2.9288 -2.9288 12.7500
|
||||||
|
v -4.6150 -4.6150 12.0000
|
||||||
|
v -4.1250 0.0000 12.7500
|
||||||
|
v -6.5000 0.0000 12.0000
|
||||||
|
v -2.9288 2.9288 12.7500
|
||||||
|
v -4.6150 4.6150 12.0000
|
||||||
|
v 0.0000 4.1250 12.7500
|
||||||
|
v 0.0000 6.5000 12.0000
|
||||||
|
v 2.9288 2.9288 12.7500
|
||||||
|
v 4.6150 4.6150 12.0000
|
||||||
|
# 137 vertices
|
||||||
|
|
||||||
|
g Teapot001
|
||||||
|
f 1 2 3 4
|
||||||
|
f 4 3 5 6
|
||||||
|
f 2 7 8 3
|
||||||
|
f 3 8 9 5
|
||||||
|
f 7 10 11 8
|
||||||
|
f 8 11 12 9
|
||||||
|
f 10 13 14 11
|
||||||
|
f 11 14 15 12
|
||||||
|
f 13 16 17 14
|
||||||
|
f 14 17 18 15
|
||||||
|
f 16 19 20 17
|
||||||
|
f 17 20 21 18
|
||||||
|
f 19 22 23 20
|
||||||
|
f 20 23 24 21
|
||||||
|
f 22 1 4 23
|
||||||
|
f 23 4 6 24
|
||||||
|
f 6 5 25 26
|
||||||
|
f 26 25 27 28
|
||||||
|
f 5 9 29 25
|
||||||
|
f 25 29 30 27
|
||||||
|
f 9 12 31 29
|
||||||
|
f 29 31 32 30
|
||||||
|
f 12 15 33 31
|
||||||
|
f 31 33 34 32
|
||||||
|
f 15 18 35 33
|
||||||
|
f 33 35 36 34
|
||||||
|
f 18 21 37 35
|
||||||
|
f 35 37 38 36
|
||||||
|
f 21 24 39 37
|
||||||
|
f 37 39 40 38
|
||||||
|
f 24 6 26 39
|
||||||
|
f 39 26 28 40
|
||||||
|
f 28 27 41 42
|
||||||
|
f 42 41 43 44
|
||||||
|
f 27 30 45 41
|
||||||
|
f 41 45 46 43
|
||||||
|
f 30 32 47 45
|
||||||
|
f 45 47 48 46
|
||||||
|
f 32 34 49 47
|
||||||
|
f 47 49 50 48
|
||||||
|
f 34 36 51 49
|
||||||
|
f 49 51 52 50
|
||||||
|
f 36 38 53 51
|
||||||
|
f 51 53 54 52
|
||||||
|
f 38 40 55 53
|
||||||
|
f 53 55 56 54
|
||||||
|
f 40 28 42 55
|
||||||
|
f 55 42 44 56
|
||||||
|
f 44 43 57 58
|
||||||
|
f 58 57 59
|
||||||
|
f 43 46 60 57
|
||||||
|
f 57 60 59
|
||||||
|
f 46 48 61 60
|
||||||
|
f 60 61 59
|
||||||
|
f 48 50 62 61
|
||||||
|
f 61 62 59
|
||||||
|
f 50 52 63 62
|
||||||
|
f 62 63 59
|
||||||
|
f 52 54 64 63
|
||||||
|
f 63 64 59
|
||||||
|
f 54 56 65 64
|
||||||
|
f 64 65 59
|
||||||
|
f 56 44 58 65
|
||||||
|
f 65 58 59
|
||||||
|
f 66 67 68 69
|
||||||
|
f 69 68 70 71
|
||||||
|
f 67 72 73 68
|
||||||
|
f 68 73 74 70
|
||||||
|
f 72 75 76 73
|
||||||
|
f 73 76 77 74
|
||||||
|
f 75 66 69 76
|
||||||
|
f 76 69 71 77
|
||||||
|
f 71 70 78 79
|
||||||
|
f 79 78 80 34
|
||||||
|
f 70 74 81 78
|
||||||
|
f 78 81 82 80
|
||||||
|
f 74 77 83 81
|
||||||
|
f 81 83 84 82
|
||||||
|
f 77 71 79 83
|
||||||
|
f 83 79 34 84
|
||||||
|
f 85 86 87 88
|
||||||
|
f 88 87 89 90
|
||||||
|
f 86 91 92 87
|
||||||
|
f 87 92 93 89
|
||||||
|
f 91 94 95 92
|
||||||
|
f 92 95 96 93
|
||||||
|
f 94 85 88 95
|
||||||
|
f 95 88 90 96
|
||||||
|
f 90 89 97 98
|
||||||
|
f 98 97 99 100
|
||||||
|
f 89 93 101 97
|
||||||
|
f 97 101 102 99
|
||||||
|
f 93 96 103 101
|
||||||
|
f 101 103 104 102
|
||||||
|
f 96 90 98 103
|
||||||
|
f 103 98 100 104
|
||||||
|
f 105 106 107
|
||||||
|
f 106 105 108 109
|
||||||
|
f 110 105 107
|
||||||
|
f 105 110 111 108
|
||||||
|
f 112 110 107
|
||||||
|
f 110 112 113 111
|
||||||
|
f 114 112 107
|
||||||
|
f 112 114 115 113
|
||||||
|
f 116 114 107
|
||||||
|
f 114 116 117 115
|
||||||
|
f 118 116 107
|
||||||
|
f 116 118 119 117
|
||||||
|
f 120 118 107
|
||||||
|
f 118 120 121 119
|
||||||
|
f 106 120 107
|
||||||
|
f 120 106 109 121
|
||||||
|
f 109 108 122 123
|
||||||
|
f 123 122 124 125
|
||||||
|
f 108 111 126 122
|
||||||
|
f 122 126 127 124
|
||||||
|
f 111 113 128 126
|
||||||
|
f 126 128 129 127
|
||||||
|
f 113 115 130 128
|
||||||
|
f 128 130 131 129
|
||||||
|
f 115 117 132 130
|
||||||
|
f 130 132 133 131
|
||||||
|
f 117 119 134 132
|
||||||
|
f 132 134 135 133
|
||||||
|
f 119 121 136 134
|
||||||
|
f 134 136 137 135
|
||||||
|
f 121 109 123 136
|
||||||
|
f 136 123 125 137
|
||||||
|
# 112 polygons - 16 triangles
|
||||||
|
|
||||||
BIN
output/ch15_teapot_objfile.png
Normal file
BIN
output/ch15_teapot_objfile.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 149 KiB |
@@ -19,7 +19,7 @@ class Cone : public Shape {
|
|||||||
protected:
|
protected:
|
||||||
Intersect localIntersect(Ray r);
|
Intersect localIntersect(Ray r);
|
||||||
|
|
||||||
Tuple localNormalAt(Tuple point);
|
Tuple localNormalAt(Tuple point, Intersection *hit = nullptr);
|
||||||
|
|
||||||
bool checkCap(Ray r, double t, double y);
|
bool checkCap(Ray r, double t, double y);
|
||||||
void intersectCaps(Ray r, Intersect &xs);
|
void intersectCaps(Ray r, Intersect &xs);
|
||||||
|
|||||||
@@ -16,12 +16,12 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
class Cube : public Shape {
|
class Cube : public Shape {
|
||||||
private:
|
protected:
|
||||||
void checkAxis(double axeOrigin, double axeDirection, double *axeMin, double *axeMax);
|
void checkAxis(double axeOrigin, double axeDirection, double *axeMin, double *axeMax);
|
||||||
|
|
||||||
Intersect localIntersect(Ray r);
|
Intersect localIntersect(Ray r);
|
||||||
|
|
||||||
Tuple localNormalAt(Tuple point);
|
Tuple localNormalAt(Tuple point, Intersection *hit = nullptr);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Cube() : Shape(SHAPE_CUBE) { stats.addCube(); };
|
Cube() : Shape(SHAPE_CUBE) { stats.addCube(); };
|
||||||
|
|||||||
@@ -16,10 +16,11 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
class Cylinder : public Shape {
|
class Cylinder : public Shape {
|
||||||
private:
|
|
||||||
|
protected:
|
||||||
Intersect localIntersect(Ray r);
|
Intersect localIntersect(Ray r);
|
||||||
|
|
||||||
Tuple localNormalAt(Tuple point);
|
Tuple localNormalAt(Tuple point, Intersection *hit = nullptr);
|
||||||
|
|
||||||
bool checkCap(Ray r, double t);
|
bool checkCap(Ray r, double t);
|
||||||
void intersectCaps(Ray r, Intersect &xs);
|
void intersectCaps(Ray r, Intersect &xs);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ private:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
Intersect localIntersect(Ray r);
|
Intersect localIntersect(Ray r);
|
||||||
Tuple localNormalAt(Tuple point);
|
Tuple localNormalAt(Tuple point, Intersection *hit = nullptr);
|
||||||
|
|
||||||
BoundingBox bounds;
|
BoundingBox bounds;
|
||||||
|
|
||||||
|
|||||||
@@ -74,8 +74,10 @@ public:
|
|||||||
double t;
|
double t;
|
||||||
Shape *object;
|
Shape *object;
|
||||||
|
|
||||||
|
double u, v;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Intersection(double t, Shape *object) : t(t), object(object) { stats.addIntersection(); };
|
Intersection(double t, Shape *object, double u = NAN, double v = NAN) : t(t), object(object), u(u), v(v) { stats.addIntersection(); };
|
||||||
bool nothing() { return (this->object == nullptr); };
|
bool nothing() { return (this->object == nullptr); };
|
||||||
|
|
||||||
Computation prepareComputation(Ray r, Intersect *xs = nullptr);
|
Computation prepareComputation(Ray r, Intersect *xs = nullptr);
|
||||||
|
|||||||
@@ -26,9 +26,13 @@ private:
|
|||||||
Point* *vertexList;
|
Point* *vertexList;
|
||||||
uint32_t vertexCount;
|
uint32_t vertexCount;
|
||||||
|
|
||||||
|
uint32_t allocatedVertexNormalCount;
|
||||||
|
Vector* *vertexNormalList;
|
||||||
|
uint32_t vertexNormalCount;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Intersect localIntersect(Ray r);
|
Intersect localIntersect(Ray r);
|
||||||
Tuple localNormalAt(Tuple point);
|
Tuple localNormalAt(Tuple point, Intersection *hit = nullptr);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* Some stats */
|
/* Some stats */
|
||||||
@@ -37,6 +41,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
void addGroup(Group *group);
|
void addGroup(Group *group);
|
||||||
void addVertex(Point *vertex);
|
void addVertex(Point *vertex);
|
||||||
|
void addVertexNormal(Vector *vertexNormal);
|
||||||
|
|
||||||
void parseLine(char *line, uint32_t currentLine);
|
void parseLine(char *line, uint32_t currentLine);
|
||||||
int execLine(int argc, char *argv[], uint32_t currentLine);
|
int execLine(int argc, char *argv[], uint32_t currentLine);
|
||||||
@@ -50,6 +55,7 @@ public:
|
|||||||
|
|
||||||
/* OBJ file expect the first vertice to be 1 and not 0 */
|
/* OBJ file expect the first vertice to be 1 and not 0 */
|
||||||
Point vertices(uint32_t i) { return *this->vertexList[i - 1]; };
|
Point vertices(uint32_t i) { return *this->vertexList[i - 1]; };
|
||||||
|
Vector verticesNormal(uint32_t i) { return *this->vertexNormalList[i - 1]; };
|
||||||
Group *groups(uint32_t i) { return this->faceGroupList[i]; };
|
Group *groups(uint32_t i) { return this->faceGroupList[i]; };
|
||||||
Intersect intersect(Ray r);
|
Intersect intersect(Ray r);
|
||||||
BoundingBox getLocalBounds();
|
BoundingBox getLocalBounds();
|
||||||
|
|||||||
@@ -13,9 +13,9 @@
|
|||||||
|
|
||||||
class Plane : public Shape
|
class Plane : public Shape
|
||||||
{
|
{
|
||||||
private:
|
protected:
|
||||||
Intersect localIntersect(Ray r);
|
Intersect localIntersect(Ray r);
|
||||||
Tuple localNormalAt(Tuple point);
|
Tuple localNormalAt(Tuple point, Intersection *hit = nullptr);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Plane() : Shape(SHAPE_PLANE) { stats.addPlane(); };
|
Plane() : Shape(SHAPE_PLANE) { stats.addPlane(); };
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ private:
|
|||||||
uint64_t planeCount; /* Total number of plane */
|
uint64_t planeCount; /* Total number of plane */
|
||||||
uint64_t sphereCount; /* Total number of sphere */
|
uint64_t sphereCount; /* Total number of sphere */
|
||||||
uint64_t triangleCount; /* Total number of triangle */
|
uint64_t triangleCount; /* Total number of triangle */
|
||||||
|
uint64_t smoothTriangleCount; /* Total number of smooth triangle */
|
||||||
uint64_t objfileCount; /* Total number of OBJ File */
|
uint64_t objfileCount; /* Total number of OBJ File */
|
||||||
|
|
||||||
uint64_t pixelCount; /* Total number of rendered pixels */
|
uint64_t pixelCount; /* Total number of rendered pixels */
|
||||||
@@ -40,7 +41,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
RenderStats() : coneCount(0), cylinderCount(0), cubeCount(0), groupCount(0), lightCount(0), planeCount(0), sphereCount(0), triangleCount(0),
|
RenderStats() : coneCount(0), cylinderCount(0), cubeCount(0), groupCount(0), lightCount(0), planeCount(0), sphereCount(0), triangleCount(0),
|
||||||
pixelCount(0), rayCount(0), lightRayEmitedCount(0), reflectionRayCount(0), refractedRayCount(0),
|
pixelCount(0), rayCount(0), lightRayEmitedCount(0), reflectionRayCount(0), refractedRayCount(0),
|
||||||
intersectCount(0), intersectionCount(0), reallocCallCount(0), mallocCallCount(0),
|
intersectCount(0), intersectionCount(0), reallocCallCount(0), mallocCallCount(0), smoothTriangleCount(0),
|
||||||
discardedIntersectCount(0), maxDepthAttained(UINT64_MAX), maxIntersectOnARay(0), objfileCount(0) {};
|
discardedIntersectCount(0), maxDepthAttained(UINT64_MAX), maxIntersectOnARay(0), objfileCount(0) {};
|
||||||
#ifdef RENDER_STATS
|
#ifdef RENDER_STATS
|
||||||
void addCone();
|
void addCone();
|
||||||
@@ -52,6 +53,7 @@ public:
|
|||||||
void addSphere();
|
void addSphere();
|
||||||
void addOBJFile();
|
void addOBJFile();
|
||||||
void addTriangle();
|
void addTriangle();
|
||||||
|
void addSmoothTriangle();
|
||||||
void printStats();
|
void printStats();
|
||||||
void addPixel();
|
void addPixel();
|
||||||
void addRay();
|
void addRay();
|
||||||
@@ -74,6 +76,7 @@ public:
|
|||||||
static void addPlane() {};
|
static void addPlane() {};
|
||||||
static void addSphere() {};
|
static void addSphere() {};
|
||||||
static void addTriangle() {};
|
static void addTriangle() {};
|
||||||
|
static void addSmoothTriangle() {};
|
||||||
static void printStats() {};
|
static void printStats() {};
|
||||||
static void addPixel() {};
|
static void addPixel() {};
|
||||||
static void addRay() {};
|
static void addRay() {};
|
||||||
|
|||||||
@@ -30,17 +30,19 @@ enum ShapeType
|
|||||||
SHAPE_GROUP,
|
SHAPE_GROUP,
|
||||||
SHAPE_TRIANGLE,
|
SHAPE_TRIANGLE,
|
||||||
SHAPE_OBJFILE,
|
SHAPE_OBJFILE,
|
||||||
|
SHAPE_SMOOTHTRIANGLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Base class for all object that can be presented in the world */
|
/* Base class for all object that can be presented in the world */
|
||||||
class Shape
|
class Shape
|
||||||
{
|
{
|
||||||
private:
|
protected:
|
||||||
ShapeType type;
|
ShapeType type;
|
||||||
Matrix localTransformMatrix;
|
Matrix localTransformMatrix;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual Intersect localIntersect(Ray r) = 0;
|
virtual Intersect localIntersect(Ray r) = 0;
|
||||||
virtual Tuple localNormalAt(Tuple point) = 0;
|
virtual Tuple localNormalAt(Tuple point, Intersection *hit) = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Matrix transformMatrix;
|
Matrix transformMatrix;
|
||||||
@@ -50,13 +52,14 @@ public:
|
|||||||
Material material;
|
Material material;
|
||||||
bool dropShadow;
|
bool dropShadow;
|
||||||
Shape *parent;
|
Shape *parent;
|
||||||
|
bool materialSet;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Shape(ShapeType = SHAPE_NONE);
|
Shape(ShapeType = SHAPE_NONE);
|
||||||
|
|
||||||
virtual Intersect intersect(Ray r);
|
virtual Intersect intersect(Ray r);
|
||||||
virtual Intersect intersectOOB(Ray r) { return this->intersect(r); };
|
virtual Intersect intersectOOB(Ray r) { return this->intersect(r); };
|
||||||
Tuple normalAt(Tuple point);
|
Tuple normalAt(Tuple point, Intersection *hit = nullptr);
|
||||||
|
|
||||||
/* Bounding box points are always world value */
|
/* Bounding box points are always world value */
|
||||||
virtual BoundingBox getLocalBounds();
|
virtual BoundingBox getLocalBounds();
|
||||||
|
|||||||
28
source/include/smoothtriangle.h
Normal file
28
source/include/smoothtriangle.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* DoRayMe - a quick and dirty Raytracer
|
||||||
|
* Smooth Triangle header
|
||||||
|
*
|
||||||
|
* Created by Manoël Trapier
|
||||||
|
* Copyright (c) 2020 986-Studio.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef DORAYME_SMOOTHTRIANGLE_H
|
||||||
|
#define DORAYME_SMOOTHTRIANGLE_H
|
||||||
|
|
||||||
|
#include <triangle.h>
|
||||||
|
|
||||||
|
class SmoothTriangle : public Triangle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Vector n1;
|
||||||
|
Vector n2;
|
||||||
|
Vector n3;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Tuple localNormalAt(Tuple point, Intersection *hit);
|
||||||
|
|
||||||
|
public:
|
||||||
|
SmoothTriangle(Point p1, Point p2, Point p3, Vector n1, Vector n2, Vector n3);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* DORAYME_SMOOTHTRIANGLE_H */
|
||||||
@@ -19,7 +19,7 @@ class Sphere : public Shape
|
|||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
Intersect localIntersect(Ray r);
|
Intersect localIntersect(Ray r);
|
||||||
Tuple localNormalAt(Tuple point);
|
Tuple localNormalAt(Tuple point, Intersection *hit = nullptr);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Sphere() : Shape(SHAPE_SPHERE) { stats.addSphere(); };
|
Sphere() : Shape(SHAPE_SPHERE) { stats.addSphere(); };
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class TestShape : public Shape
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Intersect localIntersect(Ray r);
|
Intersect localIntersect(Ray r);
|
||||||
Tuple localNormalAt(Tuple point);
|
Tuple localNormalAt(Tuple point, Intersection *hit = nullptr);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Ray localRay;
|
Ray localRay;
|
||||||
|
|||||||
@@ -14,8 +14,9 @@
|
|||||||
|
|
||||||
class Triangle : public Shape
|
class Triangle : public Shape
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
Intersect localIntersect(Ray r);
|
Intersect localIntersect(Ray r);
|
||||||
Tuple localNormalAt(Tuple point);
|
Tuple localNormalAt(Tuple point, Intersection *hit = nullptr);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Tuple p1, p2, p3;
|
Tuple p1, p2, p3;
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ void Intersect::add(Intersection i)
|
|||||||
this->list = (Intersection **)realloc(this->list, sizeof(Intersection *) * this->allocated);
|
this->list = (Intersection **)realloc(this->list, sizeof(Intersection *) * this->allocated);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->list[this->num++] = new Intersection(i.t, i.object);
|
this->list[this->num++] = new Intersection(i.t, i.object, i.u, i.v);
|
||||||
|
|
||||||
stats.setMaxIntersect(this->num);
|
stats.setMaxIntersect(this->num);
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,18 @@ Computation Intersection::prepareComputation(Ray r, Intersect *xs)
|
|||||||
double n2 = 1.0;
|
double n2 = 1.0;
|
||||||
|
|
||||||
Tuple hitP = r.position(this->t);
|
Tuple hitP = r.position(this->t);
|
||||||
Tuple normalV = this->object->normalAt(hitP);
|
Tuple normalV;
|
||||||
|
|
||||||
|
if (xs != nullptr)
|
||||||
|
{
|
||||||
|
Intersection hit = xs->hit();
|
||||||
|
normalV = this->object->normalAt(hitP, &hit);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
normalV = this->object->normalAt(hitP, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
Tuple eyeV = -r.direction;
|
Tuple eyeV = -r.direction;
|
||||||
bool inside = false;
|
bool inside = false;
|
||||||
|
|
||||||
@@ -70,8 +81,9 @@ Computation Intersection::prepareComputation(Ray r, Intersect *xs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Shape *s = this->object;
|
Shape *s = this->object;
|
||||||
|
|
||||||
/* For now don't get root group material */
|
/* For now don't get root group material */
|
||||||
//while(s->parent != nullptr) { s = s->parent; }
|
while((!s->materialSet) && (s->parent != nullptr)) { s = s->parent; }
|
||||||
|
|
||||||
return Computation(this->object,
|
return Computation(this->object,
|
||||||
this->t,
|
this->t,
|
||||||
|
|||||||
@@ -61,6 +61,12 @@ void RenderStats::addTriangle()
|
|||||||
this->triangleCount++;
|
this->triangleCount++;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void RenderStats::addSmoothTriangle()
|
||||||
|
{
|
||||||
|
#pragma omp atomic
|
||||||
|
this->smoothTriangleCount++;
|
||||||
|
};
|
||||||
|
|
||||||
void RenderStats::addOBJFile()
|
void RenderStats::addOBJFile()
|
||||||
{
|
{
|
||||||
#pragma omp atomic
|
#pragma omp atomic
|
||||||
@@ -154,6 +160,8 @@ void RenderStats::printStats()
|
|||||||
printf("Planes : %lld\n", this->planeCount);
|
printf("Planes : %lld\n", this->planeCount);
|
||||||
printf("Spheres : %lld\n", this->sphereCount);
|
printf("Spheres : %lld\n", this->sphereCount);
|
||||||
printf("Triangles : %lld\n", this->triangleCount);
|
printf("Triangles : %lld\n", this->triangleCount);
|
||||||
|
printf("Smooth Triangles : %lld\n", this->smoothTriangleCount);
|
||||||
|
printf("OBJ File : %lld\n", this->objfileCount);
|
||||||
printf("==================================================\n");
|
printf("==================================================\n");
|
||||||
printf("Pixel rendered : %lld\n", this->pixelCount);
|
printf("Pixel rendered : %lld\n", this->pixelCount);
|
||||||
printf("Ray casted : %lld\n", this->rayCount);
|
printf("Ray casted : %lld\n", this->rayCount);
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ Intersect Cone::localIntersect(Ray r)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tuple Cone::localNormalAt(Tuple point)
|
Tuple Cone::localNormalAt(Tuple point, Intersection *hit)
|
||||||
{
|
{
|
||||||
/* Compute the square of the distance from the Y axis */
|
/* Compute the square of the distance from the Y axis */
|
||||||
double dist = point.x * point.x + point.z * point.z;
|
double dist = point.x * point.x + point.z * point.z;
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ Intersect Cube::localIntersect(Ray r)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tuple Cube::localNormalAt(Tuple point)
|
Tuple Cube::localNormalAt(Tuple point, Intersection *hit)
|
||||||
{
|
{
|
||||||
double maxC = max3(fabs(point.x), fabs(point.y), fabs(point.z));
|
double maxC = max3(fabs(point.x), fabs(point.y), fabs(point.z));
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ Intersect Cylinder::localIntersect(Ray r)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tuple Cylinder::localNormalAt(Tuple point)
|
Tuple Cylinder::localNormalAt(Tuple point, Intersection *hit)
|
||||||
{
|
{
|
||||||
/* Compute the square of the distance from the Y axis */
|
/* Compute the square of the distance from the Y axis */
|
||||||
double dist = point.x * point.x + point.z * point.z;
|
double dist = point.x * point.x + point.z * point.z;
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ Intersect Group::localIntersect(Ray r)
|
|||||||
return Intersect();
|
return Intersect();
|
||||||
}
|
}
|
||||||
|
|
||||||
Tuple Group::localNormalAt(Tuple point)
|
Tuple Group::localNormalAt(Tuple point, Intersection *hit)
|
||||||
{
|
{
|
||||||
return Vector(1, 0, 0);
|
return Vector(1, 0, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <math_helper.h>
|
#include <math_helper.h>
|
||||||
#include <group.h>
|
#include <group.h>
|
||||||
#include <triangle.h>
|
#include <triangle.h>
|
||||||
|
#include <smoothtriangle.h>
|
||||||
|
|
||||||
#define MIN_ALLOC (2)
|
#define MIN_ALLOC (2)
|
||||||
#define DEFAULT_GROUP (0)
|
#define DEFAULT_GROUP (0)
|
||||||
@@ -33,6 +34,11 @@ OBJFile::OBJFile() : Shape(SHAPE_OBJFILE), ignoredLines(0)
|
|||||||
this->vertexList = (Point **)calloc(sizeof(Point **), MIN_ALLOC);
|
this->vertexList = (Point **)calloc(sizeof(Point **), MIN_ALLOC);
|
||||||
this->vertexCount = 0;
|
this->vertexCount = 0;
|
||||||
|
|
||||||
|
|
||||||
|
this->allocatedVertexNormalCount = MIN_ALLOC;
|
||||||
|
this->vertexNormalList = (Vector **)calloc(sizeof(Vector **), MIN_ALLOC);
|
||||||
|
this->vertexNormalCount = 0;
|
||||||
|
|
||||||
/* There is always a default group */
|
/* There is always a default group */
|
||||||
this->addGroup(new Group());
|
this->addGroup(new Group());
|
||||||
};
|
};
|
||||||
@@ -89,13 +95,24 @@ void OBJFile::addVertex(Point *vertex)
|
|||||||
this->vertexList[this->vertexCount++] = vertex;
|
this->vertexList[this->vertexCount++] = vertex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OBJFile::addVertexNormal(Vector *vertexNormal)
|
||||||
|
{
|
||||||
|
if ((this->vertexNormalCount + 1) > this->allocatedVertexNormalCount)
|
||||||
|
{
|
||||||
|
this->allocatedVertexNormalCount *= 2;
|
||||||
|
this->vertexNormalList = (Vector **)realloc(this->vertexNormalList, sizeof(Vector **) * this->allocatedVertexNormalCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->vertexNormalList[this->vertexNormalCount++] = vertexNormal;
|
||||||
|
}
|
||||||
|
|
||||||
Intersect OBJFile::intersect(Ray r)
|
Intersect OBJFile::intersect(Ray r)
|
||||||
{
|
{
|
||||||
Intersect ret;
|
Intersect ret;
|
||||||
int i, j;
|
int i, j;
|
||||||
if (this->faceGroupCount > 0)
|
if (this->faceGroupCount > 0)
|
||||||
{
|
{
|
||||||
//if (this->bounds.intesectMe(r))
|
if (this->bounds.intesectMe(r))
|
||||||
{
|
{
|
||||||
for (i = 0 ; i < this->faceGroupCount ; i++)
|
for (i = 0 ; i < this->faceGroupCount ; i++)
|
||||||
{
|
{
|
||||||
@@ -118,7 +135,7 @@ Intersect OBJFile::localIntersect(Ray r)
|
|||||||
return Intersect();
|
return Intersect();
|
||||||
}
|
}
|
||||||
|
|
||||||
Tuple OBJFile::localNormalAt(Tuple point)
|
Tuple OBJFile::localNormalAt(Tuple point, Intersection *hit)
|
||||||
{
|
{
|
||||||
return Vector(0, 1, 0);
|
return Vector(0, 1, 0);
|
||||||
}
|
}
|
||||||
@@ -262,11 +279,51 @@ void OBJFile::parseLine(char *line, uint32_t currentLine)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int parseFaceVertex(char *buf, uint32_t &v, uint32_t &vt, uint32_t &vn)
|
||||||
|
{
|
||||||
|
uint32_t bufPos = 0;
|
||||||
|
uint32_t lineLength = strlen(buf);
|
||||||
|
char *tmp = buf;
|
||||||
|
vt = INT32_MAX;
|
||||||
|
vn = INT32_MAX;
|
||||||
|
int ret = 0;
|
||||||
|
int token = 0;
|
||||||
|
|
||||||
|
while(bufPos < lineLength)
|
||||||
|
{
|
||||||
|
char *next = strchr(buf, '/');
|
||||||
|
if (next != nullptr)
|
||||||
|
{
|
||||||
|
*next = '\0';
|
||||||
|
bufPos = next - buf;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bufPos = lineLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(buf) > 0)
|
||||||
|
{
|
||||||
|
switch(token)
|
||||||
|
{
|
||||||
|
case 0: v = atol(buf); break;
|
||||||
|
case 1: vt = atol(buf); break;
|
||||||
|
case 2: vn = atol(buf); break;
|
||||||
|
default: printf("ERROR: Too many entry for a face vertice!"); ret = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf = next + 1;
|
||||||
|
token++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Actually execute the line */
|
/* Actually execute the line */
|
||||||
int OBJFile::execLine(int argc, char *argv[], uint32_t currentLine)
|
int OBJFile::execLine(int argc, char *argv[], uint32_t currentLine)
|
||||||
{
|
{
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
if (strncmp(argv[0], "v", 1) == 0)
|
if (strncmp(argv[0], "v", 2) == 0)
|
||||||
{
|
{
|
||||||
/* Vertice entry */
|
/* Vertice entry */
|
||||||
if (argc != 4)
|
if (argc != 4)
|
||||||
@@ -279,25 +336,71 @@ int OBJFile::execLine(int argc, char *argv[], uint32_t currentLine)
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strncmp(argv[0], "f", 1) == 0)
|
else if (strncmp(argv[0], "vn", 3) == 0)
|
||||||
{
|
{
|
||||||
/* Vertice entry */
|
/* Vertice Normal entry */
|
||||||
|
if (argc != 4)
|
||||||
|
{
|
||||||
|
printf("ERROR: Malformed file at line %d: Vertices normal expect 3 parameters!\n", currentLine);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->addVertexNormal(new Vector(atof(argv[1]), atof(argv[2]), atof(argv[3])));
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strncmp(argv[0], "f", 2) == 0)
|
||||||
|
{
|
||||||
|
/* Faces entry */
|
||||||
|
int i;
|
||||||
|
uint32_t v[MAX_ARGS], vt[MAX_ARGS], vn[MAX_ARGS];
|
||||||
|
for(i = 1; i < argc; i++)
|
||||||
|
{
|
||||||
|
parseFaceVertex(argv[i], v[i], vt[i], vn[i]);
|
||||||
|
}
|
||||||
|
|
||||||
if (argc == 4)
|
if (argc == 4)
|
||||||
{
|
{
|
||||||
Shape *t = new Triangle(this->vertices(atoi(argv[1])),
|
Shape *t;
|
||||||
this->vertices(atoi(argv[2])),
|
if (vn[1] == INT32_MAX)
|
||||||
this->vertices(atoi(argv[3])));
|
{
|
||||||
|
t = new Triangle(this->vertices(v[1]),
|
||||||
|
this->vertices(v[2]),
|
||||||
|
this->vertices(v[3]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t = new SmoothTriangle(this->vertices(v[1]),
|
||||||
|
this->vertices(v[2]),
|
||||||
|
this->vertices(v[3]),
|
||||||
|
this->verticesNormal(vn[1]),
|
||||||
|
this->verticesNormal(vn[2]),
|
||||||
|
this->verticesNormal(vn[3]));
|
||||||
|
}
|
||||||
this->faceGroupList[this->faceGroupCount - 1]->addObject(t);
|
this->faceGroupList[this->faceGroupCount - 1]->addObject(t);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
else if (argc > 4)
|
else if (argc > 4)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
for(i = 2; i < (argc - 1); i++)
|
for(i = 2; i < (argc - 1); i++)
|
||||||
{
|
{
|
||||||
Shape *t = new Triangle(this->vertices(atoi(argv[1])),
|
|
||||||
this->vertices(atoi(argv[i])),
|
Shape *t;
|
||||||
this->vertices(atoi(argv[i+1])));
|
if (vn[1] == INT32_MAX)
|
||||||
|
{
|
||||||
|
t = new Triangle(this->vertices(v[1]),
|
||||||
|
this->vertices(v[i]),
|
||||||
|
this->vertices(v[i + 1]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t = new SmoothTriangle(this->vertices(v[1]),
|
||||||
|
this->vertices(v[i]),
|
||||||
|
this->vertices(v[i + 1]),
|
||||||
|
this->verticesNormal(vn[1]),
|
||||||
|
this->verticesNormal(vn[i]),
|
||||||
|
this->verticesNormal(vn[i + 1]));
|
||||||
|
}
|
||||||
this->faceGroupList[this->faceGroupCount - 1]->addObject(t);
|
this->faceGroupList[this->faceGroupCount - 1]->addObject(t);
|
||||||
}
|
}
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@@ -307,7 +410,7 @@ int OBJFile::execLine(int argc, char *argv[], uint32_t currentLine)
|
|||||||
printf("ERROR: Malformed file at line %d: Too few/many parameters!\n", currentLine);
|
printf("ERROR: Malformed file at line %d: Too few/many parameters!\n", currentLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strncmp(argv[0], "g", 1) == 0)
|
else if (strncmp(argv[0], "g", 2) == 0)
|
||||||
{
|
{
|
||||||
if (argc == 2)
|
if (argc == 2)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ Intersect Plane::localIntersect(Ray r)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tuple Plane::localNormalAt(Tuple point)
|
Tuple Plane::localNormalAt(Tuple point, Intersection *hit)
|
||||||
{
|
{
|
||||||
return Vector(0, 1, 0);
|
return Vector(0, 1, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ Shape::Shape(ShapeType type)
|
|||||||
this->type = type;
|
this->type = type;
|
||||||
this->localTransformMatrix = Matrix4().identity();
|
this->localTransformMatrix = Matrix4().identity();
|
||||||
this->updateTransform();
|
this->updateTransform();
|
||||||
|
this->materialSet = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Intersect Shape::intersect(Ray r)
|
Intersect Shape::intersect(Ray r)
|
||||||
@@ -37,11 +38,11 @@ Tuple Shape::normalToWorld(Tuple normalVector)
|
|||||||
return world_normal.normalise();
|
return world_normal.normalise();
|
||||||
};
|
};
|
||||||
|
|
||||||
Tuple Shape::normalAt(Tuple point)
|
Tuple Shape::normalAt(Tuple point, Intersection *hit)
|
||||||
{
|
{
|
||||||
Tuple local_point = this->worldToObject(point);
|
Tuple local_point = this->worldToObject(point);
|
||||||
|
|
||||||
Tuple local_normal = this->localNormalAt(local_point);
|
Tuple local_normal = this->localNormalAt(local_point, hit);
|
||||||
|
|
||||||
Tuple world_normal = this->normalToWorld(local_normal);
|
Tuple world_normal = this->normalToWorld(local_normal);
|
||||||
|
|
||||||
|
|||||||
28
source/shapes/smoothtriangle.cpp
Normal file
28
source/shapes/smoothtriangle.cpp
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* DoRayMe - a quick and dirty Raytracer
|
||||||
|
* Smooth Triangle implementation
|
||||||
|
*
|
||||||
|
* Created by Manoël Trapier
|
||||||
|
* Copyright (c) 2020 986-Studio.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <ray.h>
|
||||||
|
#include <shape.h>
|
||||||
|
#include <triangle.h>
|
||||||
|
#include <smoothtriangle.h>
|
||||||
|
#include <math_helper.h>
|
||||||
|
#include <renderstat.h>
|
||||||
|
|
||||||
|
SmoothTriangle::SmoothTriangle(Point p1, Point p2, Point p3, Vector n1, Vector n2, Vector n3) : Triangle(p1, p2, p3),
|
||||||
|
n1(n1), n2(n2), n3(n3)
|
||||||
|
{
|
||||||
|
this->type = SHAPE_SMOOTHTRIANGLE;
|
||||||
|
stats.addSmoothTriangle();
|
||||||
|
}
|
||||||
|
|
||||||
|
Tuple SmoothTriangle::localNormalAt(Tuple point, Intersection *hit)
|
||||||
|
{
|
||||||
|
return (this->n2 * hit->u +
|
||||||
|
this->n3 * hit->v +
|
||||||
|
this->n1 * (1 - hit->u - hit->v)).normalise();
|
||||||
|
}
|
||||||
@@ -35,7 +35,7 @@ Intersect Sphere::localIntersect(Ray r)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tuple Sphere::localNormalAt(Tuple point)
|
Tuple Sphere::localNormalAt(Tuple point, Intersection *hit)
|
||||||
{
|
{
|
||||||
return (point - Point(0, 0, 0)).normalise();
|
return (point - Point(0, 0, 0)).normalise();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ Intersect TestShape::localIntersect(Ray r)
|
|||||||
return Intersect();
|
return Intersect();
|
||||||
}
|
}
|
||||||
|
|
||||||
Tuple TestShape::localNormalAt(Tuple point)
|
Tuple TestShape::localNormalAt(Tuple point, Intersection *hit)
|
||||||
{
|
{
|
||||||
return Vector(point.x, point.y, point.z);
|
return Vector(point.x, point.y, point.z);
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* DoRayMe - a quick and dirty Raytracer
|
* DoRayMe - a quick and dirty Raytracer
|
||||||
* Cone implementation
|
* Triangle implementation
|
||||||
*
|
*
|
||||||
* Created by Manoël Trapier
|
* Created by Manoël Trapier
|
||||||
* Copyright (c) 2020 986-Studio.
|
* Copyright (c) 2020 986-Studio.
|
||||||
@@ -49,12 +49,12 @@ Intersect Triangle::localIntersect(Ray r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
double t = f * this->e2.dot(originCrossE1);
|
double t = f * this->e2.dot(originCrossE1);
|
||||||
ret.add(Intersection(t, this));
|
ret.add(Intersection(t, this, u, v));
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tuple Triangle::localNormalAt(Tuple point)
|
Tuple Triangle::localNormalAt(Tuple point, Intersection *hit)
|
||||||
{
|
{
|
||||||
return this->normal;
|
return this->normal;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ link_libraries(rayonnement)
|
|||||||
set(TESTS_SRC math_test.cpp tuple_test.cpp colour_test.cpp canvas_test.cpp matrix_test.cpp transformation_test.cpp
|
set(TESTS_SRC math_test.cpp tuple_test.cpp colour_test.cpp canvas_test.cpp matrix_test.cpp transformation_test.cpp
|
||||||
ray_test.cpp intersect_test.cpp sphere_test.cpp light_test.cpp material_test.cpp world_test.cpp camera_test.cpp
|
ray_test.cpp intersect_test.cpp sphere_test.cpp light_test.cpp material_test.cpp world_test.cpp camera_test.cpp
|
||||||
shape_test.cpp plane_test.cpp pattern_test.cpp cube_test.cpp cylinder_test.cpp cone_test.cpp group_test.cpp
|
shape_test.cpp plane_test.cpp pattern_test.cpp cube_test.cpp cylinder_test.cpp cone_test.cpp group_test.cpp
|
||||||
boundingbox_test.cpp triangle_test.cpp sequence_test.cpp objfile_test.cpp)
|
boundingbox_test.cpp triangle_test.cpp sequence_test.cpp objfile_test.cpp smoothtriangle_test.cpp)
|
||||||
|
|
||||||
add_executable(testMyRays)
|
add_executable(testMyRays)
|
||||||
target_include_directories(testMyRays PUBLIC ${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
|
target_include_directories(testMyRays PUBLIC ${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
|
||||||
@@ -147,6 +147,7 @@ add_test(NAME Chapter12_Test COMMAND $<TARGET_FILE:ch12_test>)
|
|||||||
add_test(NAME Chapter13_Test COMMAND $<TARGET_FILE:ch13_test>)
|
add_test(NAME Chapter13_Test COMMAND $<TARGET_FILE:ch13_test>)
|
||||||
add_test(NAME Chapter13_ConeBonus COMMAND $<TARGET_FILE:ch13_cone>)
|
add_test(NAME Chapter13_ConeBonus COMMAND $<TARGET_FILE:ch13_cone>)
|
||||||
add_test(NAME Chapter14_Test COMMAND $<TARGET_FILE:ch14_test>)
|
add_test(NAME Chapter14_Test COMMAND $<TARGET_FILE:ch14_test>)
|
||||||
|
add_test(NAME Chapter15_Teapots COMMAND $<TARGET_FILE:ch15_teapot_objfile>)
|
||||||
add_test(NAME AreaLight_Test COMMAND $<TARGET_FILE:arealight_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_CheckeredSphere COMMAND $<TARGET_FILE:uvmap_checkeredsphere>)
|
||||||
add_test(NAME UVMap_CheckeredPlane COMMAND $<TARGET_FILE:uvmap_checkeredplane>)
|
add_test(NAME UVMap_CheckeredPlane COMMAND $<TARGET_FILE:uvmap_checkeredplane>)
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ int main()
|
|||||||
/* ----------------------------- */
|
/* ----------------------------- */
|
||||||
|
|
||||||
/* Set the camera */
|
/* Set the camera */
|
||||||
Camera camera = Camera(400, 160, 0.7854);
|
Camera camera = Camera(40, 16, 0.7854);
|
||||||
camera.setTransform(viewTransform(Point(-3, 1, 2.5),
|
camera.setTransform(viewTransform(Point(-3, 1, 2.5),
|
||||||
Point(0, 0.5, 0),
|
Point(0, 0.5, 0),
|
||||||
Vector(0, 1, 0)));
|
Vector(0, 1, 0)));
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ int main()
|
|||||||
bg4.material.shininess = 50;
|
bg4.material.shininess = 50;
|
||||||
w.addObject(&bg4);
|
w.addObject(&bg4);
|
||||||
|
|
||||||
/* Forground balls */
|
/* Foreground balls */
|
||||||
|
|
||||||
/* Red sphere */
|
/* Red sphere */
|
||||||
Sphere redBall = Sphere();
|
Sphere redBall = Sphere();
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ int main()
|
|||||||
World w = World();
|
World w = World();
|
||||||
|
|
||||||
/* Add lights */
|
/* Add lights */
|
||||||
Light light1 = Light(POINT_LIGHT, Point(0, 20, 2), Colour(1, 1, 1));
|
Light light1 = Light(POINT_LIGHT, Point(50, 100, 20), Colour(.5, .5, .5));
|
||||||
w.addLight(&light1);
|
w.addLight(&light1);
|
||||||
Light light2 = Light(POINT_LIGHT, Point(0, 2, 20), Colour(1, 1, 1));
|
Light light2 = Light(POINT_LIGHT, Point(2, 50, 100), Colour(.5, .5, .5));
|
||||||
w.addLight(&light2);
|
w.addLight(&light2);
|
||||||
|
|
||||||
/* ----------------------------- */
|
/* ----------------------------- */
|
||||||
@@ -42,6 +42,7 @@ int main()
|
|||||||
p.material.ambient = 1;
|
p.material.ambient = 1;
|
||||||
p.material.diffuse = 0;
|
p.material.diffuse = 0;
|
||||||
p.material.specular = 0;
|
p.material.specular = 0;
|
||||||
|
p.material.reflective = 0.1;
|
||||||
w.addObject(&p);
|
w.addObject(&p);
|
||||||
|
|
||||||
Plane p2 = Plane();
|
Plane p2 = Plane();
|
||||||
@@ -53,26 +54,31 @@ int main()
|
|||||||
w.addObject(&p2);
|
w.addObject(&p2);
|
||||||
|
|
||||||
OBJFile teapot = OBJFile("teapot-low.obj");
|
OBJFile teapot = OBJFile("teapot-low.obj");
|
||||||
teapot.setTransform(rotationY(M_PI) * rotationX(-M_PI/2) * scaling(0.4, 0.4, 0.4));
|
teapot.setTransform(translation(7, 0, 3) * rotationY(M_PI*23/22) * rotationX(-M_PI/2) * scaling(0.3, 0.3, 0.3));
|
||||||
teapot.material.colour = Colour(1, 0.2, 0.1);
|
teapot.material.colour = Colour(1, 0.3, 0.2);
|
||||||
teapot.material.ambient = 0.2;
|
teapot.material.shininess = 5;
|
||||||
teapot.material.specular = 0.2;
|
teapot.material.specular = 0.4;
|
||||||
teapot.material.diffuse = 20;
|
|
||||||
w.addObject(&teapot);
|
w.addObject(&teapot);
|
||||||
|
|
||||||
/* ----------------------------- */
|
OBJFile teapot2 = OBJFile("teapot-lowtri.obj");
|
||||||
|
teapot2.setTransform(translation(-7, 0, 3) * rotationY(-M_PI*46/22) * rotationX(-M_PI/2) * scaling(0.3, 0.3, 0.3));
|
||||||
|
teapot2.material.colour = Colour(1, 0.3, 0.2);
|
||||||
|
teapot2.material.shininess = 5;
|
||||||
|
teapot2.material.specular = 0.4;
|
||||||
|
w.addObject(&teapot2);
|
||||||
|
|
||||||
FILE *fpOut = fopen("teapot_worlddump.json", "wt");
|
OBJFile teapot3= OBJFile("teapot.obj");
|
||||||
if (fpOut)
|
teapot3.setTransform(translation(0, 0, -5) * rotationY(-M_PI) * rotationX(-M_PI/2) * scaling(0.4, 0.4, 0.4));
|
||||||
{
|
teapot3.material.colour = Colour(0.3, 1, 0.2);
|
||||||
w.dumpMe(fpOut);
|
teapot3.material.shininess = 5;
|
||||||
fclose(fpOut);
|
teapot3.material.specular = 0.4;
|
||||||
}
|
teapot3.material.reflective = 0.5;
|
||||||
|
w.addObject(&teapot3);
|
||||||
|
|
||||||
/* ----------------------------- */
|
/* ----------------------------- */
|
||||||
|
|
||||||
/* Set the camera */
|
/* Set the camera */
|
||||||
Camera camera = Camera(800, 400, M_PI/2);
|
Camera camera = Camera(80, 40, M_PI/2);
|
||||||
camera.setTransform(viewTransform(Point(0, 7, 13),
|
camera.setTransform(viewTransform(Point(0, 7, 13),
|
||||||
Point(0, 1, 0),
|
Point(0, 1, 0),
|
||||||
Vector(0, 1, 0)));
|
Vector(0, 1, 0)));
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <intersection.h>
|
#include <intersection.h>
|
||||||
#include <sphere.h>
|
#include <sphere.h>
|
||||||
#include <plane.h>
|
#include <plane.h>
|
||||||
|
#include <triangle.h>
|
||||||
#include <transformation.h>
|
#include <transformation.h>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
@@ -303,3 +304,12 @@ TEST(IntersectTest, The_Schlick_approximation_with_small_angle_and_n2_gt_n1)
|
|||||||
|
|
||||||
set_equal_precision(FLT_EPSILON);
|
set_equal_precision(FLT_EPSILON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(IntersectTest, An_intersection_can_encapsulage_u_and_v)
|
||||||
|
{
|
||||||
|
Triangle s = Triangle(Point(0, 1, 0), Point(-1, 0, 0), Point(1, 0, 0));
|
||||||
|
Intersection i = Intersection(3.5, &s, 0.2, 0.4);
|
||||||
|
|
||||||
|
ASSERT_EQ(i.u, 0.2);
|
||||||
|
ASSERT_EQ(i.v, 0.4);
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <triangle.h>
|
#include <triangle.h>
|
||||||
|
#include <smoothtriangle.h>
|
||||||
|
|
||||||
TEST(OBJFileTest, Ignoring_unrecognised_lines)
|
TEST(OBJFileTest, Ignoring_unrecognised_lines)
|
||||||
{
|
{
|
||||||
@@ -119,3 +120,57 @@ TEST(OBJFileTest, Triangle_in_groups)
|
|||||||
ASSERT_EQ(t2->p2, parser.vertices(3));
|
ASSERT_EQ(t2->p2, parser.vertices(3));
|
||||||
ASSERT_EQ(t2->p3, parser.vertices(4));
|
ASSERT_EQ(t2->p3, parser.vertices(4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(OBJFileTest, Vertex_normal_record)
|
||||||
|
{
|
||||||
|
const char file[] = "vn 0 0 1\n"
|
||||||
|
"vn 0.707 0 -0.707\n"
|
||||||
|
"vn 1 2 3\n";
|
||||||
|
|
||||||
|
OBJFile parser = OBJFile();
|
||||||
|
parser.parseOBJFile(file);
|
||||||
|
|
||||||
|
ASSERT_EQ(parser.verticesNormal(1), Vector(0, 0, 1));
|
||||||
|
ASSERT_EQ(parser.verticesNormal(2), Vector(0.707, 0, -0.707));
|
||||||
|
ASSERT_EQ(parser.verticesNormal(3), Vector(1, 2, 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(OBJFileTest, Faces_with_normal)
|
||||||
|
{
|
||||||
|
const char file[] = "v 0 1 0\n"
|
||||||
|
"v -1 0 0\n"
|
||||||
|
"v 1 0 0\n"
|
||||||
|
"\n"
|
||||||
|
"vn -1 0 0\n"
|
||||||
|
"vn 1 0 0\n"
|
||||||
|
"vn 0 1 0\n"
|
||||||
|
"\n"
|
||||||
|
"f 1//3 2//1 3//2\n"
|
||||||
|
"f 1/0/3 2/102/1 3/14/2\n";
|
||||||
|
|
||||||
|
OBJFile parser = OBJFile();
|
||||||
|
parser.parseOBJFile(file);
|
||||||
|
|
||||||
|
Group *g0 = parser.groups(0);
|
||||||
|
|
||||||
|
SmoothTriangle *t1 = (SmoothTriangle *)(*g0)[0];
|
||||||
|
SmoothTriangle *t2 = (SmoothTriangle *)(*g0)[1];
|
||||||
|
|
||||||
|
ASSERT_EQ(t1->p1, parser.vertices(1));
|
||||||
|
ASSERT_EQ(t1->p2, parser.vertices(2));
|
||||||
|
ASSERT_EQ(t1->p3, parser.vertices(3));
|
||||||
|
|
||||||
|
ASSERT_EQ(t1->n1, parser.verticesNormal(3));
|
||||||
|
ASSERT_EQ(t1->n2, parser.verticesNormal(1));
|
||||||
|
ASSERT_EQ(t1->n3, parser.verticesNormal(2));
|
||||||
|
|
||||||
|
ASSERT_EQ(t2->p1, parser.vertices(1));
|
||||||
|
ASSERT_EQ(t2->p2, parser.vertices(2));
|
||||||
|
ASSERT_EQ(t2->p3, parser.vertices(3));
|
||||||
|
|
||||||
|
ASSERT_EQ(t2->n1, parser.verticesNormal(3));
|
||||||
|
ASSERT_EQ(t2->n2, parser.verticesNormal(1));
|
||||||
|
ASSERT_EQ(t2->n3, parser.verticesNormal(2));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
83
tests/smoothtriangle_test.cpp
Normal file
83
tests/smoothtriangle_test.cpp
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* DoRayMe - a quick and dirty Raytracer
|
||||||
|
* Smooth Triangle unit tests
|
||||||
|
*
|
||||||
|
* Created by Manoël Trapier
|
||||||
|
* Copyright (c) 2020 986-Studio.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <smoothtriangle.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
class SmoothTriTest : public SmoothTriangle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SmoothTriTest(Point p1, Point p2, Point p3, Vector n1, Vector n2, Vector n3) : SmoothTriangle(p1, p2, p3, n1, n2, n3) {};
|
||||||
|
Intersect doLocalIntersect(Ray ray)
|
||||||
|
{
|
||||||
|
return this->localIntersect(ray);
|
||||||
|
};
|
||||||
|
|
||||||
|
Tuple doLocalNormalAt(Tuple point, Intersection *hit)
|
||||||
|
{
|
||||||
|
return this->localNormalAt(point, hit);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Point p1 = Point(0, 1, 0);
|
||||||
|
Point p2 = Point(-1, 0, 0);
|
||||||
|
Point p3 = Point(1, 0, 0);
|
||||||
|
Vector n1 = Vector(0, 1, 0);
|
||||||
|
Vector n2 = Vector(-1, 0, 0);
|
||||||
|
Vector n3 = Vector(1, 0, 0);
|
||||||
|
|
||||||
|
SmoothTriTest tri = SmoothTriTest(p1, p2, p3, n1, n2, n3);
|
||||||
|
|
||||||
|
TEST(SmoothTriangleTest, Construcring_a_smooth_triangle)
|
||||||
|
{
|
||||||
|
ASSERT_EQ(tri.p1, p1);
|
||||||
|
ASSERT_EQ(tri.p2, p2);
|
||||||
|
ASSERT_EQ(tri.p3, p3);
|
||||||
|
ASSERT_EQ(tri.n1, n1);
|
||||||
|
ASSERT_EQ(tri.n2, n2);
|
||||||
|
ASSERT_EQ(tri.n3, n3);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SmoothTriangleTest, An_intersection_with_a_smooth_triangle_stores_u_v)
|
||||||
|
{
|
||||||
|
Ray r = Ray(Point(-0.2, 0.3, -2), Vector(0, 0, 1));
|
||||||
|
|
||||||
|
Intersect xs = tri.doLocalIntersect(r);
|
||||||
|
|
||||||
|
ASSERT_TRUE(double_equal(xs[0].u, 0.45));
|
||||||
|
ASSERT_TRUE(double_equal(xs[0].v, 0.25));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SmoothTriangleTest, A_smooth_triangle_uses_u_v_to_interpolate_the_normal)
|
||||||
|
{
|
||||||
|
Intersection i = Intersection(1, &tri, 0.45, 0.25);
|
||||||
|
|
||||||
|
Tuple n = tri.doLocalNormalAt(Point(0, 0, 0), &i);
|
||||||
|
|
||||||
|
/* Temporary lower the precision */
|
||||||
|
set_equal_precision(0.00001);
|
||||||
|
|
||||||
|
ASSERT_EQ(n, Vector(-0.5547, 0.83205, 0));
|
||||||
|
|
||||||
|
set_equal_precision(FLT_EPSILON);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SmoothTriangleTest, Preparing_a_normal_on_a_smooth_triangle)
|
||||||
|
{
|
||||||
|
Intersection i = Intersection(1, &tri, 0.45, 0.25);
|
||||||
|
|
||||||
|
Tuple n = tri.normalAt(Point(0, 0, 0), &i);
|
||||||
|
|
||||||
|
/* Temporary lower the precision */
|
||||||
|
set_equal_precision(0.00001);
|
||||||
|
|
||||||
|
ASSERT_EQ(n, Vector(-0.5547, 0.83205, 0));
|
||||||
|
|
||||||
|
set_equal_precision(FLT_EPSILON);
|
||||||
|
}
|
||||||
@@ -119,7 +119,7 @@ int main()
|
|||||||
/* ----------------------------- */
|
/* ----------------------------- */
|
||||||
|
|
||||||
/* Set the camera */
|
/* Set the camera */
|
||||||
Camera camera = Camera(1280, 900, deg_to_rad(90));
|
Camera camera = Camera(40, 10, deg_to_rad(90));
|
||||||
camera.setTransform(viewTransform(Point(-2, 2.5, -3.5),
|
camera.setTransform(viewTransform(Point(-2, 2.5, -3.5),
|
||||||
Point(2, 0, 3),
|
Point(2, 0, 3),
|
||||||
Vector(0, 1, 0)));
|
Vector(0, 1, 0)));
|
||||||
|
|||||||
Reference in New Issue
Block a user