mirror of
https://github.com/griffi-gh/kubi.git
synced 2024-11-22 06:48:43 -06:00
rendering chunks
This commit is contained in:
parent
3cfd6448cc
commit
213075c5f9
22
src/game.rs
22
src/game.rs
|
@ -1,6 +1,5 @@
|
||||||
use glam::Vec2;
|
use glam::Vec2;
|
||||||
use glium::{Surface, uniform};
|
use glium::Surface;
|
||||||
use glium::uniforms::{Sampler, MinifySamplerFilter, MagnifySamplerFilter};
|
|
||||||
use glium::glutin::{
|
use glium::glutin::{
|
||||||
event::{Event, WindowEvent, DeviceEvent},
|
event::{Event, WindowEvent, DeviceEvent},
|
||||||
event_loop::{EventLoop, ControlFlow},
|
event_loop::{EventLoop, ControlFlow},
|
||||||
|
@ -19,7 +18,7 @@ mod options;
|
||||||
|
|
||||||
use assets::Assets;
|
use assets::Assets;
|
||||||
use display::init_display;
|
use display::init_display;
|
||||||
use shaders::{Programs, chunk::Vertex as ChunkVertex};
|
use shaders::Programs;
|
||||||
use camera::Camera;
|
use camera::Camera;
|
||||||
use controller::Controls;
|
use controller::Controls;
|
||||||
use world::World;
|
use world::World;
|
||||||
|
@ -53,15 +52,15 @@ pub fn run() {
|
||||||
let options = GameOptions::default();
|
let options = GameOptions::default();
|
||||||
log::info!("init game state");
|
log::info!("init game state");
|
||||||
let mut state = State::init();
|
let mut state = State::init();
|
||||||
state.camera.position = [0., 0., -1.];
|
state.camera.position = [0., 260., -1.];
|
||||||
log::info!("game loaded");
|
log::info!("game loaded");
|
||||||
|
|
||||||
//=======================
|
//=======================
|
||||||
let vertex1 = ChunkVertex { position: [-0.5, -0.5, 0.], uv: [0., 0.], normal: [0., 1., 0.] };
|
// let vertex1 = ChunkVertex { position: [-0.5, -0.5, 0.], uv: [0., 0.], normal: [0., 1., 0.] };
|
||||||
let vertex2 = ChunkVertex { position: [ 0.0, 0.5, 0.], uv: [0., 1.], normal: [0., 1., 0.] };
|
// let vertex2 = ChunkVertex { position: [ 0.0, 0.5, 0.], uv: [0., 1.], normal: [0., 1., 0.] };
|
||||||
let vertex3 = ChunkVertex { position: [ 0.5, -0.5, 0.], uv: [1., 1.], normal: [0., 1., 0.] };
|
// let vertex3 = ChunkVertex { position: [ 0.5, -0.5, 0.], uv: [1., 1.], normal: [0., 1., 0.] };
|
||||||
let shape = vec![vertex1, vertex2, vertex3];
|
// let shape = vec![vertex1, vertex2, vertex3];
|
||||||
let vertex_buffer = glium::VertexBuffer::new(&display, &shape).unwrap();
|
// let vertex_buffer = glium::VertexBuffer::new(&display, &shape).unwrap();
|
||||||
//=======================
|
//=======================
|
||||||
|
|
||||||
let mut last_render = Instant::now();
|
let mut last_render = Instant::now();
|
||||||
|
@ -122,12 +121,11 @@ pub fn run() {
|
||||||
let target_dimensions = target.get_dimensions();
|
let target_dimensions = target.get_dimensions();
|
||||||
let perspective = state.camera.perspective_matrix(target_dimensions);
|
let perspective = state.camera.perspective_matrix(target_dimensions);
|
||||||
let view = state.camera.view_matrix();
|
let view = state.camera.view_matrix();
|
||||||
|
|
||||||
//Draw example triangle
|
|
||||||
|
|
||||||
//Draw chunks
|
//Draw chunks
|
||||||
state.world.render(&mut target, &programs, &assets, perspective, view);
|
state.world.render(&mut target, &programs, &assets, perspective, view);
|
||||||
|
|
||||||
|
//Draw example triangle
|
||||||
// target.draw(
|
// target.draw(
|
||||||
// &vertex_buffer,
|
// &vertex_buffer,
|
||||||
// glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList),
|
// glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList),
|
||||||
|
|
|
@ -109,7 +109,7 @@ impl Default for Controls {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
inputs: Default::default(),
|
inputs: Default::default(),
|
||||||
speed: 1.,
|
speed: 10.,
|
||||||
sensitivity: 2.,
|
sensitivity: 2.,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use glam::{Vec2, IVec2};
|
use glam::{Vec2, IVec2};
|
||||||
use glium::{
|
use glium::{
|
||||||
Display, Frame, Surface, uniform,
|
Display, Frame, Surface,
|
||||||
|
DrawParameters, Depth,
|
||||||
|
DepthTest, uniform,
|
||||||
uniforms::{
|
uniforms::{
|
||||||
Sampler, SamplerBehavior,
|
Sampler, SamplerBehavior,
|
||||||
MinifySamplerFilter, MagnifySamplerFilter,
|
MinifySamplerFilter, MagnifySamplerFilter,
|
||||||
|
@ -24,6 +26,8 @@ const NEGATIVE_X_NEIGHBOR: usize = 1;
|
||||||
const POSITIVE_Z_NEIGHBOR: usize = 2;
|
const POSITIVE_Z_NEIGHBOR: usize = 2;
|
||||||
const NEGATIVE_Z_NEIGHBOR: usize = 3;
|
const NEGATIVE_Z_NEIGHBOR: usize = 3;
|
||||||
|
|
||||||
|
const MAX_TASKS: usize = 8;
|
||||||
|
|
||||||
pub struct World {
|
pub struct World {
|
||||||
pub chunks: HashMap<IVec2, Chunk>,
|
pub chunks: HashMap<IVec2, Chunk>,
|
||||||
pub thread: WorldThreading,
|
pub thread: WorldThreading,
|
||||||
|
@ -37,12 +41,14 @@ impl World {
|
||||||
self.chunks.get(&(position - IVec2::new(0, 1))),
|
self.chunks.get(&(position - IVec2::new(0, 1))),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
chunks: HashMap::new(),
|
chunks: HashMap::new(),
|
||||||
thread: WorldThreading::new(),
|
thread: WorldThreading::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(
|
pub fn render(
|
||||||
&self,
|
&self,
|
||||||
target: &mut Frame,
|
target: &mut Frame,
|
||||||
|
@ -56,28 +62,39 @@ impl World {
|
||||||
magnify_filter: MagnifySamplerFilter::Nearest,
|
magnify_filter: MagnifySamplerFilter::Nearest,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
let draw_parameters = DrawParameters {
|
||||||
|
depth: Depth {
|
||||||
|
test: DepthTest::IfLess,
|
||||||
|
write: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
//backface_culling: glium::draw_parameters::BackfaceCullingMode::CullClockwise,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
for (&position, chunk) in &self.chunks {
|
for (&position, chunk) in &self.chunks {
|
||||||
if let Some((_, vertex, index)) = &chunk.mesh {
|
if let Some(mesh) = &chunk.mesh {
|
||||||
target.draw(
|
target.draw(
|
||||||
vertex,
|
&mesh.vertex_buffer,
|
||||||
index,
|
&mesh.index_buffer,
|
||||||
&programs.chunk,
|
&programs.chunk,
|
||||||
&uniform! {
|
&uniform! {
|
||||||
model: [
|
model: [
|
||||||
[1., 0., 0., 0.],
|
[1., 0., 0., 0.],
|
||||||
[0., 1., 0., 0.],
|
[0., 1., 0., 0.],
|
||||||
[0., 0., 1., 0.],
|
[0., 0., 1., 0.],
|
||||||
|
//[0., 0., 0., 1.0_f32]
|
||||||
[(position.x * CHUNK_SIZE as i32) as f32, 0., (position.y * CHUNK_SIZE as i32) as f32, 1.0_f32]
|
[(position.x * CHUNK_SIZE as i32) as f32, 0., (position.y * CHUNK_SIZE as i32) as f32, 1.0_f32]
|
||||||
],
|
],
|
||||||
view: view,
|
view: view,
|
||||||
persperctive: perspective,
|
perspective: perspective,
|
||||||
tex: Sampler(&assets.textures.block_atlas, sampler)
|
tex: Sampler(&assets.textures.block_atlas, sampler)
|
||||||
},
|
},
|
||||||
&Default::default()
|
&draw_parameters
|
||||||
).unwrap();
|
).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_loaded_chunks(&mut self, around_position: Vec2, options: &GameOptions, display: &Display) {
|
pub fn update_loaded_chunks(&mut self, around_position: Vec2, options: &GameOptions, display: &Display) {
|
||||||
let render_dist = options.render_distance as i32 + 1;
|
let render_dist = options.render_distance as i32 + 1;
|
||||||
let inside_chunk = (around_position / CHUNK_SIZE as f32).as_ivec2();
|
let inside_chunk = (around_position / CHUNK_SIZE as f32).as_ivec2();
|
||||||
|
@ -98,43 +115,49 @@ impl World {
|
||||||
{
|
{
|
||||||
//we only need mutable reference here:
|
//we only need mutable reference here:
|
||||||
let chunk = self.chunks.get_mut(&position).unwrap();
|
let chunk = self.chunks.get_mut(&position).unwrap();
|
||||||
if x == 0 || z == 0 || x == render_dist || z == render_dist {
|
if x == -render_dist || z == -render_dist || x == render_dist || z == render_dist {
|
||||||
chunk.desired = ChunkState::Loaded;
|
chunk.desired = ChunkState::Loaded;
|
||||||
} else {
|
} else {
|
||||||
chunk.desired = ChunkState::Rendered;
|
chunk.desired = ChunkState::Rendered;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//borrow chunk immutably
|
|
||||||
let chunk = self.chunks.get(&position).unwrap();
|
let chunk = self.chunks.get(&position).unwrap();
|
||||||
if matches!(chunk.state, ChunkState::Nothing) && matches!(chunk.desired, ChunkState::Loaded | ChunkState::Rendered) {
|
if self.thread.task_amount() < MAX_TASKS {
|
||||||
self.thread.queue_load(position);
|
if matches!(chunk.state, ChunkState::Nothing) && matches!(chunk.desired, ChunkState::Loaded | ChunkState::Rendered) {
|
||||||
} else if matches!(chunk.state, ChunkState::Loaded) && matches!(chunk.desired, ChunkState::Rendered) {
|
self.thread.queue_load(position);
|
||||||
fn all_some<'a>(x: [Option<&'a Chunk>; 4]) -> Option<[&'a Chunk; 4]> {
|
self.chunks.get_mut(&position).unwrap().state = ChunkState::Loading;
|
||||||
Some([x[0]?, x[1]?, x[2]?, x[3]?])
|
} else if matches!(chunk.state, ChunkState::Loaded) && matches!(chunk.desired, ChunkState::Rendered) {
|
||||||
}
|
let mut state_changed = false;
|
||||||
if let Some(neighbors) = all_some(self.chunk_neighbors(chunk.position)) {
|
fn all_some<'a>(x: [Option<&'a Chunk>; 4]) -> Option<[&'a Chunk; 4]> {
|
||||||
if {
|
Some([x[0]?, x[1]?, x[2]?, x[3]?])
|
||||||
neighbors[0].block_data.is_some() &&
|
}
|
||||||
neighbors[1].block_data.is_some() &&
|
if let Some(neighbors) = all_some(self.chunk_neighbors(chunk.position)) {
|
||||||
neighbors[2].block_data.is_some() &&
|
if {
|
||||||
neighbors[3].block_data.is_some()
|
neighbors[0].block_data.is_some() &&
|
||||||
} {
|
neighbors[1].block_data.is_some() &&
|
||||||
self.thread.queue_mesh(
|
neighbors[2].block_data.is_some() &&
|
||||||
position,
|
neighbors[3].block_data.is_some()
|
||||||
chunk.block_data.clone().unwrap(),
|
} {
|
||||||
[
|
self.thread.queue_mesh(
|
||||||
neighbors[0].block_data.clone().unwrap(),
|
position,
|
||||||
neighbors[1].block_data.clone().unwrap(),
|
chunk.block_data.clone().unwrap(),
|
||||||
neighbors[2].block_data.clone().unwrap(),
|
[
|
||||||
neighbors[3].block_data.clone().unwrap(),
|
neighbors[0].block_data.clone().unwrap(),
|
||||||
]
|
neighbors[1].block_data.clone().unwrap(),
|
||||||
);
|
neighbors[2].block_data.clone().unwrap(),
|
||||||
|
neighbors[3].block_data.clone().unwrap(),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
state_changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if state_changed {
|
||||||
|
self.chunks.get_mut(&position).unwrap().state = ChunkState::Rendering;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Unloads and state downgrades
|
//Unloads and state downgrades
|
||||||
self.chunks.retain(|_, chunk| {
|
self.chunks.retain(|_, chunk| {
|
||||||
match chunk.desired {
|
match chunk.desired {
|
||||||
|
|
|
@ -19,10 +19,16 @@ pub enum ChunkState {
|
||||||
|
|
||||||
pub type ChunkData = Box<[[[Block; CHUNK_SIZE]; CHUNK_HEIGHT]; CHUNK_SIZE]>;
|
pub type ChunkData = Box<[[[Block; CHUNK_SIZE]; CHUNK_HEIGHT]; CHUNK_SIZE]>;
|
||||||
|
|
||||||
|
pub struct ChunkMesh {
|
||||||
|
pub is_dirty: bool,
|
||||||
|
pub vertex_buffer: VertexBuffer<ChunkVertex>,
|
||||||
|
pub index_buffer: IndexBuffer<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Chunk {
|
pub struct Chunk {
|
||||||
pub position: IVec2,
|
pub position: IVec2,
|
||||||
pub block_data: Option<ChunkData>,
|
pub block_data: Option<ChunkData>,
|
||||||
pub mesh: Option<(bool, VertexBuffer<ChunkVertex>, IndexBuffer<u16>)>,
|
pub mesh: Option<ChunkMesh>,
|
||||||
pub state: ChunkState,
|
pub state: ChunkState,
|
||||||
pub desired: ChunkState,
|
pub desired: ChunkState,
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use glium::{Display, VertexBuffer, IndexBuffer, index::PrimitiveType};
|
||||||
use std::{mem, thread::{self, JoinHandle}};
|
use std::{mem, thread::{self, JoinHandle}};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use super::chunk::{Chunk, ChunkData, ChunkState};
|
use super::chunk::{Chunk, ChunkData, ChunkState};
|
||||||
use crate::game::shaders::chunk::Vertex as ChunkVertex;
|
use crate::game::{shaders::chunk::Vertex as ChunkVertex, world::chunk::ChunkMesh};
|
||||||
|
|
||||||
mod world_gen;
|
mod world_gen;
|
||||||
mod mesh_gen;
|
mod mesh_gen;
|
||||||
|
@ -14,7 +14,7 @@ pub struct WorldThreading {
|
||||||
//Options are needed here to take ownership,
|
//Options are needed here to take ownership,
|
||||||
//None values should never appear here!
|
//None values should never appear here!
|
||||||
pub load_tasks: HashMap<IVec2, Option<JoinHandle<ChunkData>>>,
|
pub load_tasks: HashMap<IVec2, Option<JoinHandle<ChunkData>>>,
|
||||||
pub mesh_tasks: HashMap<IVec2, Option<JoinHandle<(Vec<ChunkVertex>, Vec<u16>)>>>,
|
pub mesh_tasks: HashMap<IVec2, Option<JoinHandle<(Vec<ChunkVertex>, Vec<u32>)>>>,
|
||||||
}
|
}
|
||||||
impl WorldThreading {
|
impl WorldThreading {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
|
@ -84,11 +84,11 @@ impl WorldThreading {
|
||||||
let handle = mem::take(handle).unwrap();
|
let handle = mem::take(handle).unwrap();
|
||||||
let (shape, index) = handle.join().unwrap();
|
let (shape, index) = handle.join().unwrap();
|
||||||
let chunk = chunks.get_mut(position).unwrap();
|
let chunk = chunks.get_mut(position).unwrap();
|
||||||
chunk.mesh = Some((
|
chunk.mesh = Some(ChunkMesh {
|
||||||
true,
|
is_dirty: false,
|
||||||
VertexBuffer::immutable(display, &shape).expect("Failed to build VertexBuffer"),
|
vertex_buffer: VertexBuffer::new(display, &shape).expect("Failed to build VertexBuffer"),
|
||||||
IndexBuffer::immutable(display, PrimitiveType::TrianglesList, &index).expect("Failed to build IndexBuffer")
|
index_buffer: IndexBuffer::new(display, PrimitiveType::TrianglesList, &index).expect("Failed to build IndexBuffer")
|
||||||
));
|
});
|
||||||
chunk.state = ChunkState::Rendered;
|
chunk.state = ChunkState::Rendered;
|
||||||
false
|
false
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,15 +1,126 @@
|
||||||
use glam::IVec2;
|
use glam::{IVec2, IVec3, Vec2, Vec3A, vec3a, vec2, ivec3};
|
||||||
use crate::game::world::chunk::ChunkData;
|
use strum::{EnumIter, IntoEnumIterator};
|
||||||
use crate::game::shaders::chunk::Vertex as ChunkVertex;
|
use crate::game::{
|
||||||
|
world::{
|
||||||
|
POSITIVE_X_NEIGHBOR,
|
||||||
|
NEGATIVE_X_NEIGHBOR,
|
||||||
|
POSITIVE_Z_NEIGHBOR,
|
||||||
|
NEGATIVE_Z_NEIGHBOR,
|
||||||
|
chunk::{ChunkData, CHUNK_SIZE, CHUNK_HEIGHT}
|
||||||
|
},
|
||||||
|
shaders::chunk::Vertex,
|
||||||
|
blocks::Block
|
||||||
|
};
|
||||||
|
|
||||||
pub fn generate_mesh(position: IVec2, chunk_data: ChunkData, neighbors: [ChunkData; 4]) -> (Vec<ChunkVertex>, Vec<u16>) {
|
#[repr(usize)]
|
||||||
let mut vertex = Vec::new();
|
#[derive(Clone, Copy, Debug, EnumIter)]
|
||||||
let mut index = Vec::new();
|
pub enum CubeFace {
|
||||||
vertex.push(ChunkVertex { position: [-0.5, -0.5, 0.], uv: [0., 0.], normal: [0., 1., 0.] });
|
Top = 0,
|
||||||
vertex.push(ChunkVertex { position: [ 0.0, 0.5, 0.], uv: [0., 1.], normal: [0., 1., 0.] });
|
Front = 1,
|
||||||
vertex.push(ChunkVertex { position: [ 0.5, -0.5, 0.], uv: [1., 1.], normal: [0., 1., 0.] });
|
Left = 2,
|
||||||
index.push(0);
|
Right = 3,
|
||||||
index.push(1);
|
Back = 4,
|
||||||
index.push(2);
|
Bottom = 5,
|
||||||
(vertex, index)
|
}
|
||||||
|
const CUBE_FACE_VERTICES: [[Vec3A; 4]; 6] = [
|
||||||
|
[vec3a(0., 1., 0.), vec3a(0., 1., 1.), vec3a(1., 1., 0.), vec3a(1., 1., 1.)],
|
||||||
|
[vec3a(0., 0., 0.), vec3a(0., 1., 0.), vec3a(1., 0., 0.), vec3a(1., 1., 0.)],
|
||||||
|
[vec3a(0., 0., 1.), vec3a(0., 1., 1.), vec3a(0., 0., 0.), vec3a(0., 1., 0.)],
|
||||||
|
[vec3a(1., 0., 0.), vec3a(1., 1., 0.), vec3a(1., 0., 1.), vec3a(1., 1., 1.)],
|
||||||
|
[vec3a(1., 0., 1.), vec3a(1., 1., 1.), vec3a(0., 0., 1.), vec3a(0., 1., 1.)],
|
||||||
|
[vec3a(0., 0., 1.), vec3a(0., 0., 0.), vec3a(1., 0., 1.), vec3a(1., 0., 0.)]
|
||||||
|
];
|
||||||
|
pub const CUBE_FACE_NORMALS: [[f32; 3]; 6] = [
|
||||||
|
[0., 1., 0.],
|
||||||
|
[0., 0., -1.],
|
||||||
|
[-1., 0., 0.],
|
||||||
|
[1., 0., 0.],
|
||||||
|
[0., 0., 1.],
|
||||||
|
[0., -1., 0.]
|
||||||
|
];
|
||||||
|
pub const CUBE_FACE_INDICES: [u32; 6] = [0, 1, 2, 2, 1, 3];
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct MeshBuilder {
|
||||||
|
vertex_buffer: Vec<Vertex>,
|
||||||
|
index_buffer: Vec<u32>,
|
||||||
|
idx_counter: u32,
|
||||||
|
}
|
||||||
|
impl MeshBuilder {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_face(&mut self, face: CubeFace, coord: IVec3, uvs: [Vec2; 4]) {
|
||||||
|
let coord = coord.as_vec3a();
|
||||||
|
let face_index = face as usize;
|
||||||
|
|
||||||
|
//Push vertexes
|
||||||
|
let norm = CUBE_FACE_NORMALS[face_index];
|
||||||
|
let vert = CUBE_FACE_VERTICES[face_index];
|
||||||
|
self.vertex_buffer.reserve(4);
|
||||||
|
for i in 0..4 {
|
||||||
|
self.vertex_buffer.push(Vertex {
|
||||||
|
position: (coord + vert[i]).to_array(),
|
||||||
|
normal: norm,
|
||||||
|
uv: uvs[i].to_array()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//Push indices
|
||||||
|
self.index_buffer.extend_from_slice(&CUBE_FACE_INDICES.map(|x| x + self.idx_counter));
|
||||||
|
self.idx_counter += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn finish(self) -> (Vec<Vertex>, Vec<u32>) {
|
||||||
|
(self.vertex_buffer, self.index_buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_mesh(position: IVec2, chunk_data: ChunkData, neighbors: [ChunkData; 4]) -> (Vec<Vertex>, Vec<u32>) {
|
||||||
|
let get_block = |pos: IVec3| -> Block {
|
||||||
|
if pos.x < 0 {
|
||||||
|
neighbors[NEGATIVE_X_NEIGHBOR][(CHUNK_SIZE as i32 + pos.x) as usize][pos.y as usize][pos.z as usize]
|
||||||
|
} else if pos.x >= CHUNK_SIZE as i32 {
|
||||||
|
neighbors[POSITIVE_X_NEIGHBOR][pos.x as usize - CHUNK_SIZE as usize][pos.y as usize][pos.z as usize]
|
||||||
|
} else if pos.z < 0 {
|
||||||
|
neighbors[NEGATIVE_Z_NEIGHBOR][pos.x as usize][pos.y as usize][(CHUNK_SIZE as i32 + pos.z) as usize]
|
||||||
|
} else if pos.z >= CHUNK_SIZE as i32 {
|
||||||
|
neighbors[POSITIVE_Z_NEIGHBOR][pos.x as usize][pos.y as usize][pos.z as usize - CHUNK_SIZE as usize]
|
||||||
|
} else {
|
||||||
|
chunk_data[pos.x as usize][pos.y as usize][pos.z as usize]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut builer = MeshBuilder::new();
|
||||||
|
|
||||||
|
for x in 0..CHUNK_SIZE {
|
||||||
|
for y in 0..CHUNK_HEIGHT {
|
||||||
|
for z in 0..CHUNK_SIZE {
|
||||||
|
let coord = ivec3(x as i32, y as i32, z as i32);
|
||||||
|
if get_block(coord).descriptor().render.is_none() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for face in CubeFace::iter() {
|
||||||
|
let facing = Vec3A::from_array(CUBE_FACE_NORMALS[face as usize]).as_ivec3();
|
||||||
|
let facing_coord = coord + facing;
|
||||||
|
let show = {
|
||||||
|
(facing_coord.y < 0) ||
|
||||||
|
(facing_coord.y >= CHUNK_HEIGHT as i32) ||
|
||||||
|
get_block(facing_coord).descriptor().render.is_none()
|
||||||
|
};
|
||||||
|
if show {
|
||||||
|
builer.add_face(face, coord, [
|
||||||
|
vec2(0., 0.),
|
||||||
|
vec2(0., 1.),
|
||||||
|
vec2(1., 0.),
|
||||||
|
vec2(1., 1.),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
builer.finish()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue