#include "../include/objects.hpp" /* Plane */ Plane::Plane(const v3& n, choice_t offset, const Material& specs, int surface_type) : Renderable(specs), n(n), offset(offset), surface_type(surface_type) {} Plane::Plane(const v3& n, choice_t offset, const Material& specs) : Plane(n, offset, specs, 2) {} int Plane::intersect(const v3& eye, const v3& dir, choice_t& hit_dist, v3& hit_loc, v3& hit_normal) { const choice_t d = dir ^ n; if(d <= 0) return 0; const choice_t k = -((eye ^ n) + offset) / d; hit_loc = eye + dir * k; hit_normal = n; hit_dist = (hit_loc - eye).len(); return surface_type; } /* Sphere */ Sphere::Sphere(const v3& origin, choice_t r, const Material& specs, int surface_type) : Renderable(specs), o(origin), r(r), surface_type(surface_type) {} Sphere::Sphere(const v3& origin, choice_t r) : Sphere(origin, r, Material(), 1) {} template static inline int _sphere_intersect(Sphere& self, const v3& eye, const v3& dir, choice_t& hit_dist, v3& hit_loc, v3& hit_normal) { const v3 d = self.o - eye; const choice_t dist_above_o = dir ^ d; // We're facing directly away from the sphere if(dist_above_o < 0) { return -1; } // The ray is pointing directly at the center of the sphere // if(fabs(dist_above_o - d.len()) < 1e-5) { // hit_loc = eye + d.norm() * (d.len() - self.r); // hit_normal = self.normal(hit_loc); // hit_dist = (hit_loc - eye).len(); // return self.surface_type; // } const choice_t rejection = sqrtf(d.len() * d.len() - dist_above_o * dist_above_o); // The ray is tangent/missing the sphere if(rejection >= self.r) return -1; choice_t inside = sqrt(self.r*self.r - rejection*rejection) * K; hit_dist = dist_above_o - inside; hit_loc = eye + dir * hit_dist; hit_normal = self.normal(hit_loc); return self.surface_type; } int Sphere::intersect(const v3& eye, const v3& dir, choice_t& hit_dist, v3& hit_loc, v3& hit_normal) { return _sphere_intersect(*this, eye, dir, hit_dist, hit_loc, hit_normal); } int Sphere::transmit(const v3& eye, const v3& dir, choice_t& hit_dist, v3& hit_loc, v3& hit_normal) { return _sphere_intersect<-1>(*this, eye, dir, hit_dist, hit_loc, hit_normal); } /* Light */ Light::Light(const v3& origin, choice_t r, const v3& colour) : Light(origin, r, Material{ .specular = 0, .roughness = 1, .colour = colour }) {} Light::Light(const v3& origin, choice_t r, const Material& specs) : Sphere(origin, r, specs, 0) {}