CHUNK GENERATION IS REAL

This commit is contained in:
2024-06-21 00:36:37 -04:00
parent aa466a248c
commit b8ed5297fa
43 changed files with 1341 additions and 517 deletions

View File

@@ -0,0 +1,124 @@
use std::collections::{HashMap, HashSet};
use crate::{
client::render::voxel::{VoxelColor, VoxelFace},
util::oct_tree::OctTree,
};
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::{bundle::Bundle, component::Component, entity::Entity, system::Resource};
use block_mesh::{ndshape::RuntimeShape, UnitQuadBuffer, RIGHT_HANDED_Y_UP_CONFIG};
use nalgebra::Vector3;
use ndarray::{s, Array3, Axis};
pub const SIDE_LENGTH: usize = 16 * 16;
pub const SHAPE: (usize, usize, usize) = (SIDE_LENGTH, SIDE_LENGTH, SIDE_LENGTH);
pub const DIMENSIONS: Vector3<usize> = Vector3::new(SIDE_LENGTH, SIDE_LENGTH, SIDE_LENGTH);
pub const LEN: usize = SHAPE.0 * SHAPE.1 * SHAPE.2;
#[derive(Debug, Component, Clone, Deref, DerefMut)]
pub struct ChunkData {
#[deref]
data: OctTree<VoxelColor>,
}
impl ChunkData {
pub fn empty() -> Self {
Self {
data: OctTree::Leaf(VoxelColor::none()),
}
}
pub fn from_tree(t: OctTree<VoxelColor>) -> Self {
Self { data: t }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Component, Default, Deref, DerefMut)]
pub struct ChunkPos(pub Vector3<i32>);
impl ChunkPos {
pub fn new(x: i32, y: i32, z: i32) -> Self {
Self(Vector3::new(x, y, z))
}
}
impl From<Vector3<i32>> for ChunkPos {
fn from(val: Vector3<i32>) -> Self {
ChunkPos(val)
}
}
#[derive(Debug, Clone, Component)]
pub struct ChunkMesh {
pub faces: [Vec<VoxelFace>; 6],
}
impl ChunkMesh {
pub fn from_data(data: &Array3<VoxelColor>) -> Self {
let dim_pad = Vector3::new(
data.len_of(Axis(0)) as u32,
data.len_of(Axis(1)) as u32,
data.len_of(Axis(2)) as u32,
);
let dim = dim_pad - Vector3::from_element(2);
let mut buffer = UnitQuadBuffer::new();
let shape = RuntimeShape::<u32, 3>::new(dim_pad.into());
let slice = data.as_slice().unwrap();
block_mesh::visible_block_faces(
slice,
&shape,
[0; 3],
(dim_pad - Vector3::new(1, 1, 1)).into(),
&RIGHT_HANDED_Y_UP_CONFIG.faces,
&mut buffer,
);
let faces = [2, 1, 0, 5, 4, 3].map(|f| {
buffer.groups[f]
.iter()
.map(|a| {
let i = (a.minimum[0]-1) + (a.minimum[1]-1) * dim.y + (a.minimum[2]-1) * dim.y * dim.x;
let i_pad = a.minimum[0] + a.minimum[1] * dim_pad.y + a.minimum[2] * dim_pad.y * dim_pad.x;
VoxelFace {
index: i,
color: slice[i_pad as usize],
}
})
.collect()
});
Self { faces }
}
}
#[derive(Debug, Clone, Component, Deref, DerefMut)]
pub struct LoadedChunks {
loaded: HashSet<ChunkPos>,
}
impl LoadedChunks {
pub fn new() -> Self {
Self {
loaded: HashSet::new(),
}
}
}
#[derive(Resource, Deref, DerefMut)]
pub struct ChunkMap {
#[deref]
map: HashMap<ChunkPos, Entity>,
pub generating: HashSet<ChunkPos>,
}
impl ChunkMap {
pub fn new() -> Self {
Self {
map: HashMap::new(),
generating: HashSet::new(),
}
}
}
#[derive(Bundle, Clone)]
pub struct ChunkBundle {
pub pos: ChunkPos,
pub data: ChunkData,
pub mesh: ChunkMesh,
}

View File

@@ -0,0 +1,46 @@
use crate::client::render::voxel::VoxelColor;
use bevy_ecs::{bundle::Bundle, component::Component};
use ndarray::{Array3, ArrayBase, Dim, SliceArg};
use std::ops::Range;
use super::{Orientation, Pos};
pub type VoxelGrid = TrackedGrid<VoxelColor>;
pub type GridRegion = (Range<usize>, Range<usize>, Range<usize>);
#[derive(Debug, Clone, Component)]
pub struct TrackedGrid<T> {
data: Array3<T>,
changes: Vec<GridRegion>,
}
impl<T> TrackedGrid<T> {
pub fn new(data: Array3<T>) -> Self {
Self {
data,
changes: Vec::new(),
}
}
pub fn view_slice_mut<I: SliceArg<Dim<[usize; 3]>>>(
&mut self,
slice: I,
) -> ArrayBase<ndarray::ViewRepr<&mut T>, <I as SliceArg<Dim<[usize; 3]>>>::OutDim> {
self.data.slice_mut(slice)
}
pub fn take_changes(&mut self) -> Vec<GridRegion> {
std::mem::take(&mut self.changes)
}
}
impl<T> std::ops::Deref for TrackedGrid<T> {
type Target = Array3<T>;
fn deref(&self) -> &Self::Target {
&self.data
}
}
#[derive(Bundle, Clone)]
pub struct VoxelGridBundle {
pub pos: Pos,
pub orientation: Orientation,
pub grid: VoxelGrid,
}

View File

@@ -0,0 +1,62 @@
pub mod chunk;
mod grid;
use chunk::LoadedChunks;
pub use chunk::{ChunkBundle, ChunkData, ChunkMap, ChunkMesh, ChunkPos};
pub use grid::*;
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::{bundle::Bundle, component::Component};
use nalgebra::{Rotation3, Vector3};
#[derive(Debug, Clone, Copy, Component, Default, Deref, DerefMut)]
pub struct Pos(pub Vector3<f32>);
impl Pos {
pub fn new(x: f32, y: f32, z: f32) -> Self {
Self(Vector3::new(x, y, z))
}
}
impl From<Vector3<f32>> for Pos {
fn from(val: Vector3<f32>) -> Self {
Pos(val)
}
}
#[derive(Debug, Clone, Copy, Component, Default, Deref, DerefMut)]
pub struct Orientation(pub Rotation3<f32>);
impl Orientation {
pub fn from_axis_angle<SB: nalgebra::Storage<f32, nalgebra::Const<3>>>(
axis: &nalgebra::Unit<nalgebra::Matrix<f32, nalgebra::Const<3>, nalgebra::Const<1>, SB>>,
angle: f32,
) -> Self {
Self(Rotation3::from_axis_angle(axis, angle))
}
}
impl From<Rotation3<f32>> for Orientation {
fn from(val: Rotation3<f32>) -> Self {
Orientation(val)
}
}
#[derive(Debug, Clone, Copy, Component)]
pub struct Player;
#[derive(Debug, Clone, Bundle)]
pub struct PlayerBundle {
pub player: Player,
pub loaded_chunks: LoadedChunks,
pub pos: Pos,
pub orientation: Orientation,
}
impl PlayerBundle {
pub fn new() -> Self {
Self {
player: Player,
loaded_chunks: LoadedChunks::new(),
pos: Pos::default(),
orientation: Orientation::default(),
}
}
}