🦀 collision detection bugs are gone 🦀
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Sijmen 2021-06-07 19:06:16 +02:00
parent 191f9b1f28
commit 6794213f7d
Signed by: vijfhoek
GPG key ID: 82D05C89B28B0DAE
4 changed files with 64 additions and 26 deletions

View file

@ -1,11 +1,9 @@
use cgmath::Point3;
type T = f32;
#[derive(Debug)]
pub struct Aabb {
pub min: Point3<T>,
pub max: Point3<T>,
pub min: Point3<f32>,
pub max: Point3<f32>,
}
impl Aabb {
@ -15,17 +13,33 @@ impl Aabb {
&& (self.min.z <= other.max.z && self.max.z >= other.min.z)
}
pub fn get_corners(&self) -> [Point3<T>; 8] {
[
Point3::new(self.min.x, self.min.y, self.min.z),
Point3::new(self.min.x, self.min.y, self.max.z),
Point3::new(self.min.x, self.max.y, self.min.z),
Point3::new(self.min.x, self.max.y, self.max.z),
Point3::new(self.max.x, self.min.y, self.min.z),
Point3::new(self.max.x, self.min.y, self.max.z),
Point3::new(self.max.x, self.max.y, self.min.z),
Point3::new(self.max.x, self.max.y, self.max.z),
]
/// Gets the corners of the AABB that should be checked when checking
/// collision with the world.
///
/// Returns a `Vec` of all `Point3`s that cover the faces of `self` with
/// no more than 1 unit of distance between them.
pub fn get_corners(&self) -> Vec<Point3<f32>> {
let mut corners = Vec::new();
let mut x = self.min.x;
while x < self.max.x.ceil() {
let mut y = self.min.y;
while y < self.max.y.ceil() {
let mut z = self.min.z;
while z < self.max.z.ceil() {
corners.push(Point3::new(
x.min(self.max.x),
y.min(self.max.y),
z.min(self.max.z),
));
z += 1.0;
}
y += 1.0;
}
x += 1.0;
}
corners
}
}

View file

@ -11,6 +11,7 @@ mod time;
mod vertex;
mod view;
mod world;
mod utils;
use std::time::{Duration, Instant};
use wgpu::SwapChainError;

View file

@ -17,6 +17,7 @@ use crate::{
renderable::Renderable,
texture::{Texture, TextureManager},
time::Time,
utils,
vertex::{BlockVertex, Vertex},
view::View,
world::World,
@ -408,35 +409,38 @@ impl WorldState {
None
}
/// Updates the player's position by their velocity, checks for and
/// resolves any subsequent collisions, and then adds the jumping speed to
/// the velocity.
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 = 10.0 * (self.sprinting as i32 * 2 + 1) as f32;
let speed = 10.0 * (self.sprinting as i32 * 2 + 1) as f32 * dt.as_secs_f32();
let forward_speed = self.forward_pressed as i32 - self.backward_pressed as i32;
let forward = Vector3::new(yaw_cos, 0.0, yaw_sin);
let forward = forward * forward_speed as f32;
let forward = Vector3::new(yaw_cos, 0.0, yaw_sin) * forward_speed as f32;
let right_speed = self.right_pressed as i32 - self.left_pressed as i32;
let right = Vector3::new(-yaw_sin, 0.0, yaw_cos);
let right = right * right_speed as f32;
let right = Vector3::new(-yaw_sin, 0.0, yaw_cos) * right_speed as f32;
let mut velocity = forward + right;
if velocity.magnitude2() > 1.0 {
velocity = velocity.normalize();
}
velocity *= speed * dt.as_secs_f32();
velocity *= speed;
velocity.y = self.up_speed * 10.0 * dt.as_secs_f32();
let mut new_position = self.camera.position;
// y component (jumping)
new_position.y += self.up_speed * speed * dt_seconds;
new_position.y += velocity.y;
if let Some(aabb) = self.check_collision(new_position) {
if self.up_speed < 0.0 {
new_position.y = aabb.min.y.ceil() + 1.62;
new_position.y = utils::f32_successor(new_position.y);
} else if self.up_speed > 0.0 {
new_position.y = aabb.max.y.floor() - 0.1801;
new_position.y = aabb.max.y.floor() - 0.18;
new_position.y = utils::f32_predecessor(new_position.y);
}
self.up_speed = 0.0;
@ -447,8 +451,10 @@ impl WorldState {
if let Some(aabb) = self.check_collision(new_position) {
if velocity.x < 0.0 {
new_position.x = aabb.min.x.ceil() + 0.3;
new_position.x = utils::f32_successor(new_position.x);
} else if velocity.x > 0.0 {
new_position.x = aabb.max.x.floor() - 0.3001;
new_position.x = aabb.max.x.floor() - 0.3;
new_position.x = utils::f32_predecessor(new_position.x);
}
}
@ -457,8 +463,10 @@ impl WorldState {
if let Some(aabb) = self.check_collision(new_position) {
if velocity.z < 0.0 {
new_position.z = aabb.min.z.ceil() + 0.3;
new_position.z = utils::f32_successor(new_position.z);
} else if velocity.z > 0.0 {
new_position.z = aabb.max.z.floor() - 0.3001;
new_position.z = aabb.max.z.floor() - 0.3;
new_position.z = utils::f32_predecessor(new_position.z);
}
}

15
src/utils.rs Normal file
View file

@ -0,0 +1,15 @@
/// Returns `x` incremented with the lowest possible value that a
/// single-precision floating point with `x`'s value can represent.
pub fn f32_successor(x: f32) -> f32 {
let x = x.to_bits();
let x = if (x >> 31) == 0 { x + 1 } else { x - 1 };
f32::from_bits(x)
}
/// Returns `x` decremented with the lowest possible value that a
/// single-precision floating point with `x`'s value can represent.
pub fn f32_predecessor(x: f32) -> f32 {
let x = x.to_bits();
let x = if (x >> 31) == 0 { x - 1 } else { x + 1 };
f32::from_bits(x)
}