-
Notifications
You must be signed in to change notification settings - Fork 0
/
1905095_object.h
313 lines (273 loc) · 8.7 KB
/
1905095_object.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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
#include "1905095_spotLight.h"
class object;
extern vector <pointLight*> point_lights;
extern vector <spotLight*> spot_lights;
extern vector <object*> objects;
extern int recursion_depth;
class object
{
protected:
vectorPoint3D ref_point;
double height, width, length;
color clr;
double ambient, diffuse, specular, reflection, refraction;
int shininess;
public:
object();
// getter and setter
void setRefPoint(vectorPoint3D p);
void setHeight(double h);
void setWidth(double w);
void setLength(double l);
void setColor(color c);
void setAmbient(double a);
void setDiffuse(double d);
void setSpecular(double s);
void setShininess(int s);
void setReflection(double r);
void setRefraction(double r);
vectorPoint3D getRefPoint();
double getHeight();
double getWidth();
double getLength();
virtual color getColor(vectorPoint3D p);
double getAmbient();
double getDiffuse();
double getSpecular();
int getShininess();
double getReflection();
double getRefraction();
virtual void draw() = 0;
virtual double findIntersection(ray r, color &col, int depth) = 0;
virtual ray getNormalAt(vectorPoint3D point, ray incident) = 0;
virtual double intersect(ray r, color &col, int depth);
// distructor
~object();
};
object::object()
{
ref_point = vectorPoint3D();
height = 0;
width = 0;
length = 0;
clr = color();
ambient = 0;
diffuse = 0;
specular = 0;
shininess = 0;
reflection = 0;
refraction = 0;
}
// getter and setter
void object::setRefPoint(vectorPoint3D p)
{
ref_point = p;
}
void object::setHeight(double h)
{
height = h;
}
void object::setWidth(double w)
{
width = w;
}
void object::setLength(double l)
{
length = l;
}
void object::setColor(color c)
{
clr = c;
}
void object::setAmbient(double a)
{
ambient = a;
}
void object::setDiffuse(double d)
{
diffuse = d;
}
void object::setSpecular(double s)
{
specular = s;
}
void object::setShininess(int s)
{
shininess = s;
}
void object::setReflection(double r)
{
reflection = r;
}
void object::setRefraction(double r)
{
refraction = r;
}
vectorPoint3D object::getRefPoint()
{
return ref_point;
}
double object::getHeight()
{
return height;
}
double object::getWidth()
{
return width;
}
double object::getLength()
{
return length;
}
color object::getColor(vectorPoint3D p)
{
return color(this->clr.r , this->clr.g , this->clr.b);
}
double object::getAmbient()
{
return ambient;
}
double object::getDiffuse()
{
return diffuse;
}
double object::getSpecular()
{
return specular;
}
int object::getShininess()
{
return shininess;
}
double object::getReflection()
{
return reflection;
}
double object::getRefraction()
{
return refraction;
}
double object::intersect(ray r, color &col, int depth)
{
double t = findIntersection(r, col, depth);
if(t<0) return -1;
if(depth == 0) return t;
// find intersection point
vectorPoint3D intersection = r.getOrigin() + r.getDirection() * t;
// find the color at the intersection point
color intersection_color = getColor(intersection);
// update the color with ambient light
col.r = intersection_color.r * ambient;
col.g = intersection_color.g * ambient;
col.b = intersection_color.b * ambient;
for(int i=0; i<point_lights.size(); i++)
{
// find the direction of the light
vectorPoint3D light_position = point_lights[i]->getPosition();
vectorPoint3D light_direction = intersection - light_position;
light_direction.normalize();
// cast a incident ray from the light to the intersection point
ray incidentRay = ray(light_position, light_direction);
ray normal = getNormalAt(intersection, incidentRay);
// avoid self recursion
double dist = (intersection - light_position).length();
if(dist < 0.00001) continue;
// check if the light is blocked by any object
bool blocked = false;
for(object *o : objects)
{
double t = o->findIntersection(incidentRay, col, 0);
if(t > 0 && t+0.00001 < dist)
{
blocked = true;
break;
}
}
if(!blocked)
{
double lambert = max(0.0, incidentRay.getDirection()*normal.getDirection()*(-1));
ray reflectionRay = ray(intersection, incidentRay.getDirection() - normal.getDirection() * 2 * (incidentRay.getDirection()*normal.getDirection()));
double phong = max(0.0, reflectionRay.getDirection()*r.getDirection()*(-1));
// update diffuse and specular
col.r += point_lights[i]->clr.r * diffuse * lambert * intersection_color.r;
col.r += point_lights[i]->clr.r * specular * pow(phong, shininess)*intersection_color.r;
col.g += point_lights[i]->clr.g * diffuse * lambert * intersection_color.g;
col.g += point_lights[i]->clr.g * specular * pow(phong, shininess)*intersection_color.g;
col.b += point_lights[i]->clr.b * diffuse * lambert * intersection_color.b;
col.b += point_lights[i]->clr.b * specular * pow(phong, shininess)*intersection_color.b;
}
}
// for spotlights, dot and angle needed to be calculated
for(int i=0; i<spot_lights.size(); i++)
{
// find the direction of the light
vectorPoint3D light_position = spot_lights[i]->getPointLight().getPosition();
vectorPoint3D light_direction = intersection - light_position;
light_direction.normalize();
double dot = light_direction*spot_lights[i]->getDirection();
double angle = acos(dot/(light_direction.length()*spot_lights[i]->getDirection().length()));
angle = angle * 180.0 / pi;
if(fabs(angle)<spot_lights[i]->getAngle()){
// cast a incident ray from the light to the intersection point
ray incidentRay = ray(light_position, light_direction);
ray normal = getNormalAt(intersection, incidentRay);
ray reflectionRay = ray(intersection, incidentRay.getDirection() - normal.getDirection() * 2 * (incidentRay.getDirection()*normal.getDirection()));
double dist = (intersection - light_position).length();
if(dist < 0.00001) continue;
// check if the light is blocked by any object
bool blocked = false;
for(object *o : objects)
{
if(o == this) continue;
double t = o->findIntersection(incidentRay, col, 0);
if(t > 0 && t+0.00001 < dist)
{
blocked = true;
break;
}
}
if(!blocked)
{
double lambert = max(0.0, incidentRay.getDirection()*normal.getDirection()*(-1));
double phong = max(0.0, reflectionRay.getDirection()*r.getDirection()*(-1));
// update diffuse and specular
col.r+= spot_lights[i]->getPointLight().clr.r * diffuse * lambert * intersection_color.r;
col.r+= spot_lights[i]->getPointLight().clr.r * specular * pow(phong, shininess)*intersection_color.r;
col.g+= spot_lights[i]->getPointLight().clr.g * diffuse * lambert * intersection_color.g;
col.g+= spot_lights[i]->getPointLight().clr.g * specular * pow(phong, shininess)*intersection_color.g;
col.b+= spot_lights[i]->getPointLight().clr.b * diffuse * lambert * intersection_color.b;
col.b+= spot_lights[i]->getPointLight().clr.b * specular * pow(phong, shininess)*intersection_color.b;
}
}
}
if(depth< recursion_depth){
ray normal = getNormalAt(intersection, r);
ray reflectionRay = ray(intersection, r.getDirection() - normal.getDirection() * 2 * (r.getDirection()*normal.getDirection()));
reflectionRay.origin = reflectionRay.origin + reflectionRay.direction*0.00001;
int index = -1;
double min_t = 1e9;
double t = -1;
for(int i=0; i<(int)objects.size(); i++)
{
t = objects[i]->intersect(reflectionRay, col, 0);
if(t > 0 && t < min_t)
{
min_t = t;
index = i;
}
}
if(index != -1)
{
color reflection_color(0,0,0);
t = objects[index]->intersect(reflectionRay, reflection_color, depth+1);
col.r += reflection_color.r * reflection;
col.g += reflection_color.g * reflection;
col.b += reflection_color.b * reflection;
}
}
return t;
}
// destructor
object::~object()
{
}