1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
use crate::hittable::{Hit, Hittable};
use crate::material::Material;
use crate::ray::Ray;
use cgmath::prelude::*;
use cgmath::{dot, Vector3};
use core::borrow::Borrow;
pub struct Sphere {
center0: Vector3<f64>,
center1: Vector3<f64>,
time0: f64,
time1: f64,
radius: f64,
material: Box<dyn Material + std::marker::Sync>,
}
impl Sphere {
pub fn new(
center: Vector3<f64>,
time0: f64,
time1: f64,
radius: f64,
material: Box<dyn Material + std::marker::Sync>,
) -> Sphere {
Sphere {
center0: center,
center1: center,
time0,
time1,
radius,
material,
}
}
pub fn new_moving(
center0: Vector3<f64>,
center1: Vector3<f64>,
time0: f64,
time1: f64,
radius: f64,
material: Box<dyn Material + std::marker::Sync>,
) -> Sphere {
Sphere {
center0,
center1,
time0,
time1,
radius,
material,
}
}
pub fn center(&self, time: f64) -> Vector3<f64> {
self.center0
+ ((time - self.time0) / (self.time1 - self.time0)) * (self.center1 - self.center0)
}
}
impl Hittable for Sphere {
fn is_hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option<Hit> {
let oc = ray.orig - self.center(ray.time);
let a = ray.dir.magnitude2();
let b = dot(oc, ray.dir);
let c = oc.magnitude2() - self.radius * self.radius;
let discriminant = b * b - a * c;
if discriminant > 0.0 {
let soln = (-b - discriminant.sqrt()) / a;
if soln < t_max && soln > t_min {
return Some(Hit::new(
ray,
soln,
(ray.at(soln) - self.center(ray.time)) / self.radius,
self.material.borrow(),
));
}
let soln = (-b + discriminant.sqrt()) / a;
if soln < t_max && soln > t_min {
return Some(Hit::new(
ray,
soln,
(ray.at(soln) - self.center(ray.time)) / self.radius,
self.material.borrow(),
));
}
}
None
}
}
|