Implement simple colission detection

This commit is contained in:
Sijmen 2021-06-01 21:04:48 +02:00
parent df7f78163d
commit 9ce89b707c
Signed by: vijfhoek
GPG key ID: 82D05C89B28B0DAE
5 changed files with 96 additions and 8 deletions

49
src/aabb.rs Normal file
View 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))
}
}

View file

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

View file

@ -10,6 +10,7 @@ mod vertex;
mod world;
mod render_context;
mod text_renderer;
mod aabb;
use std::time::{Duration, Instant};
use wgpu::SwapChainError;

View file

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

View file

@ -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()
});