Implement acceleration tree

This commit is contained in:
hodasemi 2019-04-15 20:05:22 +02:00
parent f44716e2c4
commit 636dc6450b
4 changed files with 66 additions and 76 deletions

View file

@ -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<Intersection> {
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<F>(&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<AABB> {
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);
}

View file

@ -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(),
}
}
}

View file

@ -49,7 +49,6 @@ fn generate_grid(width: u32, height: u32) -> Vec<Triangle> {
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<f32> {
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;

View file

@ -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<f32>,
@ -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<f32>) -> bool {
let v0v1 = self.vertices[1].position - self.vertices[0].position;