Implement simple colission detection
This commit is contained in:
parent
df7f78163d
commit
9ce89b707c
5 changed files with 96 additions and 8 deletions
49
src/aabb.rs
Normal file
49
src/aabb.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
use cgmath::Vector3;
|
||||
use std::ops::{Div, Sub};
|
||||
|
||||
pub struct Aabb<T> {
|
||||
pub min: Vector3<T>,
|
||||
pub max: Vector3<T>,
|
||||
}
|
||||
|
||||
impl<T: Ord + Copy + Sub<Output = T> + Div<Output = T>> Aabb<T> {
|
||||
pub fn intersects_ray(
|
||||
&self,
|
||||
ray_origin: Vector3<T>,
|
||||
ray_direction: Vector3<T>,
|
||||
) -> Option<(T, T)> {
|
||||
let mut t_min = (self.min.x - ray_origin.x) / ray_direction.x;
|
||||
let mut t_max = (self.max.x - ray_origin.x) / ray_direction.x;
|
||||
if t_min > t_max {
|
||||
std::mem::swap(&mut t_min, &mut t_max);
|
||||
}
|
||||
|
||||
let mut ty_min = (self.min.y - ray_origin.y) / ray_direction.y;
|
||||
let mut ty_max = (self.max.y - ray_origin.y) / ray_direction.y;
|
||||
if ty_min > ty_max {
|
||||
std::mem::swap(&mut ty_min, &mut ty_max);
|
||||
}
|
||||
|
||||
if t_min > ty_max || ty_min > t_max {
|
||||
return None;
|
||||
}
|
||||
|
||||
t_min = T::max(t_min, ty_min);
|
||||
t_max = T::min(t_min, ty_max);
|
||||
|
||||
let mut tz_min = (self.min.z - ray_origin.z) / ray_direction.z;
|
||||
let mut tz_max = (self.max.z - ray_origin.z) / ray_direction.z;
|
||||
if tz_min > tz_max {
|
||||
std::mem::swap(&mut tz_min, &mut tz_max);
|
||||
}
|
||||
|
||||
if t_min > tz_max || tz_min > t_max {
|
||||
return None;
|
||||
}
|
||||
|
||||
t_min = T::max(t_min, tz_min);
|
||||
t_max = T::max(t_max, tz_max);
|
||||
|
||||
Some((t_min, t_max))
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
use cgmath::{Matrix4, Point3, Rad, Vector3};
|
||||
|
||||
use crate::aabb::Aabb;
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub const OPENGL_TO_WGPU_MATRIX: Matrix4<f32> = Matrix4::new(
|
||||
1.0, 0.0, 0.0, 0.0,
|
||||
|
@ -8,6 +10,11 @@ pub const OPENGL_TO_WGPU_MATRIX: Matrix4<f32> = Matrix4::new(
|
|||
0.0, 0.0, 0.5, 1.0,
|
||||
);
|
||||
|
||||
const AABB: Aabb<f32> = Aabb {
|
||||
min: Vector3::new(-0.3, 1.62, -0.3),
|
||||
max: Vector3::new(0.3, 1.8 - 1.62, 0.3),
|
||||
};
|
||||
|
||||
pub struct Camera {
|
||||
pub position: Point3<f32>,
|
||||
pub yaw: Rad<f32>,
|
||||
|
|
|
@ -10,6 +10,7 @@ mod vertex;
|
|||
mod world;
|
||||
mod render_context;
|
||||
mod text_renderer;
|
||||
mod aabb;
|
||||
|
||||
use std::time::{Duration, Instant};
|
||||
use wgpu::SwapChainError;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::time::{Duration, Instant};
|
||||
|
||||
use ahash::AHashMap;
|
||||
use cgmath::{EuclideanSpace, InnerSpace, Rad, Vector2, Vector3};
|
||||
use cgmath::{EuclideanSpace, InnerSpace, Point3, Rad, Vector2, Vector3};
|
||||
use wgpu::{
|
||||
util::{BufferInitDescriptor, DeviceExt},
|
||||
CommandEncoder, SwapChainTexture,
|
||||
|
@ -57,7 +57,7 @@ impl WorldState {
|
|||
|
||||
fn create_camera(render_context: &RenderContext) -> (Camera, Projection) {
|
||||
let camera = Camera::new(
|
||||
(-10.0, 140.0, -10.0).into(),
|
||||
(10.0, 140.0, 10.0).into(),
|
||||
cgmath::Deg(45.0).into(),
|
||||
cgmath::Deg(-20.0).into(),
|
||||
);
|
||||
|
@ -499,26 +499,56 @@ impl WorldState {
|
|||
VirtualKeyCode::S => self.forward_speed -= amount,
|
||||
VirtualKeyCode::A => self.right_speed -= amount,
|
||||
VirtualKeyCode::D => self.right_speed += amount,
|
||||
VirtualKeyCode::LShift => self.up_speed -= amount,
|
||||
// VirtualKeyCode::LShift => self.up_speed -= amount,
|
||||
VirtualKeyCode::Space if state == &ElementState::Pressed => self.up_speed = 0.6,
|
||||
VirtualKeyCode::LControl => self.sprinting = state == &ElementState::Pressed,
|
||||
VirtualKeyCode::Space => self.up_speed += amount,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn check_collision(&self, position: Point3<f32>) -> bool {
|
||||
self.world
|
||||
.get_block(
|
||||
position.x as isize,
|
||||
(position.y - 1.62) as isize,
|
||||
position.z as isize,
|
||||
)
|
||||
.is_some()
|
||||
}
|
||||
|
||||
fn update_position(&mut self, dt: Duration) {
|
||||
let dt_seconds = dt.as_secs_f32();
|
||||
let (yaw_sin, yaw_cos) = self.camera.yaw.0.sin_cos();
|
||||
|
||||
let speed = 30.0 * (self.sprinting as i32 * 2 + 1) as f32;
|
||||
let speed = 10.0 * (self.sprinting as i32 * 2 + 1) as f32;
|
||||
|
||||
let mut new_position = self.camera.position;
|
||||
|
||||
let up = Vector3::unit_y() * self.up_speed * speed * dt_seconds;
|
||||
new_position += up;
|
||||
if self.check_collision(new_position) {
|
||||
new_position -= up;
|
||||
self.up_speed = 0.0;
|
||||
}
|
||||
|
||||
let forward = Vector3::new(yaw_cos, 0.0, yaw_sin).normalize();
|
||||
self.camera.position += forward * self.forward_speed * speed * dt_seconds;
|
||||
let forward = forward * self.forward_speed * speed * dt_seconds;
|
||||
new_position += forward;
|
||||
if self.check_collision(new_position) {
|
||||
new_position -= forward;
|
||||
}
|
||||
|
||||
let right = Vector3::new(-yaw_sin, 0.0, yaw_cos).normalize();
|
||||
self.camera.position += right * self.right_speed * speed * dt_seconds;
|
||||
let right = right * self.right_speed * speed * dt_seconds;
|
||||
new_position += right;
|
||||
if self.check_collision(new_position) {
|
||||
new_position -= right;
|
||||
}
|
||||
|
||||
self.camera.position += Vector3::unit_y() * self.up_speed * speed * dt_seconds;
|
||||
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);
|
||||
}
|
||||
|
||||
pub fn update(&mut self, dt: Duration, render_context: &RenderContext) {
|
||||
|
|
|
@ -160,6 +160,7 @@ impl TextureManager {
|
|||
address_mode_u: wgpu::AddressMode::Repeat,
|
||||
address_mode_v: wgpu::AddressMode::Repeat,
|
||||
address_mode_w: wgpu::AddressMode::Repeat,
|
||||
mag_filter: wgpu::FilterMode::Linear,
|
||||
..wgpu::SamplerDescriptor::default()
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue