diff --git a/README b/README new file mode 100644 index 0000000..0bd8a5a --- /dev/null +++ b/README @@ -0,0 +1 @@ +install environment described as in https://kylemayes.github.io/vulkanalia/development_environment.html \ No newline at end of file diff --git a/src/app_data.rs b/src/app_data.rs index 5825fe5..71a99e6 100644 --- a/src/app_data.rs +++ b/src/app_data.rs @@ -34,6 +34,9 @@ pub struct AppData { pub uniform_buffers: Vec, pub uniform_buffers_memory: Vec, + pub storage_buffers: Vec, + pub storage_buffers_memory: Vec, + pub descriptor_pool: vk::DescriptorPool, pub descriptor_sets: Vec, diff --git a/src/buffer.rs b/src/buffer.rs index 65df11b..56f1206 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -199,8 +199,14 @@ pub unsafe fn create_descriptor_set_layout( .descriptor_type(vk::DescriptorType::COMBINED_IMAGE_SAMPLER) .descriptor_count(1) .stage_flags(vk::ShaderStageFlags::FRAGMENT); + + let storage_binding = vk::DescriptorSetLayoutBinding::builder() + .binding(2) + .descriptor_type(vk::DescriptorType::STORAGE_BUFFER) + .descriptor_count(1) + .stage_flags(vk::ShaderStageFlags::FRAGMENT); - let bindings = &[ubo_binding, sampler_binding]; + let bindings = &[ubo_binding, sampler_binding, storage_binding]; let info = vk::DescriptorSetLayoutCreateInfo::builder() .bindings(bindings); @@ -234,6 +240,31 @@ pub unsafe fn create_uniform_buffers( Ok(()) } +pub unsafe fn create_storage_buffers( + instance: &Instance, + device: &Device, + data: &mut app_data::AppData, +) -> Result<()> { + data.storage_buffers.clear(); + data.storage_buffers_memory.clear(); + + for _ in 0..data.swapchain_images.len() { + let (storage_buffer, storage_buffer_memory) = create_buffer( + instance, + device, + data, + size_of::() as u64, + vk::BufferUsageFlags::STORAGE_BUFFER, + vk::MemoryPropertyFlags::HOST_COHERENT | vk::MemoryPropertyFlags::HOST_VISIBLE, + )?; + + data.storage_buffers.push(storage_buffer); + data.storage_buffers_memory.push(storage_buffer_memory); + } + + Ok(()) +} + pub unsafe fn create_descriptor_pool(device: &Device, data: &mut app_data::AppData) -> Result<()> { let ubo_size = vk::DescriptorPoolSize::builder() .type_(vk::DescriptorType::UNIFORM_BUFFER) @@ -242,8 +273,12 @@ pub unsafe fn create_descriptor_pool(device: &Device, data: &mut app_data::AppDa let sampler_size = vk::DescriptorPoolSize::builder() .type_(vk::DescriptorType::COMBINED_IMAGE_SAMPLER) .descriptor_count(data.swapchain_images.len() as u32); + + let storage_size = vk::DescriptorPoolSize::builder() + .type_(vk::DescriptorType::STORAGE_BUFFER) + .descriptor_count(data.swapchain_images.len() as u32); - let pool_sizes = &[ubo_size, sampler_size]; + let pool_sizes = &[ubo_size, sampler_size, storage_size]; let info = vk::DescriptorPoolCreateInfo::builder() .pool_sizes(pool_sizes) .max_sets(data.swapchain_images.len() as u32); @@ -286,8 +321,21 @@ pub unsafe fn create_descriptor_sets(device: &Device, data: &mut app_data::AppDa .descriptor_type(vk::DescriptorType::COMBINED_IMAGE_SAMPLER) .image_info(image_info); + let info = vk::DescriptorBufferInfo::builder() + .buffer(data.storage_buffers[i]) + .offset(0) + .range(size_of::() as u64); + let storage_info = &[info]; + + let storage_write = vk::WriteDescriptorSet::builder() + .dst_set(data.descriptor_sets[i]) + .dst_binding(2) + .dst_array_element(0) + .descriptor_type(vk::DescriptorType::STORAGE_BUFFER) + .buffer_info(storage_info); + device.update_descriptor_sets( - &[ubo_write, sampler_write], + &[ubo_write, sampler_write, storage_write], &[] as &[vk::CopyDescriptorSet], ); } diff --git a/src/main.rs b/src/main.rs index 5e1ad72..5fa20a9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -111,7 +111,11 @@ fn main() -> Result<()> { app.cam_angle_y = app.cam_angle_y.max(-90.0).min(90.0); } - window.set_cursor_position(LogicalPosition::new(window.inner_size().width / 2, window.inner_size().height / 2)).expect("Cannot set Cursor!"); + let cursor_res = window.set_cursor_position(LogicalPosition::new(window.inner_size().width / 2, window.inner_size().height / 2)); + if cursor_res.is_err() { + println!("Attempted to move cursor while not in possession") + } + app.last_pos = LogicalPosition::new(window.inner_size().width as f32 / 2 as f32, window.inner_size().height as f32 / 2 as f32); }, WindowEvent::KeyboardInput { device_id, event, is_synthetic } => { @@ -192,6 +196,7 @@ impl App { scene_handler.prepare_data(&instance, &device, &data)?; buffer::create_uniform_buffers(&instance, &device, &mut data)?; + buffer::create_storage_buffers(&instance, &device, &mut data)?; buffer::create_descriptor_pool(&device, &mut data)?; buffer::create_descriptor_sets(&device, &mut data)?; @@ -321,6 +326,7 @@ impl App { depth_buffer::create_depth_objects(&self.instance, &self.device, &mut self.data)?; create_framebuffers(&self.device, &mut self.data)?; buffer::create_uniform_buffers(&self.instance, &self.device, &mut self.data)?; + buffer::create_storage_buffers(&self.instance, &self.device, &mut self.data)?; buffer::create_descriptor_sets(&self.device, &mut self.data)?; command_buffer::create_command_buffers(&self.device, &mut self.data, &self.scene_handler)?; self.data @@ -346,6 +352,13 @@ impl App { self.data.uniform_buffers_memory .iter() .for_each(|m| self.device.free_memory(*m, None)); + self.data.storage_buffers + .iter() + .for_each(|b| self.device.destroy_buffer(*b, None)); + self.data.storage_buffers_memory + .iter() + .for_each(|m| self.device.free_memory(*m, None)); + self.data.framebuffers .iter() .for_each(|f| self.device.destroy_framebuffer(*f, None)); @@ -411,6 +424,17 @@ impl App { self.device.unmap_memory(self.data.uniform_buffers_memory[image_index]); + let memory = self.device.map_memory( + self.data.storage_buffers_memory[image_index], + 0, + size_of::() as u64, + vk::MemoryMapFlags::empty(), + )?; + + memcpy(&ubo, memory.cast(), 1); + + self.device.unmap_memory(self.data.storage_buffers_memory[image_index]); + Ok(()) } } diff --git a/src/primitives/cube.rs b/src/primitives/cube.rs index 685ea01..cfc75b4 100644 --- a/src/primitives/cube.rs +++ b/src/primitives/cube.rs @@ -4,7 +4,7 @@ use crate::vertex; use crate::scene::Scene; use crate::primitives::drawable::Drawable; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct Cube{ pub pos: vertex::Vec3, pub color: vertex::Vec3, diff --git a/src/primitives/rec_cuboid.rs b/src/primitives/rec_cuboid.rs index f376d81..280d665 100644 --- a/src/primitives/rec_cuboid.rs +++ b/src/primitives/rec_cuboid.rs @@ -4,7 +4,7 @@ use crate::vertex; use crate::scene::Scene; use crate::primitives::drawable::Drawable; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct Cuboid{ pub pos: vertex::Vec3, pub color: vertex::Vec3, diff --git a/src/scene.rs b/src/scene.rs index a552210..f5bc778 100644 --- a/src/scene.rs +++ b/src/scene.rs @@ -17,9 +17,9 @@ use crate::primitives::drawable::Drawable; extern crate rand; use rand::Rng; -const CHUNK_SIZE_EXPONENT: u32 = 10; +const CHUNK_SIZE_EXPONENT: u32 = 9; const CHUNK_SIZE: usize = (2 as usize).pow(CHUNK_SIZE_EXPONENT); -const MAX_TREE_DEPTH: usize = 8; +const MAX_TREE_DEPTH: usize = 7; const MIN_CHUNK_SIZE: usize = CHUNK_SIZE / (2 as usize).pow(MAX_TREE_DEPTH as u32); #[derive(Clone, Debug, Default)] @@ -45,10 +45,10 @@ pub struct Scene { impl Scene { pub unsafe fn prepare_data(&mut self, instance: &vulkanalia::Instance, device: &vulkanalia::Device, data: &AppData) -> Result<()> { let mut rng = rand::thread_rng(); - let grid_size = 50; //CHUNK_SIZE as i32; + let grid_size = 512; //CHUNK_SIZE as i32; // todo store the chunks somewhere (or only use them as intermediary for neighbouthood calculation idc) - let mut oct_tree = OctTree::create(CHUNK_SIZE)?; + let mut oct_tree: OctTree = OctTree::create(CHUNK_SIZE)?; //todo use the 14 vertice box method. Not using geometry shaders seems to be faster... make this a setting? // have cube elements with a method asking for vertices, while giving a primitive type -> method for preferred primitive type as well as one collecting all primitives @@ -56,7 +56,7 @@ impl Scene { 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, 0.0), + 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) }; @@ -65,6 +65,9 @@ impl Scene { } } + let mut test = EmptyVolume::from_oct_tree(&oct_tree); + println!("number of empty volumes is {}", test.len()); + let oct_tree_iter = OctTreeIter::create(&oct_tree)?; for item in oct_tree_iter { let sized_index = self.sized_vertices.len(); @@ -120,7 +123,7 @@ impl Scene { #[derive(Clone, Debug)] #[allow(non_snake_case)] -struct OctTree { +struct OctTree { pub child_XYZ: Option>>, pub child_xYZ: Option>>, pub child_xyZ: Option>>, @@ -130,15 +133,27 @@ struct OctTree { pub child_xyz: Option>>, pub child_Xyz: Option>>, - pub blocks: Vec>, + pub blocks: Vec>, size: usize, } #[warn(non_snake_case)] -impl OctTree { +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![]; + let mut blocks: Vec> = vec![]; if size == MIN_CHUNK_SIZE { for _ in 0..MIN_CHUNK_SIZE { for _ in 0..MIN_CHUNK_SIZE { @@ -165,17 +180,14 @@ 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; + 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_cube_internal(cube, x, y, z); + self.set_element_internal(element, x, y, z); } - - fn set_cube_internal(&mut self, cube: Cube, x: usize, y: usize, z: usize) { + + 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 { @@ -183,11 +195,11 @@ impl OctTree { if z >= mid_point { match &self.child_XYZ { Some(child) => { - child.borrow_mut().set_cube_internal(cube, x - mid_point, y - mid_point, z - mid_point); + 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_cube_internal(cube, x - mid_point, y - mid_point, z - mid_point); + child.set_element_internal(element, x - mid_point, y - mid_point, z - mid_point); self.child_XYZ = Some(Rc::new(RefCell::new(child))); } } @@ -195,11 +207,11 @@ impl OctTree { else { match &self.child_XYz { Some(child) => { - child.borrow_mut().set_cube_internal(cube, x - mid_point, y - mid_point, z); + 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_cube_internal(cube, x - mid_point, y - mid_point, z); + child.set_element_internal(element, x - mid_point, y - mid_point, z); self.child_XYz = Some(Rc::new(RefCell::new(child))); } } @@ -209,11 +221,11 @@ impl OctTree { if z >= mid_point { match &self.child_XyZ { Some(child) => { - child.borrow_mut().set_cube_internal(cube, x - mid_point, y, z - mid_point); + 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_cube_internal(cube, x - mid_point, y, z - mid_point); + child.set_element_internal(element, x - mid_point, y, z - mid_point); self.child_XyZ = Some(Rc::new(RefCell::new(child))); } } @@ -221,11 +233,11 @@ impl OctTree { else { match &self.child_Xyz { Some(child) => { - child.borrow_mut().set_cube_internal(cube, x - mid_point, y, z); + child.borrow_mut().set_element_internal(element, x - mid_point, y, z); }, None => { let mut child = OctTree::create(self.size / 2).unwrap(); - child.set_cube_internal(cube, x - mid_point, y, z); + child.set_element_internal(element, x - mid_point, y, z); self.child_Xyz = Some(Rc::new(RefCell::new(child))); } } @@ -237,11 +249,11 @@ impl OctTree { if z >= mid_point { match &self.child_xYZ { Some(child) => { - child.borrow_mut().set_cube_internal(cube, x, y - mid_point, z - mid_point); + 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_cube_internal(cube, x, y - mid_point, z - mid_point); + child.set_element_internal(element, x, y - mid_point, z - mid_point); self.child_xYZ = Some(Rc::new(RefCell::new(child))); } } @@ -249,11 +261,11 @@ impl OctTree { else { match &self.child_xYz { Some(child) => { - child.borrow_mut().set_cube_internal(cube, x, y - mid_point, z); + child.borrow_mut().set_element_internal(element, x, y - mid_point, z); }, None => { let mut child = OctTree::create(self.size / 2).unwrap(); - child.set_cube_internal(cube, x, y - mid_point, z); + child.set_element_internal(element, x, y - mid_point, z); self.child_xYz = Some(Rc::new(RefCell::new(child))); } } @@ -263,11 +275,11 @@ impl OctTree { if z >= mid_point { match &self.child_xyZ { Some(child) => { - child.borrow_mut().set_cube_internal(cube, x, y, z - mid_point); + child.borrow_mut().set_element_internal(element, x, y, z - mid_point); }, None => { let mut child = OctTree::create(self.size / 2).unwrap(); - child.set_cube_internal(cube, x, y, z - mid_point); + child.set_element_internal(element, x, y, z - mid_point); self.child_xyZ = Some(Rc::new(RefCell::new(child))); } } @@ -275,11 +287,11 @@ impl OctTree { else { match &self.child_xyz { Some(child) => { - child.borrow_mut().set_cube_internal(cube, x, y, z); + child.borrow_mut().set_element_internal(element, x, y, z); }, None => { let mut child = OctTree::create(self.size / 2).unwrap(); - child.set_cube_internal(cube, x, y, z); + child.set_element_internal(element, x, y, z); self.child_xyz = Some(Rc::new(RefCell::new(child))); } } @@ -288,7 +300,7 @@ impl OctTree { } } else { - self.blocks[z * MIN_CHUNK_SIZE * MIN_CHUNK_SIZE + y * MIN_CHUNK_SIZE + x] = Some(cube); + self.blocks[z * MIN_CHUNK_SIZE * MIN_CHUNK_SIZE + y * MIN_CHUNK_SIZE + x] = Some(element); } } @@ -385,18 +397,107 @@ impl OctTree { 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 + todo: Vec>>>, + chunk: &'a OctTree } impl<'a> OctTreeIter<'a> { - pub fn create(chunk: &'a OctTree) -> Result { + pub fn create(chunk: &'a OctTree) -> Result { let mut out = Self { iter_x: 0, iter_y: 0, @@ -408,7 +509,7 @@ impl<'a> OctTreeIter<'a> { Ok(out) } - fn add_todo(&mut self, oct_tree: &OctTree) { + fn add_todo(&mut self, oct_tree: &OctTree) { match &oct_tree.child_XYZ { Some(child) => { self.todo.push(child.clone()); @@ -500,4 +601,207 @@ impl<'a> Iterator for OctTreeIter<'a> { self.add_todo(&self.chunk); None } -} \ No newline at end of file +} + + +struct EmptyVolume { + pub memory_start: usize, + + pub size_x: usize, + pub size_y: usize, + pub size_z: usize, + + pub position: Vector3, + + pub color_front: Vec>, + pub color_back: Vec>, + pub color_top: Vec>, + pub color_bottom: Vec>, + pub color_left: Vec>, + pub color_right: Vec>, + + pub roughness_front: Vec>, + pub roughness_back: Vec>, + pub roughness_top: Vec>, + pub roughness_bottom: Vec>, + pub roughness_left: Vec>, + pub roughness_right: Vec>, + + pub neighbor_front: Vec>>, + pub neighbor_back: Vec>>, + pub neighbor_top: Vec>>, + pub neighbor_bottom: Vec>>, + pub neighbor_left: Vec>>, + pub neighbor_right: Vec>>, +} + +impl EmptyVolume { + pub fn contains(&self, pos: &Vector3) -> bool { + self.position[0] + self.size_x > pos[0] && pos[0] >= self.position[0] && + self.position[1] + self.size_y > pos[1] && pos[1] >= self.position[1] && + self.position[2] + self.size_z > pos[2] && pos[2] >= self.position[2] + } + + pub fn from_oct_tree(tree: &OctTree) -> Vec>> { + let mut volumes: Vec>> = vec![]; + + let mut neighbors: OctTree>> = OctTree::create(tree.size).unwrap(); + + // iterate over all block positions in the oct tree + for x_index in 0..tree.size { + for y_index in 0..tree.size { + for z_index in 0..tree.size { + // check if there is a block at that position + let query_result = tree.get_element(x_index, y_index, z_index); + + match query_result { + Some(cube) => { + //if so do nothing + }, + None => { + //if not check that it is not already inside of a volume + let mut contained = false; + for volume in &volumes { + if volume.borrow().contains(&Vector3{x: x_index, y: y_index, z: z_index}) { + contained = true; + } + } + if contained { + // abort if it is already covered + continue; + } + println!("new starting pos: {}, {}, {}", x_index, y_index, z_index); + println!("start growing volume x"); + let mut x_size = 0; + let mut grow = true; + while grow { + grow = tree.get_element(x_index + x_size + 1, y_index, z_index).is_none() && neighbors.get_element(x_index + x_size + 1, y_index, z_index).is_none(); + grow &= (x_index + x_size + 1) < tree.size; + if grow { + x_size += 1; + } + } + println!("start growing volume y"); + let mut y_size = 0; + grow = true; + while grow { + grow &= (y_index + y_size + 1) < tree.size; + if grow { + for x in 0..x_size { + grow &= tree.get_element(x_index + x, y_index + y_size + 1, z_index).is_none() && + neighbors.get_element(x_index + x, y_index + y_size + 1, z_index).is_none(); + + if !grow { + break; + } + } + } + + if grow { + y_size += 1; + } + } + println!("start growing volume z"); + let mut z_size = 0; + grow = true; + while grow { + grow &= (z_index + z_size + 1) < tree.size; + if grow { + for x in 0..x_size { + for y in 0..y_size { + grow &= tree.get_element(x_index + x, y_index + y, z_index + z_size + 1).is_none() && + neighbors.get_element(x_index + x, y_index + y, z_index + z_size + 1).is_none(); + if !grow { + break; + } + } + if !grow { + break; + } + } + } + if grow { + z_size += 1; + } + } + println!("final size: {}, {}, {}", x_size+1, y_size+1, z_size+1); + // create new empty volume + let new_volume = EmptyVolume { + memory_start: 0, + size_x: x_size + 1, + size_y: y_size + 1, + size_z: z_size + 1, + position: Vector3{x: x_index, y: y_index, z: z_index}, + color_front: vec![], + color_back: vec![], + color_top: vec![], + color_bottom: vec![], + color_left: vec![], + color_right: vec![], + roughness_front: vec![], + roughness_back: vec![], + roughness_top: vec![], + roughness_bottom: vec![], + roughness_left: vec![], + roughness_right: vec![], + neighbor_front: vec![], + neighbor_back: vec![], + neighbor_top: vec![], + neighbor_bottom: vec![], + neighbor_left: vec![], + neighbor_right: vec![], + }; + println!("adding neighbor references"); + //fill in info in the neighbor octtree + let reference = Rc::new(RefCell::new(new_volume)); + for x in 0..x_size+1 { + for y in 0..y_size+1 { + for z in 0..z_size+1 { + if x == 0 || x == x_size || y == 0 || y == y_size || z==0 || z == z_size { + neighbors.set_element(reference.clone(), reference.borrow().position.x + x, reference.borrow().position.y + y, reference.borrow().position.z + z) + } + } + } + } + println!("new volume done"); + //push to the list + volumes.push(reference); + } + } + } + } + } + + volumes + } +} + +#[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); + } +}