From 5fa358a465d32d1420a8cdfd23dd1a88ca4ae797 Mon Sep 17 00:00:00 2001 From: HampusM Date: Tue, 14 Jan 2025 13:32:02 +0100 Subject: feat(engine): add simple collision --- engine/src/collision.rs | 142 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 engine/src/collision.rs (limited to 'engine/src/collision.rs') diff --git a/engine/src/collision.rs b/engine/src/collision.rs new file mode 100644 index 0000000..aefd9b6 --- /dev/null +++ b/engine/src/collision.rs @@ -0,0 +1,142 @@ +use ecs::Component; + +use crate::mesh::Mesh; +use crate::vector::Vec3; + +pub trait Collider +{ + fn intersects(&self, other: &Other) -> bool; +} + +#[derive(Debug, Default, Clone, Component)] +#[non_exhaustive] +pub struct BoxCollider +{ + pub min: Vec3, + pub max: Vec3, +} + +impl BoxCollider +{ + pub fn for_mesh(mesh: &Mesh) -> Self + { + let furthest_dir_points = mesh.find_furthest_vertex_positions(); + + Self { + min: Vec3 { + x: furthest_dir_points.left.x, + y: furthest_dir_points.down.y, + z: furthest_dir_points.back.z, + }, + max: Vec3 { + x: furthest_dir_points.right.x, + y: furthest_dir_points.up.y, + z: furthest_dir_points.front.z, + }, + } + } + + pub fn offset(self, offset: Vec3) -> Self + { + Self { + min: self.min + offset, + max: self.max + offset, + } + } +} + +impl Collider for BoxCollider +{ + fn intersects(&self, other: &BoxCollider) -> bool + { + self.min.x <= other.max.x + && self.max.x >= other.min.x + && self.min.y <= other.max.y + && self.max.y >= other.min.y + && self.min.z <= other.max.z + && self.max.z >= other.min.z + } +} + +impl Collider for BoxCollider +{ + fn intersects(&self, other: &SphereCollider) -> bool + { + other.intersects(self) + } +} + +impl Collider> for BoxCollider +{ + fn intersects(&self, other: &Vec3) -> bool + { + other.x >= self.min.x + && other.y >= self.min.y + && other.z >= self.min.z + && other.x <= self.max.x + && other.y <= self.max.y + && other.z <= self.max.z + } +} + +#[derive(Debug, Default, Clone, Component)] +pub struct SphereCollider +{ + pub center: Vec3, + pub radius: f32, +} + +impl SphereCollider +{ + pub fn offset(self, offset: Vec3) -> Self + { + Self { + center: self.center + offset, + radius: self.radius, + } + } +} + +impl Collider for SphereCollider +{ + fn intersects(&self, other: &SphereCollider) -> bool + { + (&self.center - &other.center).length() <= self.radius + other.radius + } +} + +impl Collider for SphereCollider +{ + fn intersects(&self, other: &BoxCollider) -> bool + { + let mut min_distance = 0.0; + + if self.center.x < other.min.x { + min_distance += (self.center.x - other.min.x).powf(2.0); + } else if self.center.x > other.max.x { + min_distance += (self.center.x - other.max.x).powf(2.0); + } + + if self.center.y < other.min.y { + min_distance += (self.center.y - other.min.y).powf(2.0); + } else if self.center.y > other.max.y { + min_distance += (self.center.y - other.max.y).powf(2.0); + } + + if self.center.z < other.min.z { + min_distance += (self.center.z - other.min.z).powf(2.0); + } else if self.center.z > other.max.z { + min_distance += (self.center.z - other.max.z).powf(2.0); + } + + min_distance <= self.radius.powf(2.0) + } +} + +impl Collider> for SphereCollider +{ + fn intersects(&self, other: &Vec3) -> bool + { + (&self.center - other).length() <= self.radius + } +} -- cgit v1.2.3-18-g5258