-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhittable.h
102 lines (95 loc) · 4.28 KB
/
hittable.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
#ifndef HITTABLE_H
#define HITTABLE_H
#include <memory>
#include <vector>
#include "ray.h"
#include "vec3.h"
//#include "hit_record.h"
#include "aabb.h"
struct material;
struct hit_record {
point3 p; vec3 normal;
double t, u, v; bool front_face;
std::shared_ptr<material> mat_ptr;
inline void set_face_normal(const ray& r, const vec3& outward_normal) {
front_face = dot(r.direction(), outward_normal) < 0;
normal = (dot(r.direction(), outward_normal) < 0) ? outward_normal : -outward_normal;
}
};
struct hittable {
virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const = 0;
virtual bool bounding_box(double time0, double time1, aabb& output_box) const = 0;
virtual double pdf_value(const point3& o, const vec3& v) const {return 0.0;}
virtual vec3 random(const vec3& o) const {return vec3(1, 0, 0);}
};
struct translate : public hittable {
translate(std::shared_ptr<hittable> p, const vec3& displacement) : ptr(p), offset(displacement) {}
std::shared_ptr<hittable> ptr;
vec3 offset;
virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const override {
ray moved_r(r.origin() - offset, r.direction(), r.time());
if (!ptr->hit(moved_r, t_min, t_max, rec)) return false;
rec.p += offset; rec.set_face_normal(moved_r, rec.normal);
return true;
}
virtual bool bounding_box(double time0, double time1, aabb& output_box) const override {
if (!ptr->bounding_box(time0, time1, output_box)) return false;
output_box = aabb(output_box.min() + offset, output_box.max() + offset);
return true;
}
};
struct rotate_y : public hittable {
rotate_y(std::shared_ptr<hittable> p, double angle) : ptr(p) {
auto radians = Pi*angle/180.;
sin_theta = sin(radians); cos_theta = cos(radians);
hasbox = ptr->bounding_box(0, 1, bbox);
point3 min( infinity, infinity, infinity), max(-infinity, -infinity, -infinity);
for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) for (int k = 0; k < 2; k++) {
auto x = i*bbox.max().x() + (1 - i)*bbox.min().x();
auto y = j*bbox.max().y() + (1 - j)*bbox.min().y();
auto z = k*bbox.max().z() + (1 - k)*bbox.min().z();
auto newx = cos_theta*x + sin_theta*z;
auto newz = -sin_theta*x + cos_theta*z;
vec3 tester(newx, y, newz);
for (int c = 0; c < 3; c++) {
min[c] = fmin(min[c], tester[c]);
max[c] = fmax(max[c], tester[c]);
}
}
bbox = aabb(min, max);
}
std::shared_ptr<hittable> ptr;
double sin_theta, cos_theta;
bool hasbox; aabb bbox;
virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const override {
auto origin = r.origin(), direction = r.direction();
origin[0] = cos_theta*r.origin()[0] - sin_theta*r.origin()[2];
origin[2] = sin_theta*r.origin()[0] + cos_theta*r.origin()[2];
direction[0] = cos_theta*r.direction()[0] - sin_theta*r.direction()[2];
direction[2] = sin_theta*r.direction()[0] + cos_theta*r.direction()[2];
ray rotated_r(origin, direction, r.time());
if (!ptr->hit(rotated_r, t_min, t_max, rec)) return false;
auto p = rec.p; auto normal = rec.normal;
p[0] = cos_theta*rec.p[0] + sin_theta*rec.p[2];
p[2] = -sin_theta*rec.p[0] + cos_theta*rec.p[2];
normal[0] = cos_theta*rec.normal[0] + sin_theta*rec.normal[2];
normal[2] = -sin_theta*rec.normal[0] + cos_theta*rec.normal[2];
rec.p = p; rec.set_face_normal(rotated_r, normal);
return true;
}
virtual bool bounding_box(double time0, double time1, aabb& output_box) const override {
output_box = bbox;
return hasbox;
}
};
struct flip_face : public hittable {
flip_face(std::shared_ptr<hittable> p) : ptr(p) {}
std::shared_ptr<hittable> ptr;
virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const override {
if (!ptr->hit(r, t_min, t_max, rec)) return false;
rec.front_face = !rec.front_face;
return true;
}
virtual bool bounding_box(double time0, double time1, aabb& output_box) const override {return ptr->bounding_box(time0, time1, output_box);}
};
#endif