-
Notifications
You must be signed in to change notification settings - Fork 1
/
Scene.cpp
76 lines (53 loc) · 3.29 KB
/
Scene.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
//
// Created by federico on 11/04/2020.
//
#include "Scene.h"
#include "Utils/BaseGeometry/Values.h"
//tests all objects for intersection and returns the closest one
Scene::IntersectionData Scene::ray_intersection(const Line &ray, float time) const {
IntersectionData closest_intersection;
for (Object* object : objects)
for (std::pair<float, Surface * > intersection : object->intersections(ray, time))
if (intersection.first < closest_intersection.distance and intersection.first > 0)
closest_intersection = IntersectionData(intersection.first, intersection.second, object);
return closest_intersection;
}
//returns the color of a surface at a given point, using Phong's illumination model
Color Scene::surface_color(Scene::IntersectionData intersection_data, const Line& ray, int reflections, float time) const {
Color result = ambient_intensity.scale(intersection_data.surface->get_aspect().get_k_diffuse());
Vector3 intersection_point = ray.evaluate(intersection_data.distance - 10.0f * Values::eps, time);
for (Light * light : lights) {
Line light_line = Line::between_points(intersection_point, light->get_reference_frame().get_location(time));
float light_distance = ray_intersection(light_line, time).distance;
UnitVector3 surface_normal =
intersection_data.object->get_reference_frame().unit_from_ref_frame(
intersection_data.surface->get_normal(
intersection_data.object->get_reference_frame().to_ref_frame(intersection_point, time), time), time);
UnitVector3 viewer_vector = static_cast<UnitVector3>(ray.get_direction(time) * (-1));
if (intersection_point.distance(light->get_reference_frame().get_location(time)) < light_distance) {
// diffuse shading
result = result.add(light->get_intensity().scale(
intersection_data.surface->get_aspect().get_k_diffuse().scale(
std::abs(light_line.get_direction(time).dot(surface_normal)))));
// specular reflection
result = result.add(light->get_intensity().scale(
intersection_data.surface->get_aspect().get_k_specular().scale(
std::pow(
std::max(0.0f, surface_normal.reflect(light_line.get_direction(time)).dot(viewer_vector)),
intersection_data.surface->get_aspect().get_roughness()))));
// mirror reflection
if (!intersection_data.surface->get_aspect().get_k_mirror().is_zero())
result = result.add(intersection_data.surface->get_aspect().get_k_mirror().scale(
cast_ray(
Line(intersection_point, static_cast<UnitVector3>(surface_normal.reflect(viewer_vector))),
reflections - 1,
time
)));
}
}
return result;
}
Color Scene::cast_ray(const Line& ray, int reflections, float time) const {
IntersectionData closest_intersection = ray_intersection(ray, time);
return (closest_intersection.surface == nullptr || reflections == 0) ? Color() : surface_color(closest_intersection, ray, reflections, time);
}