mirror of
https://github.com/griffi-gh/kubi.git
synced 2024-11-21 14:28:43 -06:00
i see... something?
This commit is contained in:
parent
3f768a8318
commit
f4e4886d33
|
@ -9,7 +9,7 @@ pub fn init() {
|
|||
use env_logger::{fmt::Color, Builder, Env};
|
||||
|
||||
let env = Env::default()
|
||||
.filter_or("RUST_LOG", "trace,gilrs=warn,rusty_xinput=warn,wgpu=warn,wgpu_core=warn,wgpu_hal=warn,hui=info,hui-winit=info,hui-glium=info,hui-wgpu=info");
|
||||
.filter_or("RUST_LOG", "trace,gilrs=warn,rusty_xinput=warn,wgpu=warn,wgpu_core=warn,wgpu_hal=warn,hui=info,hui-winit=info,hui-glium=info,hui-wgpu=info,naga=warn");
|
||||
Builder::from_env(env)
|
||||
.format(|buf, record| {
|
||||
let mut level_style = buf.style();
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// struct Uniforms {
|
||||
// transform: mat4x4<f32>;
|
||||
// };
|
||||
struct CameraUniform {
|
||||
view_proj: mat4x4<f32>,
|
||||
};
|
||||
|
||||
// @group(1) @binding(0)
|
||||
// var<uniform> uniforms: Uniforms;
|
||||
@group(1) @binding(0)
|
||||
var<uniform> camera: CameraUniform;
|
||||
|
||||
struct VertexInput {
|
||||
@location(0) position: vec3<f32>,
|
||||
|
@ -26,7 +26,7 @@ fn vs_main(
|
|||
) -> VertexOutput {
|
||||
var out: VertexOutput;
|
||||
out.uv = in.uv;
|
||||
out.clip_position = vec4<f32>(in.position, 1.0);
|
||||
out.clip_position = camera.view_proj * vec4<f32>(in.position, 1.0);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
|
@ -79,8 +79,11 @@ use player_controller::{debug_switch_ctl_type, update_player_controllers};
|
|||
// clear_background, entities::render_entities, init_window_size, primitives::init_primitives, resize_renderer, selection_box::render_selection_box, sumberge::render_submerged_view, update_window_size, world::{draw_current_chunk_border, draw_world, draw_world_trans, init_trans_chunk_queue}, BackgroundColor, RenderTarget, Renderer
|
||||
// };
|
||||
use rendering::{
|
||||
init_window_size, render_master, resize_renderer, update_window_size,
|
||||
world::{init_trans_chunk_queue, TransChunkQueue},
|
||||
init_render_states,
|
||||
init_window_size,
|
||||
render_master,
|
||||
resize_renderer,
|
||||
update_window_size,
|
||||
BackgroundColor, Renderer,
|
||||
};
|
||||
use block_placement::update_block_placement;
|
||||
|
@ -116,7 +119,7 @@ fn startup() -> Workload {
|
|||
init_window_size,
|
||||
kubi_ui_init,
|
||||
load_prefabs,
|
||||
//init_primitives,
|
||||
init_render_states,
|
||||
insert_lock_state,
|
||||
init_state,
|
||||
initialize_from_args,
|
||||
|
@ -139,7 +142,6 @@ fn update() -> Workload {
|
|||
process_inputs,
|
||||
kubi_ui_begin,
|
||||
(
|
||||
init_trans_chunk_queue.run_if_missing_unique::<TransChunkQueue>(),
|
||||
init_game_world.run_if_missing_unique::<ChunkTaskManager>(),
|
||||
(
|
||||
spawn_player.run_if_storage_empty::<MainPlayer>(),
|
||||
|
|
|
@ -38,6 +38,7 @@ impl AssetPaths for BlockTexture {
|
|||
#[derive(Unique)]
|
||||
pub struct TexturePrefabs {
|
||||
pub block_diffuse_texture: wgpu::Texture,
|
||||
pub block_diffuse_bind_group_layout: wgpu::BindGroupLayout,
|
||||
pub block_diffuse_bind_group: wgpu::BindGroup,
|
||||
}
|
||||
|
||||
|
@ -107,6 +108,7 @@ pub fn load_prefabs(
|
|||
});
|
||||
storages.add_unique_non_send_sync(TexturePrefabs {
|
||||
block_diffuse_texture,
|
||||
block_diffuse_bind_group_layout,
|
||||
block_diffuse_bind_group,
|
||||
});
|
||||
|
||||
|
|
|
@ -1,16 +1,50 @@
|
|||
use shipyard::{AllStoragesView, AllStoragesViewMut, IntoIter, Unique, UniqueView, UniqueViewMut, View};
|
||||
use shipyard::{AllStoragesView, AllStoragesViewMut, IntoIter, IntoWorkload, Unique, UniqueView, UniqueViewMut, View, Workload};
|
||||
use winit::dpi::PhysicalSize;
|
||||
use glam::{Vec3, UVec2};
|
||||
use glam::{mat4, vec4, Mat4, UVec2, Vec3};
|
||||
use crate::{events::WindowResizedEvent, state::is_ingame};
|
||||
|
||||
mod renderer;
|
||||
pub use renderer::Renderer;
|
||||
|
||||
pub mod primitives;
|
||||
use self::camera::update_camera_unform_buffer;
|
||||
|
||||
pub mod world;
|
||||
pub mod selection_box;
|
||||
pub mod entities;
|
||||
pub mod sumberge;
|
||||
pub mod camera;
|
||||
//pub mod primitives;
|
||||
//pub mod selection_box;
|
||||
//pub mod entities;
|
||||
//pub mod sumberge;
|
||||
|
||||
pub const WGPU_COORDINATE_SYSTEM: Mat4 = mat4(
|
||||
vec4(1.0, 0.0, 0.0, 0.0),
|
||||
vec4(0.0, 1.0, 0.0, 0.0),
|
||||
vec4(0.0, 0.0, 0.5, 0.5),
|
||||
vec4(0.0, 0.0, 0.0, 1.0),
|
||||
);
|
||||
|
||||
// #[repr(C)]
|
||||
// #[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
// struct TrasnformUniformData {
|
||||
// pub transform: [[f32; 4]; 4],
|
||||
// }
|
||||
|
||||
// impl TrasnformUniformData {
|
||||
// pub const LAYOUT: &wgpu::Layou
|
||||
// }
|
||||
|
||||
// impl From<Mat4> for TrasnformUniformData {
|
||||
// fn from(mat: Mat4) -> Self {
|
||||
// Self {
|
||||
// transform: mat.to_cols_array_2d(),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl From<Transform> for TrasnformUniformData {
|
||||
// fn from(value: Transform) -> Self {
|
||||
// value.0.into()
|
||||
// }
|
||||
// }
|
||||
|
||||
pub struct BufferPair {
|
||||
pub index: wgpu::Buffer,
|
||||
|
@ -28,6 +62,13 @@ pub struct RenderCtx<'a> {
|
|||
pub surface_view: &'a wgpu::TextureView,
|
||||
}
|
||||
|
||||
pub fn init_render_states() -> Workload {
|
||||
(
|
||||
camera::init_camera_uniform_buffer,
|
||||
world::init_world_render_state,
|
||||
).into_workload()
|
||||
}
|
||||
|
||||
pub fn render_master(storages: AllStoragesViewMut) {
|
||||
let renderer = storages.borrow::<UniqueView<Renderer>>().unwrap();
|
||||
|
||||
|
@ -66,6 +107,10 @@ pub fn render_master(storages: AllStoragesViewMut) {
|
|||
};
|
||||
|
||||
if storages.run(is_ingame) {
|
||||
//XXX: probably should be in pre_update or sth
|
||||
storages.run(update_camera_unform_buffer);
|
||||
|
||||
//TODO init world render state on demand
|
||||
storages.run_with_data(world::draw_world, &mut data);
|
||||
}
|
||||
|
||||
|
|
84
kubi/src/rendering/camera.rs
Normal file
84
kubi/src/rendering/camera.rs
Normal file
|
@ -0,0 +1,84 @@
|
|||
use bytemuck::{Pod, Zeroable};
|
||||
use kubi_shared::transform::Transform;
|
||||
use shipyard::{AllStoragesView, IntoIter, Unique, UniqueView, View};
|
||||
use wgpu::util::DeviceExt;
|
||||
use crate::camera::{self, Camera};
|
||||
|
||||
use super::{Renderer, WGPU_COORDINATE_SYSTEM};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default, Pod, Zeroable)]
|
||||
#[repr(C, packed)]
|
||||
pub struct CameraUniformData {
|
||||
pub view_proj: [[f32; 4]; 4],
|
||||
}
|
||||
|
||||
|
||||
//TODO if multiple cameras, buffer per camera
|
||||
#[derive(Unique)]
|
||||
pub struct CameraUniformBuffer {
|
||||
pub camera_uniform_buffer: wgpu::Buffer,
|
||||
pub camera_bind_group_layout: wgpu::BindGroupLayout,
|
||||
pub camera_bind_group: wgpu::BindGroup,
|
||||
}
|
||||
|
||||
impl CameraUniformBuffer {
|
||||
pub fn init(renderer: &Renderer, data: CameraUniformData) -> Self {
|
||||
let camera_uniform_buffer = renderer.device().create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("camera_uniform_buffer"),
|
||||
contents: bytemuck::cast_slice(&[data]),
|
||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||
});
|
||||
|
||||
let camera_bind_group_layout = renderer.device().create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some("camera_bind_group_layout"),
|
||||
entries: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStages::VERTEX,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
let camera_bind_group = renderer.device().create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: Some("camera_bind_group"),
|
||||
layout: &camera_bind_group_layout,
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: camera_uniform_buffer.as_entire_binding(),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
Self { camera_uniform_buffer, camera_bind_group_layout, camera_bind_group }
|
||||
}
|
||||
|
||||
pub fn init_default(renderer: &Renderer) -> Self {
|
||||
Self::init(renderer, CameraUniformData::default())
|
||||
}
|
||||
|
||||
pub fn update(&self, renderer: &Renderer, data: CameraUniformData) {
|
||||
renderer.queue().write_buffer(&self.camera_uniform_buffer, 0, bytemuck::cast_slice(&[data]));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_camera_uniform_buffer(storages: AllStoragesView) {
|
||||
let renderer = storages.borrow::<UniqueView<Renderer>>().unwrap();
|
||||
storages.add_unique(CameraUniformBuffer::init_default(&renderer));
|
||||
}
|
||||
|
||||
pub fn update_camera_unform_buffer(
|
||||
renderer: UniqueView<Renderer>,
|
||||
camera_uniform_buffer: UniqueView<CameraUniformBuffer>,
|
||||
camera: View<Camera>,
|
||||
) {
|
||||
let Some(camera) = camera.iter().next() else { return };
|
||||
let proj = camera.view_matrix * camera.perspective_matrix * WGPU_COORDINATE_SYSTEM;
|
||||
camera_uniform_buffer.update(&renderer, CameraUniformData { view_proj: proj.to_cols_array_2d() });
|
||||
}
|
|
@ -1,57 +1,44 @@
|
|||
use bytemuck::{Pod, Zeroable};
|
||||
use glam::{IVec3, Vec3};
|
||||
use shipyard::{AllStoragesView, IntoIter, NonSendSync, Unique, UniqueView, UniqueViewMut, View};
|
||||
use kubi_shared::{chunk::CHUNK_SIZE, transform::Transform};
|
||||
use wgpu::util::RenderEncoder;
|
||||
use crate::{
|
||||
camera::Camera,
|
||||
prefabs::TexturePrefabs,
|
||||
settings::GameSettings,
|
||||
world::{ChunkMeshStorage, ChunkStorage},
|
||||
};
|
||||
use super::{RenderCtx, Renderer};
|
||||
use super::{camera::CameraUniformBuffer, RenderCtx, WGPU_COORDINATE_SYSTEM};
|
||||
|
||||
#[derive(Clone, Copy, Pod, Zeroable)]
|
||||
#[repr(C, packed)]
|
||||
pub struct ChunkVertex {
|
||||
pub position: [f32; 3],
|
||||
pub normal: [f32; 3],
|
||||
pub uv: [f32; 2],
|
||||
pub tex_index: u8,
|
||||
}
|
||||
|
||||
impl ChunkVertex {
|
||||
pub const LAYOUT: wgpu::VertexBufferLayout<'static> = wgpu::VertexBufferLayout {
|
||||
array_stride: std::mem::size_of::<ChunkVertex>() as wgpu::BufferAddress,
|
||||
step_mode: wgpu::VertexStepMode::Vertex,
|
||||
attributes: &wgpu::vertex_attr_array![
|
||||
0 => Float32x3,
|
||||
1 => Float32x3,
|
||||
2 => Float32x2,
|
||||
3 => Uint32,
|
||||
],
|
||||
};
|
||||
}
|
||||
mod pipeline;
|
||||
mod vertex;
|
||||
pub use vertex::ChunkVertex;
|
||||
|
||||
#[derive(Unique)]
|
||||
pub struct TransChunkQueue(pub Vec<IVec3>);
|
||||
pub struct WorldRenderState {
|
||||
pub pipeline: wgpu::RenderPipeline,
|
||||
pub trans_chunk_queue: Vec<IVec3>,
|
||||
}
|
||||
|
||||
pub fn init_trans_chunk_queue(storages: AllStoragesView) {
|
||||
storages.add_unique(TransChunkQueue(Vec::with_capacity(512)));
|
||||
pub fn init_world_render_state(storages: AllStoragesView) {
|
||||
storages.add_unique(WorldRenderState {
|
||||
pipeline: storages.run(pipeline::init_world_pipeline),
|
||||
trans_chunk_queue: Vec::with_capacity(512),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn draw_world(
|
||||
ctx: &mut RenderCtx,
|
||||
mut state: UniqueViewMut<WorldRenderState>,
|
||||
textures: UniqueView<TexturePrefabs>,
|
||||
chunks: UniqueView<ChunkStorage>,
|
||||
meshes: NonSendSync<UniqueView<ChunkMeshStorage>>,
|
||||
transform: View<Transform>,
|
||||
//transform: View<Transform>,
|
||||
camera: View<Camera>,
|
||||
camera_ubo: UniqueView<CameraUniformBuffer>,
|
||||
settings: UniqueView<GameSettings>,
|
||||
mut trans_queue: UniqueViewMut<TransChunkQueue>,
|
||||
) {
|
||||
let camera = camera.iter().next().expect("No cameras in the scene");
|
||||
let camera_matrix = camera.view_matrix * camera.perspective_matrix;
|
||||
let matrix = WGPU_COORDINATE_SYSTEM * camera.view_matrix * camera.perspective_matrix;
|
||||
|
||||
let mut render_pass = ctx.encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
label: Some("draw_world"),
|
||||
|
@ -66,6 +53,10 @@ pub fn draw_world(
|
|||
..Default::default()
|
||||
});
|
||||
|
||||
render_pass.set_pipeline(&state.pipeline);
|
||||
render_pass.set_bind_group(0, &textures.block_diffuse_bind_group, &[]);
|
||||
render_pass.set_bind_group(1, &camera_ubo.camera_bind_group, &[]);
|
||||
|
||||
for (&position, chunk) in &chunks.chunks {
|
||||
if let Some(key) = chunk.mesh_index {
|
||||
let mesh = meshes.get(key).expect("Mesh index pointing to nothing");
|
||||
|
@ -85,10 +76,8 @@ pub fn draw_world(
|
|||
|
||||
//Draw chunk mesh
|
||||
if mesh.main.index.size() > 0 {
|
||||
//TODO
|
||||
render_pass.set_index_buffer(mesh.main.index.slice(..), wgpu::IndexFormat::Uint32);
|
||||
render_pass.set_vertex_buffer(0, mesh.main.vertex.slice(..));
|
||||
render_pass.set_bind_group(0, &textures.block_diffuse_bind_group, &[]);
|
||||
render_pass.draw_indexed(0..mesh.main.index_len, 0, 0..1);
|
||||
}
|
||||
|
||||
|
|
59
kubi/src/rendering/world/pipeline.rs
Normal file
59
kubi/src/rendering/world/pipeline.rs
Normal file
|
@ -0,0 +1,59 @@
|
|||
use shipyard::{Unique, UniqueView};
|
||||
use crate::{
|
||||
prefabs::TexturePrefabs,
|
||||
rendering::{camera::CameraUniformBuffer, world::ChunkVertex, Renderer}
|
||||
};
|
||||
|
||||
pub fn init_world_pipeline(
|
||||
ren: UniqueView<Renderer>,
|
||||
textures: UniqueView<TexturePrefabs>,
|
||||
camera_ubo: UniqueView<CameraUniformBuffer>,
|
||||
) -> wgpu::RenderPipeline {
|
||||
let shader = ren.device().create_shader_module(
|
||||
wgpu::include_wgsl!("../../../shaders/world.wgsl")
|
||||
);
|
||||
|
||||
let world_pipeline_layout = ren.device().create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("world_pipeline_layout"),
|
||||
bind_group_layouts: &[
|
||||
&textures.block_diffuse_bind_group_layout,
|
||||
&camera_ubo.camera_bind_group_layout,
|
||||
],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
ren.device().create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: Some("world_pipeline"),
|
||||
layout: Some(&world_pipeline_layout),
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &shader,
|
||||
entry_point: "fs_main",
|
||||
compilation_options: wgpu::PipelineCompilationOptions::default(),
|
||||
targets: &[Some(wgpu::ColorTargetState {
|
||||
format: ren.surface_config().format,
|
||||
blend: Some(wgpu::BlendState::REPLACE),
|
||||
write_mask: wgpu::ColorWrites::ALL,
|
||||
})],
|
||||
}),
|
||||
vertex: wgpu::VertexState {
|
||||
module: &shader,
|
||||
entry_point: "vs_main",
|
||||
compilation_options: wgpu::PipelineCompilationOptions::default(),
|
||||
buffers: &[
|
||||
ChunkVertex::LAYOUT,
|
||||
],
|
||||
},
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
strip_index_format: None,
|
||||
cull_mode: Some(wgpu::Face::Back),
|
||||
front_face: wgpu::FrontFace::Cw,
|
||||
unclipped_depth: false,
|
||||
polygon_mode: wgpu::PolygonMode::Fill,
|
||||
conservative: false,
|
||||
},
|
||||
depth_stencil: None,
|
||||
multisample: wgpu::MultisampleState::default(),
|
||||
multiview: None,
|
||||
})
|
||||
}
|
23
kubi/src/rendering/world/vertex.rs
Normal file
23
kubi/src/rendering/world/vertex.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
use bytemuck::{Pod, Zeroable};
|
||||
|
||||
#[derive(Clone, Copy, Pod, Zeroable)]
|
||||
#[repr(C, packed)]
|
||||
pub struct ChunkVertex {
|
||||
pub position: [f32; 3],
|
||||
pub normal: [f32; 3],
|
||||
pub uv: [f32; 2],
|
||||
pub tex_index: u32,
|
||||
}
|
||||
|
||||
impl ChunkVertex {
|
||||
pub const LAYOUT: wgpu::VertexBufferLayout<'static> = wgpu::VertexBufferLayout {
|
||||
array_stride: std::mem::size_of::<ChunkVertex>() as wgpu::BufferAddress,
|
||||
step_mode: wgpu::VertexStepMode::Vertex,
|
||||
attributes: &wgpu::vertex_attr_array![
|
||||
0 => Float32x3,
|
||||
1 => Float32x3,
|
||||
2 => Float32x2,
|
||||
3 => Uint32,
|
||||
],
|
||||
};
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
use glam::{IVec3, ivec3};
|
||||
use glam::{ivec3, IVec3, Vec3};
|
||||
use strum::IntoEnumIterator;
|
||||
use kubi_shared::block::{Block, RenderType, Transparency};
|
||||
use crate::world::chunk::CHUNK_SIZE;
|
||||
|
@ -10,7 +10,7 @@ mod builder;
|
|||
use data::MeshGenData;
|
||||
use builder::{MeshBuilder, CubeFace, DiagonalFace};
|
||||
|
||||
pub fn generate_mesh(data: MeshGenData) -> (
|
||||
pub fn generate_mesh(position: IVec3, data: MeshGenData) -> (
|
||||
(Vec<ChunkVertex>, Vec<u32>),
|
||||
(Vec<ChunkVertex>, Vec<u32>),
|
||||
) {
|
||||
|
@ -32,7 +32,7 @@ pub fn generate_mesh(data: MeshGenData) -> (
|
|||
}
|
||||
};
|
||||
|
||||
let mut builder = MeshBuilder::new();
|
||||
let mut builder = MeshBuilder::new_with_offset((position * CHUNK_SIZE as i32).as_vec3());
|
||||
let mut trans_builder = MeshBuilder::new();
|
||||
|
||||
for x in 0..CHUNK_SIZE as i32 {
|
||||
|
|
|
@ -1,176 +1,182 @@
|
|||
use strum::EnumIter;
|
||||
use glam::{Vec3, vec3, IVec3, ivec3};
|
||||
use std::f32::consts::FRAC_1_SQRT_2;
|
||||
use crate::rendering::world::ChunkVertex;
|
||||
|
||||
#[repr(usize)]
|
||||
#[derive(Clone, Copy, Debug, EnumIter)]
|
||||
pub enum CubeFace {
|
||||
Top = 0,
|
||||
Front = 4,
|
||||
Left = 2,
|
||||
Right = 3,
|
||||
Back = 1,
|
||||
Bottom = 5,
|
||||
}
|
||||
impl CubeFace {
|
||||
pub const fn normal(self) -> IVec3 {
|
||||
CUBE_FACE_NORMALS_IVEC3[self as usize]
|
||||
}
|
||||
}
|
||||
|
||||
const CUBE_FACE_VERTICES: [[Vec3; 4]; 6] = [
|
||||
[vec3(0., 1., 0.), vec3(0., 1., 1.), vec3(1., 1., 0.), vec3(1., 1., 1.)],
|
||||
[vec3(0., 0., 0.), vec3(0., 1., 0.), vec3(1., 0., 0.), vec3(1., 1., 0.)],
|
||||
[vec3(0., 0., 1.), vec3(0., 1., 1.), vec3(0., 0., 0.), vec3(0., 1., 0.)],
|
||||
[vec3(1., 0., 0.), vec3(1., 1., 0.), vec3(1., 0., 1.), vec3(1., 1., 1.)],
|
||||
[vec3(1., 0., 1.), vec3(1., 1., 1.), vec3(0., 0., 1.), vec3(0., 1., 1.)],
|
||||
[vec3(0., 0., 1.), vec3(0., 0., 0.), vec3(1., 0., 1.), vec3(1., 0., 0.)],
|
||||
];
|
||||
const CUBE_FACE_NORMALS_IVEC3: [IVec3; 6] = [
|
||||
ivec3( 0, 1, 0),
|
||||
ivec3( 0, 0, -1),
|
||||
ivec3(-1, 0, 0),
|
||||
ivec3( 1, 0, 0),
|
||||
ivec3( 0, 0, 1),
|
||||
ivec3( 0, -1, 0)
|
||||
];
|
||||
const CUBE_FACE_NORMALS: [Vec3; 6] = [
|
||||
vec3(0., 1., 0.),
|
||||
vec3(0., 0., -1.),
|
||||
vec3(-1.,0., 0.),
|
||||
vec3(1., 0., 0.),
|
||||
vec3(0., 0., 1.),
|
||||
vec3(0., -1.,0.)
|
||||
];
|
||||
const CUBE_FACE_INDICES: [u32; 6] = [0, 1, 2, 2, 1, 3];
|
||||
|
||||
#[repr(usize)]
|
||||
pub enum DiagonalFace {
|
||||
RigthZ = 0,
|
||||
LeftZ = 1,
|
||||
}
|
||||
const CROSS_FACES: [[Vec3; 4]; 2] = [
|
||||
[
|
||||
vec3(0., 0., 0.),
|
||||
vec3(0., 1., 0.),
|
||||
vec3(1., 0., 1.),
|
||||
vec3(1., 1., 1.),
|
||||
],
|
||||
[
|
||||
vec3(0., 0., 1.),
|
||||
vec3(0., 1., 1.),
|
||||
vec3(1., 0., 0.),
|
||||
vec3(1., 1., 0.),
|
||||
]
|
||||
];
|
||||
const CROSS_FACE_NORMALS: [Vec3; 2] = [
|
||||
vec3(-FRAC_1_SQRT_2, 0., FRAC_1_SQRT_2),
|
||||
vec3( FRAC_1_SQRT_2, 0., FRAC_1_SQRT_2),
|
||||
];
|
||||
const CROSS_FACE_NORMALS_BACK: [Vec3; 2] = [
|
||||
vec3( FRAC_1_SQRT_2, 0., -FRAC_1_SQRT_2),
|
||||
vec3(-FRAC_1_SQRT_2, 0., -FRAC_1_SQRT_2),
|
||||
];
|
||||
const CROSS_FACE_INDICES: [u32; 12] = [
|
||||
0, 1, 2, 2, 1, 3, //Front side
|
||||
6, 5, 4, 7, 5, 6, //Back side
|
||||
];
|
||||
|
||||
|
||||
const UV_COORDS: [[f32; 2]; 4] = [
|
||||
[0., 0.],
|
||||
[0., 1.],
|
||||
[1., 0.],
|
||||
[1., 1.],
|
||||
];
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct MeshBuilder {
|
||||
vertex_buffer: Vec<ChunkVertex>,
|
||||
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, texture: u8) {
|
||||
let coord = coord.as_vec3();
|
||||
let face_index = face as usize;
|
||||
|
||||
//Push vertices
|
||||
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(ChunkVertex {
|
||||
position: (coord + vert[i]).to_array(),
|
||||
normal: norm.to_array(),
|
||||
uv: UV_COORDS[i],
|
||||
tex_index: texture
|
||||
});
|
||||
}
|
||||
|
||||
//Push indices
|
||||
self.index_buffer.extend_from_slice(&CUBE_FACE_INDICES.map(|x| x + self.idx_counter));
|
||||
|
||||
//Increment idx counter
|
||||
self.idx_counter += 4;
|
||||
}
|
||||
|
||||
pub fn add_diagonal_face(&mut self, coord: IVec3, face_type: DiagonalFace, front_texture: u8, back_texture: u8) {
|
||||
//Push vertices
|
||||
let face_type = face_type as usize;
|
||||
let vertices = CROSS_FACES[face_type];
|
||||
let normal_front = CROSS_FACE_NORMALS[face_type].to_array();
|
||||
let normal_back = CROSS_FACE_NORMALS_BACK[face_type].to_array();
|
||||
self.vertex_buffer.reserve(8);
|
||||
for i in 0..4 { //push front vertices
|
||||
self.vertex_buffer.push(ChunkVertex {
|
||||
position: (coord.as_vec3() + vertices[i]).to_array(),
|
||||
normal: normal_front,
|
||||
uv: UV_COORDS[i],
|
||||
tex_index: front_texture
|
||||
})
|
||||
}
|
||||
for i in 0..4 { //push back vertices
|
||||
self.vertex_buffer.push(ChunkVertex {
|
||||
position: (coord.as_vec3() + vertices[i]).to_array(),
|
||||
normal: normal_back,
|
||||
uv: UV_COORDS[i],
|
||||
tex_index: back_texture
|
||||
})
|
||||
}
|
||||
|
||||
//Push indices
|
||||
self.index_buffer.extend_from_slice(&CROSS_FACE_INDICES.map(|x| x + self.idx_counter));
|
||||
|
||||
//Increment idx counter
|
||||
self.idx_counter += 8;
|
||||
}
|
||||
|
||||
pub fn add_model(&mut self, position: Vec3, vertices: &[ChunkVertex], indices: Option<&[u32]>) {
|
||||
//push vertices
|
||||
self.vertex_buffer.extend(vertices.iter().map(|vertex| {
|
||||
let mut vertex = *vertex;
|
||||
vertex.position[0] += position.x;
|
||||
vertex.position[0] += position.y;
|
||||
vertex.position[0] += position.z;
|
||||
vertex
|
||||
}));
|
||||
//push indices
|
||||
if let Some(indices) = indices {
|
||||
self.index_buffer.extend(indices.iter().map(|x| x + self.idx_counter));
|
||||
} else {
|
||||
self.index_buffer.extend(0..(self.vertex_buffer.len() as u32));
|
||||
}
|
||||
//increment idx counter
|
||||
self.idx_counter += vertices.len() as u32;
|
||||
}
|
||||
|
||||
pub fn finish(self) -> (Vec<ChunkVertex>, Vec<u32>) {
|
||||
(self.vertex_buffer, self.index_buffer)
|
||||
}
|
||||
}
|
||||
use strum::EnumIter;
|
||||
use glam::{ivec3, vec3, IVec3, Vec3};
|
||||
use std::f32::consts::FRAC_1_SQRT_2;
|
||||
use crate::rendering::world::ChunkVertex;
|
||||
|
||||
#[repr(usize)]
|
||||
#[derive(Clone, Copy, Debug, EnumIter)]
|
||||
pub enum CubeFace {
|
||||
Top = 0,
|
||||
Front = 4,
|
||||
Left = 2,
|
||||
Right = 3,
|
||||
Back = 1,
|
||||
Bottom = 5,
|
||||
}
|
||||
impl CubeFace {
|
||||
pub const fn normal(self) -> IVec3 {
|
||||
CUBE_FACE_NORMALS_IVEC3[self as usize]
|
||||
}
|
||||
}
|
||||
|
||||
const CUBE_FACE_VERTICES: [[Vec3; 4]; 6] = [
|
||||
[vec3(0., 1., 0.), vec3(0., 1., 1.), vec3(1., 1., 0.), vec3(1., 1., 1.)],
|
||||
[vec3(0., 0., 0.), vec3(0., 1., 0.), vec3(1., 0., 0.), vec3(1., 1., 0.)],
|
||||
[vec3(0., 0., 1.), vec3(0., 1., 1.), vec3(0., 0., 0.), vec3(0., 1., 0.)],
|
||||
[vec3(1., 0., 0.), vec3(1., 1., 0.), vec3(1., 0., 1.), vec3(1., 1., 1.)],
|
||||
[vec3(1., 0., 1.), vec3(1., 1., 1.), vec3(0., 0., 1.), vec3(0., 1., 1.)],
|
||||
[vec3(0., 0., 1.), vec3(0., 0., 0.), vec3(1., 0., 1.), vec3(1., 0., 0.)],
|
||||
];
|
||||
const CUBE_FACE_NORMALS_IVEC3: [IVec3; 6] = [
|
||||
ivec3( 0, 1, 0),
|
||||
ivec3( 0, 0, -1),
|
||||
ivec3(-1, 0, 0),
|
||||
ivec3( 1, 0, 0),
|
||||
ivec3( 0, 0, 1),
|
||||
ivec3( 0, -1, 0)
|
||||
];
|
||||
const CUBE_FACE_NORMALS: [Vec3; 6] = [
|
||||
vec3(0., 1., 0.),
|
||||
vec3(0., 0., -1.),
|
||||
vec3(-1.,0., 0.),
|
||||
vec3(1., 0., 0.),
|
||||
vec3(0., 0., 1.),
|
||||
vec3(0., -1.,0.)
|
||||
];
|
||||
const CUBE_FACE_INDICES: [u32; 6] = [0, 1, 2, 2, 1, 3];
|
||||
|
||||
#[repr(usize)]
|
||||
pub enum DiagonalFace {
|
||||
RigthZ = 0,
|
||||
LeftZ = 1,
|
||||
}
|
||||
const CROSS_FACES: [[Vec3; 4]; 2] = [
|
||||
[
|
||||
vec3(0., 0., 0.),
|
||||
vec3(0., 1., 0.),
|
||||
vec3(1., 0., 1.),
|
||||
vec3(1., 1., 1.),
|
||||
],
|
||||
[
|
||||
vec3(0., 0., 1.),
|
||||
vec3(0., 1., 1.),
|
||||
vec3(1., 0., 0.),
|
||||
vec3(1., 1., 0.),
|
||||
]
|
||||
];
|
||||
const CROSS_FACE_NORMALS: [Vec3; 2] = [
|
||||
vec3(-FRAC_1_SQRT_2, 0., FRAC_1_SQRT_2),
|
||||
vec3( FRAC_1_SQRT_2, 0., FRAC_1_SQRT_2),
|
||||
];
|
||||
const CROSS_FACE_NORMALS_BACK: [Vec3; 2] = [
|
||||
vec3( FRAC_1_SQRT_2, 0., -FRAC_1_SQRT_2),
|
||||
vec3(-FRAC_1_SQRT_2, 0., -FRAC_1_SQRT_2),
|
||||
];
|
||||
const CROSS_FACE_INDICES: [u32; 12] = [
|
||||
0, 1, 2, 2, 1, 3, //Front side
|
||||
6, 5, 4, 7, 5, 6, //Back side
|
||||
];
|
||||
|
||||
|
||||
const UV_COORDS: [[f32; 2]; 4] = [
|
||||
[0., 0.],
|
||||
[0., 1.],
|
||||
[1., 0.],
|
||||
[1., 1.],
|
||||
];
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct MeshBuilder {
|
||||
offset: Vec3,
|
||||
vertex_buffer: Vec<ChunkVertex>,
|
||||
index_buffer: Vec<u32>,
|
||||
idx_counter: u32,
|
||||
}
|
||||
impl MeshBuilder {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn new_with_offset(offset: Vec3) -> Self {
|
||||
Self { offset, ..Self::new() }
|
||||
}
|
||||
|
||||
pub fn add_face(&mut self, face: CubeFace, coord: IVec3, texture: u8) {
|
||||
let coord = coord.as_vec3();
|
||||
let face_index = face as usize;
|
||||
|
||||
//Push vertices
|
||||
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(ChunkVertex {
|
||||
position: (coord + vert[i] + self.offset).to_array(),
|
||||
normal: norm.to_array(),
|
||||
uv: UV_COORDS[i],
|
||||
tex_index: texture as u32
|
||||
});
|
||||
}
|
||||
|
||||
//Push indices
|
||||
self.index_buffer.extend_from_slice(&CUBE_FACE_INDICES.map(|x| x + self.idx_counter));
|
||||
|
||||
//Increment idx counter
|
||||
self.idx_counter += 4;
|
||||
}
|
||||
|
||||
pub fn add_diagonal_face(&mut self, coord: IVec3, face_type: DiagonalFace, front_texture: u8, back_texture: u8) {
|
||||
//Push vertices
|
||||
let face_type = face_type as usize;
|
||||
let vertices = CROSS_FACES[face_type];
|
||||
let normal_front = CROSS_FACE_NORMALS[face_type].to_array();
|
||||
let normal_back = CROSS_FACE_NORMALS_BACK[face_type].to_array();
|
||||
self.vertex_buffer.reserve(8);
|
||||
for i in 0..4 { //push front vertices
|
||||
self.vertex_buffer.push(ChunkVertex {
|
||||
position: (coord.as_vec3() + vertices[i] + self.offset).to_array(),
|
||||
normal: normal_front,
|
||||
uv: UV_COORDS[i],
|
||||
tex_index: front_texture as u32
|
||||
})
|
||||
}
|
||||
for i in 0..4 { //push back vertices
|
||||
self.vertex_buffer.push(ChunkVertex {
|
||||
position: (coord.as_vec3() + vertices[i] + self.offset).to_array(),
|
||||
normal: normal_back,
|
||||
uv: UV_COORDS[i],
|
||||
tex_index: back_texture as u32
|
||||
})
|
||||
}
|
||||
|
||||
//Push indices
|
||||
self.index_buffer.extend_from_slice(&CROSS_FACE_INDICES.map(|x| x + self.idx_counter));
|
||||
|
||||
//Increment idx counter
|
||||
self.idx_counter += 8;
|
||||
}
|
||||
|
||||
//XXX: needs offset supprt
|
||||
// pub fn add_model(&mut self, position: Vec3, vertices: &[ChunkVertex], indices: Option<&[u32]>) {
|
||||
// //push vertices
|
||||
// self.vertex_buffer.extend(vertices.iter().map(|vertex| {
|
||||
// let mut vertex = *vertex;
|
||||
// vertex.position[0] += position.x;
|
||||
// vertex.position[0] += position.y;
|
||||
// vertex.position[0] += position.z;
|
||||
// vertex
|
||||
// }));
|
||||
// //push indices
|
||||
// if let Some(indices) = indices {
|
||||
// self.index_buffer.extend(indices.iter().map(|x| x + self.idx_counter));
|
||||
// } else {
|
||||
// self.index_buffer.extend(0..(self.vertex_buffer.len() as u32));
|
||||
// }
|
||||
// //increment idx counter
|
||||
// self.idx_counter += vertices.len() as u32;
|
||||
// }
|
||||
|
||||
pub fn finish(self) -> (Vec<ChunkVertex>, Vec<u32>) {
|
||||
(self.vertex_buffer, self.index_buffer)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ impl ChunkTaskManager {
|
|||
let (
|
||||
(vertices, indices),
|
||||
(trans_vertices, trans_indices),
|
||||
) = generate_mesh(data);
|
||||
) = generate_mesh(position, data);
|
||||
ChunkTaskResponse::GeneratedMesh {
|
||||
position,
|
||||
vertices, indices,
|
||||
|
|
Loading…
Reference in a new issue