2 #include <acceleration/aabb.hpp>
4 #include <camera/ray.hpp>
6 #include <math3d/vec3.hpp>
7 using namespace ptracey;
14 shared_ptr<material> mat_ptr;
20 inline void set_face_normal(
const ray &r,
21 const vec3 &outward_normal) {
22 front_face = dot(r.direction(), outward_normal) < 0;
23 normal = front_face ? outward_normal : -outward_normal;
27 Real get_pdf_surface(
point3 dir,
vec3 normal, Real dist,
29 auto distance_squared =
30 dist * dist * dir.length_squared();
31 Real cosine = fabs(dot(dir, normal) / dir.length());
33 return distance_squared / (cosine * area);
37 shared_ptr<material> mat_ptr;
38 virtual bool hit(
const ray &r, Real t_min, Real t_max,
40 virtual bool bounding_box(Real time0, Real time1,
41 aabb &output_box)
const = 0;
43 virtual Real pdf_value(
const vec3 &o,
44 const vec3 &v)
const {
48 virtual vec3 random(
const vec3 &o)
const {
54 flip_face(shared_ptr<hittable> p) : ptr(p) {}
56 virtual bool hit(
const ray &r, Real t_min, Real t_max,
59 if (!ptr->hit(r, t_min, t_max, rec))
62 rec.front_face = !rec.front_face;
67 bounding_box(Real time0, Real time1,
68 aabb &output_box)
const override {
69 return ptr->bounding_box(time0, time1, output_box);
73 shared_ptr<hittable> ptr;
79 const vec3 &displacement)
80 : ptr(p), offset(displacement) {}
82 virtual bool hit(
const ray &r, Real t_min, Real t_max,
86 bounding_box(Real time0, Real time1,
87 aabb &output_box)
const override;
90 shared_ptr<hittable> ptr;
93 bool translate::hit(
const ray &r, Real t_min, Real t_max,
95 ray moved_r(r.origin() - offset, r.direction(), r.time(),
97 if (!ptr->hit(moved_r, t_min, t_max, rec))
101 rec.set_face_normal(moved_r, rec.normal);
105 bool translate::bounding_box(Real time0, Real time1,
106 aabb &output_box)
const {
107 if (!ptr->bounding_box(time0, time1, output_box))
110 output_box =
aabb(output_box.min() + offset,
111 output_box.max() + offset);
117 rotate_y(shared_ptr<hittable> p, Real angle);
119 bool hit(
const ray &r, Real t_min, Real t_max,
122 bool bounding_box(Real time0, Real time1,
123 aabb &output_box)
const override {
129 shared_ptr<hittable> ptr;
135 rotate_y::rotate_y(shared_ptr<hittable> p, Real angle)
137 auto radians = degrees_to_radians(angle);
138 sin_theta = sin(radians);
139 cos_theta = cos(radians);
140 hasbox = ptr->bounding_box(0, 1, bbox);
145 for (
int i = 0; i < 2; i++) {
146 for (
int j = 0; j < 2; j++) {
147 for (
int k = 0; k < 2; k++) {
149 i * bbox.max().x() + (1 - i) * bbox.min().x();
151 j * bbox.max().y() + (1 - j) * bbox.min().y();
153 k * bbox.max().z() + (1 - k) * bbox.min().z();
155 auto newx = cos_theta * x + sin_theta * z;
156 auto newz = -sin_theta * x + cos_theta * z;
158 vec3 tester(newx, y, newz);
160 for (
int c = 0; c < 3; c++) {
161 min[c] = fmin(min[c], tester[c]);
162 max[c] = fmax(max[c], tester[c]);
168 bbox =
aabb(min, max);
170 bool rotate_y::hit(
const ray &r, Real t_min, Real t_max,
172 auto origin = r.origin();
173 auto direction = r.direction();
176 cos_theta * r.origin()[0] - sin_theta * r.origin()[2];
178 sin_theta * r.origin()[0] + cos_theta * r.origin()[2];
180 direction[0] = cos_theta * r.direction()[0] -
181 sin_theta * r.direction()[2];
182 direction[2] = sin_theta * r.direction()[0] +
183 cos_theta * r.direction()[2];
185 ray rotated_r(origin, direction, r.time(),
188 if (!ptr->hit(rotated_r, t_min, t_max, rec))
192 auto normal = rec.normal;
194 p[0] = cos_theta * rec.p[0] + sin_theta * rec.p[2];
195 p[2] = -sin_theta * rec.p[0] + cos_theta * rec.p[2];
198 cos_theta * rec.normal[0] + sin_theta * rec.normal[2];
199 normal[2] = -sin_theta * rec.normal[0] +
200 cos_theta * rec.normal[2];
203 rec.set_face_normal(rotated_r, normal);