Fixed bug in kdtree that this uncovered. Marked Hit and it's dependencies as needing to implement the Debug trait.
91 lines
2.4 KiB
Rust
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),
|
|
))
|
|
}
|
|
}
|