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 cgmath::{Matrix4, Point3, Rad, Vector3};
|
||||||
|
|
||||||
|
use crate::aabb::Aabb;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub const OPENGL_TO_WGPU_MATRIX: Matrix4<f32> = Matrix4::new(
|
pub const OPENGL_TO_WGPU_MATRIX: Matrix4<f32> = Matrix4::new(
|
||||||
1.0, 0.0, 0.0, 0.0,
|
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,
|
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 struct Camera {
|
||||||
pub position: Point3<f32>,
|
pub position: Point3<f32>,
|
||||||
pub yaw: Rad<f32>,
|
pub yaw: Rad<f32>,
|
||||||
|
|
|
@ -10,6 +10,7 @@ mod vertex;
|
||||||
mod world;
|
mod world;
|
||||||
mod render_context;
|
mod render_context;
|
||||||
mod text_renderer;
|
mod text_renderer;
|
||||||
|
mod aabb;
|
||||||
|
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use wgpu::SwapChainError;
|
use wgpu::SwapChainError;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use ahash::AHashMap;
|
use ahash::AHashMap;
|
||||||
use cgmath::{EuclideanSpace, InnerSpace, Rad, Vector2, Vector3};
|
use cgmath::{EuclideanSpace, InnerSpace, Point3, Rad, Vector2, Vector3};
|
||||||
use wgpu::{
|
use wgpu::{
|
||||||
util::{BufferInitDescriptor, DeviceExt},
|
util::{BufferInitDescriptor, DeviceExt},
|
||||||
CommandEncoder, SwapChainTexture,
|
CommandEncoder, SwapChainTexture,
|
||||||
|
@ -57,7 +57,7 @@ impl WorldState {
|
||||||
|
|
||||||
fn create_camera(render_context: &RenderContext) -> (Camera, Projection) {
|
fn create_camera(render_context: &RenderContext) -> (Camera, Projection) {
|
||||||
let camera = Camera::new(
|
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(45.0).into(),
|
||||||
cgmath::Deg(-20.0).into(),
|
cgmath::Deg(-20.0).into(),
|
||||||
);
|
);
|
||||||
|
@ -499,26 +499,56 @@ impl WorldState {
|
||||||
VirtualKeyCode::S => self.forward_speed -= amount,
|
VirtualKeyCode::S => self.forward_speed -= amount,
|
||||||
VirtualKeyCode::A => self.right_speed -= amount,
|
VirtualKeyCode::A => self.right_speed -= amount,
|
||||||
VirtualKeyCode::D => 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::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) {
|
fn update_position(&mut self, dt: Duration) {
|
||||||
let dt_seconds = dt.as_secs_f32();
|
let dt_seconds = dt.as_secs_f32();
|
||||||
let (yaw_sin, yaw_cos) = self.camera.yaw.0.sin_cos();
|
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();
|
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();
|
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) {
|
pub fn update(&mut self, dt: Duration, render_context: &RenderContext) {
|
||||||
|
|
|
@ -160,6 +160,7 @@ impl TextureManager {
|
||||||
address_mode_u: wgpu::AddressMode::Repeat,
|
address_mode_u: wgpu::AddressMode::Repeat,
|
||||||
address_mode_v: wgpu::AddressMode::Repeat,
|
address_mode_v: wgpu::AddressMode::Repeat,
|
||||||
address_mode_w: wgpu::AddressMode::Repeat,
|
address_mode_w: wgpu::AddressMode::Repeat,
|
||||||
|
mag_filter: wgpu::FilterMode::Linear,
|
||||||
..wgpu::SamplerDescriptor::default()
|
..wgpu::SamplerDescriptor::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue