94 lines
2.7 KiB
C++
94 lines
2.7 KiB
C++
#include "hittable.h"
|
|
|
|
#include <cmath>
|
|
|
|
bool Flip_face::hit(const Ray& r, double tmin, double tmax, hit_record& rec) const {
|
|
if (!ptr->hit(r, tmin, tmax, rec))
|
|
return false;
|
|
|
|
rec.front_face = !rec.front_face;
|
|
return true;
|
|
}
|
|
|
|
bool Translate::hit(const Ray& r, double tmin, double tmax, hit_record& rec) const {
|
|
Ray moved_r(r.origin() - offset, r.direction(), r.time());
|
|
if (!ptr->hit(moved_r, tmin, tmax, rec))
|
|
return false;
|
|
|
|
rec.p += offset;
|
|
rec.set_face_normal(moved_r, rec.normal);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Translate::bounding_box(double t0, double t1, Aabb& output_box) const {
|
|
if (!ptr->bounding_box(t0, t1, output_box))
|
|
return false;
|
|
|
|
output_box = Aabb(output_box.min() + offset, output_box.max() + offset);
|
|
return true;
|
|
}
|
|
|
|
Rotate_y::Rotate_y(std::shared_ptr<Hittable> p, double angle) : ptr(p) {
|
|
auto radians = degrees_to_radians(angle);
|
|
sin_theta = std::sin(radians);
|
|
cos_theta = std::cos(radians);
|
|
|
|
hasbox = ptr->bounding_box(0, 1, bbox);
|
|
|
|
Point3 min( infinity, infinity, infinity);
|
|
Point3 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] = std::fmin(min[c], tester[c]);
|
|
max[c] = std::fmin(max[c], tester[c]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bbox = Aabb(min, max);
|
|
}
|
|
|
|
bool Rotate_y::hit(const Ray& r, double tmin, double tmax, hit_record& rec) const {
|
|
auto origin = r.origin();
|
|
auto 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, tmin, tmax, 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;
|
|
}
|