Cull invisible block faces, reintroduce removing/adding blocks
This commit is contained in:
parent
ff20d5ad29
commit
65f0a706d3
9 changed files with 406 additions and 190 deletions
173
src/chunk.rs
173
src/chunk.rs
|
@ -1,4 +1,4 @@
|
|||
use std::{collections::VecDeque, usize};
|
||||
use std::{collections::VecDeque, convert::TryInto, usize};
|
||||
|
||||
use crate::{cube, quad::Quad, vertex::Vertex};
|
||||
use ahash::{AHashMap, AHashSet};
|
||||
|
@ -19,9 +19,9 @@ pub enum BlockType {
|
|||
}
|
||||
|
||||
impl BlockType {
|
||||
#[rustfmt::skip]
|
||||
pub const fn texture_indices(self) -> (usize, usize, usize, usize, usize, usize) {
|
||||
#[rustfmt::skip]
|
||||
let indices = match self {
|
||||
match self {
|
||||
BlockType::Cobblestone => ( 0, 0, 0, 0, 0, 0),
|
||||
BlockType::Dirt => ( 1, 1, 1, 1, 1, 1),
|
||||
BlockType::Stone => ( 2, 2, 2, 2, 2, 2),
|
||||
|
@ -30,11 +30,23 @@ impl BlockType {
|
|||
BlockType::Sand => ( 6, 6, 6, 6, 6, 6),
|
||||
BlockType::Gravel => ( 7, 7, 7, 7, 7, 7),
|
||||
BlockType::Water => ( 8, 8, 8, 8, 8, 8), // up to 71
|
||||
};
|
||||
indices
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn is_transparent(self) -> bool {
|
||||
matches!(self, BlockType::Water)
|
||||
}
|
||||
}
|
||||
|
||||
pub type FaceFlags = usize;
|
||||
pub const FACE_NONE: FaceFlags = 0;
|
||||
pub const FACE_LEFT: FaceFlags = 1;
|
||||
pub const FACE_RIGHT: FaceFlags = 2;
|
||||
pub const FACE_BOTTOM: FaceFlags = 4;
|
||||
pub const FACE_TOP: FaceFlags = 8;
|
||||
pub const FACE_BACK: FaceFlags = 16;
|
||||
pub const FACE_FRONT: FaceFlags = 32;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Block {
|
||||
pub block_type: BlockType,
|
||||
|
@ -116,9 +128,9 @@ impl Chunk {
|
|||
});
|
||||
}
|
||||
if chunk_y < 128 / CHUNK_SIZE as i32 {
|
||||
for y in 0..CHUNK_SIZE {
|
||||
if blocks[y][z][x].is_none() {
|
||||
blocks[y][z][x] = Some(Block {
|
||||
for layer in blocks.iter_mut() {
|
||||
if layer[z][x].is_none() {
|
||||
layer[z][x] = Some(Block {
|
||||
block_type: BlockType::Water,
|
||||
});
|
||||
}
|
||||
|
@ -133,25 +145,55 @@ impl Chunk {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_visible(&self, x: usize, y: usize, z: usize) -> bool {
|
||||
self.get_block(x - 1, y - 1, z - 1).is_some()
|
||||
&& self.get_block(x + 1, y - 1, z - 1).is_some()
|
||||
&& self.get_block(x - 1, y + 1, z - 1).is_some()
|
||||
&& self.get_block(x + 1, y + 1, z - 1).is_some()
|
||||
&& self.get_block(x - 1, y - 1, z + 1).is_some()
|
||||
&& self.get_block(x + 1, y - 1, z + 1).is_some()
|
||||
&& self.get_block(x - 1, y + 1, z + 1).is_some()
|
||||
&& self.get_block(x + 1, y + 1, z + 1).is_some()
|
||||
#[rustfmt::skip]
|
||||
fn check_visible_faces(&self, x: usize, y: usize, z: usize) -> FaceFlags {
|
||||
let mut visible_faces = FACE_NONE;
|
||||
let transparent = self.blocks[y][z][x].unwrap().block_type.is_transparent();
|
||||
|
||||
if x == 0 || self.blocks[y][z][x - 1].is_none()
|
||||
|| transparent != self.blocks[y][z][x - 1].unwrap().block_type.is_transparent()
|
||||
{
|
||||
visible_faces |= FACE_LEFT;
|
||||
}
|
||||
if x == CHUNK_SIZE - 1 || self.blocks[y][z][x + 1].is_none()
|
||||
|| transparent != self.blocks[y][z][x + 1].unwrap().block_type.is_transparent()
|
||||
{
|
||||
visible_faces |= FACE_RIGHT;
|
||||
}
|
||||
|
||||
if y == 0 || self.blocks[y - 1][z][x].is_none()
|
||||
|| transparent != self.blocks[y - 1][z][x].unwrap().block_type.is_transparent()
|
||||
{
|
||||
visible_faces |= FACE_BOTTOM;
|
||||
}
|
||||
if y == CHUNK_SIZE - 1 || self.blocks[y + 1][z][x].is_none()
|
||||
|| transparent != self.blocks[y + 1][z][x].unwrap().block_type.is_transparent()
|
||||
{
|
||||
visible_faces |= FACE_TOP;
|
||||
}
|
||||
|
||||
if z == 0 || self.blocks[y][z - 1][x].is_none()
|
||||
|| transparent != self.blocks[y][z - 1][x].unwrap().block_type.is_transparent()
|
||||
{
|
||||
visible_faces |= FACE_BACK;
|
||||
}
|
||||
if z == CHUNK_SIZE - 1 || self.blocks[y][z + 1][x].is_none()
|
||||
|| transparent != self.blocks[y][z + 1][x].unwrap().block_type.is_transparent()
|
||||
{
|
||||
visible_faces |= FACE_FRONT;
|
||||
}
|
||||
|
||||
visible_faces
|
||||
}
|
||||
|
||||
fn cull_layer(
|
||||
&self,
|
||||
y: usize,
|
||||
) -> (
|
||||
AHashMap<(usize, usize), BlockType>,
|
||||
AHashMap<(usize, usize), (BlockType, FaceFlags)>,
|
||||
VecDeque<(usize, usize)>,
|
||||
) {
|
||||
let mut output = AHashMap::new();
|
||||
let mut culled = AHashMap::new();
|
||||
let mut queue = VecDeque::new();
|
||||
|
||||
let y_blocks = &self.blocks[y];
|
||||
|
@ -159,26 +201,28 @@ impl Chunk {
|
|||
for (x, block) in z_blocks.iter().enumerate() {
|
||||
if let Some(block) = block {
|
||||
// Don't add the block if it's not visible
|
||||
if self.check_visible(x, y, z) {
|
||||
let visible_faces = self.check_visible_faces(x, y, z);
|
||||
if visible_faces == FACE_NONE {
|
||||
continue;
|
||||
}
|
||||
|
||||
output.insert((x, z), block.block_type);
|
||||
culled.insert((x, z), (block.block_type, visible_faces));
|
||||
queue.push_back((x, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(output, queue)
|
||||
(culled, queue)
|
||||
}
|
||||
|
||||
fn layer_to_quads(
|
||||
&self,
|
||||
y: usize,
|
||||
offset: Vector3<i32>,
|
||||
culled: AHashMap<(usize, usize), BlockType>,
|
||||
culled: AHashMap<(usize, usize), (BlockType, FaceFlags)>,
|
||||
queue: &mut VecDeque<(usize, usize)>,
|
||||
) -> Vec<(BlockType, i32, Vector3<i32>, Quad)> {
|
||||
let mut quads: Vec<(BlockType, i32, Vector3<i32>, Quad)> = Vec::new();
|
||||
) -> Vec<(BlockType, i32, Vector3<i32>, Quad, bool, FaceFlags)> {
|
||||
let mut quads: Vec<(BlockType, i32, Vector3<i32>, Quad, bool, FaceFlags)> = Vec::new();
|
||||
let mut visited = AHashSet::new();
|
||||
while let Some((x, z)) = queue.pop_front() {
|
||||
if visited.contains(&(x, z)) {
|
||||
|
@ -186,43 +230,73 @@ impl Chunk {
|
|||
}
|
||||
visited.insert((x, z));
|
||||
|
||||
if let Some(&block_type) = &culled.get(&(x, z)) {
|
||||
if block_type == BlockType::Water {
|
||||
if let Some(&(block_type, visible_faces)) = &culled.get(&(x, z)) {
|
||||
let mut quad_faces = visible_faces;
|
||||
|
||||
if self.highlighted == Some(Vector3::new(x, y, z)) {
|
||||
let quad = Quad::new(x as i32, z as i32, 1, 1);
|
||||
quads.push((block_type, y as i32, offset, quad));
|
||||
quads.push((block_type, y as i32, offset, quad, true, quad_faces));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Extend horizontally
|
||||
if block_type == BlockType::Water {
|
||||
let quad = Quad::new(x as i32, z as i32, 1, 1);
|
||||
quads.push((block_type, y as i32, offset, quad, false, quad_faces));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Extend along the X axis
|
||||
let mut xmax = x + 1;
|
||||
for x_ in x..CHUNK_SIZE {
|
||||
xmax = x_ + 1;
|
||||
if culled.get(&(x_ + 1, z)) != Some(&block_type)
|
||||
|| visited.contains(&(x_ + 1, z))
|
||||
|
||||
if visited.contains(&(xmax, z))
|
||||
|| self.highlighted == Some(Vector3::new(xmax, y, z))
|
||||
{
|
||||
break;
|
||||
}
|
||||
visited.insert((x_ + 1, z));
|
||||
|
||||
if let Some(&(block_type_, visible_faces_)) = culled.get(&(xmax, z)) {
|
||||
quad_faces |= visible_faces_;
|
||||
if block_type != block_type_ {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
visited.insert((xmax, z));
|
||||
}
|
||||
|
||||
// Extend vertically
|
||||
// Extend along the Z axis
|
||||
let mut zmax = z + 1;
|
||||
'z: for z_ in z..CHUNK_SIZE {
|
||||
zmax = z_ + 1;
|
||||
|
||||
for x_ in x..xmax {
|
||||
if culled.get(&(x_, z_ + 1)) != Some(&block_type)
|
||||
|| visited.contains(&(x_, z_ + 1))
|
||||
if visited.contains(&(x_, zmax))
|
||||
|| self.highlighted == Some(Vector3::new(x_, y, zmax))
|
||||
{
|
||||
break 'z;
|
||||
}
|
||||
|
||||
if let Some(&(block_type_, visible_faces_)) = culled.get(&(x_, zmax)) {
|
||||
quad_faces |= visible_faces_;
|
||||
if block_type != block_type_ {
|
||||
break 'z;
|
||||
}
|
||||
} else {
|
||||
break 'z;
|
||||
}
|
||||
}
|
||||
|
||||
for x_ in x..xmax {
|
||||
visited.insert((x_, z_ + 1));
|
||||
visited.insert((x_, zmax));
|
||||
}
|
||||
}
|
||||
|
||||
let quad = Quad::new(x as i32, z as i32, (xmax - x) as i32, (zmax - z) as i32);
|
||||
quads.push((block_type, y as i32, offset, quad));
|
||||
quads.push((block_type, y as i32, offset, quad, false, quad_faces));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,28 +304,37 @@ impl Chunk {
|
|||
}
|
||||
|
||||
fn quads_to_geometry(
|
||||
quads: Vec<(BlockType, i32, Vector3<i32>, Quad)>,
|
||||
quads: Vec<(BlockType, i32, Vector3<i32>, Quad, bool, FaceFlags)>,
|
||||
) -> (Vec<Vertex>, Vec<u16>) {
|
||||
let mut vertices = Vec::new();
|
||||
let mut indices = Vec::new();
|
||||
for (quad_index, (block_type, y, offset, quad)) in quads.iter().enumerate() {
|
||||
for (block_type, y, offset, quad, highlighted, visible_faces) in quads {
|
||||
let texture_indices = block_type.texture_indices();
|
||||
vertices.extend(&cube::vertices(quad, *y, 1.0, *offset, texture_indices));
|
||||
|
||||
for index in cube::INDICES {
|
||||
indices.push(index + quad_index as u16 * 24);
|
||||
}
|
||||
let (quad_vertices, quad_indices) = &cube::vertices(
|
||||
&quad,
|
||||
y,
|
||||
1.0,
|
||||
offset,
|
||||
texture_indices,
|
||||
highlighted,
|
||||
visible_faces,
|
||||
vertices.len().try_into().unwrap(),
|
||||
);
|
||||
|
||||
vertices.extend(quad_vertices);
|
||||
indices.extend(quad_indices);
|
||||
}
|
||||
|
||||
(vertices, indices)
|
||||
}
|
||||
|
||||
pub fn to_geometry(&self, offset: Vector3<i32>) -> (Vec<Vertex>, Vec<u16>) {
|
||||
let mut quads: Vec<(BlockType, i32, Vector3<i32>, Quad)> = Vec::new();
|
||||
let mut quads: Vec<(BlockType, i32, Vector3<i32>, Quad, bool, FaceFlags)> = Vec::new();
|
||||
|
||||
for y in 0..CHUNK_SIZE {
|
||||
let (culled, mut queue) = self.cull_layer(y);
|
||||
let mut layer_quads = Self::layer_to_quads(y, offset, culled, &mut queue);
|
||||
let mut layer_quads = self.layer_to_quads(y, offset, culled, &mut queue);
|
||||
quads.append(&mut layer_quads);
|
||||
}
|
||||
|
||||
|
|
157
src/cube.rs
157
src/cube.rs
|
@ -1,15 +1,23 @@
|
|||
use cgmath::Vector3;
|
||||
|
||||
use crate::{quad::Quad, vertex::Vertex};
|
||||
use crate::{
|
||||
chunk::{FaceFlags, FACE_BACK, FACE_BOTTOM, FACE_FRONT, FACE_LEFT, FACE_RIGHT, FACE_TOP},
|
||||
quad::Quad,
|
||||
vertex::Vertex,
|
||||
};
|
||||
|
||||
#[allow(clippy::many_single_char_names)]
|
||||
#[rustfmt::skip]
|
||||
pub fn vertices(
|
||||
quad: &Quad,
|
||||
y: i32,
|
||||
z_height: f32,
|
||||
offset: Vector3<i32>,
|
||||
texture_indices: (usize, usize, usize, usize, usize, usize),
|
||||
) -> [Vertex; 24] {
|
||||
highlighted: bool,
|
||||
visible_faces: FaceFlags,
|
||||
start_index: u16,
|
||||
) -> (Vec<Vertex>, Vec<u16>) {
|
||||
let w = quad.w as f32;
|
||||
let h = quad.h as f32;
|
||||
let zh = z_height;
|
||||
|
@ -19,65 +27,100 @@ pub fn vertices(
|
|||
let z = (quad.y + offset.z) as f32;
|
||||
|
||||
let t = texture_indices;
|
||||
let highlighted = highlighted as i32;
|
||||
|
||||
#[rustfmt::skip]
|
||||
let vertices = [
|
||||
// Left
|
||||
Vertex { position: [x, y, z ], texture_coordinates: [h, 1.0, t.0 as f32], normal: [-1.0, 0.0, 0.0] },
|
||||
Vertex { position: [x, y, z + h ], texture_coordinates: [0.0, 1.0, t.0 as f32], normal: [-1.0, 0.0, 0.0] },
|
||||
Vertex { position: [x, y + zh, z + h ], texture_coordinates: [0.0, 0.0, t.0 as f32], normal: [-1.0, 0.0, 0.0] },
|
||||
Vertex { position: [x, y + zh, z ], texture_coordinates: [h, 0.0, t.0 as f32], normal: [-1.0, 0.0, 0.0] },
|
||||
let mut current_index = start_index;
|
||||
let mut vertices = Vec::new();
|
||||
let mut indices = Vec::new();
|
||||
|
||||
// Right
|
||||
Vertex { position: [x + w, y, z ], texture_coordinates: [0.0, 1.0, t.1 as f32], normal: [1.0, 0.0, 0.0] },
|
||||
Vertex { position: [x + w, y, z + h ], texture_coordinates: [h, 1.0, t.1 as f32], normal: [1.0, 0.0, 0.0] },
|
||||
Vertex { position: [x + w, y + zh, z + h ], texture_coordinates: [h, 0.0, t.1 as f32], normal: [1.0, 0.0, 0.0] },
|
||||
Vertex { position: [x + w, y + zh, z ], texture_coordinates: [0.0, 0.0, t.1 as f32], normal: [1.0, 0.0, 0.0] },
|
||||
if visible_faces & FACE_LEFT == FACE_LEFT {
|
||||
let normal = [-1.0, 0.0, 0.0];
|
||||
vertices.extend(&[
|
||||
Vertex { position: [x, y, z ], texture_coordinates: [h, 1.0, t.0 as f32], normal, highlighted },
|
||||
Vertex { position: [x, y, z + h], texture_coordinates: [0.0, 1.0, t.0 as f32], normal, highlighted },
|
||||
Vertex { position: [x, y + zh, z + h], texture_coordinates: [0.0, 0.0, t.0 as f32], normal, highlighted },
|
||||
Vertex { position: [x, y + zh, z ], texture_coordinates: [h, 0.0, t.0 as f32], normal, highlighted },
|
||||
]);
|
||||
indices.extend(&[
|
||||
2 + current_index, current_index, 1 + current_index,
|
||||
3 + current_index, current_index, 2 + current_index,
|
||||
]);
|
||||
current_index += 4;
|
||||
}
|
||||
|
||||
// Back
|
||||
Vertex { position: [x, y, z ], texture_coordinates: [w, 1.0, t.2 as f32], normal: [0.0, 0.0, -1.0] },
|
||||
Vertex { position: [x, y + zh, z ], texture_coordinates: [w, 0.0, t.2 as f32], normal: [0.0, 0.0, -1.0] },
|
||||
Vertex { position: [x + w, y + zh, z ], texture_coordinates: [0.0, 0.0, t.2 as f32], normal: [0.0, 0.0, -1.0] },
|
||||
Vertex { position: [x + w, y, z ], texture_coordinates: [0.0, 1.0, t.2 as f32], normal: [0.0, 0.0, -1.0] },
|
||||
if visible_faces & FACE_RIGHT == FACE_RIGHT {
|
||||
let normal = [1.0, 0.0, 0.0];
|
||||
vertices.extend(&[
|
||||
Vertex { position: [x + w, y, z ], texture_coordinates: [0.0, 1.0, t.1 as f32], normal, highlighted },
|
||||
Vertex { position: [x + w, y, z + h], texture_coordinates: [h, 1.0, t.1 as f32], normal, highlighted },
|
||||
Vertex { position: [x + w, y + zh, z + h], texture_coordinates: [h, 0.0, t.1 as f32], normal, highlighted },
|
||||
Vertex { position: [x + w, y + zh, z ], texture_coordinates: [0.0, 0.0, t.1 as f32], normal, highlighted },
|
||||
]);
|
||||
indices.extend(&[
|
||||
1 + current_index, current_index, 2 + current_index,
|
||||
2 + current_index, current_index, 3 + current_index,
|
||||
]);
|
||||
current_index += 4;
|
||||
}
|
||||
|
||||
// Front
|
||||
Vertex { position: [x, y, z + h ], texture_coordinates: [0.0, 1.0, t.3 as f32], normal: [0.0, 0.0, 1.0] },
|
||||
Vertex { position: [x, y + zh, z + h ], texture_coordinates: [0.0, 0.0, t.3 as f32], normal: [0.0, 0.0, 1.0] },
|
||||
Vertex { position: [x + w, y + zh, z + h ], texture_coordinates: [w, 0.0, t.3 as f32], normal: [0.0, 0.0, 1.0] },
|
||||
Vertex { position: [x + w, y, z + h ], texture_coordinates: [w, 1.0, t.3 as f32], normal: [0.0, 0.0, 1.0] },
|
||||
if visible_faces & FACE_BACK == FACE_BACK {
|
||||
let normal = [0.0, 0.0, -1.0];
|
||||
vertices.extend(&[
|
||||
Vertex { position: [x, y, z], texture_coordinates: [w, 1.0, t.2 as f32], normal, highlighted },
|
||||
Vertex { position: [x, y + zh, z], texture_coordinates: [w, 0.0, t.2 as f32], normal, highlighted },
|
||||
Vertex { position: [x + w, y + zh, z], texture_coordinates: [0.0, 0.0, t.2 as f32], normal, highlighted },
|
||||
Vertex { position: [x + w, y, z], texture_coordinates: [0.0, 1.0, t.2 as f32], normal, highlighted },
|
||||
]);
|
||||
indices.extend(&[
|
||||
2 + current_index, current_index, 1 + current_index,
|
||||
3 + current_index, current_index, 2 + current_index,
|
||||
]);
|
||||
current_index += 4;
|
||||
}
|
||||
|
||||
// Bottom
|
||||
Vertex { position: [x, y, z + 0.0], texture_coordinates: [w, 0.0, t.4 as f32], normal: [0.0, -1.0, 0.0] },
|
||||
Vertex { position: [x, y, z + h ], texture_coordinates: [w, h, t.4 as f32], normal: [0.0, -1.0, 0.0] },
|
||||
Vertex { position: [x + w, y, z + h ], texture_coordinates: [0.0, h, t.4 as f32], normal: [0.0, -1.0, 0.0] },
|
||||
Vertex { position: [x + w, y, z ], texture_coordinates: [0.0, 0.0, t.4 as f32], normal: [0.0, -1.0, 0.0] },
|
||||
if visible_faces & FACE_FRONT == FACE_FRONT {
|
||||
let normal = [0.0, 0.0, 1.0];
|
||||
vertices.extend(&[
|
||||
Vertex { position: [x, y, z + h], texture_coordinates: [0.0, 1.0, t.3 as f32], normal, highlighted },
|
||||
Vertex { position: [x, y + zh, z + h], texture_coordinates: [0.0, 0.0, t.3 as f32], normal, highlighted },
|
||||
Vertex { position: [x + w, y + zh, z + h], texture_coordinates: [w, 0.0, t.3 as f32], normal, highlighted },
|
||||
Vertex { position: [x + w, y, z + h], texture_coordinates: [w, 1.0, t.3 as f32], normal, highlighted },
|
||||
]);
|
||||
indices.extend(&[
|
||||
1 + current_index, current_index, 2 + current_index,
|
||||
2 + current_index, current_index, 3 + current_index,
|
||||
]);
|
||||
current_index += 4;
|
||||
}
|
||||
|
||||
// Top
|
||||
Vertex { position: [x, y + zh, z ], texture_coordinates: [0.0, 0.0, t.5 as f32], normal: [0.0, 1.0, 0.0] },
|
||||
Vertex { position: [x, y + zh, z + h ], texture_coordinates: [0.0, h, t.5 as f32], normal: [0.0, 1.0, 0.0] },
|
||||
Vertex { position: [x + w, y + zh, z + h ], texture_coordinates: [w, h, t.5 as f32], normal: [0.0, 1.0, 0.0] },
|
||||
Vertex { position: [x + w, y + zh, z ], texture_coordinates: [w, 0.0, t.5 as f32], normal: [0.0, 1.0, 0.0] },
|
||||
];
|
||||
vertices
|
||||
if visible_faces & FACE_BOTTOM == FACE_BOTTOM {
|
||||
let normal = [0.0, -1.0, 0.0];
|
||||
vertices.extend(&[
|
||||
Vertex { position: [x, y, z ], texture_coordinates: [w, 0.0, t.4 as f32], normal, highlighted },
|
||||
Vertex { position: [x, y, z + h], texture_coordinates: [w, h, t.4 as f32], normal, highlighted },
|
||||
Vertex { position: [x + w, y, z + h], texture_coordinates: [0.0, h, t.4 as f32], normal, highlighted },
|
||||
Vertex { position: [x + w, y, z ], texture_coordinates: [0.0, 0.0, t.4 as f32], normal, highlighted },
|
||||
]);
|
||||
indices.extend(&[
|
||||
current_index, 2 + current_index, 1 + current_index,
|
||||
current_index, 3 + current_index, 2 + current_index,
|
||||
]);
|
||||
current_index += 4;
|
||||
}
|
||||
|
||||
if visible_faces & FACE_TOP == FACE_TOP {
|
||||
let normal = [0.0, 1.0, 0.0];
|
||||
vertices.extend(&[
|
||||
Vertex { position: [x, y + zh, z ], texture_coordinates: [0.0, 0.0, t.5 as f32], normal, highlighted },
|
||||
Vertex { position: [x, y + zh, z + h], texture_coordinates: [0.0, h, t.5 as f32], normal, highlighted },
|
||||
Vertex { position: [x + w, y + zh, z + h], texture_coordinates: [w, h, t.5 as f32], normal, highlighted },
|
||||
Vertex { position: [x + w, y + zh, z ], texture_coordinates: [w, 0.0, t.5 as f32], normal, highlighted },
|
||||
]);
|
||||
indices.extend(&[
|
||||
current_index, 1 + current_index, 2 + current_index,
|
||||
current_index, 2 + current_index, 3 + current_index,
|
||||
]);
|
||||
}
|
||||
|
||||
(vertices, indices)
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub const INDICES: &[u16] = &[
|
||||
2, 0, 1,
|
||||
3, 0, 2,
|
||||
|
||||
5, 4, 6,
|
||||
6, 4, 7,
|
||||
|
||||
10, 8, 9,
|
||||
11, 8, 10,
|
||||
|
||||
13, 12, 14,
|
||||
14, 12, 15,
|
||||
|
||||
16, 18, 17,
|
||||
16, 19, 18,
|
||||
|
||||
20, 21, 22,
|
||||
20, 22, 23,
|
||||
];
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
mod camera;
|
||||
mod chunk;
|
||||
mod cube;
|
||||
mod time;
|
||||
mod quad;
|
||||
mod state;
|
||||
mod texture;
|
||||
mod time;
|
||||
mod uniforms;
|
||||
mod vertex;
|
||||
mod world;
|
||||
|
@ -100,8 +100,8 @@ fn main() {
|
|||
let fps_min = 1_000_000 / frametime_max.as_micros();
|
||||
|
||||
println!(
|
||||
"{} frames | frametime avg={:?} min={:?} max={:?} | fps avg={} min={} max={} | {} tris",
|
||||
frames, frametime, frametime_min, frametime_max, fps, fps_min, fps_max, triangle_count,
|
||||
"{:>4} frames | frametime avg={:>5.2}ms min={:>5.2}ms max={:>5.2}ms | fps avg={:>4} min={:>4} max={:>4} | {:>8} tris",
|
||||
frames, frametime.as_secs_f32() * 1000.0, frametime_min.as_secs_f32() * 1000.0, frametime_max.as_secs_f32() * 1000.0, fps, fps_min, fps_max, triangle_count,
|
||||
);
|
||||
|
||||
elapsed = Duration::from_secs(0);
|
||||
|
|
|
@ -19,6 +19,7 @@ struct VertexInput {
|
|||
[[location(0)]] position: vec3<f32>;
|
||||
[[location(1)]] texture_coordinates: vec3<f32>;
|
||||
[[location(2)]] normal: vec3<f32>;
|
||||
[[location(3)]] highlighted: i32;
|
||||
};
|
||||
|
||||
struct VertexOutput {
|
||||
|
@ -26,6 +27,7 @@ struct VertexOutput {
|
|||
[[location(0)]] texture_coordinates: vec3<f32>;
|
||||
[[location(1)]] world_normal: vec3<f32>;
|
||||
[[location(2)]] world_position: vec3<f32>;
|
||||
[[location(3)]] highlighted: i32;
|
||||
};
|
||||
|
||||
[[stage(vertex)]]
|
||||
|
@ -44,6 +46,7 @@ fn main(model: VertexInput) -> VertexOutput {
|
|||
}
|
||||
|
||||
out.clip_position = uniforms.view_projection * vec4<f32>(out.world_position, 1.0);
|
||||
out.highlighted = model.highlighted;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@ -59,7 +62,7 @@ fn main(in: VertexOutput) -> [[location(0)]] vec4<f32> {
|
|||
i32(in.texture_coordinates.z)
|
||||
);
|
||||
|
||||
let light_position = vec3<f32>(256.0, 500.0, 200.0);
|
||||
let light_position = vec3<f32>(-100.0, 500.0, -200.0);
|
||||
let light_color = vec3<f32>(1.0, 1.0, 1.0);
|
||||
|
||||
let ambient_strength = 0.1;
|
||||
|
@ -76,6 +79,9 @@ fn main(in: VertexOutput) -> [[location(0)]] vec4<f32> {
|
|||
let specular_color = specular_strength * light_color;
|
||||
|
||||
var result: vec3<f32> = (ambient_color + diffuse_color + specular_color) * object_color.xyz;
|
||||
if (in.highlighted != 0) {
|
||||
result = result + 0.3;
|
||||
}
|
||||
|
||||
return vec4<f32>(result, object_color.a);
|
||||
}
|
||||
|
|
|
@ -203,42 +203,50 @@ pub const CROSSHAIR_VERTICES: &[Vertex] = &[
|
|||
position: [-UI_SCALE_X * 8.0, UI_SCALE_Y * 8.0, 0.0],
|
||||
texture_coordinates: [240.0 / 256.0, 0.0 / 256.0, 0.0],
|
||||
normal: [0.0, 0.0, 0.0],
|
||||
highlighted: 0,
|
||||
},
|
||||
Vertex {
|
||||
position: [UI_SCALE_X * 8.0, UI_SCALE_Y * 8.0, 0.0],
|
||||
texture_coordinates: [1.0, 0.0 / 256.0, 0.0],
|
||||
normal: [0.0, 0.0, 0.0],
|
||||
highlighted: 0,
|
||||
},
|
||||
Vertex {
|
||||
position: [UI_SCALE_X * 8.0, -UI_SCALE_Y * 8.0, 0.0],
|
||||
texture_coordinates: [1.0, 16.0 / 256.0, 0.0],
|
||||
normal: [0.0, 0.0, 0.0],
|
||||
highlighted: 0,
|
||||
},
|
||||
Vertex {
|
||||
position: [-UI_SCALE_X * 8.0, -UI_SCALE_Y * 8.0, 0.0],
|
||||
texture_coordinates: [240.0 / 256.0, 16.0 / 256.0, 0.0],
|
||||
normal: [0.0, 0.0, 0.0],
|
||||
highlighted: 0,
|
||||
},
|
||||
// Hotbar
|
||||
Vertex {
|
||||
position: [-UI_SCALE_X * 91.0, -1.0 + UI_SCALE_Y * 22.0, 0.0],
|
||||
texture_coordinates: [0.0 / 256.0, 0.0 / 256.0, 0.0],
|
||||
normal: [0.0, 0.0, 0.0],
|
||||
highlighted: 0,
|
||||
},
|
||||
Vertex {
|
||||
position: [UI_SCALE_X * 91.0, -1.0 + UI_SCALE_Y * 22.0, 0.0],
|
||||
texture_coordinates: [182.0 / 256.0, 0.0 / 256.0, 0.0],
|
||||
normal: [0.0, 0.0, 0.0],
|
||||
highlighted: 0,
|
||||
},
|
||||
Vertex {
|
||||
position: [UI_SCALE_X * 91.0, -1.0, 0.0],
|
||||
texture_coordinates: [182.0 / 256.0, 22.0 / 256.0, 0.0],
|
||||
normal: [0.0, 0.0, 0.0],
|
||||
highlighted: 0,
|
||||
},
|
||||
Vertex {
|
||||
position: [-UI_SCALE_X * 91.0, -1.0, 0.0],
|
||||
texture_coordinates: [0.0 / 256.0, 22.0 / 256.0, 0.0],
|
||||
normal: [0.0, 0.0, 0.0],
|
||||
highlighted: 0,
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ mod world;
|
|||
|
||||
use std::time::Duration;
|
||||
|
||||
use cgmath::{InnerSpace, Rad, Vector3};
|
||||
use cgmath::{EuclideanSpace, InnerSpace, Rad, Vector3, Zero};
|
||||
use winit::{
|
||||
event::{DeviceEvent, ElementState, KeyboardInput, VirtualKeyCode},
|
||||
window::Window,
|
||||
|
@ -12,6 +12,8 @@ use winit::{
|
|||
use hud::HudState;
|
||||
use world::WorldState;
|
||||
|
||||
use crate::chunk::{Block, BlockType};
|
||||
|
||||
pub struct State {
|
||||
pub window_size: winit::dpi::PhysicalSize<u32>,
|
||||
render_surface: wgpu::Surface,
|
||||
|
@ -141,6 +143,9 @@ impl State {
|
|||
VirtualKeyCode::D => self.right_speed += amount,
|
||||
VirtualKeyCode::LControl => self.up_speed -= amount,
|
||||
VirtualKeyCode::Space => self.up_speed += amount,
|
||||
VirtualKeyCode::F1 if state == &ElementState::Pressed => self
|
||||
.world_state
|
||||
.toggle_wireframe(&self.render_device, &self.swap_chain_descriptor),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
@ -158,15 +163,19 @@ impl State {
|
|||
}
|
||||
|
||||
fn update_aim(&mut self) {
|
||||
// let camera = &self.world_state.camera;
|
||||
// let chunk = &mut self.world_state.chunk;
|
||||
// let position = chunk
|
||||
// .raycast(camera.position.to_vec(), camera.direction())
|
||||
// .map(|(position, _)| position);
|
||||
// if position != chunk.highlighted {
|
||||
// chunk.highlighted = position;
|
||||
// self.world_state.update_chunk(&self.render_queue);
|
||||
// }
|
||||
let camera = &self.world_state.camera;
|
||||
let chunk = &mut self.world_state.world.chunks[0][0][0];
|
||||
|
||||
let position = chunk
|
||||
.raycast(camera.position.to_vec(), camera.direction())
|
||||
.map(|(position, _)| position);
|
||||
|
||||
if position != chunk.highlighted {
|
||||
chunk.highlighted = position;
|
||||
println!("aiming at {:?}", position);
|
||||
self.world_state
|
||||
.update_chunk_geometry(&self.render_device, Vector3::zero());
|
||||
}
|
||||
}
|
||||
|
||||
fn input_mouse(&mut self, dx: f64, dy: f64) {
|
||||
|
@ -183,32 +192,34 @@ impl State {
|
|||
..
|
||||
}) => self.input_keyboard(key, state),
|
||||
|
||||
// DeviceEvent::Button {
|
||||
// button,
|
||||
// state: ElementState::Pressed,
|
||||
// } if self.mouse_grabbed => {
|
||||
// let camera = &self.world_state.camera;
|
||||
DeviceEvent::Button {
|
||||
button,
|
||||
state: ElementState::Pressed,
|
||||
} if self.mouse_grabbed => {
|
||||
let camera = &self.world_state.camera;
|
||||
let chunk = &mut self.world_state.world.chunks[0][0][0];
|
||||
|
||||
// // if let Some((pos, axis)) = self
|
||||
// // .world_state
|
||||
// // .chunk
|
||||
// // .raycast(camera.position.to_vec(), camera.direction())
|
||||
// // {
|
||||
// // if *button == 1 {
|
||||
// // self.world_state.chunk.blocks[pos.y][pos.z][pos.x].take();
|
||||
// // dbg!(&pos);
|
||||
// // self.world_state.update_chunk(&self.render_queue);
|
||||
// // } else if *button == 3 {
|
||||
// // let new_pos = pos.map(|x| x as i32) - axis;
|
||||
// // dbg!(&axis, &new_pos);
|
||||
// // self.world_state.chunk.blocks[new_pos.y as usize][new_pos.z as usize]
|
||||
// // [new_pos.x as usize] = Some(Block {
|
||||
// // block_type: BlockType::Cobblestone,
|
||||
// // });
|
||||
// // self.world_state.update_chunk(&self.render_queue);
|
||||
// // }
|
||||
// // }
|
||||
// }
|
||||
if let Some((pos, axis)) =
|
||||
chunk.raycast(camera.position.to_vec(), camera.direction())
|
||||
{
|
||||
if *button == 1 {
|
||||
chunk.blocks[pos.y][pos.z][pos.x].take();
|
||||
dbg!(&pos);
|
||||
self.world_state
|
||||
.update_chunk_geometry(&self.render_device, Vector3::zero());
|
||||
} else if *button == 3 {
|
||||
let new_pos = pos.map(|x| x as i32) - axis;
|
||||
dbg!(&axis, &new_pos);
|
||||
chunk.blocks[new_pos.y as usize][new_pos.z as usize][new_pos.x as usize] =
|
||||
Some(Block {
|
||||
block_type: BlockType::Cobblestone,
|
||||
});
|
||||
|
||||
self.world_state
|
||||
.update_chunk_geometry(&self.render_device, Vector3::zero());
|
||||
}
|
||||
}
|
||||
}
|
||||
DeviceEvent::MouseMotion { delta: (dx, dy) } => self.input_mouse(*dx, *dy),
|
||||
_ => (),
|
||||
}
|
||||
|
@ -220,13 +231,13 @@ impl State {
|
|||
let (yaw_sin, yaw_cos) = self.world_state.camera.yaw.0.sin_cos();
|
||||
|
||||
let forward = Vector3::new(yaw_cos, 0.0, yaw_sin).normalize();
|
||||
self.world_state.camera.position += forward * self.forward_speed * 15.0 * dt_secs;
|
||||
self.world_state.camera.position += forward * self.forward_speed * 30.0 * dt_secs;
|
||||
|
||||
let right = Vector3::new(-yaw_sin, 0.0, yaw_cos).normalize();
|
||||
self.world_state.camera.position += right * self.right_speed * 15.0 * dt_secs;
|
||||
self.world_state.camera.position += right * self.right_speed * 30.0 * dt_secs;
|
||||
|
||||
let up = Vector3::new(0.0, 1.0, 0.0).normalize();
|
||||
self.world_state.camera.position += up * self.up_speed * 15.0 * dt_secs;
|
||||
self.world_state.camera.position += up * self.up_speed * 30.0 * dt_secs;
|
||||
|
||||
self.world_state.update(dt, &self.render_queue);
|
||||
|
||||
|
@ -285,7 +296,9 @@ impl State {
|
|||
render_pass.set_bind_group(1, &self.world_state.uniform_bind_group, &[]);
|
||||
render_pass.set_bind_group(2, &self.world_state.time_bind_group, &[]);
|
||||
|
||||
for (chunk_vertices, chunk_indices, index_count) in &self.world_state.chunk_buffers {
|
||||
for (chunk_vertices, chunk_indices, index_count) in
|
||||
self.world_state.chunk_buffers.values()
|
||||
{
|
||||
render_pass.set_vertex_buffer(0, chunk_vertices.slice(..));
|
||||
render_pass.set_index_buffer(chunk_indices.slice(..), wgpu::IndexFormat::Uint16);
|
||||
render_pass.draw_indexed(0..*index_count as u32, 0, 0..1);
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
use std::time::{Duration, Instant};
|
||||
|
||||
use ahash::AHashMap;
|
||||
use cgmath::Vector3;
|
||||
use wgpu::util::{BufferInitDescriptor, DeviceExt};
|
||||
use winit::dpi::PhysicalSize;
|
||||
|
||||
use crate::{
|
||||
camera::{Camera, Projection},
|
||||
chunk::CHUNK_SIZE,
|
||||
texture::{Texture, TextureManager},
|
||||
time::Time,
|
||||
uniforms::Uniforms,
|
||||
|
@ -24,9 +27,12 @@ pub struct WorldState {
|
|||
pub time_bind_group: wgpu::BindGroup,
|
||||
pub world: World,
|
||||
|
||||
pub chunk_buffers: Vec<(wgpu::Buffer, wgpu::Buffer, usize)>,
|
||||
pub chunk_buffers: AHashMap<Vector3<usize>, (wgpu::Buffer, wgpu::Buffer, usize)>,
|
||||
time: Time,
|
||||
time_buffer: wgpu::Buffer,
|
||||
wireframe: bool,
|
||||
shader: wgpu::ShaderModule,
|
||||
render_pipeline_layout: wgpu::PipelineLayout,
|
||||
}
|
||||
|
||||
impl WorldState {
|
||||
|
@ -148,28 +154,13 @@ impl WorldState {
|
|||
fn create_render_pipeline(
|
||||
render_device: &wgpu::Device,
|
||||
swap_chain_descriptor: &wgpu::SwapChainDescriptor,
|
||||
bind_group_layouts: &[&wgpu::BindGroupLayout],
|
||||
shader: &wgpu::ShaderModule,
|
||||
pipeline_layout: &wgpu::PipelineLayout,
|
||||
wireframe: bool,
|
||||
) -> wgpu::RenderPipeline {
|
||||
let shader = render_device.create_shader_module(
|
||||
&(wgpu::ShaderModuleDescriptor {
|
||||
label: Some("shader"),
|
||||
flags: wgpu::ShaderFlags::all(),
|
||||
source: wgpu::ShaderSource::Wgsl(include_str!("../shaders/world.wgsl").into()),
|
||||
}),
|
||||
);
|
||||
|
||||
let render_pipeline_layout =
|
||||
render_device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("render_pipeline_layout"),
|
||||
bind_group_layouts,
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
let wireframe = false;
|
||||
|
||||
render_device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: Some("Render Pipeline"),
|
||||
layout: Some(&render_pipeline_layout),
|
||||
layout: Some(&pipeline_layout),
|
||||
vertex: wgpu::VertexState {
|
||||
module: &shader,
|
||||
entry_point: "main",
|
||||
|
@ -207,31 +198,76 @@ impl WorldState {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn update_chunk(&mut self, render_device: &wgpu::Device) {
|
||||
pub fn update_world_geometry(&mut self, render_device: &wgpu::Device) {
|
||||
let instant = Instant::now();
|
||||
|
||||
let world_geometry = self.world.to_geometry();
|
||||
self.chunk_buffers.clear();
|
||||
for (chunk_vertices, chunk_indices) in world_geometry {
|
||||
self.chunk_buffers.push((
|
||||
render_device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: &bytemuck::cast_slice(&chunk_vertices),
|
||||
usage: wgpu::BufferUsage::VERTEX,
|
||||
}),
|
||||
render_device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: &bytemuck::cast_slice(&chunk_indices),
|
||||
usage: wgpu::BufferUsage::INDEX,
|
||||
}),
|
||||
chunk_indices.len(),
|
||||
));
|
||||
for (chunk_position, chunk_vertices, chunk_indices) in world_geometry {
|
||||
self.chunk_buffers.insert(
|
||||
chunk_position,
|
||||
(
|
||||
render_device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: &bytemuck::cast_slice(&chunk_vertices),
|
||||
usage: wgpu::BufferUsage::VERTEX,
|
||||
}),
|
||||
render_device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: &bytemuck::cast_slice(&chunk_indices),
|
||||
usage: wgpu::BufferUsage::INDEX,
|
||||
}),
|
||||
chunk_indices.len(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
let elapsed = instant.elapsed();
|
||||
println!("World update took {:?}", elapsed);
|
||||
}
|
||||
|
||||
pub fn update_chunk_geometry(
|
||||
&mut self,
|
||||
render_device: &wgpu::Device,
|
||||
chunk_position: Vector3<usize>,
|
||||
) {
|
||||
let chunk = &mut self.world.chunks[chunk_position.y][chunk_position.z][chunk_position.x];
|
||||
let offset = chunk_position.map(|f| (f * CHUNK_SIZE) as i32);
|
||||
let (vertices, indices) = chunk.to_geometry(offset);
|
||||
|
||||
self.chunk_buffers.insert(
|
||||
chunk_position,
|
||||
(
|
||||
render_device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: &bytemuck::cast_slice(&vertices),
|
||||
usage: wgpu::BufferUsage::VERTEX,
|
||||
}),
|
||||
render_device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: &bytemuck::cast_slice(&indices),
|
||||
usage: wgpu::BufferUsage::INDEX,
|
||||
}),
|
||||
indices.len(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn toggle_wireframe(
|
||||
&mut self,
|
||||
render_device: &wgpu::Device,
|
||||
swap_chain_descriptor: &wgpu::SwapChainDescriptor,
|
||||
) {
|
||||
self.wireframe = !self.wireframe;
|
||||
self.render_pipeline = Self::create_render_pipeline(
|
||||
render_device,
|
||||
swap_chain_descriptor,
|
||||
&self.shader,
|
||||
&self.render_pipeline_layout,
|
||||
self.wireframe,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
render_device: &wgpu::Device,
|
||||
render_queue: &wgpu::Queue,
|
||||
|
@ -248,14 +284,31 @@ impl WorldState {
|
|||
|
||||
let (time, time_buffer, time_layout, time_bind_group) = Self::create_time(&render_device);
|
||||
|
||||
let shader = render_device.create_shader_module(
|
||||
&(wgpu::ShaderModuleDescriptor {
|
||||
label: Some("shader"),
|
||||
flags: wgpu::ShaderFlags::all(),
|
||||
source: wgpu::ShaderSource::Wgsl(include_str!("../shaders/world.wgsl").into()),
|
||||
}),
|
||||
);
|
||||
|
||||
let render_pipeline_layout =
|
||||
render_device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("render_pipeline_layout"),
|
||||
push_constant_ranges: &[],
|
||||
bind_group_layouts: &[
|
||||
&texture_manager.bind_group_layout,
|
||||
&world_uniform_layout,
|
||||
&time_layout,
|
||||
],
|
||||
});
|
||||
|
||||
let render_pipeline = Self::create_render_pipeline(
|
||||
&render_device,
|
||||
&swap_chain_descriptor,
|
||||
&[
|
||||
&texture_manager.bind_group_layout,
|
||||
&world_uniform_layout,
|
||||
&time_layout,
|
||||
],
|
||||
&shader,
|
||||
&render_pipeline_layout,
|
||||
false,
|
||||
);
|
||||
|
||||
let depth_texture =
|
||||
|
@ -270,16 +323,19 @@ impl WorldState {
|
|||
camera,
|
||||
projection,
|
||||
depth_texture,
|
||||
shader,
|
||||
render_pipeline_layout,
|
||||
|
||||
time,
|
||||
time_buffer,
|
||||
time_bind_group,
|
||||
|
||||
world,
|
||||
chunk_buffers: Vec::new(),
|
||||
chunk_buffers: AHashMap::new(),
|
||||
wireframe: false,
|
||||
};
|
||||
|
||||
world_state.update_chunk(render_device);
|
||||
world_state.update_world_geometry(render_device);
|
||||
|
||||
world_state
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ pub struct Vertex {
|
|||
pub position: [f32; 3],
|
||||
pub texture_coordinates: [f32; 3],
|
||||
pub normal: [f32; 3],
|
||||
pub highlighted: i32,
|
||||
}
|
||||
|
||||
impl Vertex {
|
||||
|
@ -29,6 +30,11 @@ impl Vertex {
|
|||
shader_location: 2,
|
||||
format: wgpu::VertexFormat::Float32x3,
|
||||
},
|
||||
wgpu::VertexAttribute {
|
||||
offset: 36,
|
||||
shader_location: 3,
|
||||
format: wgpu::VertexFormat::Sint32,
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::{chunk::Chunk, vertex::Vertex};
|
|||
use cgmath::Vector3;
|
||||
|
||||
pub struct World {
|
||||
chunks: Vec<Vec<Vec<Chunk>>>,
|
||||
pub chunks: Vec<Vec<Vec<Chunk>>>,
|
||||
}
|
||||
|
||||
const WORLD_SIZE: usize = 16;
|
||||
|
@ -26,7 +26,7 @@ impl World {
|
|||
Self { chunks }
|
||||
}
|
||||
|
||||
pub fn to_geometry(&self) -> Vec<(Vec<Vertex>, Vec<u16>)> {
|
||||
pub fn to_geometry(&self) -> Vec<(Vector3<usize>, Vec<Vertex>, Vec<u16>)> {
|
||||
let instant = std::time::Instant::now();
|
||||
let mut geometry = Vec::new();
|
||||
|
||||
|
@ -34,7 +34,8 @@ impl World {
|
|||
for (z, chunks_z) in chunks_y.iter().enumerate() {
|
||||
for (x, chunk) in chunks_z.iter().enumerate() {
|
||||
let offset = Vector3::new(x as i32 * 16, y as i32 * 16, z as i32 * 16);
|
||||
geometry.push(chunk.to_geometry(offset));
|
||||
let (vertices, indices) = chunk.to_geometry(offset);
|
||||
geometry.push((Vector3::new(x, y, z), vertices, indices));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue