Start implementing AABB tree
This commit is contained in:
parent
d732ff8a0f
commit
ad28987134
7 changed files with 241 additions and 126 deletions
|
@ -1,11 +1,10 @@
|
|||
[package]
|
||||
name = "rust_opengl"
|
||||
name = "rustray"
|
||||
edition = "2018"
|
||||
version = "0.1.0"
|
||||
authors = ["hodasemi <michaelh.95@t-online.de>"]
|
||||
|
||||
[dependencies]
|
||||
sdl2 = "0.30"
|
||||
cgmath = "*"
|
||||
utilities = { path = "../../Gavania/utilities" }
|
||||
image = "*"
|
||||
utilities = { git = "https://gitlab.com/hodasemi/utilities.git" }
|
||||
image = "*"
|
||||
|
|
13
src/aabb.rs
13
src/aabb.rs
|
@ -2,18 +2,23 @@ use cgmath::{Vector3, Zero};
|
|||
|
||||
use super::ray::Ray;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct AABB {
|
||||
pub bounds: [Vector3<f32>; 2],
|
||||
pub start_index: usize,
|
||||
pub end_index: usize,
|
||||
pub start_index: isize,
|
||||
pub end_index: isize,
|
||||
pub left_child: isize,
|
||||
pub right_child: isize,
|
||||
}
|
||||
|
||||
impl AABB {
|
||||
pub fn new() -> AABB {
|
||||
AABB {
|
||||
bounds: [Vector3::zero(), Vector3::zero()],
|
||||
start_index: 0,
|
||||
end_index: 0,
|
||||
start_index: -1,
|
||||
end_index: -1,
|
||||
left_child: -1,
|
||||
right_child: -1,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
165
src/acceleration_data.rs
Normal file
165
src/acceleration_data.rs
Normal file
|
@ -0,0 +1,165 @@
|
|||
use cgmath::{vec2, vec3, Vector2, Vector3, Zero};
|
||||
|
||||
use std::f32::{MAX, MIN};
|
||||
|
||||
use crate::aabb::AABB;
|
||||
use crate::intersection::Intersection;
|
||||
use crate::ray::Ray;
|
||||
use crate::triangle::Triangle;
|
||||
|
||||
pub struct AccelerationData<'a> {
|
||||
triangles: &'a [Triangle],
|
||||
data: [AABB; 1024],
|
||||
}
|
||||
|
||||
impl<'a> AccelerationData<'a> {
|
||||
pub fn create_tree(input_data: &'a [Triangle], triangles_per_as: u32) -> Self {
|
||||
// we are creating the tree from the bottom up
|
||||
|
||||
// create our slice
|
||||
let mut data = [AABB::new(); 1024];
|
||||
|
||||
// first lets create the leaf nodes
|
||||
let leaf_nodes = Self::create_leaf_nodes(input_data, triangles_per_as);
|
||||
|
||||
// copy leaf nodes into our final array
|
||||
for (index, aabb) in leaf_nodes.iter().enumerate() {
|
||||
data[index + 1] = *aabb;
|
||||
}
|
||||
|
||||
// create complete tree from leaf nodes
|
||||
Self::create_tree_nodes(&mut data, leaf_nodes.len() as u32);
|
||||
|
||||
// return result
|
||||
AccelerationData {
|
||||
triangles: input_data,
|
||||
data,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_closest_hit(&self, ray: &Ray) -> Option<Intersection> {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn print_tree(&self) {
|
||||
let mut discovered = vec![false; 1024];
|
||||
let mut stack = Vec::new();
|
||||
|
||||
// push root node
|
||||
stack.push(0);
|
||||
|
||||
while !stack.is_empty() {
|
||||
let v = stack.pop().unwrap();
|
||||
|
||||
if discovered[v] {
|
||||
continue;
|
||||
}
|
||||
|
||||
discovered[v] = true;
|
||||
|
||||
println!("{}\n{:?}", v, self.data[v]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// private
|
||||
impl<'a> AccelerationData<'a> {
|
||||
fn create_leaf_nodes(input_data: &[Triangle], triangles_per_as: u32) -> Vec<AABB> {
|
||||
let mut acceleration_data = Vec::new();
|
||||
|
||||
let accel_count = (input_data.len() as f32 / triangles_per_as as f32).ceil() as usize;
|
||||
|
||||
for i in 0..accel_count {
|
||||
let mut accel = AABB::new();
|
||||
|
||||
let mut bbmin = vec3(MAX, MAX, MAX);
|
||||
let mut bbmax = vec3(MIN, MIN, MIN);
|
||||
|
||||
// 3 vertices per triangles
|
||||
// 8 triangles per acceleration structure
|
||||
let start_index = triangles_per_as as usize * i;
|
||||
let mut end_index = triangles_per_as as usize * (i + 1);
|
||||
|
||||
// check if end_index exceeds input data length
|
||||
if end_index > input_data.len() {
|
||||
end_index = input_data.len();
|
||||
}
|
||||
|
||||
// set index information
|
||||
accel.start_index = start_index as isize;
|
||||
accel.end_index = end_index as isize;
|
||||
|
||||
// create bounding box
|
||||
for k in start_index..end_index {
|
||||
for vertex in input_data[k].vertices.iter() {
|
||||
// check minimum values
|
||||
bbmin.x = bbmin.x.min(vertex.position.x);
|
||||
bbmin.y = bbmin.y.min(vertex.position.y);
|
||||
bbmin.z = bbmin.z.min(vertex.position.z);
|
||||
|
||||
// check maximum values
|
||||
bbmax.x = bbmax.x.max(vertex.position.x);
|
||||
bbmax.y = bbmax.y.max(vertex.position.y);
|
||||
bbmax.z = bbmax.z.max(vertex.position.z);
|
||||
}
|
||||
}
|
||||
|
||||
accel.bounds[0] = bbmin;
|
||||
accel.bounds[1] = bbmax;
|
||||
|
||||
acceleration_data.push(accel);
|
||||
}
|
||||
|
||||
acceleration_data
|
||||
}
|
||||
|
||||
fn create_tree_nodes(data: &mut [AABB], leaf_node_count: u32) {
|
||||
let mut current_level_count = leaf_node_count;
|
||||
let mut start_index = 1;
|
||||
|
||||
loop {
|
||||
let odd = (current_level_count % 2) == 1;
|
||||
let next_level_count = (current_level_count as f32 / 2.0).ceil() as u32;
|
||||
let next_level_start = start_index + current_level_count;
|
||||
|
||||
for i in next_level_start..(next_level_start + next_level_count) {
|
||||
let mut aabb = AABB::new();
|
||||
|
||||
let index = (start_index + i * 2) as usize;
|
||||
|
||||
if i == (next_level_count + next_level_start - 1) && odd {
|
||||
aabb.bounds[0] = data[index].bounds[0];
|
||||
aabb.bounds[1] = data[index].bounds[1];
|
||||
aabb.left_child = index as isize;
|
||||
} else {
|
||||
aabb.bounds[0] = Self::min(data[index].bounds[0], data[index + 1].bounds[0]);
|
||||
aabb.bounds[1] = Self::max(data[index].bounds[1], data[index + 1].bounds[1]);
|
||||
aabb.left_child = index as isize;
|
||||
aabb.right_child = index as isize + 1;
|
||||
}
|
||||
|
||||
if next_level_count == 1 {
|
||||
data[0] = aabb;
|
||||
break;
|
||||
} else {
|
||||
data[i as usize] = aabb;
|
||||
}
|
||||
}
|
||||
|
||||
if next_level_count == 1 {
|
||||
break;
|
||||
}
|
||||
|
||||
current_level_count = next_level_count;
|
||||
start_index = next_level_start;
|
||||
}
|
||||
}
|
||||
|
||||
fn min(v0: Vector3<f32>, v1: Vector3<f32>) -> Vector3<f32> {
|
||||
Vector3::new(v0.x.min(v1.x), v0.y.min(v1.y), v0.z.min(v1.z))
|
||||
}
|
||||
|
||||
fn max(v0: Vector3<f32>, v1: Vector3<f32>) -> Vector3<f32> {
|
||||
Vector3::new(v0.x.max(v1.x), v0.y.max(v1.y), v0.z.max(v1.z))
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
fn part(p_i: f32) -> f32 {
|
||||
p_i * p_i.log2()
|
||||
}
|
||||
|
||||
fn coded_length(table: &[(char, f32, &str, &str)], word: &str) -> u32 {
|
||||
let mut length_in_bit = 0;
|
||||
|
||||
for letter in word.chars() {
|
||||
let (_l, _p, _f, huffman_word) = table
|
||||
.iter()
|
||||
.find(|(t_letter, _p, _fano, _huffman)| letter == *t_letter)
|
||||
.expect("letter not found in table");
|
||||
|
||||
length_in_bit += huffman_word.len() as u32;
|
||||
}
|
||||
|
||||
length_in_bit
|
||||
}
|
||||
|
||||
pub fn emi_main() {
|
||||
// word, probability, fano, huffman
|
||||
|
||||
let values = [
|
||||
('V', 0.65, "0", "0"),
|
||||
('Z', 0.11, "100", "100"),
|
||||
('B', 0.05, "101", "1010"),
|
||||
('E', 0.05, "1100", "1011"),
|
||||
('T', 0.04, "1101", "1100"),
|
||||
('>', 0.04, "1110", "1101"),
|
||||
('<', 0.04, "11110", "1110"),
|
||||
('S', 0.02, "11110", "1111"),
|
||||
];
|
||||
|
||||
let mut h = 0.0;
|
||||
let mut huffman_l = 0.0;
|
||||
let mut fano_l = 0.0;
|
||||
|
||||
for (_name, probability, fano, huffman) in values.iter() {
|
||||
h -= part(*probability);
|
||||
huffman_l += *probability * huffman.len() as f32;
|
||||
fano_l += *probability * fano.len() as f32;
|
||||
}
|
||||
|
||||
let huffman_r = huffman_l - h;
|
||||
|
||||
println!("Entropie H = {}", h);
|
||||
println!("Mittlere Wortlänge L(Huffman) = {}", huffman_l);
|
||||
println!("Mittlere Wortlänge L(fano) = {}", fano_l);
|
||||
println!("Redundanz R(Huffman) = {}", huffman_r);
|
||||
|
||||
let code_length = coded_length(&values, "BVVVZVVVVVSSVVE");
|
||||
|
||||
println!("Length in Huffman = {}", code_length);
|
||||
}
|
29
src/intersection.rs
Normal file
29
src/intersection.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
use cgmath::{vec2, vec3, Vector2, Vector3, Zero};
|
||||
|
||||
use crate::triangle::Triangle;
|
||||
|
||||
use std::f32::MAX;
|
||||
|
||||
pub struct Intersection {
|
||||
pub distance: f32,
|
||||
pub triangle: Triangle,
|
||||
pub barycentric: Vector2<f32>,
|
||||
}
|
||||
|
||||
impl Intersection {
|
||||
pub fn new(distance: f32, triangle: Triangle, barycentric: Vector2<f32>) -> Intersection {
|
||||
Intersection {
|
||||
distance,
|
||||
triangle,
|
||||
barycentric,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn zero() -> Intersection {
|
||||
Intersection {
|
||||
distance: MAX,
|
||||
triangle: Triangle::zero(),
|
||||
barycentric: Vector2::zero(),
|
||||
}
|
||||
}
|
||||
}
|
82
src/main.rs
82
src/main.rs
|
@ -1,16 +1,16 @@
|
|||
use cgmath::{vec2, vec3, Vector2, Vector3, Zero};
|
||||
use cgmath::{vec2, vec3, Vector3};
|
||||
|
||||
use image::ImageBuffer;
|
||||
use utilities::prelude::*;
|
||||
|
||||
use std::f32::{MAX, MIN};
|
||||
|
||||
mod aabb;
|
||||
mod acceleration_data;
|
||||
mod camera;
|
||||
mod intersection;
|
||||
mod ray;
|
||||
mod triangle;
|
||||
|
||||
use aabb::AABB;
|
||||
use acceleration_data::AccelerationData;
|
||||
use camera::Camera;
|
||||
use ray::Ray;
|
||||
use triangle::{Triangle, Vertex};
|
||||
|
@ -72,12 +72,12 @@ fn f_to_u(color: f32) -> u8 {
|
|||
fn debug_raytracer_camera(dim_x: u32, dim_y: u32, camera: &Camera, data: &[Triangle]) {
|
||||
let mut imgbuf = ImageBuffer::new(dim_x, dim_y);
|
||||
|
||||
let acceleration_data = create_acceleration_data(data, 8);
|
||||
let acceleration_data = AccelerationData::create_tree(data, 8);
|
||||
|
||||
for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
|
||||
let ray = camera.primary_ray(x, dim_y - y, dim_x, dim_y);
|
||||
|
||||
let color = pixel_color(&ray, data, &acceleration_data);
|
||||
let color = pixel_color(&ray, &acceleration_data);
|
||||
|
||||
*pixel = image::Rgb([f_to_u(color.x), f_to_u(color.y), f_to_u(color.z)]);
|
||||
}
|
||||
|
@ -85,57 +85,10 @@ fn debug_raytracer_camera(dim_x: u32, dim_y: u32, camera: &Camera, data: &[Trian
|
|||
imgbuf.save("raytrace.png").unwrap();
|
||||
}
|
||||
|
||||
fn create_acceleration_data(input_data: &[Triangle], triangles_per_as: u32) -> Vec<AABB> {
|
||||
let mut acceleration_data = Vec::new();
|
||||
|
||||
let accel_count = (input_data.len() as f32 / triangles_per_as as f32).ceil() as usize;
|
||||
|
||||
for i in 0..accel_count {
|
||||
let mut accel = AABB::new();
|
||||
|
||||
let mut bbmin = vec3(MAX, MAX, MAX);
|
||||
let mut bbmax = vec3(MIN, MIN, MIN);
|
||||
|
||||
// 3 vertices per triangles
|
||||
// 8 triangles per acceleration structure
|
||||
let start_index = triangles_per_as as usize * i;
|
||||
let mut end_index = triangles_per_as as usize * (i + 1);
|
||||
|
||||
// check if end_index exceeds input data length
|
||||
if end_index > input_data.len() {
|
||||
end_index = input_data.len();
|
||||
}
|
||||
|
||||
// set index information
|
||||
accel.start_index = start_index;
|
||||
accel.end_index = end_index;
|
||||
|
||||
// create bounding box
|
||||
for k in start_index..end_index {
|
||||
for vertex in input_data[k].vertices.iter() {
|
||||
// check minimum values
|
||||
bbmin.x = bbmin.x.min(vertex.position.x);
|
||||
bbmin.y = bbmin.y.min(vertex.position.y);
|
||||
bbmin.z = bbmin.z.min(vertex.position.z);
|
||||
|
||||
// check maximum values
|
||||
bbmax.x = bbmax.x.max(vertex.position.x);
|
||||
bbmax.y = bbmax.y.max(vertex.position.y);
|
||||
bbmax.z = bbmax.z.max(vertex.position.z);
|
||||
}
|
||||
}
|
||||
|
||||
accel.bounds[0] = bbmin;
|
||||
accel.bounds[1] = bbmax;
|
||||
|
||||
acceleration_data.push(accel);
|
||||
}
|
||||
|
||||
acceleration_data
|
||||
}
|
||||
|
||||
fn pixel_color(ray: &Ray, data: &[Triangle], acceleration_data: &Vec<AABB>) -> Vector3<f32> {
|
||||
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();
|
||||
|
@ -156,19 +109,20 @@ fn pixel_color(ray: &Ray, data: &[Triangle], acceleration_data: &Vec<AABB>) -> V
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if closest_index != -1 {
|
||||
let i = closest_index;
|
||||
|
||||
let triangle = &data[i as usize];
|
||||
if let Some(intersection) = acceleration_data.find_closest_hit(ray) {
|
||||
let triangle = intersection.triangle;
|
||||
|
||||
/*
|
||||
let wuv = vec3(
|
||||
1.0 - barycentric.x - barycentric.y,
|
||||
barycentric.x,
|
||||
barycentric.y,
|
||||
1.0 - intersection.barycentric.x - intersection.barycentric.y,
|
||||
intersection.barycentric.x,
|
||||
intersection.barycentric.y,
|
||||
);
|
||||
|
||||
let st = point_st(&triangle, &wuv);
|
||||
*/
|
||||
|
||||
final_color = triangle.color;
|
||||
}
|
||||
|
@ -176,8 +130,10 @@ fn pixel_color(ray: &Ray, data: &[Triangle], acceleration_data: &Vec<AABB>) -> V
|
|||
return final_color;
|
||||
}
|
||||
|
||||
/*
|
||||
fn point_st(triangle: &Triangle, wuv: &Vector3<f32>) -> Vector2<f32> {
|
||||
return wuv.x * triangle.vertices[0].texture_coordinate
|
||||
+ wuv.y * triangle.vertices[1].texture_coordinate
|
||||
+ wuv.z * triangle.vertices[2].texture_coordinate;
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use cgmath::{InnerSpace, Vector2, Vector3};
|
||||
use cgmath::{InnerSpace, Vector2, Vector3, Zero};
|
||||
|
||||
use super::ray::Ray;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Vertex {
|
||||
pub position: Vector3<f32>,
|
||||
pub texture_coordinate: Vector2<f32>,
|
||||
|
@ -14,6 +15,13 @@ impl Vertex {
|
|||
texture_coordinate,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn zero() -> Vertex {
|
||||
Vertex {
|
||||
position: Vector3::zero(),
|
||||
texture_coordinate: Vector2::zero(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Triangle {
|
||||
|
@ -29,6 +37,13 @@ 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;
|
||||
|
|
Loading…
Reference in a new issue