ray-trace-w1/src/sphere.rs

46 lines
1.2 KiB
Rust

use crate::hittable;
use crate::types_defined::{HitRecord, Point, Ray, Sphere};
impl Sphere {
pub fn new(c: Point, r: f32) -> Self {
Self {
center: c,
radius: r,
}
}
}
impl hittable::Hittable for Sphere {
fn hit(&self, r: &Ray, t_min: f32, t_max: f32) -> HitRecord {
let a: f32 = r.direction.length_squared();
let h = r.direction.dot(self.center - r.point);
// let b = -2.0 * r.direction.dot(sphere_center - r.point);
let c = (self.center - r.point).length_squared() - self.radius * self.radius;
let discriminant = h * h - a * c;
// // 两个交点
let disc_sqrt = discriminant.sqrt();
let near = (h - disc_sqrt) / a;
let far = (h + disc_sqrt) / a;
let mut root = near;
if root <= t_min || root >= t_max {
root = far;
if root <= t_min || root >= t_max {
root = -1.0;
}
}
let p = r.at(root);
let normal = (p - self.center) / self.radius;
HitRecord {
t: root,
// p,
normal,
// check if r.p inside(>=0) the sphere.
front_face: r.direction.dot(normal) < 0.0,
}
}
}