rtiow: break project into multiple workspaces.
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
89
rtiow/renderer/src/sphere.rs
Normal file
89
rtiow/renderer/src/sphere.rs
Normal file
@@ -0,0 +1,89 @@
|
||||
use std::f32::consts::PI;
|
||||
|
||||
use crate::aabb::AABB;
|
||||
use crate::hitable::Hit;
|
||||
use crate::hitable::HitRecord;
|
||||
use crate::material::Material;
|
||||
use crate::ray::Ray;
|
||||
use crate::vec3::dot;
|
||||
use crate::vec3::Vec3;
|
||||
|
||||
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),
|
||||
))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user