diff --git a/src/ds/aabb.rs b/src/ds/aabb.rs index 8897d60..e3500ce 100644 --- a/src/ds/aabb.rs +++ b/src/ds/aabb.rs @@ -1,5 +1,4 @@ -use crate::ds; -use crate::object::Intersectable; +use crate::{ds, object::Renderable}; pub struct Aabb { // Axis aligned bounding box x: ds::Interval, @@ -47,7 +46,7 @@ impl Aabb { } } -impl Intersectable for Aabb { +impl Renderable for Aabb { fn intersects(&self, ray: &ds::Ray) -> bool { let axes = [ // each slab we check (&self.x, ray.origin.x, ray.direction.x), @@ -82,4 +81,12 @@ impl Intersectable for Aabb { } return true } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn center(&self) -> crate::ds::Vector3 { + ds::Vector3::new(self.x.middle(), self.y.middle(), self.z.middle()) + } } \ No newline at end of file diff --git a/src/ds/interval.rs b/src/ds/interval.rs index 5a58a08..90929c5 100644 --- a/src/ds/interval.rs +++ b/src/ds/interval.rs @@ -56,4 +56,8 @@ impl Interval { pub fn max(&self) -> f64 { self.max } + + pub fn middle(&self) -> f64 { + (self.max - self.min)/2.0 + self.min + } } \ No newline at end of file diff --git a/src/ds/mod.rs b/src/ds/mod.rs index 9386e66..053d819 100644 --- a/src/ds/mod.rs +++ b/src/ds/mod.rs @@ -1,11 +1,11 @@ pub mod vector3; pub mod math; -// pub mod interval; -// pub mod aabb; -// pub mod ray +pub mod interval; +pub mod aabb; +pub mod ray; pub use vector3::Vector3; -// pub use interval::Interval; -// pub use aabb::Aabb; -// pub use ray::Ray; \ No newline at end of file +pub use interval::Interval; +pub use aabb::Aabb; +pub use ray::Ray; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 16e7f86..431bb01 100644 --- a/src/main.rs +++ b/src/main.rs @@ -340,13 +340,13 @@ fn main() { Box::new(object::Sphere::new(&ds::Vector3::new(4.0, 0.3, 3.0), 0.25, GpuMaterial::new(0x000000FF, 0, 0))), // grass block - Box::new(object::Quad::new(&ds::Vector3::new(1.0, 0.0, 5.0), &ds::Vector3::new(0.0, 0.0, 1.0), &ds::Vector3::new(0.0, 1.0, 0.0), GpuMaterial::texture(1, 0, 0))), - Box::new(object::Quad::new(&ds::Vector3::new(1.0, 0.0, 6.0), &ds::Vector3::new(1.0, 0.0, 0.0), &ds::Vector3::new(0.0, 1.0, 0.0), GpuMaterial::texture(1, 0, 0))), - Box::new(object::Quad::new(&ds::Vector3::new(2.0, 0.0, 6.0), &ds::Vector3::new(0.0, 0.0,-1.0), &ds::Vector3::new(0.0, 1.0, 0.0), GpuMaterial::texture(1, 0, 0))), - Box::new(object::Quad::new(&ds::Vector3::new(2.0, 0.0, 5.0), &ds::Vector3::new(-1.0,0.0, 0.0), &ds::Vector3::new(0.0, 1.0, 0.0), GpuMaterial::texture(1, 0, 0))), + Box::new(object::Quad::new(&ds::Vector3::new( 0.5, -0.5, 5.5), &ds::Vector3::new( 1.0, 0.0, 0.0), &ds::Vector3::new(0.0, 1.0, 0.0), GpuMaterial::texture(1, 0, 0))), + Box::new(object::Quad::new(&ds::Vector3::new( 1.5, -0.5, 5.5), &ds::Vector3::new( 0.0, 0.0, 1.0), &ds::Vector3::new(0.0, 1.0, 0.0), GpuMaterial::texture(1, 0, 0))), + Box::new(object::Quad::new(&ds::Vector3::new( 0.5, -0.5, 6.5), &ds::Vector3::new( 0.0, 0.0,-1.0), &ds::Vector3::new(0.0, 1.0, 0.0), GpuMaterial::texture(1, 0, 0))), + Box::new(object::Quad::new(&ds::Vector3::new( 1.5, -0.5, 6.5), &ds::Vector3::new(-1.0, 0.0, 0.0), &ds::Vector3::new(0.0, 1.0, 0.0), GpuMaterial::texture(1, 0, 0))), + Box::new(object::Quad::new(&ds::Vector3::new( 0.5, 0.5, 5.5), &ds::Vector3::new( 1.0, 0.0, 0.0), &ds::Vector3::new(0.0, 0.0, 1.0), GpuMaterial::texture(2, 0, 0))), + Box::new(object::Quad::new(&ds::Vector3::new( 0.5, -0.5, 5.5), &ds::Vector3::new( 1.0, 0.0, 0.0), &ds::Vector3::new(0.0, 0.0, 1.0), GpuMaterial::texture(0, 0, 0))), - Box::new(object::Quad::new(&ds::Vector3::new(1.0, 1.0, 5.0), &ds::Vector3::new(1.0, 0.0, 0.0), &ds::Vector3::new(0.0, 0.0, 1.0), GpuMaterial::texture(2, 0, 0))), - Box::new(object::Quad::new(&ds::Vector3::new(1.0, 0.0, 5.0), &ds::Vector3::new(1.0, 0.0, 0.0), &ds::Vector3::new(0.0, 0.0, 1.0), GpuMaterial::texture(0, 0, 0))), Box::new(object::Quad::new(&ds::Vector3::new(10.0, 2.0, 7.0), &ds::Vector3::new(0.5, 1.0, 0.5), &ds::Vector3::new(1.0, 0.5, 0.0), GpuMaterial::texture(0, 0, 0))), diff --git a/src/object/quad.rs b/src/object/quad.rs index aca63ef..11824d1 100644 --- a/src/object/quad.rs +++ b/src/object/quad.rs @@ -54,6 +54,33 @@ impl Renderable for Quad { fn center(&self) -> crate::ds::Vector3 { self.q + self.u/2.0 + self.v/2.0 } + + fn intersects(&self, ray: &ds::Ray) -> bool { + let denominator = self.normal.dot(&ray.direction); + + if denominator.abs() < 0.00000001 { + return false; + } + + let t = (self.d - self.normal.dot(&ray.origin)) / denominator; + + if t < 0.0 { return false; } + + let intersection = ray.at(t); + let planar_hit = intersection - self.q; + + let u_len_sq = self.u.length_sq(); + let v_len_sq = self.v.length_sq(); + + let alpha = self.u.dot(&planar_hit) / u_len_sq; + let beta = self.v.dot(&planar_hit) / v_len_sq; + + if alpha < 0.0 || alpha > 1.0 || beta < 0.0 || beta > 1.0 { + return false; + } + + return true + } } impl ToGpu for Quad { diff --git a/src/object/renderable.rs b/src/object/renderable.rs index 33001dd..888a1f5 100644 --- a/src/object/renderable.rs +++ b/src/object/renderable.rs @@ -1,6 +1,7 @@ pub trait Renderable: Send + Sync { fn as_any(&self) -> &dyn std::any::Any; fn center(&self) -> crate::ds::Vector3; + fn intersects(&self, ray: &crate::ds::Ray) -> bool; } pub trait ToGpu { diff --git a/src/object/sphere.rs b/src/object/sphere.rs index bf13123..897bac8 100644 --- a/src/object/sphere.rs +++ b/src/object/sphere.rs @@ -42,6 +42,23 @@ impl Renderable for Sphere { fn center(&self) -> crate::ds::Vector3 { self.center } + + fn intersects(&self, ray: &ds::Ray) -> bool { + let oc = self.center - ray.origin; + let a = ray.direction.dot(&ray.direction); + let h = ray.direction.dot(&oc); + let c = oc.dot(&oc) - self.radius * self.radius; + let discriminant = h*h - a*c; + + if discriminant < 0.0 { + return false; + } + + let t1 = (h - discriminant.sqrt()) / a; + let t2 = (h + discriminant.sqrt()) / a; + + return t1 > 1e-8 || t2 > 1e-8 + } } impl ToGpu for Sphere { diff --git a/src/shaders/material.wgsl b/src/shaders/material.wgsl index 4d8f50b..4861856 100644 --- a/src/shaders/material.wgsl +++ b/src/shaders/material.wgsl @@ -151,5 +151,5 @@ fn get_texture_color(record: HitRecord) -> vec3 { let pct_across = abs(dot(offset, quad.u) / dot(quad.u, quad.u)) * 16.0; let pct_up = abs(dot(offset, quad.v) / dot(quad.v, quad.v)) * 16.0; - return textureLoad(textures, vec2u((15-u32(pct_across)), (15-u32(pct_up)) + 16 * u32(material.texture_id)), 0).rgb * 255.0; + return textureLoad(textures, vec2u(u32(pct_across), (15-u32(pct_up)) + 16 * u32(material.texture_id)), 0).rgb * 255.0; } \ No newline at end of file