This repository was archived by the owner on Jan 21, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathScene3D.cpp
116 lines (90 loc) · 2.59 KB
/
Scene3D.cpp
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
#include "SceneObject.h"
#include "Camera.h"
#include "Light.h"
#include "Scene3D.h"
#include "Ray.h"
#include "ColorRGB.h"
#include "Vector3D.h"
#include "math.h"
#include <functional>
#include <cassert>
#include <algorithm>
#include <iostream>
struct delete_SO : public std::unary_function<SceneObject*,void>
{
delete_SO() { }
void operator() (SceneObject* s) { delete s; }
};
struct delete_Light : public std::unary_function<Light*,void>
{
delete_Light() { }
void operator() (Light* l) { delete l; }
};
Scene3D::Scene3D() { }
Scene3D::~Scene3D()
{
std::for_each(objects.begin(), objects.end(), delete_SO());
std::for_each(lights.begin(), lights.end(), delete_Light());
}
void Scene3D::add_object(SceneObject* SO)
{
assert (SO != NULL);
objects.push_back(SO);
}
void Scene3D::add_light(Light* l)
{
assert (l != NULL);
lights.push_back(l);
}
const ColorRGB Scene3D::traceRay(const Ray& ray, int depth) const
{
float closest_t_value = NO_INTERSECT;
const SceneObject* closest_object = findClosest(ray, closest_t_value);
if (closest_object == 0)
return ColorRGB(0,0,0);
ColorRGB retColor(0,0,0);
for (int i = 0; i < lights.size(); i++)
{
Vector3D normL = ((*lights[i]).get_position()-ray.getPointAt(closest_t_value)).normalize();
Vector3D normN = (*closest_object).surface_normal(ray.getPointAt(closest_t_value));
retColor += (*lights[i]).get_color()*(*closest_object).get_color()*std::max((normL*normN),float(0));
if (depth < 6 && (*closest_object).get_reflectivity() > 0)
{
Ray reflected_ray = ray.reflect(ray.getPointAt(closest_t_value), (*closest_object).surface_normal(ray.getPointAt(closest_t_value)));
ColorRGB reflection_color = traceRay(reflected_ray, depth+1);
retColor+= (*closest_object).get_reflectivity()*reflection_color;
}
}
return retColor;
}
const SceneObject* Scene3D::findClosest(const Ray& ray, float& t_int) const
{
t_int = NO_INTERSECT;
int closest_obj_location = -1;
for (int i = 0; i < objects.size(); i++)
{
float int_val = (*objects[i]).intersection(ray);
if ((int_val < t_int || t_int == NO_INTERSECT) && int_val >= 0)
{
t_int = int_val;
closest_obj_location = i;
}
}
if (t_int >= 0)
return objects[closest_obj_location];
return 0;
}
void Scene3D::render(const Camera& camera, const int imgSize, std::ostream& os)
{
os << "P3 " << imgSize << " " << imgSize << " " << 255 << "\n";
for (int y = 0; y < imgSize; y++)
{
for (int x = 0; x < imgSize; x++)
{
ColorRGB pixelColor = traceRay(camera.getRayForPixel(x, y, imgSize));
pixelColor*=255;
pixelColor.clamp_output(0,255, std::cout);
os << "\n";
}
}
}