VoxelEngine2/src/scene/empty_volume.rs

1240 lines
No EOL
55 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use cgmath::Vector3;
use std::cell::RefCell;
use std::rc::Rc;
use std::time::Instant;
use crate::vertex;
use crate::primitives::cube::Cube;
use crate::primitives::quad::Quad;
use crate::scene::oct_tree::OctTree;
use super::light::PointLight;
pub struct EmptyVolume {
pub memory_start: usize,
pub size_x: usize,
pub size_y: usize,
pub size_z: usize,
pub position: Vector3<usize>,
pub color_left: Vec<Vector3<u8>>,
pub color_right: Vec<Vector3<u8>>,
pub color_top: Vec<Vector3<u8>>,
pub color_bottom: Vec<Vector3<u8>>,
pub color_back: Vec<Vector3<u8>>,
pub color_front: Vec<Vector3<u8>>,
pub roughness_left: Vec<u8>,
pub roughness_right: Vec<u8>,
pub roughness_top: Vec<u8>,
pub roughness_bottom: Vec<u8>,
pub roughness_back: Vec<u8>,
pub roughness_front: Vec<u8>,
pub neighbor_left: Vec<Option<Rc<RefCell<Self>>>>,
pub neighbor_right: Vec<Option<Rc<RefCell<Self>>>>,
pub neighbor_top: Vec<Option<Rc<RefCell<Self>>>>,
pub neighbor_bottom: Vec<Option<Rc<RefCell<Self>>>>,
pub neighbor_back: Vec<Option<Rc<RefCell<Self>>>>,
pub neighbor_front: Vec<Option<Rc<RefCell<Self>>>>,
}
impl EmptyVolume {
pub fn contains(&self, pos: &Vector3<usize>) -> 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]
}
fn check_transparent(cube_result: Option<Cube>, transparent_color: &Vector3<f32>, transparent_roughness: &u8) -> bool {
if let Some(c) = cube_result {
return c.transparent && &c.color == transparent_color && &c.roughness == transparent_roughness
}
false
}
// MARK: From Oct Tree
pub fn from_oct_tree(tree: &OctTree<Cube>) -> (Vec<Rc<RefCell<EmptyVolume>>>, OctTree<Rc<RefCell<EmptyVolume>>>) {
// todo: ppotentially use a child exist check while going through the oct tree to find some obvios starting empty volumes. Will still need to check for possible expansions though
let mut volumes: Vec<Rc<RefCell<EmptyVolume>>> = vec![];
let mut neighbors: OctTree<Rc<RefCell<EmptyVolume>>> = OctTree::create(tree.size).unwrap();
let start_time = Instant::now();
// iterate over all block positions in the oct tree
let mut check_its = 0;
let mut x_index = 0;
while x_index < tree.size {
let mut y_index = 0;
while y_index < tree.size {
let mut z_index = 0;
while z_index < tree.size {
// check if there is a block at that position
let query_result = tree.test_element(x_index, y_index, z_index);
let mut transparent = false;
let mut transparent_color = Vector3 {x: 0.0, y: 0.0, z: 0.0};
let mut tranparent_roughness = 0;
if let Some(c) = query_result.3 {
transparent = c.transparent;
transparent_color = c.color;
tranparent_roughness = c.roughness;
}
if !query_result.0 || transparent {
//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;
z_index = volume.borrow().size_z + volume.borrow().position.z;
break;
}
}
if contained {
// abort if it is already covered
continue;
}
println!("new starting pos: {}, {}, {}", x_index, y_index, z_index);
println!("start growing volume x");
// MARK: Start new Volume
let mut x_size = 0;
let mut y_size = 0;
let mut z_size = 0;
if query_result.1 > 1 {
x_size = query_result.1 - 1 - (x_index - query_result.2.0);
y_size = query_result.1 - 1 - (y_index - query_result.2.1);
z_size = query_result.1 - 1 - (z_index - query_result.2.2);
println!("enhanced starting size: {}, {}, {}", x_size+1, y_size+1, z_size+1);
}
let mut grow = true;
while grow {
grow &= (x_index + x_size + 1) < tree.size;
if grow {
let mut z = 0;
let mut y = 0;
while z < z_size.max(1) && y < y_size.max(1) {
let query_result = tree.test_element(x_index + x_size + 1, y_index + y, z_index + z);
check_its += 1;
grow &= ((!query_result.0 && !transparent) || (transparent && EmptyVolume::check_transparent(query_result.3, &transparent_color, &tranparent_roughness))) &&
neighbors.get_element(x_index + x_size + 1, y_index + y, z_index + z).is_none();
if query_result.1 > 1 {
let start_x = query_result.2.0;
let start_y = query_result.2.1;
let start_z = query_result.2.2;
let end_x = query_result.2.0 + query_result.1;
let end_y = query_result.2.1 + query_result.1;
let end_z = query_result.2.2 + query_result.1;
if start_z <= z && z_index + z_size <= end_z {
// we can skip iterating z
z = end_z;
if start_y <= y && y_index + y_size <= end_y {
// we can skip iterating y
y = end_y;
}
}
}
if !grow {
break;
}
z += 1;
if z >= z_size {
z = 0;
y += 1;
}
}
}
if grow {
x_size += 1;
}
}
println!("start growing volume y");
grow = true;
while grow {
grow &= (y_index + y_size + 1) < tree.size;
if grow {
let mut z = 0;
let mut x = 0;
while z < z_size.max(1) && x < x_size.max(1) {
let query_result = tree.test_element(x_index + x, y_index + y_size + 1, z_index + z);
check_its += 1;
grow &= ((!query_result.0 && !transparent) || (transparent && EmptyVolume::check_transparent(query_result.3, &transparent_color, &tranparent_roughness))) &&
neighbors.get_element(x_index + x, y_index + y_size + 1, z_index + z).is_none();
if query_result.1 > 1 {
let start_x = query_result.2.0;
let start_y = query_result.2.1;
let start_z = query_result.2.2;
let end_x = query_result.2.0 + query_result.1;
let end_y = query_result.2.1 + query_result.1;
let end_z = query_result.2.2 + query_result.1;
if start_z <= z && z_index + z_size <= end_z {
// we can skip iterating z
z = end_z;
if start_x <= x && x_index + x_size <= end_x {
// we can skip iterating x
x = end_x;
}
}
}
if !grow {
break;
}
z += 1;
if z >= z_size {
z = 0;
x += 1;
}
}
}
if grow {
y_size += 1;
}
}
println!("start growing volume z");
grow = true;
while grow {
grow &= (z_index + z_size + 1) < tree.size;
if grow {
let mut y = 0;
let mut x = 0;
while y < y_size.max(1) && x < x_size.max(1) {
let query_result = tree.test_element(x_index + x, y_index + y, z_index + z_size + 1);
check_its += 1;
grow &= ((!query_result.0 && !transparent) || (transparent && EmptyVolume::check_transparent(query_result.3, &transparent_color, &tranparent_roughness))) &&
neighbors.get_element(x_index + x, y_index + y, z_index + z_size + 1).is_none();
if query_result.1 > 1 {
let start_x = query_result.2.0;
let start_y = query_result.2.1;
let start_z = query_result.2.2;
let end_x = query_result.2.0 + query_result.1;
let end_y = query_result.2.1 + query_result.1;
let end_z = query_result.2.2 + query_result.1;
if start_x <= x && x_index + x_size <= end_x {
// we can skip iterating x
x = end_x;
if start_y <= y && y_index + y_size <= end_y {
// we can skip iterating y
y = end_y;
}
}
}
if !grow {
break;
}
x += 1;
if x >= x_size {
x = 0;
y += 1;
}
}
}
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_left: vec![],
color_right: vec![],
color_top: vec![],
color_bottom: vec![],
color_back: vec![],
color_front: vec![],
roughness_left: vec![],
roughness_right: vec![],
roughness_top: vec![],
roughness_bottom: vec![],
roughness_back: vec![],
roughness_front: vec![],
neighbor_left: vec![],
neighbor_right: vec![],
neighbor_top: vec![],
neighbor_bottom: vec![],
neighbor_back: vec![],
neighbor_front: vec![],
};
println!("adding neighbor references");
// MARK: 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 {
//neighbors.set_element(reference.clone(), reference.borrow().position.x + x, reference.borrow().position.y + y, reference.borrow().position.z + z);
// fill only the edges
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!("add the border information for color and roughness");
let x_min_pos;
if reference.borrow().position.x == 0 {
// will result in an empty color and roughness map.
x_min_pos = 0;
}
else {
x_min_pos = reference.borrow().position.x -1;
}
let y_min_pos;
if reference.borrow().position.y == 0 {
// will result in an empty color and roughness map.
y_min_pos = 0;
}
else {
y_min_pos = reference.borrow().position.y -1;
}
let z_min_pos;
if reference.borrow().position.z == 0 {
// will result in an empty color and roughness map.
z_min_pos = 0;
}
else {
z_min_pos = reference.borrow().position.z -1;
}
let x_max_pos = reference.borrow().position.x + reference.borrow().size_x;
let y_max_pos = reference.borrow().position.y + reference.borrow().size_y;
let z_max_pos = reference.borrow().position.z + reference.borrow().size_z;
// MARK: bottom face of the volume
let mut bottom_colors = vec![];
let mut bottom_roughness = vec![];
let mut bottom_elements_num = 0;
for x in 0..x_size+1 {
for y in 0..y_size+1 {
if let Some(c) = tree.get_element(reference.borrow().position.x + x, reference.borrow().position.y + y, z_min_pos) {
bottom_elements_num += 1;
let u8_color = Vector3 {x: (c.color * 255.0).x.min(255.0).max(0.0) as u8, y: (c.color * 255.0).y.min(255.0).max(0.0) as u8, z: (c.color * 255.0).z.min(255.0).max(0.0) as u8};
bottom_colors.push(u8_color);
bottom_roughness.push(c.roughness);
}
else {
bottom_colors.push(Vector3 { x: 0, y: 0, z: 0 });
bottom_roughness.push(0);
}
}
}
if bottom_elements_num > 0 {
reference.borrow_mut().color_bottom = bottom_colors;
reference.borrow_mut().roughness_bottom = bottom_roughness;
}
else {
reference.borrow_mut().color_bottom= vec![];
reference.borrow_mut().roughness_bottom= vec![];
}
// MARK: top face of the volume
let mut top_colors = vec![];
let mut top_roughness = vec![];
let mut top_elements_num = 0;
for x in 0..x_size+1 {
for y in 0..y_size+1 {
if let Some(c) = tree.get_element(reference.borrow().position.x + x, reference.borrow().position.y + y, z_max_pos) {
top_elements_num += 1;
let u8_color = Vector3 {x: (c.color * 255.0).x.min(255.0).max(0.0) as u8, y: (c.color * 255.0).y.min(255.0).max(0.0) as u8, z: (c.color * 255.0).z.min(255.0).max(0.0) as u8};
top_colors.push(u8_color);
top_roughness.push(c.roughness);
}
else {
top_colors.push(Vector3 { x: 0, y: 0, z: 0 });
top_roughness.push(0);
}
}
}
if top_elements_num > 0 {
reference.borrow_mut().color_top = top_colors;
reference.borrow_mut().roughness_top = top_roughness;
}
else {
reference.borrow_mut().color_top= vec![];
reference.borrow_mut().roughness_top= vec![];
}
// MARK: back face of the volume
let mut back_colors = vec![];
let mut back_roughness = vec![];
let mut back_elements_num = 0;
for x in 0..x_size+1 {
for z in 0..z_size+1 {
if let Some(c) = tree.get_element(reference.borrow().position.x + x, y_max_pos, reference.borrow().position.z + z) {
back_elements_num += 1;
let u8_color = Vector3 {x: (c.color * 255.0).x.min(255.0).max(0.0) as u8, y: (c.color * 255.0).y.min(255.0).max(0.0) as u8, z: (c.color * 255.0).z.min(255.0).max(0.0) as u8};
back_colors.push(u8_color);
back_roughness.push(c.roughness);
}
else {
back_colors.push(Vector3 { x: 0, y: 0, z: 0 });
back_roughness.push(0);
}
}
}
if back_elements_num > 0 {
reference.borrow_mut().color_back = back_colors;
reference.borrow_mut().roughness_back = back_roughness;
}
else {
reference.borrow_mut().color_back= vec![];
reference.borrow_mut().roughness_back= vec![];
}
// MARK: front face of the volume
let mut front_colors = vec![];
let mut front_roughness = vec![];
let mut front_elements_num = 0;
for x in 0..x_size+1 {
for z in 0..z_size+1 {
if let Some(c) = tree.get_element(reference.borrow().position.x + x, y_min_pos, reference.borrow().position.z + z) {
front_elements_num += 1;
let u8_color = Vector3 {x: (c.color * 255.0).x.min(255.0).max(0.0) as u8, y: (c.color * 255.0).y.min(255.0).max(0.0) as u8, z: (c.color * 255.0).z.min(255.0).max(0.0) as u8};
front_colors.push(u8_color);
front_roughness.push(c.roughness);
}
else {
front_colors.push(Vector3 { x: 0, y: 0, z: 0 });
front_roughness.push(0);
}
}
}
if front_elements_num > 0 {
reference.borrow_mut().color_front = front_colors;
reference.borrow_mut().roughness_front = front_roughness;
}
else {
reference.borrow_mut().color_front= vec![];
reference.borrow_mut().roughness_front= vec![];
}
// MARK: left face of the volume
let mut left_colors = vec![];
let mut left_roughness = vec![];
let mut left_elements_num = 0;
for y in 0..y_size+1 {
for z in 0..z_size+1 {
if let Some(c) = tree.get_element(x_min_pos, reference.borrow().position.y + y, reference.borrow().position.z + z) {
left_elements_num += 1;
let u8_color = Vector3 {x: (c.color * 255.0).x.min(255.0).max(0.0) as u8, y: (c.color * 255.0).y.min(255.0).max(0.0) as u8, z: (c.color * 255.0).z.min(255.0).max(0.0) as u8};
left_colors.push(u8_color);
left_roughness.push(c.roughness);
}
else {
left_colors.push(Vector3 { x: 0, y: 0, z: 0 });
left_roughness.push(0);
}
}
}
if left_elements_num > 0 {
reference.borrow_mut().color_left = left_colors;
reference.borrow_mut().roughness_left = left_roughness;
}
else {
reference.borrow_mut().color_left= vec![];
reference.borrow_mut().roughness_left= vec![];
}
// MARK: right face of the volume
let mut right_colors = vec![];
let mut right_roughness = vec![];
let mut right_elements_num = 0;
for y in 0..y_size+1 {
for z in 0..z_size+1 {
if let Some(c) = tree.get_element(x_max_pos, reference.borrow().position.y + y, reference.borrow().position.z + z) {
right_elements_num += 1;
let u8_color = Vector3 {x: (c.color * 255.0).x.min(255.0).max(0.0) as u8, y: (c.color * 255.0).y.min(255.0).max(0.0) as u8, z: (c.color * 255.0).z.min(255.0).max(0.0) as u8};
right_colors.push(u8_color);
right_roughness.push(c.roughness);
}
else {
right_colors.push(Vector3 { x: 0, y: 0, z: 0 });
right_roughness.push(0);
}
}
}
if right_elements_num > 0 {
reference.borrow_mut().color_right = right_colors;
reference.borrow_mut().roughness_right = right_roughness;
}
else {
reference.borrow_mut().color_right= vec![];
reference.borrow_mut().roughness_right= vec![];
}
println!("new volume done");
//push to the list
volumes.push(reference);
}
z_index += 1
}
y_index += 1;
}
x_index += 1;
}
println!("Did {} oct tree checks!", check_its);
println!("add the neighbor linkage for all the volumes of the oct tree");
// MARK: Neighbor Linkage
for reference in volumes.iter_mut() {
let x_min_pos;
if reference.borrow().position.x == 0 {
// will result in an empty color and roughness map.
x_min_pos = 0;
}
else {
x_min_pos = reference.borrow().position.x -1;
}
let y_min_pos;
if reference.borrow().position.y == 0 {
// will result in an empty color and roughness map.
y_min_pos = 0;
}
else {
y_min_pos = reference.borrow().position.y -1;
}
let z_min_pos;
if reference.borrow().position.z == 0 {
// will result in an empty color and roughness map.
z_min_pos = 0;
}
else {
z_min_pos = reference.borrow().position.z -1;
}
let x_max_pos = reference.borrow().position.x + reference.borrow().size_x;
let y_max_pos = reference.borrow().position.y + reference.borrow().size_y;
let z_max_pos = reference.borrow().position.z + reference.borrow().size_z;
// MARK: bottom face of the volume
let mut bottom_neighbors = vec![];
let mut bottom_elements_num = 0;
let mut all_same = true;
if z_min_pos != 0 {
for x in 0..reference.borrow().size_x {
for y in 0..reference.borrow().size_y {
if let Some(c) = neighbors.get_element(reference.borrow().position.x + x, reference.borrow().position.y + y, z_min_pos) {
bottom_elements_num += 1;
bottom_neighbors.push(Some(c.clone()));
all_same = all_same && (bottom_neighbors[0] == Some(c));
}
else {
bottom_neighbors.push(None);
}
}
}
}
if bottom_elements_num > 0 {
if all_same {
reference.borrow_mut().neighbor_bottom = vec![bottom_neighbors[0].clone()];
}
else {
reference.borrow_mut().neighbor_bottom = bottom_neighbors;
}
}
else {
reference.borrow_mut().neighbor_bottom = vec![None];
}
// MARK: top face of the volume
let mut top_neighbors = vec![];
let mut top_elements_num = 0;
let mut all_same = true;
for x in 0..reference.borrow().size_x {
for y in 0..reference.borrow().size_y {
if let Some(c) = neighbors.get_element(reference.borrow().position.x + x, reference.borrow().position.y + y, z_max_pos) {
top_elements_num += 1;
top_neighbors.push(Some(c.clone()));
all_same = all_same && (top_neighbors[0] == Some(c));
}
else {
top_neighbors.push(None);
}
}
}
if top_elements_num > 0 {
if all_same {
reference.borrow_mut().neighbor_top = vec![top_neighbors[0].clone()];
}
else {
reference.borrow_mut().neighbor_top = top_neighbors;
}
}
else {
reference.borrow_mut().neighbor_top = vec![None];
}
// MARK: back face of the volume
let mut back_neighbors = vec![];
let mut back_elements_num = 0;
let mut all_same = true;
for x in 0..reference.borrow().size_x {
for z in 0..reference.borrow().size_z {
if let Some(c) = neighbors.get_element(reference.borrow().position.x + x, y_max_pos, reference.borrow().position.z + z) {
back_elements_num += 1;
back_neighbors.push(Some(c.clone()));
all_same = all_same && (back_neighbors[0] == Some(c));
}
else {
back_neighbors.push(None);
}
}
}
if back_elements_num > 0 {
if all_same {
reference.borrow_mut().neighbor_back = vec![back_neighbors[0].clone()];
}
else {
reference.borrow_mut().neighbor_back = back_neighbors;
}
}
else {
reference.borrow_mut().neighbor_back = vec![None];
}
// MARK: front face of the volume
let mut front_neighbors = vec![];
let mut front_elements_num = 0;
let mut all_same = true;
if y_min_pos != 0{
for x in 0..reference.borrow().size_x {
for z in 0..reference.borrow().size_z {
if let Some(c) = neighbors.get_element(reference.borrow().position.x + x, y_min_pos, reference.borrow().position.z + z) {
front_elements_num += 1;
front_neighbors.push(Some(c.clone()));
all_same = all_same && (front_neighbors[0] == Some(c));
}
else {
front_neighbors.push(None);
}
}
}
}
if front_elements_num > 0 {
if all_same {
reference.borrow_mut().neighbor_front = vec![front_neighbors[0].clone()];
}
else {
reference.borrow_mut().neighbor_front = front_neighbors;
}
}
else {
reference.borrow_mut().neighbor_front = vec![None];
}
// MARK: left face of the volume
let mut left_neighbors = vec![];
let mut left_elements_num = 0;
let mut all_same = true;
if x_min_pos != 0 {
for y in 0..reference.borrow().size_y {
for z in 0..reference.borrow().size_z {
if let Some(c) = neighbors.get_element(x_min_pos, reference.borrow().position.y + y, reference.borrow().position.z + z) {
left_elements_num += 1;
left_neighbors.push(Some(c.clone()));
all_same = all_same && (left_neighbors[0] == Some(c));
}
else {
left_neighbors.push(None);
}
}
}
}
if left_elements_num > 0 {
if all_same {
reference.borrow_mut().neighbor_left = vec![left_neighbors[0].clone()];
}
else {
reference.borrow_mut().neighbor_left = left_neighbors;
}
}
else {
reference.borrow_mut().neighbor_left = vec![None];
}
// MARK: right face of the volume
let mut right_neighbors = vec![];
let mut right_elements_num = 0;
let mut all_same = true;
for y in 0..reference.borrow().size_y {
for z in 0..reference.borrow().size_z {
if let Some(c) = neighbors.get_element(x_max_pos, reference.borrow().position.y + y, reference.borrow().position.z + z) {
right_elements_num += 1;
right_neighbors.push(Some(c.clone()));
all_same = all_same && (right_neighbors[0] == Some(c));
}
else {
right_neighbors.push(None);
}
}
}
if right_elements_num > 0 {
if all_same {
reference.borrow_mut().neighbor_right = vec![right_neighbors[0].clone()];
}
else {
reference.borrow_mut().neighbor_right = right_neighbors;
}
}
else {
reference.borrow_mut().neighbor_right = vec![None];
}
}
println!("volume creation took {} s", start_time.elapsed().as_millis() as f32 / 1000.0);
(volumes, neighbors)
}
// MARK: To Quads
pub fn to_quads(&self) -> Vec<Quad> {
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
for x in 0..self.size_x {
for y in 0..self.size_y {
let index = x * self.size_y + y;
if self.color_bottom.len() <= index {
continue;
}
if self.neighbor_bottom.len() > index {
if let Some(_) = self.neighbor_bottom[index] {
if self.color_bottom[index] == (Vector3 {x: 0, y: 0, z: 0}) {
continue;
}
}
}
let quad = Quad {
pos1: float_pos + Vector3 { x: -0.5 + x as f32, y: -0.5 + y as f32, z: -0.5 },
pos4: float_pos + Vector3 { x: 0.5 + x as f32, y: -0.5 + y as f32, z: -0.5 },
pos3: float_pos + Vector3 { x: 0.5 + x as f32, y: 0.5 + y as f32, z: -0.5 },
pos2: float_pos + Vector3 { x: -0.5 + x as f32, y: 0.5 + y as f32, z: -0.5 },
raster_pos: cgmath::Vector2 { x: x as u32, y: y as u32 },
volume_index: self.memory_start as u32,
facing: vertex::Facing::Bottom
};
quads.push(quad);
}
}
//top sides of the volumes, bottom side of the block
for x in 0..self.size_x {
for y in 0..self.size_y {
let index = x * self.size_y + y;
if self.color_top.len() <= 0 {
continue;
}
if self.neighbor_top.len() > index {
if let Some(_) = self.neighbor_top[index] {
if self.color_top[index] == (Vector3 {x: 0, y: 0, z: 0}) {
continue;
}
}
}
let quad = Quad {
pos4: float_pos + Vector3 { x: -0.5 + x as f32, y: -0.5 + y as f32, z: self.size_z as f32 - 0.5 },
pos1: float_pos + Vector3 { x: 0.5 + x as f32, y: -0.5 + y as f32, z: self.size_z as f32 - 0.5 },
pos2: float_pos + Vector3 { x: 0.5 + x as f32, y: 0.5 + y as f32, z: self.size_z as f32 - 0.5 },
pos3: float_pos + Vector3 { x: -0.5 + x as f32, y: 0.5 + y as f32, z: self.size_z as f32 - 0.5 },
raster_pos: cgmath::Vector2 { x: x as u32, y: y as u32 },
volume_index: self.memory_start as u32,
facing: vertex::Facing::Top
};
quads.push(quad);
}
}
//front sides of the volumes, back side of the block
for x in 0..self.size_x {
for z in 0..self.size_z {
let index = x * self.size_z + z;
if self.color_front.len() <= 0 {
continue;
}
if self.neighbor_front.len() > index {
if let Some(_) = self.neighbor_front[index] {
if self.color_front[index] == (Vector3 {x: 0, y: 0, z: 0}) {
continue;
}
}
}
let quad = Quad {
pos1: float_pos + Vector3 { x: -0.5 + x as f32, y: -0.5 + 0 as f32, z: z as f32 - 0.5 },
pos4: float_pos + Vector3 { x: -0.5 + x as f32, y: -0.5 + 0 as f32, z: z as f32 + 0.5 },
pos3: float_pos + Vector3 { x: 0.5 + x as f32, y: -0.5 + 0 as f32, z: z as f32 + 0.5 },
pos2: float_pos + Vector3 { x: 0.5 + x as f32, y: -0.5 + 0 as f32, z: z as f32 - 0.5 },
raster_pos: cgmath::Vector2 { x: x as u32, y: z as u32 },
volume_index: self.memory_start as u32,
facing: vertex::Facing::Front
};
quads.push(quad);
}
}
//back sides of the volumes, front side of the block
for x in 0..self.size_x {
for z in 0..self.size_z {
let index = x * self.size_z + z;
if self.color_back.len() <= 0 {
continue;
}
if self.neighbor_back.len() > index {
if let Some(_) = self.neighbor_back[index] {
if self.color_back[index] == (Vector3 {x: 0, y: 0, z: 0}) {
continue;
}
}
}
let quad = Quad {
pos4: float_pos + Vector3 { x: -0.5 + x as f32, y: -0.5 + self.size_y as f32, z: z as f32 - 0.5 },
pos1: float_pos + Vector3 { x: -0.5 + x as f32, y: -0.5 + self.size_y as f32, z: z as f32 + 0.5 },
pos2: float_pos + Vector3 { x: 0.5 + x as f32, y: -0.5 + self.size_y as f32, z: z as f32 + 0.5 },
pos3: float_pos + Vector3 { x: 0.5 + x as f32, y: -0.5 + self.size_y as f32, z: z as f32 - 0.5 },
raster_pos: cgmath::Vector2 { x: x as u32, y: z as u32 },
volume_index: self.memory_start as u32,
facing: vertex::Facing::Back
};
quads.push(quad);
}
}
//left sides of the volumes, right side of the block
for y in 0..self.size_y {
for z in 0..self.size_z {
let index = y * self.size_z + z;
if self.color_left.len() <= 0 {
continue;
}
if self.neighbor_left.len() > index {
if let Some(_) = self.neighbor_left[index] {
if self.color_left[index] == (Vector3 {x: 0, y: 0, z: 0}) {
continue;
}
}
}
let quad = Quad {
pos4: float_pos + Vector3 { x: -0.5 + 0.0 as f32, y: y as f32 - 0.5, z: z as f32 - 0.5 },
pos1: float_pos + Vector3 { x: -0.5 + 0.0 as f32, y: y as f32 - 0.5, z: z as f32 + 0.5 },
pos2: float_pos + Vector3 { x: -0.5 + 0.0 as f32, y: y as f32 + 0.5, z: z as f32 + 0.5 },
pos3: float_pos + Vector3 { x: -0.5 + 0.0 as f32, y: y as f32 + 0.5, z: z as f32 - 0.5 },
raster_pos: cgmath::Vector2 { x: y as u32, y: z as u32 },
volume_index: self.memory_start as u32,
facing: vertex::Facing::Left
};
quads.push(quad);
}
}
//right sides of the volumes, left side of the block
for y in 0..self.size_y {
for z in 0..self.size_z {
let index = y * self.size_z + z;
if self.color_right.len() <= 0 {
continue;
}
if self.neighbor_right.len() > index {
if let Some(_) = self.neighbor_right[index] {
if self.color_right[index] == (Vector3 {x: 0, y: 0, z: 0}) {
continue;
}
}
}
let quad = Quad {
pos1: float_pos + Vector3 { x: -0.5 + self.size_x as f32, y: y as f32 - 0.5, z: z as f32 - 0.5 },
pos4: float_pos + Vector3 { x: -0.5 + self.size_x as f32, y: y as f32 - 0.5, z: z as f32 + 0.5 },
pos3: float_pos + Vector3 { x: -0.5 + self.size_x as f32, y: y as f32 + 0.5, z: z as f32 + 0.5 },
pos2: float_pos + Vector3 { x: -0.5 + self.size_x as f32, y: y as f32 + 0.5, z: z as f32 - 0.5 },
raster_pos: cgmath::Vector2 { x: y as u32, y: z as u32 },
volume_index: self.memory_start as u32,
facing: vertex::Facing::Right
};
quads.push(quad);
}
}
quads
}
// MARK: Get Buffer Mem Size
pub fn get_buffer_mem_size(&self, light_number: u32) -> u32 {
let mut mem_size: u32 = 0;
mem_size += 3; //pos
mem_size += 3; //max sizes
mem_size += light_number; // light references
mem_size += 12; //color/roughness buffer sizes, 2 values each
mem_size += 12; //neighbor buffer sizes, 2 values each
// this covers full color and roughness
mem_size += (self.color_top.len() as u32).max(1);
mem_size += (self.color_bottom.len() as u32).max(1);
mem_size += (self.color_left.len() as u32).max(1);
mem_size += (self.color_right.len() as u32).max(1);
mem_size += (self.color_front.len() as u32).max(1);
mem_size += (self.color_back.len() as u32).max(1);
mem_size += (self.neighbor_top.len() as u32).max(1);
mem_size += (self.neighbor_bottom.len() as u32).max(1);
mem_size += (self.neighbor_left.len() as u32).max(1);
mem_size += (self.neighbor_right.len() as u32).max(1);
mem_size += (self.neighbor_front.len() as u32).max(1);
mem_size += (self.neighbor_back.len() as u32).max(1);
mem_size
}
// MARK: insert into Memory
pub fn insert_into_memory(&self, mut v: Vec<u32>, light_number: u32, lights: &Vec<PointLight>) -> Vec<u32> {
let mut mem_index = self.memory_start;
//pos
v[mem_index] = self.position.x as u32;
mem_index += 1;
v[mem_index] = self.position.y as u32;
mem_index += 1;
v[mem_index] = self.position.z as u32;
mem_index += 1;
//max sizes
v[mem_index] = self.size_x as u32;
mem_index += 1;
v[mem_index] = self.size_y as u32;
mem_index += 1;
v[mem_index] = self.size_z as u32;
mem_index += 1;
//Todo: insert lights
let selected_lights = self.select_lights(lights, light_number);
for light in selected_lights {
v[mem_index] = light;
mem_index += 1;
}
//color/roughness buffer sizes, 2 values each
if self.color_top.len() > 1 {
v[mem_index] = self.size_x as u32;
v[mem_index + 1] = self.size_y as u32;
} else {
v[mem_index] = 1;
v[mem_index + 1] = 1;
}
mem_index += 2;
if self.color_bottom.len() > 1 {
v[mem_index] = self.size_x as u32;
v[mem_index + 1] = self.size_y as u32;
} else {
v[mem_index] = 1;
v[mem_index + 1] = 1;
}
mem_index += 2;
if self.color_left.len() > 1 {
v[mem_index] = self.size_y as u32;
v[mem_index + 1] = self.size_z as u32;
} else {
v[mem_index] = 1;
v[mem_index + 1] = 1;
}
mem_index += 2;
if self.color_right.len() > 1 {
v[mem_index] = self.size_y as u32;
v[mem_index + 1] = self.size_z as u32;
} else {
v[mem_index] = 1;
v[mem_index + 1] = 1;
}
mem_index += 2;
if self.color_front.len() > 1 {
v[mem_index] = self.size_x as u32;
v[mem_index + 1] = self.size_z as u32;
} else {
v[mem_index] = 1;
v[mem_index + 1] = 1;
}
mem_index += 2;
if self.color_back.len() > 1 {
v[mem_index] = self.size_x as u32;
v[mem_index + 1] = self.size_z as u32;
} else {
v[mem_index] = 1;
v[mem_index + 1] = 1;
}
mem_index += 2;
//neighbor buffer sizes, 2 values each
if self.neighbor_top.len() > 1 {
v[mem_index] = self.size_x as u32;
v[mem_index + 1] = self.size_y as u32;
} else {
v[mem_index] = 1;
v[mem_index + 1] = 1;
}
mem_index += 2;
if self.neighbor_bottom.len() > 1 {
v[mem_index] = self.size_x as u32;
v[mem_index + 1] = self.size_y as u32;
} else {
v[mem_index] = 1;
v[mem_index + 1] = 1;
}
mem_index += 2;
if self.neighbor_left.len() > 1 {
v[mem_index] = self.size_y as u32;
v[mem_index + 1] = self.size_z as u32;
} else {
v[mem_index] = 1;
v[mem_index + 1] = 1;
}
mem_index += 2;
if self.neighbor_right.len() > 1 {
v[mem_index] = self.size_y as u32;
v[mem_index + 1] = self.size_z as u32;
} else {
v[mem_index] = 1;
v[mem_index + 1] = 1;
}
mem_index += 2;
if self.neighbor_front.len() > 1 {
v[mem_index] = self.size_x as u32;
v[mem_index + 1] = self.size_z as u32;
} else {
v[mem_index] = 1;
v[mem_index + 1] = 1;
}
mem_index += 2;
if self.neighbor_back.len() > 1 {
v[mem_index] = self.size_x as u32;
v[mem_index + 1] = self.size_z as u32;
} else {
v[mem_index] = 1;
v[mem_index + 1] = 1;
}
mem_index += 2;
//color and roughness
//check which endian should be used in conjun´ction of the graphicscard (might already be handled by vulkan)
if self.color_top.len() > 0 {
for index in 0..self.color_top.len() {
let value = &self.color_top[index];
let roughness = self.roughness_top[index];
let test : u32 = 5;
v[mem_index] = u32::from_ne_bytes([value.x, value.y, value.z, roughness]);
mem_index += 1;
}
}
else {
v[mem_index] = u32::from_ne_bytes([0, 0, 0, 0]);
mem_index += 1;
}
if self.color_bottom.len() > 0 {
for index in 0..self.color_bottom.len() {
let value = &self.color_bottom[index];
let roughness = self.roughness_bottom[index];
let test : u32 = 5;
v[mem_index] = u32::from_ne_bytes([value.x, value.y, value.z, roughness]);
mem_index += 1;
}
}
else {
v[mem_index] = u32::from_ne_bytes([0, 0, 0, 0]);
mem_index += 1;
}
if self.color_left.len() > 0 {
for index in 0..self.color_left.len() {
let value = &self.color_left[index];
let roughness = self.roughness_left[index];
let test : u32 = 5;
v[mem_index] = u32::from_ne_bytes([value.x, value.y, value.z, roughness]);
mem_index += 1;
}
}
else {
v[mem_index] = u32::from_ne_bytes([0, 0, 0, 0]);
mem_index += 1;
}
if self.color_right.len() > 0 {
for index in 0..self.color_right.len() {
let value = &self.color_right[index];
let roughness = self.roughness_right[index];
let test : u32 = 5;
v[mem_index] = u32::from_ne_bytes([value.x, value.y, value.z, roughness]);
mem_index += 1;
}
}
else {
v[mem_index] = u32::from_ne_bytes([0, 0, 0, 0]);
mem_index += 1;
}
if self.color_front.len() > 0 {
for index in 0..self.color_front.len() {
let value = &self.color_front[index];
let roughness = self.roughness_front[index];
let test : u32 = 5;
v[mem_index] = u32::from_ne_bytes([value.x, value.y, value.z, roughness]);
mem_index += 1;
}
}
else {
v[mem_index] = u32::from_ne_bytes([0, 0, 0, 0]);
mem_index += 1;
}
if self.color_back.len() > 0 {
for index in 0..self.color_back.len() {
let value = &self.color_back[index];
let roughness = self.roughness_back[index];
let test : u32 = 5;
v[mem_index] = u32::from_ne_bytes([value.x, value.y, value.z, roughness]);
mem_index += 1;
}
}
else {
v[mem_index] = u32::from_ne_bytes([0, 0, 0, 0]);
mem_index += 1;
}
// neighbors
if self.neighbor_top.len() > 0 {
for nvalue in &self.neighbor_top {
if let Some(reference) = nvalue {
v[mem_index] = reference.borrow().memory_start as u32;
}
else {
v[mem_index] = 0;
}
mem_index += 1;
}
}
else {
v[mem_index] = 0;
mem_index += 1;
}
if self.neighbor_bottom.len() > 0 {
for nvalue in &self.neighbor_bottom {
if let Some(reference) = nvalue {
v[mem_index] = reference.borrow().memory_start as u32;
}
else {
v[mem_index] = 0;
}
mem_index += 1;
}
}
else {
v[mem_index] = 0;
mem_index += 1;
}
if self.neighbor_left.len() > 0 {
for nvalue in &self.neighbor_left {
if let Some(reference) = nvalue {
v[mem_index] = reference.borrow().memory_start as u32;
}
else {
v[mem_index] = 0;
}
mem_index += 1;
}
}
else {
v[mem_index] = 0;
mem_index += 1;
}
if self.neighbor_right.len() > 0 {
for nvalue in &self.neighbor_right {
if let Some(reference) = nvalue {
v[mem_index] = reference.borrow().memory_start as u32;
}
else {
v[mem_index] = 0;
}
mem_index += 1;
}
}
else {
v[mem_index] = 0;
mem_index += 1;
}
if self.neighbor_front.len() > 0 {
for nvalue in &self.neighbor_front {
if let Some(reference) = nvalue {
v[mem_index] = reference.borrow().memory_start as u32;
}
else {
v[mem_index] = 0;
}
mem_index += 1;
}
}
else {
v[mem_index] = 0;
mem_index += 1;
}
if self.neighbor_back.len() > 0 {
for nvalue in &self.neighbor_back {
if let Some(reference) = nvalue {
v[mem_index] = reference.borrow().memory_start as u32;
}
else {
v[mem_index] = 0;
}
mem_index += 1;
}
}
else {
v[mem_index] = 0;
mem_index += 1;
}
println!("last memory index of volume was {}, equivalent to {}kB", mem_index, mem_index * 32 / 8 / 1024);
v
}
pub fn select_lights(&self, lights: &Vec<PointLight>, light_number: u32) -> Vec<u32> {
let center = self.position + Vector3{x: self.size_x / 2, y: self.size_y / 2, z: self.size_z / 2};
let mut weighted_indices = vec![];
for light in lights {
let weight = light.weighted_distance(center);
weighted_indices.push((weight, light.memory_start));
}
weighted_indices.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());
let mut out_index = vec![];
for index in 0..weighted_indices.len() {
out_index.push(weighted_indices[weighted_indices.len() - (index + 1)].1 as u32);
if out_index.len() == light_number as usize {
break;
}
}
while out_index.len() < light_number as usize {
out_index.push(0);
}
out_index
}
}
impl PartialEq for EmptyVolume {
fn eq(&self, other: &Self) -> bool {
self.position == other.position
&& self.size_x == other.size_x
&& self.size_y == other.size_y
&& self.size_z == other.size_z
}
}