parent
9f4c8a856c
commit
189805dd13
@ -0,0 +1,173 @@
|
||||
use cgmath::{Matrix4, Vector3, Point3, Rad, InnerSpace};
|
||||
use winit::event::{MouseScrollDelta, VirtualKeyCode, ElementState};
|
||||
use winit::dpi::{PhysicalPosition, LogicalPosition};
|
||||
use std::time::{Duration, Instant};
|
||||
use std::f32::consts::FRAC_PI_2;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct Camera {
|
||||
pub position: Point3<f32>,
|
||||
pub yaw: Rad<f32>,
|
||||
pub pitch: Rad<f32>,
|
||||
}
|
||||
|
||||
impl Camera {
|
||||
pub fn new<
|
||||
V: Into<Point3<f32>>,
|
||||
Y: Into<Rad<f32>>,
|
||||
P: Into<Rad<f32>>,
|
||||
>(
|
||||
position: V,
|
||||
yaw: Y,
|
||||
pitch: P,
|
||||
) -> Self {
|
||||
Self {
|
||||
position: position.into(),
|
||||
yaw: yaw.into(),
|
||||
pitch: pitch.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn calc_matrix(&self) -> Matrix4<f32> {
|
||||
Matrix4::look_at_dir(
|
||||
self.position,
|
||||
Vector3::new(
|
||||
self.yaw.0.cos(),
|
||||
self.pitch.0.sin(),
|
||||
self.yaw.0.sin(),
|
||||
).normalize(),
|
||||
Vector3::unit_y(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CameraController {
|
||||
amount_left: f32,
|
||||
amount_right: f32,
|
||||
amount_forward: f32,
|
||||
amount_backward: f32,
|
||||
amount_up: f32,
|
||||
amount_down: f32,
|
||||
rotate_horizontal: f32,
|
||||
rotate_vertical: f32,
|
||||
scroll: f32,
|
||||
speed: f32,
|
||||
sensitivity: f32,
|
||||
last_frame: Instant,
|
||||
}
|
||||
|
||||
impl CameraController {
|
||||
pub fn new(speed: f32, sensitivity: f32) -> Self {
|
||||
Self {
|
||||
amount_left: 0.0,
|
||||
amount_right: 0.0,
|
||||
amount_forward: 0.0,
|
||||
amount_backward: 0.0,
|
||||
amount_up: 0.0,
|
||||
amount_down: 0.0,
|
||||
rotate_horizontal: 0.0,
|
||||
rotate_vertical: 0.0,
|
||||
scroll: 0.0,
|
||||
speed,
|
||||
sensitivity,
|
||||
last_frame: Instant::now(),
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
true
|
||||
}
|
||||
VirtualKeyCode::S | VirtualKeyCode::Down => {
|
||||
self.amount_backward = amount;
|
||||
true
|
||||
}
|
||||
VirtualKeyCode::A | VirtualKeyCode::Left => {
|
||||
self.amount_left = amount;
|
||||
true
|
||||
}
|
||||
VirtualKeyCode::D | VirtualKeyCode::Right => {
|
||||
self.amount_right = amount;
|
||||
true
|
||||
}
|
||||
VirtualKeyCode::Space => {
|
||||
self.amount_up = amount;
|
||||
true
|
||||
}
|
||||
VirtualKeyCode::LShift => {
|
||||
self.amount_down = amount;
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process_mouse(&mut self, mouse_dx: f64, mouse_dy: f64) {
|
||||
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 update_camera(&mut self, camera: &mut Camera, dt: Duration) {
|
||||
|
||||
|
||||
let dt = dt.as_secs_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;
|
||||
|
||||
// Move up/down. Since we don't use roll, we can just
|
||||
// modify the y coordinate directly.
|
||||
camera.position.y += (self.amount_up - self.amount_down) * self.speed * dt;
|
||||
|
||||
// Rotate
|
||||
camera.yaw += Rad(self.rotate_horizontal) * 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
|
||||
// when moving in a non cardinal direction.
|
||||
self.rotate_horizontal = 0.0;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,64 @@
|
||||
use wgpu::{TextureView, Buffer, BindGroup};
|
||||
use std::sync::Arc;
|
||||
use rapier3d::dynamics::{RigidBody, RigidBodyHandle};
|
||||
use rapier3d::geometry::ColliderHandle;
|
||||
use rapier3d::geometry::Collider as r3dCollider;
|
||||
|
||||
// a component is any type that is 'static, sized, send and sync
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct Position {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub z: f32,
|
||||
pub rot: cgmath::Quaternion<f32>,
|
||||
}
|
||||
|
||||
#[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<Idx> {
|
||||
pub start: Idx,
|
||||
pub end: Idx,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DirectionalLight {
|
||||
pub color: wgpu::Color,
|
||||
pub fov: f32,
|
||||
pub depth: RangeCopy<f32>,
|
||||
pub target_view: Arc<TextureView>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Mesh {
|
||||
pub index_buffer: Arc<Buffer>,
|
||||
pub index_count: usize,
|
||||
pub vertex_buffer: Arc<Buffer>,
|
||||
pub uniform_buffer: Arc<Buffer>,
|
||||
pub bind_group: Arc<BindGroup>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Physics {
|
||||
pub rigid_body: RigidBody,
|
||||
pub rigid_body_handle: Option<RigidBodyHandle>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Collider {
|
||||
pub collider: r3dCollider,
|
||||
pub collider_handle: Option<ColliderHandle>,
|
||||
}
|
@ -0,0 +1,213 @@
|
||||
use winit::window::{WindowId, Theme};
|
||||
use winit::event::{WindowEvent, DeviceId, DeviceEvent, KeyboardInput, ModifiersState, MouseScrollDelta, TouchPhase, ElementState, MouseButton, AxisId, Touch, StartCause, Event};
|
||||
use winit::dpi::{PhysicalPosition, PhysicalSize};
|
||||
use gilrs::Event as GilEvent;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum TrUIEvent<T> {
|
||||
UIEvent(T)
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum TrEventExtension {
|
||||
|
||||
/// Custom events here
|
||||
MouseHeldEvent {},
|
||||
KeyHeldEvent {},
|
||||
GamepadEvent {
|
||||
gil_event: GilEvent,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum TrEvent<T> {
|
||||
|
||||
/// Custom events here
|
||||
MouseHeldEvent {},
|
||||
KeyHeldEvent {},
|
||||
GamepadEvent {
|
||||
gil_event: GilEvent,
|
||||
},
|
||||
|
||||
/// Winit events here
|
||||
NewEvents(StartCause),
|
||||
WindowEvent {
|
||||
window_id: WindowId,
|
||||
event: TrWindowEvent,
|
||||
},
|
||||
DeviceEvent {
|
||||
device_id: DeviceId,
|
||||
event: DeviceEvent,
|
||||
},
|
||||
UserEvent(T),
|
||||
Suspended,
|
||||
Resumed,
|
||||
MainEventsCleared,
|
||||
RedrawRequested(WindowId),
|
||||
RedrawEventsCleared,
|
||||
LoopDestroyed,
|
||||
}
|
||||
|
||||
|
||||
impl<T> From<Event<'_, T>> for TrEvent<T> {
|
||||
fn from(event: Event<T>) -> Self {
|
||||
match event {
|
||||
Event::NewEvents(cause) => {
|
||||
TrEvent::NewEvents(cause)
|
||||
},
|
||||
Event::WindowEvent { window_id: window_id, event: event } => {
|
||||
TrEvent::WindowEvent {
|
||||
window_id: window_id,
|
||||
event: match event {
|
||||
WindowEvent::AxisMotion { device_id, axis, value } => {
|
||||
TrWindowEvent::AxisMotion { device_id, axis, value }
|
||||
},
|
||||
WindowEvent::Resized(physical_size) => {
|
||||
TrWindowEvent::Resized(physical_size)
|
||||
}
|
||||
WindowEvent::Moved(physical_position) => {
|
||||
TrWindowEvent::Moved(physical_position)
|
||||
}
|
||||
WindowEvent::CloseRequested => {
|
||||
TrWindowEvent::CloseRequested
|
||||
}
|
||||
WindowEvent::Destroyed => {
|
||||
TrWindowEvent::Destroyed
|
||||
}
|
||||
WindowEvent::DroppedFile(path_buf) => {
|
||||
TrWindowEvent::DroppedFile(path_buf)
|
||||
}
|
||||
WindowEvent::HoveredFile(path_buf) => {
|
||||
TrWindowEvent::HoveredFile(path_buf)
|
||||
}
|
||||
WindowEvent::HoveredFileCancelled => {
|
||||
TrWindowEvent::HoveredFileCancelled
|
||||
}
|
||||
WindowEvent::ReceivedCharacter(char) => {
|
||||
TrWindowEvent::ReceivedCharacter(char)
|
||||
}
|
||||
WindowEvent::Focused(bool) => {
|
||||
TrWindowEvent::Focused(bool)
|
||||
}
|
||||
WindowEvent::KeyboardInput { device_id: device_id, input: input, is_synthetic: is_synthetic } => {
|
||||
TrWindowEvent::KeyboardInput { device_id, input, is_synthetic }
|
||||
}
|
||||
WindowEvent::ModifiersChanged(modifiers_state) => {
|
||||
TrWindowEvent::ModifiersChanged(modifiers_state)
|
||||
}
|
||||
WindowEvent::CursorMoved { device_id: device_id, position: position, modifiers: modifiers } => {
|
||||
TrWindowEvent::CursorMoved { device_id, position, modifiers }
|
||||
}
|
||||
WindowEvent::CursorEntered { device_id: device_id } => {
|
||||
TrWindowEvent::CursorEntered { device_id }
|
||||
}
|
||||
WindowEvent::CursorLeft { device_id: device_id } => {
|
||||
TrWindowEvent::CursorLeft { device_id }
|
||||
}
|
||||
WindowEvent::MouseWheel { device_id: device_id, delta: delta, phase: phase, modifiers: modifiers } => {
|
||||
TrWindowEvent::MouseWheel { device_id, delta, phase, modifiers }
|
||||
}
|
||||
WindowEvent::MouseInput { device_id: device_id, state: state, button: button, modifiers: modifiers } => {
|
||||
TrWindowEvent::MouseInput { device_id, state, button, modifiers }
|
||||
}
|
||||
WindowEvent::TouchpadPressure { device_id: device_id, pressure: pressure, stage: stage } => {
|
||||
TrWindowEvent::TouchpadPressure { device_id, pressure, stage }
|
||||
}
|
||||
WindowEvent::Touch(touch) => {
|
||||
TrWindowEvent::Touch(touch)
|
||||
}
|
||||
WindowEvent::ScaleFactorChanged { scale_factor: scale_factor, new_inner_size: new_inner_size } => {
|
||||
TrWindowEvent::ScaleFactorChanged { scale_factor, new_inner_size: PhysicalSize { width: new_inner_size.width, height: new_inner_size.height } }
|
||||
}
|
||||
WindowEvent::ThemeChanged(theme) => {
|
||||
TrWindowEvent::ThemeChanged(theme)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Event::DeviceEvent { device_id: device_id, event: event } => {
|
||||
TrEvent::DeviceEvent { device_id, event }
|
||||
}
|
||||
Event::UserEvent(user_event) => {
|
||||
TrEvent::UserEvent(user_event)
|
||||
}
|
||||
Event::Suspended => {
|
||||
TrEvent::Suspended
|
||||
}
|
||||
Event::Resumed => {
|
||||
TrEvent::Resumed
|
||||
}
|
||||
Event::MainEventsCleared => {
|
||||
TrEvent::MainEventsCleared
|
||||
}
|
||||
Event::RedrawRequested(window_id) => {
|
||||
TrEvent::RedrawRequested(window_id)
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
TrEvent::RedrawEventsCleared
|
||||
}
|
||||
Event::LoopDestroyed => {
|
||||
TrEvent::LoopDestroyed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum TrWindowEvent {
|
||||
|
||||
Resized(PhysicalSize<u32>),
|
||||
Moved(PhysicalPosition<i32>),
|
||||
CloseRequested,
|
||||
Destroyed,
|
||||
DroppedFile(PathBuf),
|
||||
HoveredFile(PathBuf),
|
||||
HoveredFileCancelled,
|
||||
ReceivedCharacter(char),
|
||||
Focused(bool),
|
||||
KeyboardInput {
|
||||
device_id: DeviceId,
|
||||
input: KeyboardInput,
|
||||
is_synthetic: bool,
|
||||
},
|
||||
ModifiersChanged(ModifiersState),
|
||||
CursorMoved {
|
||||
device_id: DeviceId,
|
||||
position: PhysicalPosition<f64>,
|
||||
#[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"]
|
||||
modifiers: ModifiersState,
|
||||
},
|
||||
CursorEntered { device_id: DeviceId },
|
||||
CursorLeft { device_id: DeviceId },
|
||||
MouseWheel {
|
||||
device_id: DeviceId,
|
||||
delta: MouseScrollDelta,
|
||||
phase: TouchPhase,
|
||||
#[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"]
|
||||
modifiers: ModifiersState,
|
||||
},
|
||||
MouseInput {
|
||||
device_id: DeviceId,
|
||||
state: ElementState,
|
||||
button: MouseButton,
|
||||
#[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"]
|
||||
modifiers: ModifiersState,
|
||||
},
|
||||
TouchpadPressure {
|
||||
device_id: DeviceId,
|
||||
pressure: f32,
|
||||
stage: i64,
|
||||
},
|
||||
AxisMotion {
|
||||
device_id: DeviceId,
|
||||
axis: AxisId,
|
||||
value: f64,
|
||||
},
|
||||
Touch(Touch),
|
||||
ScaleFactorChanged {
|
||||
scale_factor: f64,
|
||||
new_inner_size: PhysicalSize<u32>,
|
||||
},
|
||||
ThemeChanged(Theme),
|
||||
}
|
Loading…
Reference in new issue