camera sorta works using the old voxel-raycaster style of spherical coords

master
mitchellhansen 4 years ago
parent 9c48da280c
commit b18ea7371a

@ -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

@ -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

@ -1,8 +1,10 @@
use cgmath::{Matrix4, Vector3, Point3, Rad, InnerSpace}; use std::f32::consts::{FRAC_PI_2, PI};
use winit::event::{MouseScrollDelta, VirtualKeyCode, ElementState};
use winit::dpi::{PhysicalPosition, LogicalPosition};
use std::time::{Duration, Instant}; 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; use crate::render::OPENGL_TO_WGPU_MATRIX;
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
@ -13,11 +15,7 @@ pub struct Camera {
} }
impl Camera { impl Camera {
pub fn new< pub fn new<V: Into<Point3<f32>>, Y: Into<Rad<f32>>, P: Into<Rad<f32>>>(
V: Into<Point3<f32>>,
Y: Into<Rad<f32>>,
P: Into<Rad<f32>>,
>(
position: V, position: V,
yaw: Y, yaw: Y,
pitch: P, pitch: P,
@ -30,21 +28,38 @@ impl Camera {
} }
pub fn calc_matrix(&self, projection: cgmath::Matrix4<f32>) -> Matrix4<f32> { pub fn calc_matrix(&self, projection: cgmath::Matrix4<f32>) -> Matrix4<f32> {
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, self.position,
Vector3::new( Point3::new(
self.yaw.0.cos(), view_vector.x + self.position.x,
self.pitch.0.sin(), view_vector.y + self.position.y,
self.yaw.0.sin(), view_vector.z + self.position.z,
).normalize(), ),
Vector3::unit_y(), 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; let mx_correction = OPENGL_TO_WGPU_MATRIX;
mx_correction * projection * mx_view mx_correction * projection * mx_view
} }
} }
#[derive(Debug)] #[derive(Debug)]
pub struct CameraController { pub struct CameraController {
amount_left: f32, amount_left: f32,
@ -79,8 +94,12 @@ impl CameraController {
} }
} }
pub fn process_keyboard(&mut self, key: VirtualKeyCode, state: ElementState) -> bool{ pub fn process_keyboard(&mut self, key: VirtualKeyCode, state: ElementState) -> bool {
let amount = if state == ElementState::Pressed { 1.0 } else { 0.0 }; let amount = if state == ElementState::Pressed {
1.0
} else {
0.0
};
match key { match key {
VirtualKeyCode::W | VirtualKeyCode::Up => { VirtualKeyCode::W | VirtualKeyCode::Up => {
self.amount_forward = amount; self.amount_forward = amount;
@ -111,38 +130,52 @@ impl CameraController {
} }
pub fn process_mouse(&mut self, mouse_dx: f64, mouse_dy: f64) { 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; self.rotate_vertical = mouse_dy as f32;
} }
pub fn process_scroll(&mut self, delta: &MouseScrollDelta) { // pub fn process_scroll(&mut self, delta: &MouseScrollDelta) {
self.scroll = -match delta { // self.scroll = -match delta {
// I'm assuming a line is about 100 pixels // // I'm assuming a line is about 100 pixels
MouseScrollDelta::LineDelta(_, scroll) => scroll * 100.0, // MouseScrollDelta::LineDelta(_, scroll) => scroll * 100.0,
MouseScrollDelta::PixelDelta(LogicalPosition { // MouseScrollDelta::PixelDelta(LogicalPosition {
y: scroll, // y: scroll,
.. // ..
}) => *scroll as f32, // }) => *scroll as f32,
}; // };
} // }
pub fn update_camera(&mut self, camera: &mut Camera, dt: f32) { pub fn update_camera(&mut self, camera: &mut Camera, dt: f32) {
// Move forward/backward and left/right // Move forward/backward and left/right
let (yaw_sin, yaw_cos) = camera.yaw.0.sin_cos(); let (yaw_sin, yaw_cos) = camera.yaw.0.sin_cos();
let forward = Vector3::new(yaw_cos, 0.0, yaw_sin).normalize(); let forward = Vector3::new(yaw_cos, 0.0, yaw_sin).normalize();
let right = Vector3::new(-yaw_sin, 0.0, yaw_cos).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; let view_vector = Vector3::new(
(1.0 * camera.pitch.0.sin() * camera.yaw.0.sin()),
// Move in/out (aka. "zoom") (1.0 * camera.pitch.0.cos()),
// Note: this isn't an actual zoom. The camera's position (1.0 * camera.pitch.0.sin() * camera.yaw.0.cos()),
// 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 yaw_offset = camera.yaw.0 - Rad(PI).0;
let scrollward = Vector3::new(pitch_cos * yaw_cos, pitch_sin, pitch_cos * yaw_sin).normalize(); let right_vector = Vector3::new(
camera.position += scrollward * self.scroll * self.speed * self.sensitivity * dt; (1.0 * camera.pitch.0.sin() * yaw_offset.sin()),
self.scroll = 0.0; (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 // Move up/down. Since we don't use roll, we can just
// modify the y coordinate directly. // modify the y coordinate directly.
@ -150,7 +183,7 @@ impl CameraController {
// Rotate // Rotate
camera.yaw += Rad(self.rotate_horizontal) * self.sensitivity * dt; 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 // If process_mouse isn't called every frame, these values
// will not get set to zero, and the camera will rotate // will not get set to zero, and the camera will rotate
@ -159,15 +192,10 @@ impl CameraController {
self.rotate_vertical = 0.0; self.rotate_vertical = 0.0;
// Keep the camera's angle from going too high/low. // Keep the camera's angle from going too high/low.
if camera.pitch < -Rad(FRAC_PI_2) { if camera.pitch < -Rad(0.0) {
camera.pitch = -Rad(FRAC_PI_2); camera.pitch = -Rad(0.0);
} else if camera.pitch > Rad(FRAC_PI_2) { } else if camera.pitch > Rad(PI) {
camera.pitch = Rad(FRAC_PI_2); camera.pitch = Rad(PI);
} }
} }
} }

@ -124,7 +124,7 @@ fn main() {
resources.insert(renderer); resources.insert(renderer);
let (physics_state, physics_pipeline) = 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_state);
resources.insert(physics_pipeline); resources.insert(physics_pipeline);
@ -249,14 +249,14 @@ pub fn entity_loading(world: &mut World, renderer: &mut Renderer) {
let camera_ent: Entity = world.push(( let camera_ent: Entity = world.push((
Camera { Camera {
position: Point3 { position: Point3 {
x: 5.0, x: 0.0,
y: 5.0, y: 0.0,
z: 5.0 z: 10.0
}, },
yaw: Rad(0.0), yaw: Rad(-PI),
pitch: Rad(-75.0) pitch: Rad(PI/2.0)
}, },
CameraController::new(1.0, 1.0), CameraController::new(3.0, 1.0),
)); ));
let light_entity: Entity = world.push(( 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(( let monkey_entity: Entity = world.push((
Position { Position {
x: 1.0, x: 1.0,
y: 2.0, y: 5.0,
z: 2.0, z: 2.0,
rot: Quaternion::from(Euler { rot: Quaternion::from(Euler {
x: Deg(90.0), 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() let mut static_floor_body = RigidBodyBuilder::new_static()
.position(Isometry3::new( .position(Isometry3::new(
Vector3::new(0.0, 0.0, 0.0), Vector3::new(0.0, -8.0, 0.0),
Vector::y() * PI, Vector::y() * PI,
)) ))
.build(); .build();
let ball_collider = ColliderBuilder::ball(1.5).build(); let ball_collider = ColliderBuilder::ball(1.5).build();
let floor_collider = ColliderBuilder::cuboid(0.5, 0.2, 0.1).build(); let floor_collider = ColliderBuilder::cuboid(10.0, 0.2, 10.0).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 plane_mesh = renderer.load_mesh_to_buffer("./resources/plane.obj");
// let floor_collider_handle = colliders.insert(floor_collider, dynamic_ball_body_handle, &mut bodies);
let plane_mesh = renderer.create_plane(7.0);
let plane_entity: Entity = world.push(( let plane_entity: Entity = world.push((
Position { Position {
x: 0.0, x: 0.0,
y: 0.0, y: -8.0,
z: 0.0, z: 0.0,
rot: Quaternion::from(Euler { rot: Quaternion::from(Euler {
x: Deg(0.0), x: Deg(0.0),

@ -12,6 +12,7 @@ use winit::event::{
use winit::window::{Theme, WindowId}; use winit::window::{Theme, WindowId};
use crate::camera::{Camera, CameraController}; use crate::camera::{Camera, CameraController};
use crate::owned_event::OwnedWindowEvent::MouseWheel;
#[derive(Clone)] #[derive(Clone)]
pub enum OwnedUIEvent<T> { pub enum OwnedUIEvent<T> {
@ -249,18 +250,18 @@ pub fn event_dispatch(
for event in event_stack { for event in event_stack {
match event { match event {
OwnedEvent::DeviceEvent { OwnedEvent::DeviceEvent {
event: MouseMotion { delta }, event: winit::event::DeviceEvent::MouseMotion { delta },
.. ..
} => { } => {
let mut query = <(&mut CameraController)>::query(); let mut query = <(&mut CameraController)>::query();
for (camera_controller) in query.iter_mut(world) { for (camera_controller) in query.iter_mut(world) {
camera_controller.process_mouse(delta.0, delta.1); camera_controller.process_mouse(delta.0, delta.1);
} }
} },
OwnedEvent::DeviceEvent {
OwnedEvent::DeviceEvent { device_id, event } => { event: winit::event::DeviceEvent::Key(keyboard_input),
match event { ..
winit::event::DeviceEvent::Key(keyboard_input) => { } => {
let mut query = <(&mut CameraController)>::query(); let mut query = <(&mut CameraController)>::query();
for (camera_controller) in query.iter_mut(world) { for (camera_controller) in query.iter_mut(world) {
camera_controller.process_keyboard( camera_controller.process_keyboard(
@ -288,7 +289,4 @@ pub fn event_dispatch(
_ => {} _ => {}
} }
} }
_ => {}
}
}
} }

Loading…
Cancel
Save