-
Notifications
You must be signed in to change notification settings - Fork 0
/
scene.hpp
104 lines (89 loc) · 2.4 KB
/
scene.hpp
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
#ifndef SCENE_H
#define SCENE_H
#include "primitive.hpp"
#include "ray.hpp"
#include "light.hpp"
#include "kdtree.hpp"
#include <vector>
#include <cmath>
class Camera {
Ray pos;
Vector vert;
Vector hor;
public:
Camera() {}
Camera(Ray ray, Vector vert, Vector hor) : pos(ray), vert(vert), hor(hor) {}
Ray get_ray(double x, double y) const {
Vector direction = pos.direction + hor*x + vert*y;
return Ray(pos.start, direction);
}
std::pair<double, double> get_coord(Point p) const {
Vector v = p - pos.start;
double d = dot(v, pos.direction);
if (almost_zero(d)) {
return {0, 0};
}
double x = dot(v, hor) / d;
double y = dot(v, vert) / d;
return {x, y};
}
};
class Scene {
public:
std::vector<Primitive*> objects;
std::vector<Light> lights;
Camera camera;
KDTree tree;
public:
Scene(Camera camera) : camera(camera) {}
Scene() {}
Scene(const Scene&) = delete;
Scene& operator=(const Scene&) = delete;
~Scene() {
for (auto el : objects) {
delete el;
}
}
void add_object(Primitive* pointer) {
objects.push_back(pointer);
}
void add_light(Light light) {
lights.push_back(light);
}
void prepare() {
tree.build(objects);
}
Ray get_ray(double x, double y) const {
return camera.get_ray(x, y);
}
std::pair<double, double> get_coord(Point point) const {
return camera.get_coord(point);
}
Intersection find_closest(Ray ray) const {
return tree.intersect(ray);
}
const Color AMBIENT = Color(0.1, 0.1, 0.1);
Color trace_ray(Ray ray, short depth = 0) const {
if (depth > 2) {
return Color();
}
Intersection closest = find_closest(ray);
if (std::isinf(closest.t)) {
return Color();
}
Point p = ray.get_point(closest.t);
Color result;
const Material& texture = closest.object->texture(p);
Vector normal = closest.object->normal(p);
for (auto& light : lights) {
Ray light_ray(p, light.point - p);
Intersection obstacle = find_closest(light_ray);
if (obstacle.t <= EPS || obstacle.t >= 1 - EPS) {
result += texture.color;
}
}
return result;
}
friend class RTLoader;
};
#endif