Compare commits
5 Commits
main
...
world-rewr
Author | SHA1 | Date |
---|---|---|
Jarrod Doyle | 7c9696c6f1 | |
Jarrod Doyle | 9fc4594b9a | |
Jarrod Doyle | 74f1273982 | |
Jarrod Doyle | 35ea139097 | |
Jarrod Doyle | d9a053ea5a |
|
@ -829,6 +829,16 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matrixmultiply"
|
||||||
|
version = "0.3.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"rawpointer",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.1"
|
version = "2.7.1"
|
||||||
|
@ -879,6 +889,19 @@ dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ndarray"
|
||||||
|
version = "0.15.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "adb12d4e967ec485a5f71c6311fe28158e9d6f4bc4a447b474184d0f91a8fa32"
|
||||||
|
dependencies = [
|
||||||
|
"matrixmultiply",
|
||||||
|
"num-complex",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
"rawpointer",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ndk"
|
name = "ndk"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
|
@ -909,6 +932,24 @@ dependencies = [
|
||||||
"jni-sys",
|
"jni-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-complex"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.46"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.18"
|
version = "0.2.18"
|
||||||
|
@ -1156,6 +1197,12 @@ version = "0.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42a9830a0e1b9fb145ebb365b8bc4ccd75f290f98c0247deafbbe2c75cefb544"
|
checksum = "42a9830a0e1b9fb145ebb365b8bc4ccd75f290f98c0247deafbbe2c75cefb544"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rawpointer"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.3.5"
|
version = "0.3.5"
|
||||||
|
@ -1540,6 +1587,7 @@ dependencies = [
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"glam",
|
"glam",
|
||||||
"log",
|
"log",
|
||||||
|
"ndarray",
|
||||||
"pollster",
|
"pollster",
|
||||||
"simdnoise",
|
"simdnoise",
|
||||||
"wgpu",
|
"wgpu",
|
||||||
|
|
|
@ -11,6 +11,7 @@ bytemuck = { version = "1.15.0", features = ["derive"] }
|
||||||
env_logger = "0.11.3"
|
env_logger = "0.11.3"
|
||||||
glam = "0.26.0"
|
glam = "0.26.0"
|
||||||
log = "0.4.21"
|
log = "0.4.21"
|
||||||
|
ndarray = "0.15.6"
|
||||||
pollster = "0.3.0"
|
pollster = "0.3.0"
|
||||||
simdnoise = "3.1.6"
|
simdnoise = "3.1.6"
|
||||||
wgpu = "0.19.3"
|
wgpu = "0.19.3"
|
||||||
|
|
|
@ -79,7 +79,10 @@ impl<'window> App<'window> {
|
||||||
gain: 0.5,
|
gain: 0.5,
|
||||||
lacunarity: 2.0,
|
lacunarity: 2.0,
|
||||||
},
|
},
|
||||||
glam::uvec3(32, 32, 32),
|
voxel::world::ChunkSettings {
|
||||||
|
dimensions: glam::uvec3(32, 32, 32),
|
||||||
|
block_dimensions: glam::uvec3(8, 8, 8),
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut renderer = BrickmapRenderer::new(&self.render_ctx, &camera_controller)?;
|
let mut renderer = BrickmapRenderer::new(&self.render_ctx, &camera_controller)?;
|
||||||
|
|
|
@ -1,38 +1,153 @@
|
||||||
|
use ndarray::{s, Array3};
|
||||||
|
use wgpu::naga::FastHashSet;
|
||||||
|
|
||||||
use crate::math;
|
use crate::math;
|
||||||
|
|
||||||
use super::Voxel;
|
use super::{GenerationSettings, Voxel};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct ChunkSettings {
|
||||||
|
pub dimensions: glam::UVec3,
|
||||||
|
pub block_dimensions: glam::UVec3,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Chunk {
|
pub struct Chunk {
|
||||||
pos: glam::IVec3,
|
settings: ChunkSettings,
|
||||||
|
genned_blocks: FastHashSet<(usize, usize, usize)>,
|
||||||
noise: Vec<f32>,
|
noise: Vec<f32>,
|
||||||
blocks: Vec<Vec<Voxel>>,
|
blocks: Array3<Voxel>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Chunk {
|
impl Chunk {
|
||||||
pub fn new(pos: glam::IVec3, noise: Vec<f32>, blocks: Vec<Vec<Voxel>>) -> Self {
|
pub fn new(
|
||||||
Self { pos, noise, blocks }
|
generation_settings: &GenerationSettings,
|
||||||
|
chunk_settings: ChunkSettings,
|
||||||
|
pos: glam::IVec3,
|
||||||
|
) -> Self {
|
||||||
|
let dims = chunk_settings.dimensions;
|
||||||
|
|
||||||
|
// We use dimensions of `chunk_dims + 1` because the corners on the last chunk
|
||||||
|
// block of each axis step outside of our 0..N bounds, sharing a value with the
|
||||||
|
// neighbouring chunk
|
||||||
|
let noise = simdnoise::NoiseBuilder::fbm_3d_offset(
|
||||||
|
pos.x as f32 * dims.x as f32,
|
||||||
|
dims.x as usize + 1,
|
||||||
|
pos.y as f32 * dims.y as f32,
|
||||||
|
dims.y as usize + 1,
|
||||||
|
pos.z as f32 * dims.z as f32,
|
||||||
|
dims.z as usize + 1,
|
||||||
|
)
|
||||||
|
.with_seed(generation_settings.seed)
|
||||||
|
.with_freq(generation_settings.frequency)
|
||||||
|
.with_octaves(generation_settings.octaves)
|
||||||
|
.with_gain(generation_settings.gain)
|
||||||
|
.with_lacunarity(generation_settings.lacunarity)
|
||||||
|
.generate()
|
||||||
|
.0;
|
||||||
|
|
||||||
|
let genned_blocks = FastHashSet::default();
|
||||||
|
|
||||||
|
let shape = chunk_settings.dimensions * chunk_settings.block_dimensions;
|
||||||
|
let num_voxels = shape.x * shape.y * shape.z;
|
||||||
|
let blocks = Array3::from_shape_vec(
|
||||||
|
(shape.x as usize, shape.y as usize, shape.z as usize),
|
||||||
|
vec![Voxel::Empty; num_voxels as usize],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
settings: chunk_settings,
|
||||||
|
noise,
|
||||||
|
blocks,
|
||||||
|
genned_blocks,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_block(&mut self, block_pos: glam::UVec3, chunk_dims: glam::UVec3) -> Vec<Voxel> {
|
pub fn get_region(
|
||||||
assert_eq!(
|
&mut self,
|
||||||
self.blocks.len(),
|
region_start: glam::UVec3,
|
||||||
(chunk_dims.x * chunk_dims.y * chunk_dims.z) as usize
|
region_dims: glam::UVec3,
|
||||||
);
|
) -> Vec<Voxel> {
|
||||||
|
let start = region_start;
|
||||||
|
let end = region_start + region_dims;
|
||||||
|
let dims = self.settings.dimensions * self.settings.block_dimensions;
|
||||||
|
assert!(end.x <= dims.x && end.y <= dims.y && end.z <= dims.z);
|
||||||
|
|
||||||
let block_idx = math::to_1d_index(block_pos, chunk_dims);
|
// Check that all the blocks needed are generated and generated them if needed
|
||||||
let mut block = &self.blocks[block_idx];
|
let block_dims = self.settings.block_dimensions;
|
||||||
if block.is_empty() {
|
let start_block = start / block_dims;
|
||||||
self.gen_block(block_pos, block_idx, chunk_dims);
|
let end_block = end / block_dims;
|
||||||
block = &self.blocks[block_idx]
|
for z in start_block.z..(end_block.z) {
|
||||||
|
for y in (start_block.y)..(end_block.y) {
|
||||||
|
for x in (start_block.x)..(end_block.x) {
|
||||||
|
if !self
|
||||||
|
.genned_blocks
|
||||||
|
.contains(&(x as usize, y as usize, z as usize))
|
||||||
|
{
|
||||||
|
self.gen_block(glam::uvec3(x, y, z));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
block.to_owned()
|
//
|
||||||
|
let region = self
|
||||||
|
.blocks
|
||||||
|
.slice(s![
|
||||||
|
(start.x as usize)..(end.x as usize),
|
||||||
|
(start.y as usize)..(end.y as usize),
|
||||||
|
(start.z as usize)..(end.z as usize)
|
||||||
|
])
|
||||||
|
.to_owned()
|
||||||
|
.into_raw_vec();
|
||||||
|
// dbg!(®ion);
|
||||||
|
region
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen_block(&mut self, block_pos: glam::UVec3, block_idx: usize, chunk_dims: glam::UVec3) {
|
// pub fn get_voxel(&mut self, pos: glam::UVec3) -> Voxel {
|
||||||
let block = &mut self.blocks[block_idx];
|
// let dims = self.settings.dimensions * self.settings.block_dimensions;
|
||||||
let noise_dims = chunk_dims + glam::uvec3(1, 1, 1);
|
// debug_assert!(pos.x < dims.x && pos.y < dims.y && pos.z < dims.z);
|
||||||
|
|
||||||
|
// let block_pos = pos / self.settings.block_dimensions;
|
||||||
|
// let block_idx = math::to_1d_index(block_pos, self.settings.dimensions);
|
||||||
|
// let mut block = &self.blocks[block_idx];
|
||||||
|
// if block.is_empty() {
|
||||||
|
// self.gen_block(block_pos, block_idx);
|
||||||
|
// block = &self.blocks[block_idx]
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let local_pos = pos % self.settings.block_dimensions;
|
||||||
|
// let local_idx = math::to_1d_index(local_pos, self.settings.block_dimensions);
|
||||||
|
// block[local_idx]
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn get_block(&mut self, pos: glam::UVec3) -> Vec<Voxel> {
|
||||||
|
let dims = self.settings.dimensions;
|
||||||
|
assert!(pos.x < dims.x && pos.y < dims.y && pos.z < dims.z);
|
||||||
|
|
||||||
|
let gen_key = &(pos.x as usize, pos.y as usize, pos.z as usize);
|
||||||
|
if !self.genned_blocks.contains(gen_key) {
|
||||||
|
self.gen_block(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
let block_dims = self.settings.block_dimensions;
|
||||||
|
let start = pos * block_dims;
|
||||||
|
let end = start + block_dims;
|
||||||
|
let region = self
|
||||||
|
.blocks
|
||||||
|
.slice(s![
|
||||||
|
(start.x as usize)..(end.x as usize),
|
||||||
|
(start.y as usize)..(end.y as usize),
|
||||||
|
(start.z as usize)..(end.z as usize)
|
||||||
|
])
|
||||||
|
.to_owned()
|
||||||
|
.into_raw_vec();
|
||||||
|
region
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gen_block(&mut self, block_pos: glam::UVec3) {
|
||||||
|
let noise_dims = self.settings.dimensions + glam::uvec3(1, 1, 1);
|
||||||
|
|
||||||
// Extract relevant noise values from the chunk
|
// Extract relevant noise values from the chunk
|
||||||
let mut noise_vals = Vec::new();
|
let mut noise_vals = Vec::new();
|
||||||
|
@ -50,32 +165,51 @@ impl Chunk {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If all the corners are negative, then all the interpolated values
|
// If all the corners are negative, then all the interpolated values
|
||||||
// will be negative too. In that case we can just fill with empty.
|
// will be negative too. The chunk voxels are initialised as empty already
|
||||||
if block_sign == -8.0 {
|
// so we only need to modify them if we have at least one positive corner
|
||||||
block.resize(512, Voxel::Empty);
|
if block_sign != -8.0 {
|
||||||
} else {
|
let block_dims = self.settings.block_dimensions;
|
||||||
|
|
||||||
let mut vals = [0.0f32; 512];
|
let mut vals = [0.0f32; 512];
|
||||||
math::tri_lerp_block(&noise_vals, &[8, 8, 8], &mut vals);
|
math::tri_lerp_block(
|
||||||
|
&noise_vals,
|
||||||
|
&[block_dims.x, block_dims.y, block_dims.z],
|
||||||
|
&mut vals,
|
||||||
|
);
|
||||||
|
|
||||||
|
let start = block_pos * block_dims;
|
||||||
|
let end = start + block_dims;
|
||||||
|
let mut block = self.blocks.slice_mut(s![
|
||||||
|
(start.x as usize)..(end.x as usize),
|
||||||
|
(start.y as usize)..(end.y as usize),
|
||||||
|
(start.z as usize)..(end.z as usize)
|
||||||
|
]);
|
||||||
|
|
||||||
// TODO: Better voxel colours
|
// TODO: Better voxel colours
|
||||||
let mut idx = 0;
|
let mut val_idx = 0;
|
||||||
for z in 0..8 {
|
for z in 0..block_dims.z {
|
||||||
for y in 0..8 {
|
for y in 0..block_dims.y {
|
||||||
for x in 0..8 {
|
for x in 0..block_dims.x {
|
||||||
let val = vals[idx];
|
let val = vals[val_idx];
|
||||||
idx += 1;
|
val_idx += 1;
|
||||||
|
|
||||||
if val > 0.0 {
|
if val > 0.0 {
|
||||||
let r = ((x + 1) * 32 - 1) as u8;
|
let r = ((x + 1) * 32 - 1) as u8;
|
||||||
let g = ((y + 1) * 32 - 1) as u8;
|
let g = ((y + 1) * 32 - 1) as u8;
|
||||||
let b = ((z + 1) * 32 - 1) as u8;
|
let b = ((z + 1) * 32 - 1) as u8;
|
||||||
block.push(Voxel::Color(r, g, b));
|
let block_idx = [z as usize, y as usize, x as usize];
|
||||||
} else {
|
block[block_idx] = Voxel::Color(r, g, b);
|
||||||
block.push(Voxel::Empty);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let key = (
|
||||||
|
block_pos.x as usize,
|
||||||
|
block_pos.y as usize,
|
||||||
|
block_pos.z as usize,
|
||||||
|
);
|
||||||
|
self.genned_blocks.insert(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use super::{Chunk, GenerationSettings, Voxel};
|
use super::{chunk::ChunkSettings, Chunk, GenerationSettings, Voxel};
|
||||||
|
|
||||||
pub struct WorldManager {
|
pub struct WorldManager {
|
||||||
settings: GenerationSettings,
|
generation_settings: GenerationSettings,
|
||||||
chunk_dims: glam::UVec3,
|
chunk_settings: ChunkSettings,
|
||||||
chunks: HashMap<glam::IVec3, Chunk>,
|
chunks: HashMap<glam::IVec3, Chunk>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WorldManager {
|
impl WorldManager {
|
||||||
pub fn new(settings: GenerationSettings, chunk_dims: glam::UVec3) -> Self {
|
pub fn new(generation_settings: GenerationSettings, chunk_settings: ChunkSettings) -> Self {
|
||||||
let chunks = HashMap::new();
|
let chunks = HashMap::new();
|
||||||
Self {
|
Self {
|
||||||
settings,
|
generation_settings,
|
||||||
chunk_dims,
|
chunk_settings,
|
||||||
chunks,
|
chunks,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_chunk_dims(&self) -> glam::UVec3 {
|
pub fn get_chunk_dims(&self) -> glam::UVec3 {
|
||||||
self.chunk_dims
|
self.chunk_settings.dimensions
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_block(&mut self, chunk_pos: glam::IVec3, local_pos: glam::UVec3) -> Vec<Voxel> {
|
pub fn get_block(&mut self, chunk_pos: glam::IVec3, local_pos: glam::UVec3) -> Vec<Voxel> {
|
||||||
|
@ -31,31 +31,13 @@ impl WorldManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
let chunk = self.chunks.get_mut(&chunk_pos).unwrap();
|
let chunk = self.chunks.get_mut(&chunk_pos).unwrap();
|
||||||
chunk.get_block(local_pos, self.chunk_dims)
|
let block_dims = self.chunk_settings.block_dimensions;
|
||||||
|
chunk.get_region(local_pos * block_dims, block_dims)
|
||||||
|
|
||||||
|
// chunk.get_block(local_pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_chunk(&mut self, pos: glam::IVec3) -> Chunk {
|
fn gen_chunk(&mut self, pos: glam::IVec3) -> Chunk {
|
||||||
// We use dimensions of `chunk_dims + 1` because the corners on the last chunk
|
Chunk::new(&self.generation_settings, self.chunk_settings, pos)
|
||||||
// block of each axis step outside of our 0..N bounds, sharing a value with the
|
|
||||||
// neighbouring chunk
|
|
||||||
let noise = simdnoise::NoiseBuilder::fbm_3d_offset(
|
|
||||||
pos.x as f32 * self.chunk_dims.x as f32,
|
|
||||||
self.chunk_dims.x as usize + 1,
|
|
||||||
pos.y as f32 * self.chunk_dims.y as f32,
|
|
||||||
self.chunk_dims.y as usize + 1,
|
|
||||||
pos.z as f32 * self.chunk_dims.z as f32,
|
|
||||||
self.chunk_dims.z as usize + 1,
|
|
||||||
)
|
|
||||||
.with_seed(self.settings.seed)
|
|
||||||
.with_freq(self.settings.frequency)
|
|
||||||
.with_octaves(self.settings.octaves)
|
|
||||||
.with_gain(self.settings.gain)
|
|
||||||
.with_lacunarity(self.settings.lacunarity)
|
|
||||||
.generate()
|
|
||||||
.0;
|
|
||||||
|
|
||||||
let num_blocks = self.chunk_dims.x * self.chunk_dims.y * self.chunk_dims.z;
|
|
||||||
let blocks = vec![vec![]; num_blocks as usize];
|
|
||||||
Chunk::new(pos, noise, blocks)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
mod chunk;
|
mod chunk;
|
||||||
mod manager;
|
mod manager;
|
||||||
|
|
||||||
pub use {chunk::Chunk, manager::*};
|
pub use {
|
||||||
|
chunk::{Chunk, ChunkSettings},
|
||||||
|
manager::*,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum Voxel {
|
pub enum Voxel {
|
||||||
|
|
Loading…
Reference in New Issue