156 lines
4.6 KiB
Rust
156 lines
4.6 KiB
Rust
use vulkanalia::prelude::v1_0::*;
|
|
use anyhow::Result;
|
|
|
|
use cgmath::{vec2, vec3};
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use crate::app_data::AppData;
|
|
use crate::buffer;
|
|
use crate::vertex;
|
|
use crate::primitives::cube::Cube;
|
|
|
|
extern crate rand;
|
|
use rand::Rng;
|
|
|
|
const CHUNK_SIZE: usize = 100;
|
|
|
|
#[derive(Clone, Debug, Default)]
|
|
pub struct Scene {
|
|
pub vertices: Vec<vertex::Vertex>,
|
|
pub indices: Vec<u32>,
|
|
|
|
pub vertex_buffer: vk::Buffer,
|
|
pub vertex_buffer_memory: vk::DeviceMemory,
|
|
|
|
pub index_buffer: vk::Buffer,
|
|
pub index_buffer_memory: vk::DeviceMemory,
|
|
}
|
|
|
|
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 = CHUNK_SIZE as i32;
|
|
|
|
// todo store the chunks somewhere (or only use them as intermediary for neighbouthood calculation idc)
|
|
let mut chunks = vec![Chunk::create()?];
|
|
|
|
//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
|
|
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, 0.0),
|
|
color: vec3(shade, 1.0, shade),
|
|
tex_coord: vec2(0.0, 0.0)
|
|
};
|
|
chunks[0].set_cube(cube);
|
|
}
|
|
}
|
|
|
|
let chunk = &chunks[0];
|
|
let chunk_iter = ChunkIter::create(chunk)?;
|
|
for item in chunk_iter {
|
|
let index = self.vertices.len();
|
|
match item {
|
|
Some(cube) => {
|
|
cube.draw(&data.topology, index, self);
|
|
}
|
|
None => {}
|
|
}
|
|
}
|
|
|
|
(self.vertex_buffer, self.vertex_buffer_memory) = buffer::create_vertex_buffer(instance, device, &data, &self.vertices)?;
|
|
(self.index_buffer, self.index_buffer_memory) = buffer::create_index_buffer(&instance, &device, &data, &self.indices)?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
pub unsafe fn destroy(&mut self, device: &vulkanalia::Device) {
|
|
device.destroy_buffer(self.index_buffer, None);
|
|
device.free_memory(self.index_buffer_memory, None);
|
|
|
|
device.destroy_buffer(self.vertex_buffer, None);
|
|
device.free_memory(self.vertex_buffer_memory, None);
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
struct Chunk {
|
|
//todo change to hashmap?
|
|
blocks: HashMap<cgmath::Vector3<u32>, Cube>,
|
|
}
|
|
|
|
impl Chunk {
|
|
pub fn create() -> Result<Self> {
|
|
let mut map = HashMap::new();
|
|
Ok(Self {
|
|
blocks: map
|
|
})
|
|
}
|
|
|
|
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 < CHUNK_SIZE, "x value out of range!");
|
|
assert!(y < CHUNK_SIZE, "y value out of range!");
|
|
assert!(z < CHUNK_SIZE, "z value out of range!");
|
|
self.blocks.insert(vec3(x as u32, y as u32, z as u32), cube);
|
|
}
|
|
|
|
pub fn clear_cube(&mut self, x: usize, y: usize, z: usize) {
|
|
assert!(x < CHUNK_SIZE, "x value out of range!");
|
|
assert!(y < CHUNK_SIZE, "y value out of range!");
|
|
assert!(z < CHUNK_SIZE, "z value out of range!");
|
|
self.blocks.remove(&vec3(x as u32, y as u32, z as u32));
|
|
}
|
|
|
|
}
|
|
|
|
struct ChunkIter<'a> {
|
|
iter_x: usize,
|
|
iter_y: usize,
|
|
iter_z: usize,
|
|
chunk: &'a Chunk
|
|
}
|
|
|
|
impl<'a> ChunkIter<'a> {
|
|
pub fn create(chunk: &'a Chunk) -> Result<Self> {
|
|
|
|
Ok(Self {
|
|
iter_x: 0,
|
|
iter_y: 0,
|
|
iter_z: 0,
|
|
chunk
|
|
})
|
|
}
|
|
}
|
|
|
|
impl<'a> Iterator for ChunkIter<'a> {
|
|
type Item = Option<&'a Cube>;
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
if self.iter_x < CHUNK_SIZE && self.iter_y < CHUNK_SIZE && self.iter_z < CHUNK_SIZE {
|
|
let result = self.chunk.blocks.get(&vec3(self.iter_x as u32, self.iter_y as u32, self.iter_z as u32));
|
|
|
|
self.iter_x += 1;
|
|
if self.iter_x >= CHUNK_SIZE {
|
|
self.iter_x = 0;
|
|
self.iter_y += 1;
|
|
}
|
|
if self.iter_y >= CHUNK_SIZE {
|
|
self.iter_y = 0;
|
|
self.iter_z += 1;
|
|
}
|
|
return Some(result.clone())
|
|
}
|
|
self.iter_x = 0;
|
|
self.iter_y = 0;
|
|
self.iter_z = 0;
|
|
None
|
|
}
|
|
}
|
|
|