From b18ea7371a70830ffd6134f4daea16f98d887a72 Mon Sep 17 00:00:00 2001 From: mitchellhansen Date: Sat, 13 Feb 2021 20:51:14 -0800 Subject: [PATCH] camera sorta works using the old voxel-raycaster style of spherical coords --- resources/plane.mtl | 10 ++++ resources/plane.obj | 17 ++++++ src/camera.rs | 130 +++++++++++++++++++++++++++----------------- src/main.rs | 30 ++++------ src/owned_event.rs | 60 ++++++++++---------- 5 files changed, 147 insertions(+), 100 deletions(-) create mode 100644 resources/plane.mtl create mode 100644 resources/plane.obj diff --git a/resources/plane.mtl b/resources/plane.mtl new file mode 100644 index 0000000..70d3ba1 --- /dev/null +++ b/resources/plane.mtl @@ -0,0 +1,10 @@ +# Blender MTL File: 'None' +# Material Count: 1 + +newmtl None +Ns 0 +Ka 0.000000 0.000000 0.000000 +Kd 0.8 0.8 0.8 +Ks 0.8 0.8 0.8 +d 1 +illum 2 diff --git a/resources/plane.obj b/resources/plane.obj new file mode 100644 index 0000000..c790230 --- /dev/null +++ b/resources/plane.obj @@ -0,0 +1,17 @@ +# Blender v2.79 (sub 0) OBJ File: '' +# www.blender.org +mtllib plane.mtl +o Plane +v -7.780000 0.000000 7.780000 +v 7.780000 0.000000 7.780000 +v -7.780000 0.000000 -7.780000 +v 7.780000 0.000000 -7.780000 +vt 1.000000 0.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vt 1.000000 1.000000 +vn 0.0000 1.0000 0.0000 +usemtl None +s off +f 2/1/1 3/2/1 1/3/1 +f 2/1/1 4/4/1 3/2/1 diff --git a/src/camera.rs b/src/camera.rs index 4481ec4..419bfea 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -1,8 +1,10 @@ -use cgmath::{Matrix4, Vector3, Point3, Rad, InnerSpace}; -use winit::event::{MouseScrollDelta, VirtualKeyCode, ElementState}; -use winit::dpi::{PhysicalPosition, LogicalPosition}; +use std::f32::consts::{FRAC_PI_2, PI}; use std::time::{Duration, Instant}; -use std::f32::consts::FRAC_PI_2; + +use cgmath::{Decomposed, InnerSpace, Matrix4, Point3, Rad, Vector3}; +use winit::dpi::{LogicalPosition, PhysicalPosition}; +use winit::event::{ElementState, MouseScrollDelta, VirtualKeyCode}; + use crate::render::OPENGL_TO_WGPU_MATRIX; #[derive(Clone, Copy, Debug, PartialEq)] @@ -13,11 +15,7 @@ pub struct Camera { } impl Camera { - pub fn new< - V: Into>, - Y: Into>, - P: Into>, - >( + pub fn new>, Y: Into>, P: Into>>( position: V, yaw: Y, pitch: P, @@ -30,21 +28,38 @@ impl Camera { } pub fn calc_matrix(&self, projection: cgmath::Matrix4) -> Matrix4 { - let mx_view = Matrix4::look_at_dir( + + let view_vector = Point3::new( + (1.0 * self.pitch.0.sin() * self.yaw.0.sin()), + (1.0 * self.pitch.0.cos()), + (1.0 * self.pitch.0.sin() * self.yaw.0.cos()), + ); + + let mx_view = Matrix4::look_at( self.position, - Vector3::new( - self.yaw.0.cos(), - self.pitch.0.sin(), - self.yaw.0.sin(), - ).normalize(), + Point3::new( + view_vector.x + self.position.x, + view_vector.y + self.position.y, + view_vector.z + self.position.z, + ), Vector3::unit_y(), ); + // I don't know how this works, but it limits pitching to like + // 70 degrees. Lame + // let mx_view = Matrix4::look_at_dir( + // self.position, + // Vector3::new( + // self.yaw.0.cos(), + // self.pitch.0.sin(), + // self.yaw.0.sin(), + // ).normalize(), + // Vector3::unit_y(), + // ); let mx_correction = OPENGL_TO_WGPU_MATRIX; mx_correction * projection * mx_view } } - #[derive(Debug)] pub struct CameraController { amount_left: f32, @@ -79,8 +94,12 @@ impl CameraController { } } - pub fn process_keyboard(&mut self, key: VirtualKeyCode, state: ElementState) -> bool{ - let amount = if state == ElementState::Pressed { 1.0 } else { 0.0 }; + pub fn process_keyboard(&mut self, key: VirtualKeyCode, state: ElementState) -> bool { + let amount = if state == ElementState::Pressed { + 1.0 + } else { + 0.0 + }; match key { VirtualKeyCode::W | VirtualKeyCode::Up => { self.amount_forward = amount; @@ -111,38 +130,52 @@ impl CameraController { } pub fn process_mouse(&mut self, mouse_dx: f64, mouse_dy: f64) { - self.rotate_horizontal = mouse_dx as f32; + self.rotate_horizontal = -mouse_dx as f32; self.rotate_vertical = mouse_dy as f32; } - pub fn process_scroll(&mut self, delta: &MouseScrollDelta) { - self.scroll = -match delta { - // I'm assuming a line is about 100 pixels - MouseScrollDelta::LineDelta(_, scroll) => scroll * 100.0, - MouseScrollDelta::PixelDelta(LogicalPosition { - y: scroll, - .. - }) => *scroll as f32, - }; - } + // pub fn process_scroll(&mut self, delta: &MouseScrollDelta) { + // self.scroll = -match delta { + // // I'm assuming a line is about 100 pixels + // MouseScrollDelta::LineDelta(_, scroll) => scroll * 100.0, + // MouseScrollDelta::PixelDelta(LogicalPosition { + // y: scroll, + // .. + // }) => *scroll as f32, + // }; + // } pub fn update_camera(&mut self, camera: &mut Camera, dt: f32) { - // Move forward/backward and left/right let (yaw_sin, yaw_cos) = camera.yaw.0.sin_cos(); let forward = Vector3::new(yaw_cos, 0.0, yaw_sin).normalize(); let right = Vector3::new(-yaw_sin, 0.0, yaw_cos).normalize(); - camera.position += forward * (self.amount_forward - self.amount_backward) * self.speed * dt; - camera.position += right * (self.amount_right - self.amount_left) * self.speed * dt; - - // Move in/out (aka. "zoom") - // Note: this isn't an actual zoom. The camera's position - // changes when zooming. I've added this to make it easier - // to get closer to an object you want to focus on. - let (pitch_sin, pitch_cos) = camera.pitch.0.sin_cos(); - let scrollward = Vector3::new(pitch_cos * yaw_cos, pitch_sin, pitch_cos * yaw_sin).normalize(); - camera.position += scrollward * self.scroll * self.speed * self.sensitivity * dt; - self.scroll = 0.0; + + let view_vector = Vector3::new( + (1.0 * camera.pitch.0.sin() * camera.yaw.0.sin()), + (1.0 * camera.pitch.0.cos()), + (1.0 * camera.pitch.0.sin() * camera.yaw.0.cos()), + ); + + let yaw_offset = camera.yaw.0 - Rad(PI).0; + let right_vector = Vector3::new( + (1.0 * camera.pitch.0.sin() * yaw_offset.sin()), + (1.0 * camera.pitch.0.cos()), + (1.0 * camera.pitch.0.sin() * yaw_offset.cos()), + ); + + camera.position += view_vector * (self.amount_forward - self.amount_backward) * self.speed * dt; + camera.position += right_vector * (self.amount_right - self.amount_left) * self.speed * dt; + + // I'm not a huge fan of this + // // Move in/out (aka. "zoom") + // // Note: this isn't an actual zoom. The camera's position + // // changes when zooming. I've added this to make it easier + // // to get closer to an object you want to focus on. + // let (pitch_sin, pitch_cos) = camera.pitch.0.sin_cos(); + // let scrollward = Vector3::new(pitch_cos * yaw_cos, pitch_sin, pitch_cos * yaw_sin).normalize(); + // camera.position += scrollward * self.scroll * self.speed * self.sensitivity * dt; + // self.scroll = 0.0; // Move up/down. Since we don't use roll, we can just // modify the y coordinate directly. @@ -150,7 +183,7 @@ impl CameraController { // Rotate camera.yaw += Rad(self.rotate_horizontal) * self.sensitivity * dt; - camera.pitch += Rad(-self.rotate_vertical) * self.sensitivity * dt; + camera.pitch += Rad(self.rotate_vertical) * self.sensitivity * dt; // If process_mouse isn't called every frame, these values // will not get set to zero, and the camera will rotate @@ -159,15 +192,10 @@ impl CameraController { self.rotate_vertical = 0.0; // Keep the camera's angle from going too high/low. - if camera.pitch < -Rad(FRAC_PI_2) { - camera.pitch = -Rad(FRAC_PI_2); - } else if camera.pitch > Rad(FRAC_PI_2) { - camera.pitch = Rad(FRAC_PI_2); + if camera.pitch < -Rad(0.0) { + camera.pitch = -Rad(0.0); + } else if camera.pitch > Rad(PI) { + camera.pitch = Rad(PI); } } } - - - - - diff --git a/src/main.rs b/src/main.rs index 56093a4..73fb22e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -124,7 +124,7 @@ fn main() { resources.insert(renderer); let (physics_state, physics_pipeline) = - PhysicsState::build(rapier3d::math::Vector::new(0.0, 0.0, -9.81)); + PhysicsState::build(rapier3d::math::Vector::new(0.0, -9.81, 0.0)); resources.insert(physics_state); resources.insert(physics_pipeline); @@ -249,14 +249,14 @@ pub fn entity_loading(world: &mut World, renderer: &mut Renderer) { let camera_ent: Entity = world.push(( Camera { position: Point3 { - x: 5.0, - y: 5.0, - z: 5.0 + x: 0.0, + y: 0.0, + z: 10.0 }, - yaw: Rad(0.0), - pitch: Rad(-75.0) + yaw: Rad(-PI), + pitch: Rad(PI/2.0) }, - CameraController::new(1.0, 1.0), + CameraController::new(3.0, 1.0), )); let light_entity: Entity = world.push(( @@ -287,7 +287,7 @@ pub fn entity_loading(world: &mut World, renderer: &mut Renderer) { let monkey_entity: Entity = world.push(( Position { x: 1.0, - y: 2.0, + y: 5.0, z: 2.0, rot: Quaternion::from(Euler { x: Deg(90.0), @@ -313,26 +313,20 @@ pub fn entity_loading(world: &mut World, renderer: &mut Renderer) { let mut static_floor_body = RigidBodyBuilder::new_static() .position(Isometry3::new( - Vector3::new(0.0, 0.0, 0.0), + Vector3::new(0.0, -8.0, 0.0), Vector::y() * PI, )) .build(); let ball_collider = ColliderBuilder::ball(1.5).build(); - let floor_collider = ColliderBuilder::cuboid(0.5, 0.2, 0.1).build(); - - //let mut dynamic_ball_body_handle = bodies.insert(dynamic_ball_body); - //let mut static_floor_body_handle = bodies.insert(static_floor_body.clone()); - - // let ball_collider_handle = colliders.insert(ball_collider, dynamic_ball_body_handle, &mut bodies); - // let floor_collider_handle = colliders.insert(floor_collider, dynamic_ball_body_handle, &mut bodies); + let floor_collider = ColliderBuilder::cuboid(10.0, 0.2, 10.0).build(); - let plane_mesh = renderer.create_plane(7.0); + let plane_mesh = renderer.load_mesh_to_buffer("./resources/plane.obj"); let plane_entity: Entity = world.push(( Position { x: 0.0, - y: 0.0, + y: -8.0, z: 0.0, rot: Quaternion::from(Euler { x: Deg(0.0), diff --git a/src/owned_event.rs b/src/owned_event.rs index 639176c..4fcd018 100644 --- a/src/owned_event.rs +++ b/src/owned_event.rs @@ -12,6 +12,7 @@ use winit::event::{ use winit::window::{Theme, WindowId}; use crate::camera::{Camera, CameraController}; +use crate::owned_event::OwnedWindowEvent::MouseWheel; #[derive(Clone)] pub enum OwnedUIEvent { @@ -249,44 +250,41 @@ pub fn event_dispatch( for event in event_stack { match event { OwnedEvent::DeviceEvent { - event: MouseMotion { delta }, + event: winit::event::DeviceEvent::MouseMotion { delta }, .. } => { let mut query = <(&mut CameraController)>::query(); for (camera_controller) in query.iter_mut(world) { camera_controller.process_mouse(delta.0, delta.1); } - } - - OwnedEvent::DeviceEvent { device_id, event } => { - match event { - winit::event::DeviceEvent::Key(keyboard_input) => { - let mut query = <(&mut CameraController)>::query(); - for (camera_controller) in query.iter_mut(world) { - camera_controller.process_keyboard( - keyboard_input.virtual_keycode.unwrap(), - keyboard_input.state, - ); - } - - // match keyboard_input.virtual_keycode.unwrap() { - // VirtualKeyCode::A => { - // if keyboard_input.state == ElementState::Pressed {} - // } - // VirtualKeyCode::S => { - // if keyboard_input.state == ElementState::Pressed {} - // } - // VirtualKeyCode::P => { - // if keyboard_input.state == ElementState::Pressed { - // let data = world.write_resource::().read_compute_buffer(compute_buffer.clone()); - // image::save_buffer(&Path::new("image.png"), data.as_slice(), (image_data.1).0, (image_data.1).1, image::RGBA(8)); - // } - // } - // _ => () - // } - } - _ => {} + }, + OwnedEvent::DeviceEvent { + event: winit::event::DeviceEvent::Key(keyboard_input), + .. + } => { + let mut query = <(&mut CameraController)>::query(); + for (camera_controller) in query.iter_mut(world) { + camera_controller.process_keyboard( + keyboard_input.virtual_keycode.unwrap(), + keyboard_input.state, + ); } + + // match keyboard_input.virtual_keycode.unwrap() { + // VirtualKeyCode::A => { + // if keyboard_input.state == ElementState::Pressed {} + // } + // VirtualKeyCode::S => { + // if keyboard_input.state == ElementState::Pressed {} + // } + // VirtualKeyCode::P => { + // if keyboard_input.state == ElementState::Pressed { + // let data = world.write_resource::().read_compute_buffer(compute_buffer.clone()); + // image::save_buffer(&Path::new("image.png"), data.as_slice(), (image_data.1).0, (image_data.1).1, image::RGBA(8)); + // } + // } + // _ => () + // } } _ => {} }