-
Notifications
You must be signed in to change notification settings - Fork 0
/
camera.h
183 lines (141 loc) · 5.76 KB
/
camera.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#ifndef _CAMERA_H
#define _CAMERA_H
#include <vector>
#include "mathHelper.h"
#include "world.h"
#include <future>
#include <thread>
class Camera {
// camera'ss position
Point position;
// camera's lookat
Point lookAt;
// camera's up vector
Vector up;
// the view-plane distance, fixed at 0.5
double focalLength = 0.5;
// view corrdinate system
Vector u,v,w;
//
// values to render the world
//
// pixels
int imageHeight, imageWidth;
// keeping the aspect ratio of the window pixels
double viewPlaneHeigth, viewPlaneWidth;
// each pixel
double unitsHigh, unitsWidth;
// 'first pixels' where the view will stay
double firstPixelx, firstPixely;
// max depth, the bounces of the ray
int MAX_DEPTH;
// number of rays we will use per pixel
int raysPerPixel;
// This function is given the world and the pixel, it will return the color
// of that pixel. In other words i ranges from [0,imageWidth] and
// j ranges from [0,imageHeight]
Color getColorInPixel(World world, int i, int j) {
// ray direction
double dx,dy,dz;
// Color average
Color average;
double startx = (firstPixelx + i * unitsWidth);
double starty = (firstPixely - j * unitsHigh);
for(int a = 0; a < raysPerPixel; ++a) {
double randx = static_cast <double> (rand()) / (static_cast <double> (RAND_MAX/unitsWidth));
double randy = static_cast <double> (rand()) / (static_cast <double> (RAND_MAX/unitsHigh));
dx = startx + randx ;
dy = starty - randy ;
dz = focalLength;
Vector dir = dx*u + dy*v - dz*w;
normalize(dir);
// ray
Ray ray(position, dir);
// Color average
average += world.spawn( ray , MAX_DEPTH );
}
// get final color, if grid need to average
average = (average / static_cast <double> (raysPerPixel));
return average;
}
public:
// rayType = if we are doing ray tracing or ray marching
// ray marching here was implemented so far only for volumetric lighthing,
// so some other values will need to be set up before using it (ka and ks for instance)
Camera(Point pos, Point look, Vector up, int imH, int imW, double viewH, double viewW, int depthOrSamples, int raysPerPixel) :
position(pos), lookAt(look), up(up), imageHeight(imH), imageWidth(imW), viewPlaneHeigth(viewH), viewPlaneWidth(viewW), raysPerPixel(raysPerPixel) {
// each pixel
unitsHigh = viewH/imH;
unitsWidth = viewW/imW;
// first pixel of our view// first pixel is at
firstPixelx = -viewPlaneWidth*0.5;
firstPixely = viewPlaneHeigth*0.5;
// defining the viewing coordinates
// oposite direction to help calculations
w = Vector(lookAt,position,true);
normalize(w);
u = cross(up,w);
normalize(u);
v = cross(w,u);
MAX_DEPTH = depthOrSamples;
}
std::vector<Color> render (World world) {
// Size of canvas
int pixelNum = imageWidth * imageHeight;
#ifdef MULTI_THREADED
std::cout << "Status: Using multi threaded ray tracer." << std::endl;
int cores = std::thread::hardware_concurrency();
volatile std::atomic<int> count(0);
volatile std::atomic<double> tenPercentIncrement(0.01);
std::vector<std::future<void> > futureVector;
// Result color of a ray
std::vector<Color> colorMap(pixelNum);
while (cores--) {
futureVector.push_back(
std::async([=, &colorMap, &world, &count, &tenPercentIncrement]()
{
while (true) {
int index = count++;
if (index >= pixelNum)
break;
#ifdef SHOW_PROGRESS
if (index > pixelNum * tenPercentIncrement) {
std::cout << "Status: Image processing: " << 100 * tenPercentIncrement << "% complete..." << std::endl;
tenPercentIncrement = 0.01 + tenPercentIncrement;
}
#endif
int i = index / imageWidth;
int j = index % imageWidth;
colorMap[index] = getColorInPixel(world,i,j);
}
}));
}
#else
std::cout << "Status: Using single thread ray tracer." << std::endl;
int count = 0;
double tenPercentIncrement = 0.01;
// Result color of a ray
std::vector<Color> colorMap;
// this loop is going like
// consider origin at top left
// fixate column
// go through the rows in the column
// then go to next column
for(int i = 0; i < imageWidth; ++i) {
for(int j = 0; j < imageHeight; ++j) {
colorMap.push_back( getColorInPixel(world,i,j) );
#ifdef SHOW_PROGRESS
count++;
if (count > pixelNum * tenPercentIncrement) {
std::cout << "Status: Image processing: " << 100 * tenPercentIncrement << "% complete..." << std::endl;
tenPercentIncrement = 0.01 + tenPercentIncrement;
}
#endif
}
}
#endif
// will return a vector with imageWidth * imageHeight values, use it to paint the canvas
return colorMap;
}
};
#endif