From 636dc6450b5bc8ac0ecd0e0b56ac9a19cf94c150 Mon Sep 17 00:00:00 2001 From: hodasemi Date: Mon, 15 Apr 2019 20:05:22 +0200 Subject: [PATCH] Implement acceleration tree --- src/acceleration_data.rs | 80 +++++++++++++++++++++++++++++++--------- src/intersection.rs | 12 +----- src/main.rs | 33 ----------------- src/triangle.rs | 17 +-------- 4 files changed, 66 insertions(+), 76 deletions(-) diff --git a/src/acceleration_data.rs b/src/acceleration_data.rs index 8dc5734..83ff513 100644 --- a/src/acceleration_data.rs +++ b/src/acceleration_data.rs @@ -1,4 +1,4 @@ -use cgmath::{vec2, vec3, Vector2, Vector3, Zero}; +use cgmath::{vec3, Vector2, Vector3, Zero}; use std::f32::{MAX, MIN}; @@ -38,10 +38,59 @@ impl<'a> AccelerationData<'a> { } pub fn find_closest_hit(&self, ray: &Ray) -> Option { - None + let mut closest_index = -1; + let mut closest_distance = MAX; + let mut barycentric = Vector2::zero(); + + self.traverse_tree(|_, aabb| { + if aabb.intersect(ray) { + // check if node is a leaf + if aabb.start_index != -1 { + for i in aabb.start_index..aabb.end_index { + let mut t = 0.0; + let mut tmp_bary = Vector2::zero(); + + if self.triangles[i as usize].intersect_mt(ray, &mut t, &mut tmp_bary) { + if t < closest_distance { + closest_index = i as i32; + closest_distance = t; + barycentric = tmp_bary; + } + } + } + } + + true + } else { + false + } + }); + + if closest_index == -1 { + None + } else { + Some(Intersection::new( + closest_distance, + self.triangles[closest_index as usize].clone(), + barycentric, + )) + } } pub fn print_tree(&self) { + self.traverse_tree(|index, aabb| { + print_aabb(index, aabb); + true + }) + } +} + +// private +impl<'a> AccelerationData<'a> { + fn traverse_tree(&self, mut f: F) + where + F: FnMut(usize, &AABB) -> bool, + { let mut discovered = vec![false; 1024]; let mut stack = Vec::new(); @@ -57,27 +106,24 @@ impl<'a> AccelerationData<'a> { discovered[v] = true; - print_aabb(v, self.data[v]); - - let left_child = self.data[v].left_child; - if left_child != -1 { - if !discovered[left_child as usize] { - stack.push(left_child as usize); + if (f)(v, &self.data[v]) { + let left_child = self.data[v].left_child; + if left_child != -1 { + if !discovered[left_child as usize] { + stack.push(left_child as usize); + } } - } - let right_child = self.data[v].right_child; - if right_child != -1 { - if !discovered[right_child as usize] { - stack.push(right_child as usize); + let right_child = self.data[v].right_child; + if right_child != -1 { + if !discovered[right_child as usize] { + stack.push(right_child as usize); + } } } } } -} -// private -impl<'a> AccelerationData<'a> { fn create_leaf_nodes(input_data: &[Triangle], triangles_per_as: u32) -> Vec { let mut acceleration_data = Vec::new(); @@ -178,6 +224,6 @@ impl<'a> AccelerationData<'a> { } } -fn print_aabb(index: usize, aabb: AABB) { +fn print_aabb(index: usize, aabb: &AABB) { println!("({}):\t{:?}", index, aabb); } diff --git a/src/intersection.rs b/src/intersection.rs index bce116d..5d3eb4b 100644 --- a/src/intersection.rs +++ b/src/intersection.rs @@ -1,9 +1,7 @@ -use cgmath::{vec2, vec3, Vector2, Vector3, Zero}; +use cgmath::Vector2; use crate::triangle::Triangle; -use std::f32::MAX; - pub struct Intersection { pub distance: f32, pub triangle: Triangle, @@ -18,12 +16,4 @@ impl Intersection { barycentric, } } - - pub fn zero() -> Intersection { - Intersection { - distance: MAX, - triangle: Triangle::zero(), - barycentric: Vector2::zero(), - } - } } diff --git a/src/main.rs b/src/main.rs index 69a017a..65a9c74 100644 --- a/src/main.rs +++ b/src/main.rs @@ -49,7 +49,6 @@ fn generate_grid(width: u32, height: u32) -> Vec { fn main() { let input_data = generate_grid(5, 5); - /* let camera = Camera::new( vec3(0.0, -4.0, 4.0), vec3(0.0, 0.0, 0.0), @@ -57,15 +56,6 @@ fn main() { 45.0, 1280.0 / 720.0, ); - */ - - let camera = Camera::new( - vec3(0.0, 0.0, 3.0), - vec3(0.0, 0.0, 0.0), - vec3(0.0, 1.0, 1.0), - 45.0, - 1280.0 / 720.0, - ); debug_raytracer_camera(1280, 720, &camera, &input_data); } @@ -95,29 +85,6 @@ fn debug_raytracer_camera(dim_x: u32, dim_y: u32, camera: &Camera, data: &[Trian fn pixel_color(ray: &Ray, acceleration_data: &AccelerationData) -> Vector3 { let mut final_color = vec3(0.0, 1.0, 0.0); - /* - let mut closest_value = MAX; - let mut closest_index = -1; - let mut barycentric = Vector2::zero(); - - for accel in acceleration_data.iter() { - if accel.intersect(ray) { - for i in accel.start_index..accel.end_index { - let mut t = 0.0; - let mut tmp_bary = Vector2::zero(); - - if data[i].intersect_mt(ray, &mut t, &mut tmp_bary) { - if t < closest_value { - closest_index = i as i32; - closest_value = t; - barycentric = tmp_bary; - } - } - } - } - } - */ - if let Some(intersection) = acceleration_data.find_closest_hit(ray) { let triangle = intersection.triangle; diff --git a/src/triangle.rs b/src/triangle.rs index 33118bb..4132eb5 100644 --- a/src/triangle.rs +++ b/src/triangle.rs @@ -1,4 +1,4 @@ -use cgmath::{InnerSpace, Vector2, Vector3, Zero}; +use cgmath::{InnerSpace, Vector2, Vector3}; use super::ray::Ray; @@ -15,15 +15,9 @@ impl Vertex { texture_coordinate, } } - - pub fn zero() -> Vertex { - Vertex { - position: Vector3::zero(), - texture_coordinate: Vector2::zero(), - } - } } +#[derive(Clone)] pub struct Triangle { pub vertices: [Vertex; 3], pub color: Vector3, @@ -37,13 +31,6 @@ impl Triangle { } } - pub fn zero() -> Triangle { - Triangle { - vertices: [Vertex::zero(); 3], - color: Vector3::zero(), - } - } - // source: https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/moller-trumbore-ray-triangle-intersection pub fn intersect_mt(&self, ray: &Ray, t: &mut f32, barycentric: &mut Vector2) -> bool { let v0v1 = self.vertices[1].position - self.vertices[0].position;