71 lines
2.5 KiB
C++
71 lines
2.5 KiB
C++
#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<int K = 1>
|
|
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) {}
|