From 15a94c2f93b30dcb88c31ae59f18a14333dd0f12 Mon Sep 17 00:00:00 2001 From: zomseffen Date: Wed, 8 Jan 2025 12:30:54 +0100 Subject: [PATCH] refactor scene.rs into multiple files --- src/{scene.rs => scene/empty_volume.rs} | 697 +----------------------- src/scene/mod.rs | 180 ++++++ src/scene/oct_tree.rs | 526 ++++++++++++++++++ 3 files changed, 711 insertions(+), 692 deletions(-) rename src/{scene.rs => scene/empty_volume.rs} (63%) create mode 100644 src/scene/mod.rs create mode 100644 src/scene/oct_tree.rs diff --git a/src/scene.rs b/src/scene/empty_volume.rs similarity index 63% rename from src/scene.rs rename to src/scene/empty_volume.rs index 0c08f4d..ad3d5e6 100644 --- a/src/scene.rs +++ b/src/scene/empty_volume.rs @@ -1,673 +1,16 @@ -use anyhow::Ok; -use vulkanalia::prelude::v1_0::*; -use anyhow::Result; - -use cgmath::{vec2, vec3, Vector3}; +use cgmath::Vector3; use std::cell::RefCell; -use std::mem; use std::rc::Rc; use std::time::Instant; -use crate::app_data::AppData; -use crate::buffer; -use crate::primitives::rec_cuboid::Cuboid; use crate::vertex; use crate::primitives::cube::Cube; use crate::primitives::quad::Quad; -use crate::primitives::drawable::Drawable; +use crate::scene::oct_tree::OctTree; -extern crate rand; -use rand::Rng; - -const CHUNK_SIZE_EXPONENT: u32 = 4; -const CHUNK_SIZE: usize = (2 as usize).pow(CHUNK_SIZE_EXPONENT); -const MAX_TREE_DEPTH: usize = 2; -const MIN_CHUNK_SIZE: usize = CHUNK_SIZE / (2 as usize).pow(MAX_TREE_DEPTH as u32); - -#[repr(C)] -#[derive(Clone, Debug, Default)] -pub struct Scene { - pub vertices: Vec, - pub sized_vertices: Vec, - pub rt_vertices: Vec, - pub indices_cube: Vec, - pub indices_cuboid: Vec, - pub indices_rt: Vec, - - pub vertex_buffer_cube: vk::Buffer, - pub vertex_buffer_memory_cube: vk::DeviceMemory, - - pub index_buffer_cube: vk::Buffer, - pub index_buffer_memory_cube: vk::DeviceMemory, - - pub vertex_buffer_cuboid: vk::Buffer, - pub vertex_buffer_memory_cuboid: vk::DeviceMemory, - - pub index_buffer_cuboid: vk::Buffer, - pub index_buffer_memory_cuboid: vk::DeviceMemory, - - pub vertex_buffer_quad: vk::Buffer, - pub vertex_buffer_memory_quad: vk::DeviceMemory, - - pub index_buffer_quad: vk::Buffer, - pub index_buffer_memory_quad: vk::DeviceMemory, - - pub rt_memory: Vec, -} - -impl Scene { - pub unsafe fn prepare_data(&mut self, instance: &vulkanalia::Instance, device: &vulkanalia::Device, data: &mut AppData) -> Result<()> { - let mut rng = rand::thread_rng(); - let grid_size = CHUNK_SIZE as i32; - - // todo store the chunks somewhere (or only use them as intermediary for neighbouthood calculation idc) - let mut oct_tree: OctTree = OctTree::create(CHUNK_SIZE)?; - - for x_index in 0..grid_size { - for y_index in 0..grid_size { - let shade = (rng.gen_range(0..25) as f32) / 100.0; - let cube = Cube { - pos: vec3(x_index as f32, y_index as f32, 5.0), - color: vec3(shade, 1.0, shade), - tex_coord: vec2(0.0, 0.0) - }; - - oct_tree.set_cube(cube.clone()); - } - } - - let shade = (rng.gen_range(0..25) as f32) / 100.0; - let cube = Cube { - pos: vec3(10.0, 10.0, 10.0), - color: vec3(shade, 1.0, shade), - tex_coord: vec2(0.0, 0.0) - }; - - oct_tree.set_cube(cube.clone()); - - let mut empty_volumes: Vec>>; - (empty_volumes, _) = EmptyVolume::from_oct_tree(&oct_tree); - println!("number of empty volumes is {}", empty_volumes.len()); - - let oct_tree_iter = OctTreeIter::create(&oct_tree)?; - for item in oct_tree_iter { - let sized_index = self.sized_vertices.len(); - let index = self.vertices.len(); - match item { - Some(cube) => { - /*if (cube.pos.x + cube.pos.y) as usize % 2 == 0{ - /**/ - let cuboid = Cuboid { - pos: cube.pos, - color: cube.color, - tex_coord: cube.tex_coord, - size: Vector3 {x: 1.0, y: 1.0, z: 1.0}, - }; - cuboid.draw(&data.topology, sized_index, self); - } - else { - cube.draw(&data.topology, index, self); - }*/ - cube.draw(&data.topology, index, self); - } - None => {} - } - } - - let mut memory_index = 1; // zero should be the location for the overall length (also will be the invalid memory allocation for pointing to a nonexistant neighbor) - for volume in &empty_volumes { - volume.borrow_mut().memory_start = memory_index; - memory_index += volume.borrow().get_buffer_mem_size() as usize; - - } - for volume in &empty_volumes { - let quads = volume.borrow().to_quads(); - for quad in quads { - quad.draw(&data.topology, self.rt_vertices.len(), self); - } - } - println!("Memory size is {} kB, max indes is {}", memory_index * 32 / 8 /1024 + 1, memory_index); - let mut volume_vec = vec![memory_index as u32; memory_index]; - for volume in &empty_volumes { - volume_vec = volume.borrow().insert_into_memory(volume_vec); - } - println!("volume_vec print {:?}", volume_vec); - let mut empty_count = 0; - for element in &volume_vec { - if *element == memory_index as u32 { - empty_count += 1; - } - } - println!("empty elements count is {}", empty_count); - self.rt_memory = volume_vec; - data.scene_rt_memory_size = (self.rt_memory.len() * 4) as u64; // size of the needed buffer size in bytes - - if self.vertices.len() != 0 { - (self.vertex_buffer_cube, self.vertex_buffer_memory_cube) = buffer::create_vertex_buffer(instance, device, &data, &self.vertices)?; - (self.index_buffer_cube, self.index_buffer_memory_cube) = buffer::create_index_buffer(&instance, &device, &data, &self.indices_cube)?; - } - - if self.sized_vertices.len() != 0 { - (self.vertex_buffer_cuboid, self.vertex_buffer_memory_cuboid) = buffer::create_vertex_buffer(instance, device, &data, &self.sized_vertices)?; - (self.index_buffer_cuboid, self.index_buffer_memory_cuboid) = buffer::create_index_buffer(&instance, &device, &data, &self.indices_cuboid)?; - } - - if self.rt_vertices.len() != 0 { - (self.vertex_buffer_quad, self.vertex_buffer_memory_quad) = buffer::create_vertex_buffer(instance, device, &data, &self.rt_vertices)?; - (self.index_buffer_quad, self.index_buffer_memory_quad) = buffer::create_index_buffer(&instance, &device, &data, &self.indices_rt)?; - } - - Ok(()) - - } - - pub unsafe fn destroy(&mut self, device: &vulkanalia::Device) { - device.destroy_buffer(self.index_buffer_cube, None); - device.free_memory(self.index_buffer_memory_cube, None); - - device.destroy_buffer(self.vertex_buffer_cube, None); - device.free_memory(self.vertex_buffer_memory_cube, None); - - device.destroy_buffer(self.index_buffer_cuboid, None); - device.free_memory(self.index_buffer_memory_cuboid, None); - - device.destroy_buffer(self.vertex_buffer_cuboid, None); - device.free_memory(self.vertex_buffer_memory_cuboid, None); - - device.destroy_buffer(self.index_buffer_quad, None); - device.free_memory(self.index_buffer_memory_quad, None); - - device.destroy_buffer(self.vertex_buffer_quad, None); - device.free_memory(self.vertex_buffer_memory_quad, None); - } -} - -#[derive(Clone, Debug)] -#[allow(non_snake_case)] -struct OctTree { - pub child_XYZ: Option>>, - pub child_xYZ: Option>>, - pub child_xyZ: Option>>, - pub child_XyZ: Option>>, - pub child_XYz: Option>>, - pub child_xYz: Option>>, - pub child_xyz: Option>>, - pub child_Xyz: Option>>, - - pub blocks: Vec>, - - size: usize, -} -#[warn(non_snake_case)] - -impl OctTree { - pub fn set_cube(&mut self, cube: Cube) { - let x = cube.pos.x as usize; - let y = cube.pos.y as usize; - let z = cube.pos.z as usize; - assert!(x < self.size, "x value out of range!"); - assert!(y < self.size, "y value out of range!"); - assert!(z < self.size, "z value out of range!"); - self.set_element_internal(cube, x, y, z); - } -} - -impl OctTree { - pub fn create(size: usize) -> Result { - let mut blocks: Vec> = vec![]; - if size == MIN_CHUNK_SIZE { - for _ in 0..MIN_CHUNK_SIZE { - for _ in 0..MIN_CHUNK_SIZE { - for _ in 0..MIN_CHUNK_SIZE { - blocks.push(None); - } - } - } - } - - Ok(Self { - child_XYZ: None, - child_xYZ: None, - child_xyZ: None, - child_XyZ: None, - child_XYz: None, - child_xYz: None, - child_xyz: None, - child_Xyz: None, - - blocks: blocks, - - size, - }) - } - - pub fn set_element(&mut self, element: T, x: usize, y: usize, z: usize) { - assert!(x < self.size, "x value out of range!"); - assert!(y < self.size, "y value out of range!"); - assert!(z < self.size, "z value out of range!"); - self.set_element_internal(element, x, y, z); - } - - fn set_element_internal(&mut self, element: T, x: usize, y: usize, z: usize) { - if self.size > MIN_CHUNK_SIZE { - let mid_point = self.size / 2; - if x >= mid_point { - if y >= mid_point { - if z >= mid_point { - match &self.child_XYZ { - Some(child) => { - child.borrow_mut().set_element_internal(element, x - mid_point, y - mid_point, z - mid_point); - }, - None => { - let mut child = OctTree::create(self.size / 2).unwrap(); - child.set_element_internal(element, x - mid_point, y - mid_point, z - mid_point); - self.child_XYZ = Some(Rc::new(RefCell::new(child))); - } - } - } - else { - match &self.child_XYz { - Some(child) => { - child.borrow_mut().set_element_internal(element, x - mid_point, y - mid_point, z); - }, - None => { - let mut child = OctTree::create(self.size / 2).unwrap(); - child.set_element_internal(element, x - mid_point, y - mid_point, z); - self.child_XYz = Some(Rc::new(RefCell::new(child))); - } - } - } - } - else { - if z >= mid_point { - match &self.child_XyZ { - Some(child) => { - child.borrow_mut().set_element_internal(element, x - mid_point, y, z - mid_point); - }, - None => { - let mut child = OctTree::create(self.size / 2).unwrap(); - child.set_element_internal(element, x - mid_point, y, z - mid_point); - self.child_XyZ = Some(Rc::new(RefCell::new(child))); - } - } - } - else { - match &self.child_Xyz { - Some(child) => { - child.borrow_mut().set_element_internal(element, x - mid_point, y, z); - }, - None => { - let mut child = OctTree::create(self.size / 2).unwrap(); - child.set_element_internal(element, x - mid_point, y, z); - self.child_Xyz = Some(Rc::new(RefCell::new(child))); - } - } - } - } - } - else { - if y >= mid_point { - if z >= mid_point { - match &self.child_xYZ { - Some(child) => { - child.borrow_mut().set_element_internal(element, x, y - mid_point, z - mid_point); - }, - None => { - let mut child = OctTree::create(self.size / 2).unwrap(); - child.set_element_internal(element, x, y - mid_point, z - mid_point); - self.child_xYZ = Some(Rc::new(RefCell::new(child))); - } - } - } - else { - match &self.child_xYz { - Some(child) => { - child.borrow_mut().set_element_internal(element, x, y - mid_point, z); - }, - None => { - let mut child = OctTree::create(self.size / 2).unwrap(); - child.set_element_internal(element, x, y - mid_point, z); - self.child_xYz = Some(Rc::new(RefCell::new(child))); - } - } - } - } - else { - if z >= mid_point { - match &self.child_xyZ { - Some(child) => { - child.borrow_mut().set_element_internal(element, x, y, z - mid_point); - }, - None => { - let mut child = OctTree::create(self.size / 2).unwrap(); - child.set_element_internal(element, x, y, z - mid_point); - self.child_xyZ = Some(Rc::new(RefCell::new(child))); - } - } - } - else { - match &self.child_xyz { - Some(child) => { - child.borrow_mut().set_element_internal(element, x, y, z); - }, - None => { - let mut child = OctTree::create(self.size / 2).unwrap(); - child.set_element_internal(element, x, y, z); - self.child_xyz = Some(Rc::new(RefCell::new(child))); - } - } - } - } - } - } - else { - self.blocks[z * MIN_CHUNK_SIZE * MIN_CHUNK_SIZE + y * MIN_CHUNK_SIZE + x] = Some(element); - } - } - - pub fn clear_cube(&mut self, x: usize, y: usize, z: usize) { - assert!(x < self.size, "x value out of range!"); - assert!(y < self.size, "y value out of range!"); - assert!(z < self.size, "z value out of range!"); - //self.blocks.remove(&vec3(x as u32, y as u32, z as u32)); - - self.clear_cube_internal(x, y, z) - } - - fn clear_cube_internal(&mut self, x: usize, y: usize, z: usize) { - if self.size > MIN_CHUNK_SIZE { - let mid_point = self.size / 2; - if x >= mid_point { - if y >= mid_point { - if z >= mid_point { - match &self.child_XYZ { - Some(child) => { - child.borrow_mut().clear_cube_internal(x - mid_point, y - mid_point, z - mid_point); - }, - None => {} - } - } - else { - match &self.child_XYz { - Some(child) => { - child.borrow_mut().clear_cube_internal(x - mid_point, y - mid_point, z); - }, - None => {} - } - } - } - else { - if z >= mid_point { - match &self.child_XyZ { - Some(child) => { - child.borrow_mut().clear_cube_internal(x - mid_point, y, z - mid_point); - }, - None => {} - } - } - else { - match &self.child_Xyz { - Some(child) => { - child.borrow_mut().clear_cube_internal(x - mid_point, y, z); - }, - None => {} - } - } - } - } - else { - if y >= mid_point { - if z >= mid_point { - match &self.child_xYZ { - Some(child) => { - child.borrow_mut().clear_cube_internal(x, y - mid_point, z - mid_point); - }, - None => {} - } - } - else { - match &self.child_xYz { - Some(child) => { - child.borrow_mut().clear_cube_internal(x, y - mid_point, z); - }, - None => {} - } - } - } - else { - if z >= mid_point { - match &self.child_xyZ { - Some(child) => { - child.borrow_mut().clear_cube_internal(x, y, z - mid_point); - }, - None => {} - } - } - else { - match &self.child_xyz { - Some(child) => { - child.borrow_mut().clear_cube_internal(x, y, z); - }, - None => {} - } - } - } - } - } - else { - self.blocks[z * MIN_CHUNK_SIZE * MIN_CHUNK_SIZE + y * MIN_CHUNK_SIZE + x] = None; - } - } - - pub fn get_element(&self, x: usize, y: usize, z: usize) -> Option { - if x >= self.size || y >= self.size || z >= self.size { - return None - } - - if self.size > MIN_CHUNK_SIZE { - let mid_point = self.size / 2; - if x >= mid_point { - if y >= mid_point { - if z >= mid_point { - match &self.child_XYZ { - Some(child) => { - child.borrow().get_element(x - mid_point, y - mid_point, z - mid_point) - }, - None => None - } - } - else { - match &self.child_XYz { - Some(child) => { - child.borrow().get_element( x - mid_point, y - mid_point, z) - }, - None => None - } - } - } - else { - if z >= mid_point { - match &self.child_XyZ { - Some(child) => { - child.borrow().get_element(x - mid_point, y, z - mid_point) - }, - None => None - } - } - else { - match &self.child_Xyz { - Some(child) => { - child.borrow().get_element(x - mid_point, y, z) - }, - None => None - } - } - } - } - else { - if y >= mid_point { - if z >= mid_point { - match &self.child_xYZ { - Some(child) => { - child.borrow().get_element(x, y - mid_point, z - mid_point) - }, - None => None - } - } - else { - match &self.child_xYz { - Some(child) => { - child.borrow().get_element(x, y - mid_point, z) - }, - None => None - } - } - } - else { - if z >= mid_point { - match &self.child_xyZ { - Some(child) => { - child.borrow().get_element(x, y, z - mid_point) - }, - None => None - } - } - else { - match &self.child_xyz { - Some(child) => { - child.borrow().get_element(x, y, z) - }, - None => None - } - } - } - } - } - else { - self.blocks[z * MIN_CHUNK_SIZE * MIN_CHUNK_SIZE + y * MIN_CHUNK_SIZE + x].clone() - } - } -} - -struct OctTreeIter<'a> { - iter_x: usize, - iter_y: usize, - iter_z: usize, - todo: Vec>>>, - chunk: &'a OctTree -} - -impl<'a> OctTreeIter<'a> { - pub fn create(chunk: &'a OctTree) -> Result { - let mut out = Self { - iter_x: 0, - iter_y: 0, - iter_z: 0, - todo: vec![], - chunk - }; - out.add_todo(&chunk); - Ok(out) - } - - fn add_todo(&mut self, oct_tree: &OctTree) { - match &oct_tree.child_XYZ { - Some(child) => { - self.todo.push(child.clone()); - }, - None => {}, - }; - match &oct_tree.child_xYZ { - Some(child) => { - self.todo.push(child.clone()); - }, - None => {}, - }; - match &oct_tree.child_xyZ { - Some(child) => { - self.todo.push(child.clone()); - }, - None => {}, - }; - match &oct_tree.child_XyZ { - Some(child) => { - self.todo.push(child.clone()); - }, - None => {}, - }; - match &oct_tree.child_XYz { - Some(child) => { - self.todo.push(child.clone()); - }, - None => {}, - }; - match &oct_tree.child_xYz { - Some(child) => { - self.todo.push(child.clone()); - }, - None => {}, - }; - match &oct_tree.child_xyz { - Some(child) => { - self.todo.push(child.clone()); - }, - None => {}, - }; - match &oct_tree.child_Xyz { - Some(child) => { - self.todo.push(child.clone()); - }, - None => {}, - }; - } -} - -impl<'a> Iterator for OctTreeIter<'a> { - type Item = Option; - - fn next(&mut self) -> Option { - if self.todo.len() != 0 { - while self.todo.last().unwrap().borrow().blocks.len() == 0 { - let oct_tree = self.todo.pop().unwrap(); - self.add_todo(&oct_tree.borrow()); - } - - if self.iter_x < MIN_CHUNK_SIZE && self.iter_y < MIN_CHUNK_SIZE && self.iter_z < MIN_CHUNK_SIZE { - let result = self.todo.last().unwrap().borrow().blocks[self.iter_x + self.iter_y * MIN_CHUNK_SIZE + self.iter_z * MIN_CHUNK_SIZE * MIN_CHUNK_SIZE].clone(); - - self.iter_x += 1; - if self.iter_x >= MIN_CHUNK_SIZE { - self.iter_x = 0; - self.iter_y += 1; - } - if self.iter_y >= MIN_CHUNK_SIZE { - self.iter_y = 0; - self.iter_z += 1; - } - - if self.iter_z == MIN_CHUNK_SIZE { - self.todo.pop(); - self.iter_x = 0; - self.iter_y = 0; - self.iter_z = 0; - } - - return Some(result) - } - } - - self.iter_x = 0; - self.iter_y = 0; - self.iter_z = 0; - self.add_todo(&self.chunk); - None - } -} - - -struct EmptyVolume { +pub struct EmptyVolume { pub memory_start: usize, pub size_x: usize, @@ -1190,7 +533,7 @@ impl EmptyVolume { (volumes, neighbors) } - fn to_quads(&self) -> Vec { + pub fn to_quads(&self) -> Vec { let mut quads = vec![]; let float_pos = Vector3 {x: self.position.x as f32, y: self.position.y as f32, z: self.position.z as f32}; //bottom sides of the volumes, top side of the block @@ -1671,34 +1014,4 @@ impl EmptyVolume { println!("last memory index of volume was {}, equivalent to {}kB", mem_index, mem_index * 32 / 8 / 1024); v } -} - -#[cfg(test)] -mod test { - use cgmath::Vector2; - - use super::*; - - #[test] - fn test_oct_tree(){ - let mut test_tree: OctTree = OctTree::create(512).unwrap(); - let test_cube = Cube{color: Vector3 { x: 1.0, y: 0.0, z: 0.0 }, pos: Vector3 { x: 5.0, y: 2.0, z: 10.0 }, tex_coord: Vector2{x: 0.0, y: 0.0}}; - - test_tree.set_cube(test_cube.clone()); - - let cube_result = test_tree.get_element(5, 2, 10).unwrap(); - let cube_result2 = test_tree.get_element(300, 2, 10); - assert_eq!(test_cube, cube_result); - assert_eq!(cube_result2, None); - - let test_iter = OctTreeIter::create(&test_tree).unwrap(); - - let mut count = 0; - for result in test_iter { - if let Some(_) = result { - count += 1; - } - } - assert_eq!(count, 1); - } -} +} \ No newline at end of file diff --git a/src/scene/mod.rs b/src/scene/mod.rs new file mode 100644 index 0000000..9103b37 --- /dev/null +++ b/src/scene/mod.rs @@ -0,0 +1,180 @@ +mod oct_tree; +mod empty_volume; + +use anyhow::Ok; +use vulkanalia::prelude::v1_0::*; +use anyhow::Result; + +use cgmath::{vec2, vec3}; + +use std::cell::RefCell; +use std::rc::Rc; + +use crate::app_data::AppData; +use crate::buffer; +use crate::vertex; +use crate::primitives::cube::Cube; +use crate::primitives::drawable::Drawable; +use crate::scene::oct_tree::{OctTree, OctTreeIter, CHUNK_SIZE}; +use crate::scene::empty_volume::EmptyVolume; + +extern crate rand; +use rand::Rng; + +#[repr(C)] +#[derive(Clone, Debug, Default)] +pub struct Scene { + pub vertices: Vec, + pub sized_vertices: Vec, + pub rt_vertices: Vec, + pub indices_cube: Vec, + pub indices_cuboid: Vec, + pub indices_rt: Vec, + + pub vertex_buffer_cube: vk::Buffer, + pub vertex_buffer_memory_cube: vk::DeviceMemory, + + pub index_buffer_cube: vk::Buffer, + pub index_buffer_memory_cube: vk::DeviceMemory, + + pub vertex_buffer_cuboid: vk::Buffer, + pub vertex_buffer_memory_cuboid: vk::DeviceMemory, + + pub index_buffer_cuboid: vk::Buffer, + pub index_buffer_memory_cuboid: vk::DeviceMemory, + + pub vertex_buffer_quad: vk::Buffer, + pub vertex_buffer_memory_quad: vk::DeviceMemory, + + pub index_buffer_quad: vk::Buffer, + pub index_buffer_memory_quad: vk::DeviceMemory, + + pub rt_memory: Vec, +} + +impl Scene { + pub unsafe fn prepare_data(&mut self, instance: &vulkanalia::Instance, device: &vulkanalia::Device, data: &mut AppData) -> Result<()> { + let mut rng = rand::thread_rng(); + let grid_size = CHUNK_SIZE as i32; + + // todo store the chunks somewhere (or only use them as intermediary for neighbouthood calculation idc) + let mut oct_tree: OctTree = OctTree::create(CHUNK_SIZE)?; + + for x_index in 0..grid_size { + for y_index in 0..grid_size { + let shade = (rng.gen_range(0..25) as f32) / 100.0; + let cube = Cube { + pos: vec3(x_index as f32, y_index as f32, 5.0), + color: vec3(shade, 1.0, shade), + tex_coord: vec2(0.0, 0.0) + }; + + oct_tree.set_cube(cube.clone()); + } + } + + let shade = (rng.gen_range(0..25) as f32) / 100.0; + let cube = Cube { + pos: vec3(10.0, 10.0, 10.0), + color: vec3(shade, 1.0, shade), + tex_coord: vec2(0.0, 0.0) + }; + + oct_tree.set_cube(cube.clone()); + + let mut empty_volumes: Vec>>; + (empty_volumes, _) = EmptyVolume::from_oct_tree(&oct_tree); + println!("number of empty volumes is {}", empty_volumes.len()); + + let oct_tree_iter = OctTreeIter::create(&oct_tree)?; + for item in oct_tree_iter { + let sized_index = self.sized_vertices.len(); + let index = self.vertices.len(); + match item { + Some(cube) => { + /*if (cube.pos.x + cube.pos.y) as usize % 2 == 0{ + /**/ + let cuboid = Cuboid { + pos: cube.pos, + color: cube.color, + tex_coord: cube.tex_coord, + size: Vector3 {x: 1.0, y: 1.0, z: 1.0}, + }; + cuboid.draw(&data.topology, sized_index, self); + } + else { + cube.draw(&data.topology, index, self); + }*/ + cube.draw(&data.topology, index, self); + } + None => {} + } + } + + let mut memory_index = 1; // zero should be the location for the overall length (also will be the invalid memory allocation for pointing to a nonexistant neighbor) + for volume in &empty_volumes { + volume.borrow_mut().memory_start = memory_index; + memory_index += volume.borrow().get_buffer_mem_size() as usize; + + } + for volume in &empty_volumes { + let quads = volume.borrow().to_quads(); + for quad in quads { + quad.draw(&data.topology, self.rt_vertices.len(), self); + } + } + println!("Memory size is {} kB, max indes is {}", memory_index * 32 / 8 /1024 + 1, memory_index); + let mut volume_vec = vec![memory_index as u32; memory_index]; + for volume in &empty_volumes { + volume_vec = volume.borrow().insert_into_memory(volume_vec); + } + println!("volume_vec print {:?}", volume_vec); + let mut empty_count = 0; + for element in &volume_vec { + if *element == memory_index as u32 { + empty_count += 1; + } + } + println!("empty elements count is {}", empty_count); + self.rt_memory = volume_vec; + data.scene_rt_memory_size = (self.rt_memory.len() * 4) as u64; // size of the needed buffer size in bytes + + if self.vertices.len() != 0 { + (self.vertex_buffer_cube, self.vertex_buffer_memory_cube) = buffer::create_vertex_buffer(instance, device, &data, &self.vertices)?; + (self.index_buffer_cube, self.index_buffer_memory_cube) = buffer::create_index_buffer(&instance, &device, &data, &self.indices_cube)?; + } + + if self.sized_vertices.len() != 0 { + (self.vertex_buffer_cuboid, self.vertex_buffer_memory_cuboid) = buffer::create_vertex_buffer(instance, device, &data, &self.sized_vertices)?; + (self.index_buffer_cuboid, self.index_buffer_memory_cuboid) = buffer::create_index_buffer(&instance, &device, &data, &self.indices_cuboid)?; + } + + if self.rt_vertices.len() != 0 { + (self.vertex_buffer_quad, self.vertex_buffer_memory_quad) = buffer::create_vertex_buffer(instance, device, &data, &self.rt_vertices)?; + (self.index_buffer_quad, self.index_buffer_memory_quad) = buffer::create_index_buffer(&instance, &device, &data, &self.indices_rt)?; + } + + Ok(()) + + } + + pub unsafe fn destroy(&mut self, device: &vulkanalia::Device) { + device.destroy_buffer(self.index_buffer_cube, None); + device.free_memory(self.index_buffer_memory_cube, None); + + device.destroy_buffer(self.vertex_buffer_cube, None); + device.free_memory(self.vertex_buffer_memory_cube, None); + + device.destroy_buffer(self.index_buffer_cuboid, None); + device.free_memory(self.index_buffer_memory_cuboid, None); + + device.destroy_buffer(self.vertex_buffer_cuboid, None); + device.free_memory(self.vertex_buffer_memory_cuboid, None); + + device.destroy_buffer(self.index_buffer_quad, None); + device.free_memory(self.index_buffer_memory_quad, None); + + device.destroy_buffer(self.vertex_buffer_quad, None); + device.free_memory(self.vertex_buffer_memory_quad, None); + } +} \ No newline at end of file diff --git a/src/scene/oct_tree.rs b/src/scene/oct_tree.rs new file mode 100644 index 0000000..006d16d --- /dev/null +++ b/src/scene/oct_tree.rs @@ -0,0 +1,526 @@ +use anyhow::Ok; +use anyhow::Result; + +use std::cell::RefCell; +use std::rc::Rc; +use crate::primitives::cube::Cube; + +extern crate rand; + +pub const CHUNK_SIZE_EXPONENT: u32 = 4; +pub const CHUNK_SIZE: usize = (2 as usize).pow(CHUNK_SIZE_EXPONENT); +pub const MAX_TREE_DEPTH: usize = 2; +pub const MIN_CHUNK_SIZE: usize = CHUNK_SIZE / (2 as usize).pow(MAX_TREE_DEPTH as u32); + +#[derive(Clone, Debug)] +#[allow(non_snake_case)] +pub struct OctTree { + pub child_XYZ: Option>>, + pub child_xYZ: Option>>, + pub child_xyZ: Option>>, + pub child_XyZ: Option>>, + pub child_XYz: Option>>, + pub child_xYz: Option>>, + pub child_xyz: Option>>, + pub child_Xyz: Option>>, + + pub blocks: Vec>, + + pub size: usize, +} +#[warn(non_snake_case)] + +impl OctTree { + pub fn set_cube(&mut self, cube: Cube) { + let x = cube.pos.x as usize; + let y = cube.pos.y as usize; + let z = cube.pos.z as usize; + assert!(x < self.size, "x value out of range!"); + assert!(y < self.size, "y value out of range!"); + assert!(z < self.size, "z value out of range!"); + self.set_element_internal(cube, x, y, z); + } +} + +impl OctTree { + pub fn create(size: usize) -> Result { + let mut blocks: Vec> = vec![]; + if size == MIN_CHUNK_SIZE { + for _ in 0..MIN_CHUNK_SIZE { + for _ in 0..MIN_CHUNK_SIZE { + for _ in 0..MIN_CHUNK_SIZE { + blocks.push(None); + } + } + } + } + + Ok(Self { + child_XYZ: None, + child_xYZ: None, + child_xyZ: None, + child_XyZ: None, + child_XYz: None, + child_xYz: None, + child_xyz: None, + child_Xyz: None, + + blocks: blocks, + + size, + }) + } + + pub fn set_element(&mut self, element: T, x: usize, y: usize, z: usize) { + assert!(x < self.size, "x value out of range!"); + assert!(y < self.size, "y value out of range!"); + assert!(z < self.size, "z value out of range!"); + self.set_element_internal(element, x, y, z); + } + + fn set_element_internal(&mut self, element: T, x: usize, y: usize, z: usize) { + if self.size > MIN_CHUNK_SIZE { + let mid_point = self.size / 2; + if x >= mid_point { + if y >= mid_point { + if z >= mid_point { + match &self.child_XYZ { + Some(child) => { + child.borrow_mut().set_element_internal(element, x - mid_point, y - mid_point, z - mid_point); + }, + None => { + let mut child = OctTree::create(self.size / 2).unwrap(); + child.set_element_internal(element, x - mid_point, y - mid_point, z - mid_point); + self.child_XYZ = Some(Rc::new(RefCell::new(child))); + } + } + } + else { + match &self.child_XYz { + Some(child) => { + child.borrow_mut().set_element_internal(element, x - mid_point, y - mid_point, z); + }, + None => { + let mut child = OctTree::create(self.size / 2).unwrap(); + child.set_element_internal(element, x - mid_point, y - mid_point, z); + self.child_XYz = Some(Rc::new(RefCell::new(child))); + } + } + } + } + else { + if z >= mid_point { + match &self.child_XyZ { + Some(child) => { + child.borrow_mut().set_element_internal(element, x - mid_point, y, z - mid_point); + }, + None => { + let mut child = OctTree::create(self.size / 2).unwrap(); + child.set_element_internal(element, x - mid_point, y, z - mid_point); + self.child_XyZ = Some(Rc::new(RefCell::new(child))); + } + } + } + else { + match &self.child_Xyz { + Some(child) => { + child.borrow_mut().set_element_internal(element, x - mid_point, y, z); + }, + None => { + let mut child = OctTree::create(self.size / 2).unwrap(); + child.set_element_internal(element, x - mid_point, y, z); + self.child_Xyz = Some(Rc::new(RefCell::new(child))); + } + } + } + } + } + else { + if y >= mid_point { + if z >= mid_point { + match &self.child_xYZ { + Some(child) => { + child.borrow_mut().set_element_internal(element, x, y - mid_point, z - mid_point); + }, + None => { + let mut child = OctTree::create(self.size / 2).unwrap(); + child.set_element_internal(element, x, y - mid_point, z - mid_point); + self.child_xYZ = Some(Rc::new(RefCell::new(child))); + } + } + } + else { + match &self.child_xYz { + Some(child) => { + child.borrow_mut().set_element_internal(element, x, y - mid_point, z); + }, + None => { + let mut child = OctTree::create(self.size / 2).unwrap(); + child.set_element_internal(element, x, y - mid_point, z); + self.child_xYz = Some(Rc::new(RefCell::new(child))); + } + } + } + } + else { + if z >= mid_point { + match &self.child_xyZ { + Some(child) => { + child.borrow_mut().set_element_internal(element, x, y, z - mid_point); + }, + None => { + let mut child = OctTree::create(self.size / 2).unwrap(); + child.set_element_internal(element, x, y, z - mid_point); + self.child_xyZ = Some(Rc::new(RefCell::new(child))); + } + } + } + else { + match &self.child_xyz { + Some(child) => { + child.borrow_mut().set_element_internal(element, x, y, z); + }, + None => { + let mut child = OctTree::create(self.size / 2).unwrap(); + child.set_element_internal(element, x, y, z); + self.child_xyz = Some(Rc::new(RefCell::new(child))); + } + } + } + } + } + } + else { + self.blocks[z * MIN_CHUNK_SIZE * MIN_CHUNK_SIZE + y * MIN_CHUNK_SIZE + x] = Some(element); + } + } + + pub fn clear_cube(&mut self, x: usize, y: usize, z: usize) { + assert!(x < self.size, "x value out of range!"); + assert!(y < self.size, "y value out of range!"); + assert!(z < self.size, "z value out of range!"); + //self.blocks.remove(&vec3(x as u32, y as u32, z as u32)); + + self.clear_cube_internal(x, y, z) + } + + fn clear_cube_internal(&mut self, x: usize, y: usize, z: usize) { + if self.size > MIN_CHUNK_SIZE { + let mid_point = self.size / 2; + if x >= mid_point { + if y >= mid_point { + if z >= mid_point { + match &self.child_XYZ { + Some(child) => { + child.borrow_mut().clear_cube_internal(x - mid_point, y - mid_point, z - mid_point); + }, + None => {} + } + } + else { + match &self.child_XYz { + Some(child) => { + child.borrow_mut().clear_cube_internal(x - mid_point, y - mid_point, z); + }, + None => {} + } + } + } + else { + if z >= mid_point { + match &self.child_XyZ { + Some(child) => { + child.borrow_mut().clear_cube_internal(x - mid_point, y, z - mid_point); + }, + None => {} + } + } + else { + match &self.child_Xyz { + Some(child) => { + child.borrow_mut().clear_cube_internal(x - mid_point, y, z); + }, + None => {} + } + } + } + } + else { + if y >= mid_point { + if z >= mid_point { + match &self.child_xYZ { + Some(child) => { + child.borrow_mut().clear_cube_internal(x, y - mid_point, z - mid_point); + }, + None => {} + } + } + else { + match &self.child_xYz { + Some(child) => { + child.borrow_mut().clear_cube_internal(x, y - mid_point, z); + }, + None => {} + } + } + } + else { + if z >= mid_point { + match &self.child_xyZ { + Some(child) => { + child.borrow_mut().clear_cube_internal(x, y, z - mid_point); + }, + None => {} + } + } + else { + match &self.child_xyz { + Some(child) => { + child.borrow_mut().clear_cube_internal(x, y, z); + }, + None => {} + } + } + } + } + } + else { + self.blocks[z * MIN_CHUNK_SIZE * MIN_CHUNK_SIZE + y * MIN_CHUNK_SIZE + x] = None; + } + } + + pub fn get_element(&self, x: usize, y: usize, z: usize) -> Option { + if x >= self.size || y >= self.size || z >= self.size { + return None + } + + if self.size > MIN_CHUNK_SIZE { + let mid_point = self.size / 2; + if x >= mid_point { + if y >= mid_point { + if z >= mid_point { + match &self.child_XYZ { + Some(child) => { + child.borrow().get_element(x - mid_point, y - mid_point, z - mid_point) + }, + None => None + } + } + else { + match &self.child_XYz { + Some(child) => { + child.borrow().get_element( x - mid_point, y - mid_point, z) + }, + None => None + } + } + } + else { + if z >= mid_point { + match &self.child_XyZ { + Some(child) => { + child.borrow().get_element(x - mid_point, y, z - mid_point) + }, + None => None + } + } + else { + match &self.child_Xyz { + Some(child) => { + child.borrow().get_element(x - mid_point, y, z) + }, + None => None + } + } + } + } + else { + if y >= mid_point { + if z >= mid_point { + match &self.child_xYZ { + Some(child) => { + child.borrow().get_element(x, y - mid_point, z - mid_point) + }, + None => None + } + } + else { + match &self.child_xYz { + Some(child) => { + child.borrow().get_element(x, y - mid_point, z) + }, + None => None + } + } + } + else { + if z >= mid_point { + match &self.child_xyZ { + Some(child) => { + child.borrow().get_element(x, y, z - mid_point) + }, + None => None + } + } + else { + match &self.child_xyz { + Some(child) => { + child.borrow().get_element(x, y, z) + }, + None => None + } + } + } + } + } + else { + self.blocks[z * MIN_CHUNK_SIZE * MIN_CHUNK_SIZE + y * MIN_CHUNK_SIZE + x].clone() + } + } +} + +pub struct OctTreeIter<'a> { + iter_x: usize, + iter_y: usize, + iter_z: usize, + todo: Vec>>>, + chunk: &'a OctTree +} + +impl<'a> OctTreeIter<'a> { + pub fn create(chunk: &'a OctTree) -> Result { + let mut out = Self { + iter_x: 0, + iter_y: 0, + iter_z: 0, + todo: vec![], + chunk + }; + out.add_todo(&chunk); + Ok(out) + } + + fn add_todo(&mut self, oct_tree: &OctTree) { + match &oct_tree.child_XYZ { + Some(child) => { + self.todo.push(child.clone()); + }, + None => {}, + }; + match &oct_tree.child_xYZ { + Some(child) => { + self.todo.push(child.clone()); + }, + None => {}, + }; + match &oct_tree.child_xyZ { + Some(child) => { + self.todo.push(child.clone()); + }, + None => {}, + }; + match &oct_tree.child_XyZ { + Some(child) => { + self.todo.push(child.clone()); + }, + None => {}, + }; + match &oct_tree.child_XYz { + Some(child) => { + self.todo.push(child.clone()); + }, + None => {}, + }; + match &oct_tree.child_xYz { + Some(child) => { + self.todo.push(child.clone()); + }, + None => {}, + }; + match &oct_tree.child_xyz { + Some(child) => { + self.todo.push(child.clone()); + }, + None => {}, + }; + match &oct_tree.child_Xyz { + Some(child) => { + self.todo.push(child.clone()); + }, + None => {}, + }; + } +} + +impl<'a> Iterator for OctTreeIter<'a> { + type Item = Option; + + fn next(&mut self) -> Option { + if self.todo.len() != 0 { + while self.todo.last().unwrap().borrow().blocks.len() == 0 { + let oct_tree = self.todo.pop().unwrap(); + self.add_todo(&oct_tree.borrow()); + } + + if self.iter_x < MIN_CHUNK_SIZE && self.iter_y < MIN_CHUNK_SIZE && self.iter_z < MIN_CHUNK_SIZE { + let result = self.todo.last().unwrap().borrow().blocks[self.iter_x + self.iter_y * MIN_CHUNK_SIZE + self.iter_z * MIN_CHUNK_SIZE * MIN_CHUNK_SIZE].clone(); + + self.iter_x += 1; + if self.iter_x >= MIN_CHUNK_SIZE { + self.iter_x = 0; + self.iter_y += 1; + } + if self.iter_y >= MIN_CHUNK_SIZE { + self.iter_y = 0; + self.iter_z += 1; + } + + if self.iter_z == MIN_CHUNK_SIZE { + self.todo.pop(); + self.iter_x = 0; + self.iter_y = 0; + self.iter_z = 0; + } + + return Some(result) + } + } + + self.iter_x = 0; + self.iter_y = 0; + self.iter_z = 0; + self.add_todo(&self.chunk); + None + } +} + +#[cfg(test)] +mod test { + use cgmath::{Vector2, Vector3}; + + use super::*; + + #[test] + fn test_oct_tree(){ + let mut test_tree: OctTree = OctTree::create(512).unwrap(); + let test_cube = Cube{color: Vector3 { x: 1.0, y: 0.0, z: 0.0 }, pos: Vector3 { x: 5.0, y: 2.0, z: 10.0 }, tex_coord: Vector2{x: 0.0, y: 0.0}}; + + test_tree.set_cube(test_cube.clone()); + + let cube_result = test_tree.get_element(5, 2, 10).unwrap(); + let cube_result2 = test_tree.get_element(300, 2, 10); + assert_eq!(test_cube, cube_result); + assert_eq!(cube_result2, None); + + let test_iter = OctTreeIter::create(&test_tree).unwrap(); + + let mut count = 0; + for result in test_iter { + if let Some(_) = result { + count += 1; + } + } + assert_eq!(count, 1); + } +} +