diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..53ec8ed --- /dev/null +++ b/.drone.yml @@ -0,0 +1,9 @@ +kind: pipeline +type: docker +name: frontend + +steps: + - name: dependencies + image: rust:slim + commands: + - cargo doc diff --git a/Cargo.lock b/Cargo.lock index 36d1a93..cbfde82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -85,6 +85,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "base64" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" + [[package]] name = "bit-set" version = "0.5.2" @@ -805,6 +811,43 @@ dependencies = [ "web-sys", ] +[[package]] +name = "gltf" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ff38b75359a0096dd0a8599b6e4f37a6ee41d5df300cc7669e62aafa697f7a2" +dependencies = [ + "base64", + "byteorder", + "gltf-json", + "image", + "lazy_static", +] + +[[package]] +name = "gltf-derive" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f2a9333e0f9c7bca94dfc20bcf44fa12a61eeec662d6e007563ff748aa59c70" +dependencies = [ + "inflections", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "gltf-json" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1414d3a98cbaabdb2f134328b1f6036d14b282febc1df51952a435d2ca17fb6" +dependencies = [ + "gltf-derive", + "serde", + "serde_derive", + "serde_json", +] + [[package]] name = "gpu-alloc" version = "0.4.7" @@ -903,6 +946,12 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "inflections" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" + [[package]] name = "inplace_it" version = "0.3.3" @@ -921,6 +970,12 @@ dependencies = [ "web-sys", ] +[[package]] +name = "itoa" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" + [[package]] name = "jni-sys" version = "0.3.0" @@ -1058,6 +1113,7 @@ dependencies = [ "cgmath", "env_logger", "futures", + "gltf", "image", "log", "noise", @@ -1537,6 +1593,12 @@ version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +[[package]] +name = "ryu" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" + [[package]] name = "scoped_threadpool" version = "0.1.9" @@ -1555,6 +1617,28 @@ version = "1.0.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" +[[package]] +name = "serde_derive" +version = "1.0.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" +dependencies = [ + "itoa", + "ryu", + "serde", +] + [[package]] name = "slab" version = "0.4.3" diff --git a/Cargo.toml b/Cargo.toml index 23161e2..f4f9d21 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +gltf = "0.16" ahash = "0.7.4" anyhow = "1.0.40" bytemuck = { version = "1.5.1", features = ["derive"] } diff --git a/assets/models/minecrab.glb b/assets/models/minecrab.glb new file mode 100644 index 0000000..9f2051b --- /dev/null +++ b/assets/models/minecrab.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4521de51494995a990f0cdad33005d72d38a32bc6bcb83d18c591ce755128a20 +size 43368 diff --git a/src/main.rs b/src/main.rs index 05b921d..cebc99a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,6 +11,7 @@ mod time; mod vertex; mod view; mod world; +mod npc; use std::time::{Duration, Instant}; use wgpu::SwapChainError; diff --git a/src/npc.rs b/src/npc.rs new file mode 100644 index 0000000..080b281 --- /dev/null +++ b/src/npc.rs @@ -0,0 +1,65 @@ +extern crate gltf; +extern crate wgpu; + +use cgmath::Vector3; + +use crate::vertex::BlockVertex; + +pub struct Npc { + pub position: Vector3, + pub scale: Vector3, + pub rotation: Vector3, + pub vertices: Vec, + pub indices: Vec, + pub vertex_buffer: Option, + pub index_buffer: Option, +} + +impl Npc { + pub fn load() -> Self { + let position: Vector3 = Vector3::new(0.0, 0.0, 0.0); + let scale: Vector3 = Vector3::new(0.0, 0.0, 0.0); + let rotation: Vector3 = Vector3::new(0.0, 0.0, 0.0); + + let (model, buffers, _) = gltf::import("assets/models/minecrab.glb").unwrap(); + + let mut indices = Vec::new(); + let mut vertices = Vec::new(); + + for mesh in model.meshes() { + for primitive in mesh.primitives() { + let reader = primitive.reader(|buffer| Some(&buffers[buffer.index()])); + indices = reader.read_indices().unwrap().into_u32().collect(); + + // loop over all primitives and get the normals, position and color + let pos_iter = reader.read_positions().unwrap(); + let norm_iter = reader.read_normals().unwrap(); + let tex_iter = reader.read_tex_coords(0).unwrap().into_f32(); + + for ((position, normal), texture_coordinates) in + pos_iter.zip(norm_iter).zip(tex_iter) + { + let current_vert = BlockVertex { + position, + texture_coordinates, + normal, + highlighted: 0, + texture_id: 0, + }; + + vertices.push(current_vert); + } + } + } + + return Self { + position, + scale, + rotation, + indices, + vertices, + vertex_buffer: None, + index_buffer: None, + }; + } +} diff --git a/src/state/world_state.rs b/src/state/world_state.rs index f334aa0..cbb0e55 100644 --- a/src/state/world_state.rs +++ b/src/state/world_state.rs @@ -50,6 +50,7 @@ pub struct WorldState { pub up_speed: f32, pub sprinting: bool, + pub creative: bool, } impl WorldState { @@ -234,6 +235,24 @@ impl WorldState { println!("World update took {:?}", elapsed); } + pub fn load_npc_geometry(&mut self, render_context: &RenderContext) { + self.world.npc.vertex_buffer = Some(render_context.device.create_buffer_init( + &BufferInitDescriptor { + label: None, + contents: &bytemuck::cast_slice(&self.world.npc.vertices), + usage: wgpu::BufferUsage::VERTEX, + }, + )); + + self.world.npc.index_buffer = Some(render_context.device.create_buffer_init( + &BufferInitDescriptor { + label: None, + contents: &bytemuck::cast_slice(&self.world.npc.indices), + usage: wgpu::BufferUsage::INDEX, + }, + )); + } + pub fn update_chunk_geometry( &mut self, render_context: &RenderContext, @@ -326,9 +345,11 @@ impl WorldState { backward_pressed: false, left_pressed: false, right_pressed: false, + creative: false, }; world_state.update_world_geometry(render_context); + world_state.load_npc_geometry(render_context); world_state } @@ -383,6 +404,16 @@ impl WorldState { triangle_count += buffers.index_count / 3; } + { + let vertex_buffer = self.world.npc.vertex_buffer.as_ref(); + let index_buffer = self.world.npc.index_buffer.as_ref(); + + render_pass.set_vertex_buffer(0, vertex_buffer.unwrap().slice(..)); + render_pass + .set_index_buffer(index_buffer.unwrap().slice(..), wgpu::IndexFormat::Uint32); + render_pass.draw_indexed(0..self.world.npc.indices.len() as u32, 0, 0..1); + } + triangle_count } @@ -459,7 +490,21 @@ impl WorldState { VirtualKeyCode::S => self.backward_pressed = pressed, VirtualKeyCode::A => self.left_pressed = pressed, VirtualKeyCode::D => self.right_pressed = pressed, - VirtualKeyCode::Space if state == ElementState::Pressed => self.up_speed = 0.6, + VirtualKeyCode::F2 if pressed => self.creative = !self.creative, + VirtualKeyCode::Space => { + self.up_speed = if self.creative { + if pressed { + 1.0 + } else { + 0.0 + } + } else { + 0.6 + } + } + VirtualKeyCode::LShift if self.creative => { + self.up_speed = if pressed { -1.0 } else { 0.0 } + } VirtualKeyCode::LControl => self.sprinting = state == ElementState::Pressed, _ => (), } @@ -485,7 +530,7 @@ impl WorldState { let up = Vector3::unit_y() * self.up_speed * speed * dt_seconds; new_position += up; - if self.check_collision(new_position) { + if !self.creative && self.check_collision(new_position) { new_position -= up; self.up_speed = 0.0; } @@ -494,7 +539,7 @@ impl WorldState { let forward = Vector3::new(yaw_cos, 0.0, yaw_sin).normalize(); let forward = forward * forward_speed as f32 * speed * dt_seconds; new_position += forward; - if self.check_collision(new_position) { + if !self.creative && self.check_collision(new_position) { new_position -= forward; } @@ -502,14 +547,16 @@ impl WorldState { let right = Vector3::new(-yaw_sin, 0.0, yaw_cos).normalize(); let right = right * right_speed as f32 * speed * dt_seconds; new_position += right; - if self.check_collision(new_position) { + if !self.creative && self.check_collision(new_position) { new_position -= right; } self.camera.position = new_position; - self.up_speed -= 1.6 * dt.as_secs_f32(); - self.up_speed *= 0.98_f32.powf(dt.as_secs_f32() / 20.0); + if !self.creative { + self.up_speed -= 1.6 * dt.as_secs_f32(); + self.up_speed *= 0.98_f32.powf(dt.as_secs_f32() / 20.0); + } } pub fn update(&mut self, dt: Duration, render_context: &RenderContext) { diff --git a/src/world.rs b/src/world.rs index c91e452..483a59e 100644 --- a/src/world.rs +++ b/src/world.rs @@ -1,6 +1,7 @@ use crate::{ chunk::{Block, Chunk, CHUNK_SIZE}, geometry::Geometry, + npc::Npc, vertex::BlockVertex, }; use cgmath::{InnerSpace, Vector3}; @@ -8,6 +9,7 @@ use rayon::prelude::*; pub struct World { pub chunks: Vec>>, + pub npc: Npc, } const WORLD_SIZE: Vector3 = Vector3::new( @@ -20,6 +22,8 @@ impl World { pub fn generate() -> Self { let mut chunks = Vec::new(); + let npc = Npc::load(); + (0..WORLD_SIZE.y) .into_par_iter() .map(|y| { @@ -36,7 +40,7 @@ impl World { }) .collect_into_vec(&mut chunks); - Self { chunks } + Self { chunks, npc } } pub fn highlighted_for_chunk(