Bill Thiede 4066bf4b85 rtiow: add blox with gloxy edges.
Fixed bug in kdtree that this uncovered.
Marked Hit and it's dependencies as needing to implement the Debug
trait.
2022-09-17 16:45:29 -07:00

91 lines
2.4 KiB
Rust

use std::f32::consts::PI;
use crate::{
aabb::AABB,
hitable::{Hit, HitRecord},
material::Material,
ray::Ray,
vec3::{dot, Vec3},
};
#[derive(Debug)]
pub struct Sphere<M>
where
M: Material,
{
center: Vec3,
radius: f32,
material: M,
}
pub fn get_sphere_uv(p: Vec3) -> (f32, f32) {
let phi = p.z.atan2(p.x);
let theta = p.y.asin();
let u = 1. - (phi + PI) / (2. * PI);
let v = (theta + PI / 2.) / PI;
(u, v)
}
impl<M> Sphere<M>
where
M: Material,
{
pub fn new<V>(center: V, radius: f32, material: M) -> Sphere<M>
where
V: Into<Vec3>,
{
Sphere {
center: center.into(),
radius,
material,
}
}
}
impl<M> Hit for Sphere<M>
where
M: Material,
{
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
let oc = r.origin - self.center;
let a = dot(r.direction, r.direction);
let b = dot(oc, r.direction);
let c = dot(oc, oc) - self.radius * self.radius;
let discriminant = b * b - a * c;
if discriminant > 0. {
let temp = (-b - (b * b - a * c).sqrt()) / a;
if temp < t_max && temp > t_min {
let point = r.point_at_parameter(temp);
let uv = get_sphere_uv((point - self.center) / self.radius);
return Some(HitRecord {
t: temp,
uv,
p: point,
normal: (point - self.center) / self.radius,
material: &self.material,
});
}
let temp = (-b + (b * b - a * c).sqrt()) / a;
if temp < t_max && temp > t_min {
let point = r.point_at_parameter(temp);
let uv = get_sphere_uv((point - self.center) / self.radius);
return Some(HitRecord {
t: temp,
uv,
p: point,
normal: (point - self.center) / self.radius,
material: &self.material,
});
}
}
None
}
fn bounding_box(&self, _t_min: f32, _t_max: f32) -> Option<AABB> {
Some(AABB::new(
self.center - Vec3::new(self.radius, self.radius, self.radius),
self.center + Vec3::new(self.radius, self.radius, self.radius),
))
}
}