aboutsummaryrefslogtreecommitdiff
path: root/src/scene/shapes/sphere.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/scene/shapes/sphere.rs')
-rw-r--r--src/scene/shapes/sphere.rs37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/scene/shapes/sphere.rs b/src/scene/shapes/sphere.rs
index 9598422..f8ae11e 100644
--- a/src/scene/shapes/sphere.rs
+++ b/src/scene/shapes/sphere.rs
@@ -1,5 +1,6 @@
use crate::Float;
use crate::core::{Ray, Vector3f};
+use super::Shape;
pub struct Sphere {
radius: Float,
@@ -14,3 +15,39 @@ impl Sphere {
}
}
}
+
+impl Shape for Sphere {
+ // Implementation from ray tracing in a weekend
+ fn intersect(&self, ray: &Ray) -> Option<Float> {
+ let oc = ray.origin - self.center;
+ let a = ray.direction.len_squared();
+ let half_b = oc.dot(&ray.direction);
+ let c = oc.len_squared() - self.radius * self.radius;
+ let disc = half_b*half_b - a*c;
+
+ if disc < 0.0 {
+ None
+ } else {
+ Some( (-half_b - disc.sqrt()) / a)
+ }
+
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn sphere_intersect() {
+ let sph = Sphere::new(2.0, Vector3f::new_xyz(2.0, 3.0, 4.0));
+
+ let ray = Ray {
+ origin: Vector3f::new_xyz(1.0, 0.0, 0.0),
+ direction: Vector3f::new_xyz(0.0, 1.0, 1.5).norm(),
+ };
+
+ let dist = sph.intersect(&ray);
+ assert!((dist.unwrap() - 3.28).abs() < 0.01);
+ }
+}