diff --git a/Cargo.toml b/Cargo.toml index 277784b..0a318f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ tobj = "2.0.3" gilrs = "0.8.0" gfx-backend-vulkan = { version = "0.6", features = ["x11"] } lazy_static = "1.4.0" +crossbeam = "0.8.0" cgmath = "0.18.0" rapier3d = { version = "0.5.0", features = ["simd-nightly", "parallel"] } diff --git a/src/components.rs b/src/components.rs index 65db69e..9772310 100644 --- a/src/components.rs +++ b/src/components.rs @@ -28,29 +28,12 @@ pub struct Position { pub rot: cgmath::Euler>, } -#[derive(Clone, Copy, Debug, PartialEq)] -pub struct Color { - pub r: f32, - pub g: f32, - pub b: f32, - pub a: f32, -} - -#[derive(Clone, Copy, Debug, PartialEq)] -pub struct Velocity { - pub dx: f32, - pub dy: f32, - pub rs: f32, -} - #[derive(Clone, Default, PartialEq, Eq, Hash, Copy, Debug)] pub struct RangeCopy { pub start: Idx, pub end: Idx, } - - #[derive(Clone, Debug)] pub struct Mesh { pub index_buffer: Arc, @@ -59,6 +42,7 @@ pub struct Mesh { pub vertex_buffer: Arc, pub uniform_buffer: Arc, pub bind_group: Arc, + pub color: wgpu::Color, } #[derive(Clone, Debug)] diff --git a/src/geometry.rs b/src/geometry.rs index 9f9914e..08c0ee9 100644 --- a/src/geometry.rs +++ b/src/geometry.rs @@ -1,24 +1,32 @@ use bytemuck::{Pod, Zeroable}; +use nalgebra::Vector4; + #[repr(C)] #[derive(Clone, Copy, Debug)] pub struct Vertex { - _pos: [f32; 4], - _normal: [f32; 4], + pos: [f32; 4], + normal: [f32; 4], } -unsafe impl Pod for Vertex {} +impl Vertex { + pub fn position(&self) -> Vector4 { + Vector4::new(self.pos[0], self.pos[1], self.pos[2], self.pos[3]) + } + pub fn from(pos: [f32; 3], nor: [f32; 3]) -> Vertex { + Vertex { + pos: [pos[0], pos[1], pos[2], 1.0], + normal: [nor[0], nor[1], nor[2], 0.0], + } + } +} +unsafe impl Pod for Vertex {} unsafe impl Zeroable for Vertex {} -pub fn vertex(pos: [f32; 3], nor: [f32; 3]) -> Vertex { - Vertex { - _pos: [pos[0], pos[1], pos[2], 1.0], - _normal: [nor[0], nor[1], nor[2], 0.0], - } -} -pub fn import_mesh(mesh_path: &str) -> (Vec, Vec) { + +pub fn load_obj(mesh_path: &str) -> (Vec, Vec) { let (models, materials) = tobj::load_obj(mesh_path, false).expect("Failed to load file"); @@ -46,7 +54,7 @@ pub fn import_mesh(mesh_path: &str) -> (Vec, Vec) { for v in 0..mesh.positions.len() / 3 { vertex_data.push( - vertex([ + Vertex::from([ mesh.positions[3 * v], mesh.positions[3 * v + 1], mesh.positions[3 * v + 2] diff --git a/src/main.rs b/src/main.rs index fa2ad44..6cf2ab1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,18 +1,15 @@ extern crate imgui; extern crate imgui_wgpu; -extern crate tobj; -extern crate winit_24; #[macro_use] extern crate lazy_static; +extern crate tobj; +extern crate winit_24; -use std::borrow::Borrow; use std::f32::consts::PI; -use std::rc::Rc; use std::sync::{Arc, Mutex}; #[cfg(not(target_arch = "wasm32"))] use std::time::{Duration, Instant}; -use bytemuck::__core::ops::Range; use cgmath::{ Decomposed, Deg, Euler, InnerSpace, Point3, Quaternion, Rad, Rotation3, SquareMatrix, }; @@ -32,6 +29,7 @@ use rapier3d::dynamics::{ }; use rapier3d::geometry::{BroadPhase, ColliderBuilder, ColliderHandle, ColliderSet, NarrowPhase}; use rapier3d::math; +use rapier3d::math::Point; use rapier3d::na::{Isometry, Isometry3, Vector, Vector3}; use rapier3d::pipeline::PhysicsPipeline; use wgpu::{BindGroup, Buffer, TextureView}; @@ -45,7 +43,8 @@ use winit_24::{ }; use crate::camera::{Camera, CameraController}; -use crate::components::{Collider, Color, ImguiWindow, LoopState, Physics, Position}; +use crate::components::{Collider, ImguiWindow, LoopState, Physics, Position}; +use crate::geometry::load_obj; use crate::imgui_supp::extended_winit_imgui_support; use crate::imgui_supp::imgui_support::{ImguiContext, ImguiPlatform}; use crate::owned_event::{OwnedEvent, OwnedEventExtension}; @@ -91,8 +90,9 @@ ECS // ImGUI works on more or less a global state. which is MegaLame static mut CURRENT_UI: Option> = None; -pub unsafe fn current_ui<'a>() -> Option<&'a imgui::Ui<'a>> { CURRENT_UI.as_ref() } - +pub unsafe fn current_ui<'a>() -> Option<&'a imgui::Ui<'a>> { + CURRENT_UI.as_ref() +} fn main() { let mut world = World::default(); @@ -190,18 +190,18 @@ fn main() { if gamepad_.name() == "PS4" { gamepad = Some(gamepad_); } - println!( - "{} is {:?} {:?}", - gamepad_.name(), - gamepad_.power_info(), - gamepad_.id() - ); + // println!( + // "{} is {:?} {:?}", + // gamepad_.name(), + // gamepad_.power_info(), + // gamepad_.id() + // ); } let mut active_gamepad = None; loop { while let Some(GilEvent { id, event, time }) = gilrs.next_event() { - println!("{:?} New event from {}: {:?}", time, id, event); + //println!("{:?} New event from {}: {:?}", time, id, event); active_gamepad = Some(id); event_loop_proxy .send_event(OwnedEventExtension::GamepadEvent { @@ -235,9 +235,7 @@ fn main() { event_loop.run(move |event, _, control_flow| { *control_flow = ControlFlow::Poll; match event { - event::Event::NewEvents(cause) => { - - } + event::Event::NewEvents(cause) => {} // This is the big boy section of the event loop // We : dispatch events and clear the queue, query the loops @@ -266,7 +264,7 @@ fn main() { } accumulator_time += delta_time; - while ((accumulator_time - step_size) >= step_size) { + while accumulator_time - step_size >= step_size { accumulator_time -= step_size; // ==== DELTA TIME LOCKED ==== update_schedule.execute(&mut world, &mut resources); @@ -280,7 +278,6 @@ fn main() { event: WindowEvent::Resized(size), .. } => { - log::info!("Resizing to {:?}", size); let width = size.width; let height = size.height; @@ -295,8 +292,8 @@ fn main() { } => *control_flow = ControlFlow::Exit, event::Event::RedrawRequested(_) => { // Call the render system -// imgui_prepare_schedule.execute(&mut world, &mut resources); -// render_schedule.execute(&mut world, &mut resources); + // imgui_prepare_schedule.execute(&mut world, &mut resources); + // render_schedule.execute(&mut world, &mut resources); } _ => {} } @@ -308,10 +305,67 @@ fn main() { }); } -pub fn entity_loading(world: &mut World, renderer: &mut render::state::RenderState) { +pub fn load_colliding_mesh_entity(world: &mut World, renderer: &mut render::state::RenderState, mesh_path: &str) { + let mut static_floor_body = RigidBodyBuilder::new_static() + .position(Isometry3::new(Vector3::new(0.0, -8.0, 0.0), Vector::y())) + .build(); + + //let pair = import_mesh("./resources/terrain.obj"); + let pair = load_obj(mesh_path); + + let floor_collider = ColliderBuilder::trimesh( + pair.0 + .iter() + .map(|v| { + let position = v.position(); + Point::::new(position.x, position.y, position.z) + }) + .collect(), + pair.1 + .chunks(3) + .map(|v| [v[0], v[1], v[2]]) + .collect(), + ) + .build(); + + let plane_mesh = renderer.load_mesh_to_buffer( + "./resources/terrain.obj", + Some(wgpu::Color { + r: 1.0, + g: 0.7, + b: 0.3, + a: 1.0, + }), + ); + + let plane_entity: Entity = world.push(( + Position { + x: 0.0, + y: -8.0, + z: 0.0, + rot: Euler { + x: Deg(0.0), + y: Deg(0.0), + z: Deg(0.0), + }, + }, + plane_mesh, + Physics { + rigid_body: static_floor_body, + rigid_body_handle: None, + }, + Collider { + collider: floor_collider, + collider_handle: None, + }, + )); + +} - let monkey_mesh = renderer.load_mesh_to_buffer("./resources/monkey.obj"); +pub fn entity_loading(world: &mut World, renderer: &mut render::state::RenderState) { + let monkey_mesh = + renderer.load_mesh_to_buffer("./resources/monkey.obj", Some(wgpu::Color::GREEN)); let camera_ent: Entity = world.push(( Camera { @@ -323,16 +377,11 @@ pub fn entity_loading(world: &mut World, renderer: &mut render::state::RenderSta yaw: Rad(-PI), pitch: Rad(PI / 2.0), }, - Color { - r: 1.0, - g: 1.0, - b: 0.5, - a: 1.0, - }, CameraController::new(3.0, 1.0), )); - let light_mesh = renderer.load_mesh_to_buffer("./resources/light.obj"); + let light_mesh = + renderer.load_mesh_to_buffer("./resources/light.obj", Some(wgpu::Color::BLACK)); let light_entity: Entity = world.push(( Position { @@ -345,12 +394,6 @@ pub fn entity_loading(world: &mut World, renderer: &mut render::state::RenderSta z: Deg(0.0), }, }, - Color { - r: 1.0, - g: 0.0, - b: 1.0, - a: 1.0, - }, light_mesh.clone(), renderer.create_light(), )); @@ -384,61 +427,42 @@ pub fn entity_loading(world: &mut World, renderer: &mut render::state::RenderSta }, //mx: cgmath::Matrix4::from(transform), }, monkey_mesh, - Color { - r: 0.0, - g: 1.0, - b: 0.0, - a: 1.0, - }, )); let mut dynamic_ball_body = RigidBodyBuilder::new_dynamic() - .position(Isometry3::new(Vector3::new(0.0, 0.0, 0.0), Vector::y())) + .can_sleep(false) + .mass(1.0) + //.position(Isometry3::new(Vector3::new(0.0, 10.0, 0.0), Vector::y())) + .translation(0.0, 35.0, 0.0) .build(); - let mut static_floor_body = RigidBodyBuilder::new_static() - .position(Isometry3::new(Vector3::new(0.0, -8.0, 0.0), Vector::y())) + + let pair = load_obj("./resources/ball.obj"); + + let ball_collider = ColliderBuilder::trimesh( + pair.0 + .iter() + .map(|v| { + let position = v.position(); + Point::::new(position.x, position.y, position.z) + }) + .collect(), + pair.1 + //.iter() + .chunks(3) + .map(|v| [v[0], v[1], v[2]]) + .collect(), + ) .build(); - let ball_collider = ColliderBuilder::ball(1.5).build(); - let floor_collider = ColliderBuilder::cuboid(10.0, 0.2, 10.0).build(); - let plane_mesh = renderer.load_mesh_to_buffer("./resources/plane.obj"); - let plane_entity: Entity = world.push(( - Position { - x: 0.0, - y: -8.0, - z: 0.0, - rot: Euler { - x: Deg(0.0), - y: Deg(0.0), - z: Deg(0.0), - }, - }, - plane_mesh, - Color { - r: 1.0, - g: 0.5, - b: 0.5, - a: 1.0, - }, - Physics { - rigid_body: static_floor_body, - rigid_body_handle: None, - }, - Collider { - collider: floor_collider, - collider_handle: None, - }, - )); - - let ball_mesh = renderer.load_mesh_to_buffer("./resources/ball.obj"); + let ball_mesh = renderer.load_mesh_to_buffer("./resources/ball.obj", Some(wgpu::Color::BLUE)); let ball_mesh: Entity = world.push(( Position { x: 0.0, - y: 0.0, + y: 20.0, z: 0.0, rot: Euler { x: Deg(25.0), @@ -447,12 +471,6 @@ pub fn entity_loading(world: &mut World, renderer: &mut render::state::RenderSta }, }, ball_mesh, - Color { - r: 1.0, - g: 0.5, - b: 0.5, - a: 1.0, - }, Physics { rigid_body: dynamic_ball_body, rigid_body_handle: None, diff --git a/src/owned_event.rs b/src/owned_event.rs index 725bf58..88bf9f0 100644 --- a/src/owned_event.rs +++ b/src/owned_event.rs @@ -280,7 +280,7 @@ pub fn event_dispatch( match keyboard_input.virtual_keycode.unwrap() { VirtualKeyCode::A => { if keyboard_input.state == ElementState::Pressed { - println!("cursorijf"); + winit_window.set_cursor_position( LogicalPosition{ x: 100.0, y: 100.0 } ); diff --git a/src/physics/system.rs b/src/physics/system.rs index 3e5ed62..8767fff 100644 --- a/src/physics/system.rs +++ b/src/physics/system.rs @@ -7,7 +7,7 @@ use legion::*; use nalgebra::Quaternion as naQuaternion; use rapier3d::dynamics::{IntegrationParameters, JointSet, RigidBodySet}; use rapier3d::geometry::{BroadPhase, ColliderSet, NarrowPhase}; -use rapier3d::pipeline::PhysicsPipeline; +use rapier3d::pipeline::{PhysicsPipeline, ChannelEventCollector}; use crate::camera::{Camera, CameraController}; use crate::components::{Collider, LoopState, Mesh, Physics, Position}; @@ -45,8 +45,12 @@ pub fn run_physics( } } + let (contact_send, contact_recv) = crossbeam::channel::unbounded(); + let (intersection_send, intersection_recv) = crossbeam::channel::unbounded(); + let event_handler = ChannelEventCollector::new(intersection_send, contact_send); + + // run the physics step - let event_handler = (); physics_pipeline.step( &physics_state.gravity, &physics_state.integration_parameters, @@ -59,6 +63,14 @@ pub fn run_physics( None, &event_handler, ); + + while let Ok(intersection_event) = intersection_recv.try_recv() { + println!("{:?}", intersection_event) + } + + while let Ok(contact_event) = contact_recv.try_recv() { + println!("{:?}", contact_event) + } } diff --git a/src/render/state.rs b/src/render/state.rs index 91c8cb4..6ca0d21 100644 --- a/src/render/state.rs +++ b/src/render/state.rs @@ -24,9 +24,9 @@ use winit_24::platform::unix::x11::ffi::Time; use winit_24::window::Window; use crate::camera::{Camera, CameraController}; -use crate::components::{Color, Mesh, Position, RangeCopy}; +use crate::components::{Mesh, Position, RangeCopy}; use crate::current_ui; -use crate::geometry::{import_mesh, vertex, Vertex}; +use crate::geometry::{load_obj, Vertex}; use crate::imgui_supp::imgui_support::{ImguiContext, ImguiPlatform}; use crate::light::{DirectionalLight, LightRaw}; use crate::render::{EntityUniforms, ShadowUniforms, ForwardUniforms}; @@ -134,45 +134,10 @@ impl RenderState { (vertex_buf, index_buf) } - /// When creating a light we have to give it a target view to render to - /// This is major danger scary since we have a 10 light limit, and only - /// 2 views created at this moment, need to smarten this up - pub fn create_light(&mut self) -> DirectionalLight { - let target = self - .shadow_target_views - .get(self.views_given as usize) - .take() - .unwrap(); - self.views_given = self.views_given + 1; - DirectionalLight { - color: wgpu::Color { - r: 1.0, - g: 0.5, - b: 0.5, - a: 1.0, - }, - fov: 45.0, - depth: RangeCopy { - start: 1.0, - end: 20.0, - }, - target_view: target.clone(), - pos: Position { - x: 0.0, - y: 0.0, - z: 0.0, - rot: Euler { - x: Deg(0.0), - y: Deg(-25.0), - z: Deg(0.0), - }, - }, - } - } - - pub fn load_mesh_to_buffer(&self, filepath: &str) -> Mesh { - let (vertices, indices) = import_mesh(filepath); + pub fn load_mesh_to_buffer(&self, filepath: &str, color: Option) -> Mesh { + let (vertices, indices) = load_obj(filepath); let index_count = indices.len(); + let (vertex_buf, index_buf) = RenderState::create_buffer(&self.device, indices, vertices); let uniform_size = mem::size_of::() as wgpu::BufferAddress; @@ -205,6 +170,43 @@ impl RenderState { vertex_buffer: vertex_buf, uniform_buffer: uniform_buf, bind_group: bind_group, + color: color.unwrap_or(wgpu::Color::RED), + } + } + + /// When creating a light we have to give it a target view to render to + /// This is major danger scary since we have a 10 light limit, and only + /// 2 views created at this moment, need to smarten this up + pub fn create_light(&mut self) -> DirectionalLight { + let target = self + .shadow_target_views + .get(self.views_given as usize) + .take() + .unwrap(); + self.views_given = self.views_given + 1; + DirectionalLight { + color: wgpu::Color { + r: 1.0, + g: 0.5, + b: 0.5, + a: 1.0, + }, + fov: 45.0, + depth: RangeCopy { + start: 1.0, + end: 20.0, + }, + target_view: target.clone(), + pos: Position { + x: 0.0, + y: 0.0, + z: 0.0, + rot: Euler { + x: Deg(0.0), + y: Deg(-25.0), + z: Deg(0.0), + }, + }, } } @@ -437,7 +439,7 @@ impl RenderState { cgmath::Deg(75f32), // FOV, might wanna hook this up somewhere sc_desc.width as f32 / sc_desc.height as f32, 1.0, - 20.0, + 50.0, ); let forward_pass = { diff --git a/src/render/system.rs b/src/render/system.rs index 6f4dae0..73f0211 100644 --- a/src/render/system.rs +++ b/src/render/system.rs @@ -24,9 +24,9 @@ use winit_24::platform::unix::x11::ffi::Time; use winit_24::window::Window; use crate::camera::{Camera, CameraController}; -use crate::components::{Color, Mesh, Position, RangeCopy}; +use crate::components::{Mesh, Position, RangeCopy}; use crate::current_ui; -use crate::geometry::{import_mesh, vertex, Vertex}; +use crate::geometry::{load_obj, Vertex}; use crate::imgui_supp::imgui_support::{ImguiContext, ImguiPlatform}; use crate::light::{DirectionalLight, LightRaw}; use crate::render::state::{RenderState}; @@ -52,12 +52,12 @@ pub fn imgui_prepare( // get the frame and build a ui window unsafe { crate::CURRENT_UI = Some(std::mem::transmute(imgui_context.frame())) } } + #[system] #[write_component(Camera)] #[write_component(Position)] #[write_component(Point3)] #[write_component(Mesh)] -#[write_component(Color)] #[write_component(DirectionalLight)] pub fn render_test( world: &mut SubWorld, @@ -88,11 +88,11 @@ pub fn render_test( ); } - let mut query = <(&mut Position, &mut Mesh, &mut Color)>::query(); + let mut query = <(&mut Position, &mut Mesh)>::query(); let mut mesh_stack = Vec::new(); // Update the entity uniforms - for (pos, mesh, color) in query.iter_mut(world) { + for (pos, mesh) in query.iter_mut(world) { let d = Decomposed { scale: 1.0, rot: Quaternion::from(pos.rot), @@ -102,10 +102,10 @@ pub fn render_test( let data = EntityUniforms { model: m.into(), color: [ - color.r as f32, - color.g as f32, - color.b as f32, - color.a as f32, + mesh.color.r as f32, + mesh.color.g as f32, + mesh.color.b as f32, + mesh.color.a as f32, ], }; renderer @@ -204,9 +204,9 @@ pub fn render_test( pass.set_pipeline(&renderer.forward_pass.pipeline); pass.set_bind_group(0, &renderer.forward_pass.bind_group, &[]); - let mut query = <(&mut Position, &mut Mesh, &mut Color)>::query(); + let mut query = <(&mut Position, &mut Mesh)>::query(); - for (pos, mesh, color) in query.iter_mut(world) { + for (pos, mesh) in query.iter_mut(world) { pass.set_bind_group(1, &mesh.bind_group, &[]); // TODO: Pipe this in through the mesh pass.set_index_buffer(mesh.index_buffer.slice(..), mesh.index_format);