Allow for chunks with negative coordinates
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
023d010c84
commit
15247d12d4
6 changed files with 100 additions and 109 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -970,6 +970,15 @@ dependencies = [
|
||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "0.4.7"
|
version = "0.4.7"
|
||||||
|
@ -1115,6 +1124,7 @@ dependencies = [
|
||||||
"futures",
|
"futures",
|
||||||
"gltf",
|
"gltf",
|
||||||
"image",
|
"image",
|
||||||
|
"itertools",
|
||||||
"log",
|
"log",
|
||||||
"noise",
|
"noise",
|
||||||
"rayon",
|
"rayon",
|
||||||
|
|
|
@ -19,6 +19,7 @@ noise = "0.7.0"
|
||||||
rayon = "1.5.1"
|
rayon = "1.5.1"
|
||||||
wgpu = "0.8.1"
|
wgpu = "0.8.1"
|
||||||
winit = { version = "0.25.0", default_features = false, features = ["x11", "web-sys"] }
|
winit = { version = "0.25.0", default_features = false, features = ["x11", "web-sys"] }
|
||||||
|
itertools = "0.10.0"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
debug = true
|
debug = true
|
||||||
|
|
23
src/chunk.rs
23
src/chunk.rs
|
@ -2,7 +2,7 @@ use std::{collections::VecDeque, usize};
|
||||||
|
|
||||||
use crate::{geometry::Geometry, quad::Quad, vertex::BlockVertex};
|
use crate::{geometry::Geometry, quad::Quad, vertex::BlockVertex};
|
||||||
use ahash::{AHashMap, AHashSet};
|
use ahash::{AHashMap, AHashSet};
|
||||||
use cgmath::Vector3;
|
use cgmath::{Point3, Vector3};
|
||||||
use noise::utils::{NoiseMapBuilder, PlaneMapBuilder};
|
use noise::utils::{NoiseMapBuilder, PlaneMapBuilder};
|
||||||
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||||
|
|
||||||
|
@ -55,7 +55,8 @@ pub struct Block {
|
||||||
pub block_type: BlockType,
|
pub block_type: BlockType,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const CHUNK_SIZE: usize = 64;
|
pub const CHUNK_SIZE: usize = 32;
|
||||||
|
pub const CHUNK_ISIZE: isize = CHUNK_SIZE as isize;
|
||||||
|
|
||||||
type ChunkBlocks = [[[Option<Block>; CHUNK_SIZE]; CHUNK_SIZE]; CHUNK_SIZE];
|
type ChunkBlocks = [[[Option<Block>; CHUNK_SIZE]; CHUNK_SIZE]; CHUNK_SIZE];
|
||||||
|
|
||||||
|
@ -217,10 +218,10 @@ impl Chunk {
|
||||||
fn layer_to_quads(
|
fn layer_to_quads(
|
||||||
&self,
|
&self,
|
||||||
y: usize,
|
y: usize,
|
||||||
offset: Vector3<i32>,
|
offset: Point3<isize>,
|
||||||
culled: AHashMap<(usize, usize), (BlockType, FaceFlags)>,
|
culled: AHashMap<(usize, usize), (BlockType, FaceFlags)>,
|
||||||
queue: &mut VecDeque<(usize, usize)>,
|
queue: &mut VecDeque<(usize, usize)>,
|
||||||
highlighted: Option<&(Vector3<usize>, Vector3<i32>)>,
|
highlighted: Option<&(Point3<usize>, Vector3<i32>)>,
|
||||||
) -> Vec<Quad> {
|
) -> Vec<Quad> {
|
||||||
let mut quads: Vec<Quad> = Vec::new();
|
let mut quads: Vec<Quad> = Vec::new();
|
||||||
let mut visited = AHashSet::new();
|
let mut visited = AHashSet::new();
|
||||||
|
@ -236,7 +237,7 @@ impl Chunk {
|
||||||
if let Some(&(block_type, visible_faces)) = &culled.get(&(x, z)) {
|
if let Some(&(block_type, visible_faces)) = &culled.get(&(x, z)) {
|
||||||
let mut quad_faces = visible_faces;
|
let mut quad_faces = visible_faces;
|
||||||
|
|
||||||
if hl == Some(Vector3::new(x, y, z)) {
|
if hl == Some(Point3::new(x, y, z)) {
|
||||||
let mut quad = Quad::new(position, 1, 1);
|
let mut quad = Quad::new(position, 1, 1);
|
||||||
quad.highlighted_normal = highlighted.unwrap().1;
|
quad.highlighted_normal = highlighted.unwrap().1;
|
||||||
quad.visible_faces = quad_faces;
|
quad.visible_faces = quad_faces;
|
||||||
|
@ -258,7 +259,7 @@ impl Chunk {
|
||||||
for x_ in x..CHUNK_SIZE {
|
for x_ in x..CHUNK_SIZE {
|
||||||
xmax = x_ + 1;
|
xmax = x_ + 1;
|
||||||
|
|
||||||
if visited.contains(&(xmax, z)) || hl == Some(Vector3::new(xmax, y, z)) {
|
if visited.contains(&(xmax, z)) || hl == Some(Point3::new(xmax, y, z)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +281,7 @@ impl Chunk {
|
||||||
zmax = z_ + 1;
|
zmax = z_ + 1;
|
||||||
|
|
||||||
for x_ in x..xmax {
|
for x_ in x..xmax {
|
||||||
if visited.contains(&(x_, zmax)) || hl == Some(Vector3::new(x_, y, zmax)) {
|
if visited.contains(&(x_, zmax)) || hl == Some(Point3::new(x_, y, zmax)) {
|
||||||
break 'z;
|
break 'z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,7 +300,7 @@ impl Chunk {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut quad = Quad::new(position, (xmax - x) as i32, (zmax - z) as i32);
|
let mut quad = Quad::new(position, (xmax - x) as isize, (zmax - z) as isize);
|
||||||
quad.visible_faces = quad_faces;
|
quad.visible_faces = quad_faces;
|
||||||
quad.block_type = Some(block_type);
|
quad.block_type = Some(block_type);
|
||||||
quads.push(quad);
|
quads.push(quad);
|
||||||
|
@ -319,14 +320,14 @@ impl Chunk {
|
||||||
|
|
||||||
pub fn to_geometry(
|
pub fn to_geometry(
|
||||||
&self,
|
&self,
|
||||||
offset: Vector3<i32>,
|
position: Point3<isize>,
|
||||||
highlighted: Option<&(Vector3<usize>, Vector3<i32>)>,
|
highlighted: Option<&(Point3<usize>, Vector3<i32>)>,
|
||||||
) -> Geometry<BlockVertex> {
|
) -> Geometry<BlockVertex> {
|
||||||
let quads: Vec<Quad> = (0..CHUNK_SIZE)
|
let quads: Vec<Quad> = (0..CHUNK_SIZE)
|
||||||
.into_par_iter()
|
.into_par_iter()
|
||||||
.flat_map(|y| {
|
.flat_map(|y| {
|
||||||
let (culled, mut queue) = self.cull_layer(y);
|
let (culled, mut queue) = self.cull_layer(y);
|
||||||
self.layer_to_quads(y, offset, culled, &mut queue, highlighted)
|
self.layer_to_quads(y, position, culled, &mut queue, highlighted)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|
10
src/quad.rs
10
src/quad.rs
|
@ -1,4 +1,4 @@
|
||||||
use cgmath::{Vector3, Zero};
|
use cgmath::{Point3, Vector3, Zero};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
chunk::{
|
chunk::{
|
||||||
|
@ -11,9 +11,9 @@ use crate::{
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Quad {
|
pub struct Quad {
|
||||||
pub position: Vector3<i32>,
|
pub position: Point3<isize>,
|
||||||
pub dx: i32,
|
pub dx: isize,
|
||||||
pub dz: i32,
|
pub dz: isize,
|
||||||
|
|
||||||
pub highlighted_normal: Vector3<i32>,
|
pub highlighted_normal: Vector3<i32>,
|
||||||
pub visible_faces: FaceFlags,
|
pub visible_faces: FaceFlags,
|
||||||
|
@ -21,7 +21,7 @@ pub struct Quad {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Quad {
|
impl Quad {
|
||||||
pub fn new(position: Vector3<i32>, dx: i32, dz: i32) -> Self {
|
pub fn new(position: Point3<isize>, dx: isize, dz: isize) -> Self {
|
||||||
Quad {
|
Quad {
|
||||||
position,
|
position,
|
||||||
dx,
|
dx,
|
||||||
|
|
|
@ -13,7 +13,7 @@ use winit::{
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
camera::{Camera, Projection},
|
camera::{Camera, Projection},
|
||||||
chunk::{Block, BlockType, CHUNK_SIZE},
|
chunk::{Block, BlockType, CHUNK_ISIZE},
|
||||||
geometry::GeometryBuffers,
|
geometry::GeometryBuffers,
|
||||||
render_context::RenderContext,
|
render_context::RenderContext,
|
||||||
texture::{Texture, TextureManager},
|
texture::{Texture, TextureManager},
|
||||||
|
@ -35,13 +35,13 @@ pub struct WorldState {
|
||||||
pub time_bind_group: wgpu::BindGroup,
|
pub time_bind_group: wgpu::BindGroup,
|
||||||
pub world: World,
|
pub world: World,
|
||||||
|
|
||||||
pub chunk_buffers: AHashMap<Vector3<usize>, GeometryBuffers>,
|
pub chunk_buffers: AHashMap<Point3<isize>, GeometryBuffers>,
|
||||||
time: Time,
|
time: Time,
|
||||||
time_buffer: wgpu::Buffer,
|
time_buffer: wgpu::Buffer,
|
||||||
wireframe: bool,
|
wireframe: bool,
|
||||||
shader: wgpu::ShaderModule,
|
shader: wgpu::ShaderModule,
|
||||||
render_pipeline_layout: wgpu::PipelineLayout,
|
render_pipeline_layout: wgpu::PipelineLayout,
|
||||||
pub highlighted: Option<(Vector3<usize>, Vector3<i32>)>,
|
pub highlighted: Option<(Point3<isize>, Vector3<i32>)>,
|
||||||
|
|
||||||
pub forward_pressed: bool,
|
pub forward_pressed: bool,
|
||||||
pub backward_pressed: bool,
|
pub backward_pressed: bool,
|
||||||
|
@ -256,13 +256,13 @@ impl WorldState {
|
||||||
pub fn update_chunk_geometry(
|
pub fn update_chunk_geometry(
|
||||||
&mut self,
|
&mut self,
|
||||||
render_context: &RenderContext,
|
render_context: &RenderContext,
|
||||||
chunk_position: Vector3<usize>,
|
chunk_position: Point3<isize>,
|
||||||
) {
|
) {
|
||||||
let chunk = &mut self.world.chunks[chunk_position.y][chunk_position.z][chunk_position.x];
|
let chunk = &mut self.world.chunks.get(&chunk_position).unwrap();
|
||||||
let offset = chunk_position.map(|f| (f * CHUNK_SIZE) as i32);
|
let offset = chunk_position * CHUNK_ISIZE;
|
||||||
let geometry = chunk.to_geometry(
|
let geometry = chunk.to_geometry(
|
||||||
offset,
|
offset,
|
||||||
World::highlighted_for_chunk(self.highlighted, chunk_position).as_ref(),
|
World::highlighted_for_chunk(self.highlighted, &chunk_position).as_ref(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let buffers =
|
let buffers =
|
||||||
|
@ -393,7 +393,7 @@ impl WorldState {
|
||||||
let camera_pos = Vector2::new(camera_pos.x, camera_pos.z);
|
let camera_pos = Vector2::new(camera_pos.x, camera_pos.z);
|
||||||
|
|
||||||
for (position, buffers) in &self.chunk_buffers {
|
for (position, buffers) in &self.chunk_buffers {
|
||||||
let pos = (position * CHUNK_SIZE).cast().unwrap();
|
let pos = (position * CHUNK_ISIZE).cast().unwrap();
|
||||||
let pos = Vector2::new(pos.x, pos.z);
|
let pos = Vector2::new(pos.x, pos.z);
|
||||||
if (pos - camera_pos).magnitude() > 300.0 {
|
if (pos - camera_pos).magnitude() > 300.0 {
|
||||||
continue;
|
continue;
|
||||||
|
@ -433,12 +433,10 @@ impl WorldState {
|
||||||
let camera = &self.camera;
|
let camera = &self.camera;
|
||||||
|
|
||||||
let old = self.highlighted;
|
let old = self.highlighted;
|
||||||
let new = self
|
let new = self.world.raycast(camera.position, camera.direction());
|
||||||
.world
|
|
||||||
.raycast(camera.position.to_vec(), camera.direction());
|
|
||||||
|
|
||||||
let old_chunk = old.map(|h| h.0 / CHUNK_SIZE);
|
let old_chunk = old.map(|(pos, _)| pos.map(|n| n.div_euclid(CHUNK_ISIZE)));
|
||||||
let new_chunk = new.map(|h| h.0 / CHUNK_SIZE);
|
let new_chunk = new.map(|(pos, _)| pos.map(|n| n.div_euclid(CHUNK_ISIZE)));
|
||||||
|
|
||||||
if old != new {
|
if old != new {
|
||||||
self.highlighted = new;
|
self.highlighted = new;
|
||||||
|
@ -460,12 +458,10 @@ impl WorldState {
|
||||||
let camera = &self.camera;
|
let camera = &self.camera;
|
||||||
|
|
||||||
let world = &mut self.world;
|
let world = &mut self.world;
|
||||||
if let Some((pos, face_normal)) =
|
if let Some((pos, face_normal)) = world.raycast(camera.position, camera.direction()) {
|
||||||
world.raycast(camera.position.to_vec(), camera.direction())
|
|
||||||
{
|
|
||||||
if button == &MouseButton::Left {
|
if button == &MouseButton::Left {
|
||||||
world.set_block(pos.x as isize, pos.y as isize, pos.z as isize, None);
|
world.set_block(pos.x as isize, pos.y as isize, pos.z as isize, None);
|
||||||
self.update_chunk_geometry(render_context, pos / CHUNK_SIZE);
|
self.update_chunk_geometry(render_context, pos / CHUNK_ISIZE);
|
||||||
} else if button == &MouseButton::Right {
|
} else if button == &MouseButton::Right {
|
||||||
let new_pos = pos.cast().unwrap() + face_normal;
|
let new_pos = pos.cast().unwrap() + face_normal;
|
||||||
|
|
||||||
|
@ -478,7 +474,7 @@ impl WorldState {
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
self.update_chunk_geometry(render_context, pos / CHUNK_SIZE);
|
self.update_chunk_geometry(render_context, pos / CHUNK_ISIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
133
src/world.rs
133
src/world.rs
|
@ -1,62 +1,62 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
chunk::{Block, Chunk, CHUNK_SIZE},
|
chunk::{Block, Chunk, CHUNK_ISIZE, CHUNK_SIZE},
|
||||||
geometry::Geometry,
|
geometry::Geometry,
|
||||||
npc::Npc,
|
npc::Npc,
|
||||||
vertex::BlockVertex,
|
vertex::BlockVertex,
|
||||||
};
|
};
|
||||||
use cgmath::{InnerSpace, Vector3};
|
use cgmath::{EuclideanSpace, InnerSpace, Point3, Vector3};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
|
||||||
pub struct World {
|
pub struct World {
|
||||||
pub chunks: Vec<Vec<Vec<Chunk>>>,
|
pub chunks: HashMap<Point3<isize>, Chunk>,
|
||||||
pub npc: Npc,
|
pub npc: Npc,
|
||||||
}
|
}
|
||||||
|
|
||||||
const WORLD_SIZE: Vector3<usize> = Vector3::new(
|
const WORLD_SIZE: Vector3<usize> = Vector3::new(
|
||||||
32 * 16 / CHUNK_SIZE,
|
8 * 16 / CHUNK_SIZE,
|
||||||
16 * 16 / CHUNK_SIZE,
|
16 * 16 / CHUNK_SIZE,
|
||||||
32 * 16 / CHUNK_SIZE,
|
8 * 16 / CHUNK_SIZE,
|
||||||
);
|
);
|
||||||
|
|
||||||
impl World {
|
impl World {
|
||||||
pub fn generate() -> Self {
|
pub fn generate() -> Self {
|
||||||
let mut chunks = Vec::new();
|
|
||||||
|
|
||||||
let npc = Npc::load();
|
let npc = Npc::load();
|
||||||
|
let half: Vector3<isize> = WORLD_SIZE.cast().unwrap() / 2;
|
||||||
|
|
||||||
(0..WORLD_SIZE.y)
|
let coords: Vec<_> =
|
||||||
.into_par_iter()
|
itertools::iproduct!(-half.x..half.x, 0..WORLD_SIZE.y as isize, -half.z..half.z)
|
||||||
.map(|y| {
|
.collect();
|
||||||
let mut chunks_z = Vec::new();
|
|
||||||
for z in 0..WORLD_SIZE.z {
|
let chunks: HashMap<_, _> = coords
|
||||||
let mut chunks_x = Vec::new();
|
.par_iter()
|
||||||
for x in 0..WORLD_SIZE.x {
|
.map(|&(x, y, z)| {
|
||||||
let chunk = Chunk::generate(x as i32, y as i32, z as i32);
|
(
|
||||||
chunks_x.push(chunk);
|
Point3::new(x, y, z),
|
||||||
}
|
Chunk::generate(x as i32, y as i32, z as i32),
|
||||||
chunks_z.push(chunks_x);
|
)
|
||||||
}
|
|
||||||
chunks_z
|
|
||||||
})
|
})
|
||||||
.collect_into_vec(&mut chunks);
|
.collect();
|
||||||
|
|
||||||
Self { chunks, npc }
|
Self { chunks, npc }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn highlighted_for_chunk(
|
pub fn highlighted_for_chunk(
|
||||||
highlighted: Option<(Vector3<usize>, Vector3<i32>)>,
|
highlighted: Option<(Point3<isize>, Vector3<i32>)>,
|
||||||
chunk_position: Vector3<usize>,
|
chunk_position: &Point3<isize>,
|
||||||
) -> Option<(Vector3<usize>, Vector3<i32>)> {
|
) -> Option<(Point3<usize>, Vector3<i32>)> {
|
||||||
let position = chunk_position * CHUNK_SIZE;
|
let position = chunk_position * CHUNK_ISIZE;
|
||||||
if let Some((pos, face)) = highlighted {
|
if let Some((pos, face)) = highlighted {
|
||||||
if pos.x >= position.x
|
if pos.x >= position.x
|
||||||
&& pos.x < position.x + CHUNK_SIZE
|
&& pos.x < position.x + CHUNK_ISIZE
|
||||||
&& pos.y >= position.y
|
&& pos.y >= position.y
|
||||||
&& pos.y < position.y + CHUNK_SIZE
|
&& pos.y < position.y + CHUNK_ISIZE
|
||||||
&& pos.z >= position.z
|
&& pos.z >= position.z
|
||||||
&& pos.z < position.z + CHUNK_SIZE
|
&& pos.z < position.z + CHUNK_ISIZE
|
||||||
{
|
{
|
||||||
Some((pos - position, face))
|
let point: Point3<isize> = EuclideanSpace::from_vec(pos - position);
|
||||||
|
Some((point.cast().unwrap(), face))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -67,26 +67,18 @@ impl World {
|
||||||
|
|
||||||
pub fn to_geometry(
|
pub fn to_geometry(
|
||||||
&self,
|
&self,
|
||||||
highlighted: Option<(Vector3<usize>, Vector3<i32>)>,
|
highlighted: Option<(Point3<isize>, Vector3<i32>)>,
|
||||||
) -> Vec<(Vector3<usize>, Geometry<BlockVertex>)> {
|
) -> Vec<(Point3<isize>, Geometry<BlockVertex>)> {
|
||||||
let instant = std::time::Instant::now();
|
let instant = std::time::Instant::now();
|
||||||
|
|
||||||
let chunks = &self.chunks;
|
let chunks = &self.chunks;
|
||||||
let geometry = chunks
|
let geometry = chunks
|
||||||
.par_iter()
|
.par_iter()
|
||||||
.enumerate()
|
.map(|(chunk_position, chunk)| {
|
||||||
.flat_map(|(y, chunks_y)| {
|
let position = (chunk_position * CHUNK_ISIZE).cast().unwrap();
|
||||||
let mut chunk_geometry = Vec::new();
|
let h = Self::highlighted_for_chunk(highlighted, chunk_position);
|
||||||
for (z, chunks_z) in chunks_y.iter().enumerate() {
|
let geometry = chunk.to_geometry(position, h.as_ref());
|
||||||
for (x, chunk) in chunks_z.iter().enumerate() {
|
(*chunk_position, geometry)
|
||||||
let chunk_position = Vector3::new(x as usize, y as usize, z as usize);
|
|
||||||
let offset = (chunk_position * CHUNK_SIZE).cast().unwrap();
|
|
||||||
let h = Self::highlighted_for_chunk(highlighted, chunk_position);
|
|
||||||
let geometry = chunk.to_geometry(offset, h.as_ref());
|
|
||||||
chunk_geometry.push((Vector3::new(x, y, z), geometry));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
chunk_geometry
|
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
@ -97,41 +89,32 @@ impl World {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_block(&self, x: isize, y: isize, z: isize) -> Option<&Block> {
|
pub fn get_block(&self, x: isize, y: isize, z: isize) -> Option<&Block> {
|
||||||
if x < 0 || y < 0 || z < 0 {
|
let chunk = match self.chunks.get(&Point3::new(
|
||||||
return None;
|
x.div_euclid(CHUNK_ISIZE),
|
||||||
}
|
y.div_euclid(CHUNK_ISIZE),
|
||||||
|
z.div_euclid(CHUNK_ISIZE),
|
||||||
let chunk = match self
|
)) {
|
||||||
.chunks
|
Some(chunk) => chunk,
|
||||||
.get(y as usize / CHUNK_SIZE)
|
|
||||||
.and_then(|chunk_layer| chunk_layer.get(z as usize / CHUNK_SIZE))
|
|
||||||
.and_then(|chunk_row| chunk_row.get(x as usize / CHUNK_SIZE))
|
|
||||||
{
|
|
||||||
Some(v) => v,
|
|
||||||
None => return None,
|
None => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
chunk.blocks[y as usize % CHUNK_SIZE][z as usize % CHUNK_SIZE][x as usize % CHUNK_SIZE]
|
let bx = x.rem_euclid(CHUNK_ISIZE) as usize;
|
||||||
.as_ref()
|
let by = y.rem_euclid(CHUNK_ISIZE) as usize;
|
||||||
|
let bz = z.rem_euclid(CHUNK_ISIZE) as usize;
|
||||||
|
chunk.blocks[by][bz][bx].as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_block(&mut self, x: isize, y: isize, z: isize, block: Option<Block>) {
|
pub fn set_block(&mut self, x: isize, y: isize, z: isize, block: Option<Block>) {
|
||||||
if x < 0 || y < 0 || z < 0 {
|
if let Some(chunk) = self.chunks.get_mut(&Point3::new(
|
||||||
return;
|
x.div_euclid(CHUNK_ISIZE),
|
||||||
|
y.div_euclid(CHUNK_ISIZE),
|
||||||
|
z.div_euclid(CHUNK_ISIZE),
|
||||||
|
)) {
|
||||||
|
let bx = x.rem_euclid(CHUNK_ISIZE) as usize;
|
||||||
|
let by = y.rem_euclid(CHUNK_ISIZE) as usize;
|
||||||
|
let bz = z.rem_euclid(CHUNK_ISIZE) as usize;
|
||||||
|
chunk.blocks[by][bz][bx] = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
let chunk = match self
|
|
||||||
.chunks
|
|
||||||
.get_mut(y as usize / CHUNK_SIZE)
|
|
||||||
.and_then(|chunk_layer| chunk_layer.get_mut(z as usize / CHUNK_SIZE))
|
|
||||||
.and_then(|chunk_row| chunk_row.get_mut(x as usize / CHUNK_SIZE))
|
|
||||||
{
|
|
||||||
Some(v) => v,
|
|
||||||
None => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
chunk.blocks[y as usize % CHUNK_SIZE][z as usize % CHUNK_SIZE][x as usize % CHUNK_SIZE] =
|
|
||||||
block;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calc_scale(vector: Vector3<f32>, scalar: f32) -> f32 {
|
fn calc_scale(vector: Vector3<f32>, scalar: f32) -> f32 {
|
||||||
|
@ -145,9 +128,9 @@ impl World {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn raycast(
|
pub fn raycast(
|
||||||
&self,
|
&self,
|
||||||
origin: Vector3<f32>,
|
origin: Point3<f32>,
|
||||||
direction: Vector3<f32>,
|
direction: Vector3<f32>,
|
||||||
) -> Option<(Vector3<usize>, Vector3<i32>)> {
|
) -> Option<(Point3<isize>, Vector3<i32>)> {
|
||||||
let direction = direction.normalize();
|
let direction = direction.normalize();
|
||||||
let scale = Vector3::new(
|
let scale = Vector3::new(
|
||||||
Self::calc_scale(direction, direction.x),
|
Self::calc_scale(direction, direction.x),
|
||||||
|
@ -155,7 +138,7 @@ impl World {
|
||||||
Self::calc_scale(direction, direction.z),
|
Self::calc_scale(direction, direction.z),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut position: Vector3<i32> = origin.cast().unwrap();
|
let mut position: Point3<i32> = origin.map(|x| x.floor() as i32);
|
||||||
let step = direction.map(|x| x.signum() as i32);
|
let step = direction.map(|x| x.signum() as i32);
|
||||||
|
|
||||||
// Truncate the origin
|
// Truncate the origin
|
||||||
|
|
Loading…
Reference in a new issue