summaryrefslogtreecommitdiff
path: root/engine/src/collision.rs
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/collision.rs')
-rw-r--r--engine/src/collision.rs142
1 files changed, 142 insertions, 0 deletions
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<Other>
+{
+ fn intersects(&self, other: &Other) -> bool;
+}
+
+#[derive(Debug, Default, Clone, Component)]
+#[non_exhaustive]
+pub struct BoxCollider
+{
+ pub min: Vec3<f32>,
+ pub max: Vec3<f32>,
+}
+
+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<f32>) -> Self
+ {
+ Self {
+ min: self.min + offset,
+ max: self.max + offset,
+ }
+ }
+}
+
+impl Collider<BoxCollider> 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<SphereCollider> for BoxCollider
+{
+ fn intersects(&self, other: &SphereCollider) -> bool
+ {
+ other.intersects(self)
+ }
+}
+
+impl Collider<Vec3<f32>> for BoxCollider
+{
+ fn intersects(&self, other: &Vec3<f32>) -> 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<f32>,
+ pub radius: f32,
+}
+
+impl SphereCollider
+{
+ pub fn offset(self, offset: Vec3<f32>) -> Self
+ {
+ Self {
+ center: self.center + offset,
+ radius: self.radius,
+ }
+ }
+}
+
+impl Collider<SphereCollider> for SphereCollider
+{
+ fn intersects(&self, other: &SphereCollider) -> bool
+ {
+ (&self.center - &other.center).length() <= self.radius + other.radius
+ }
+}
+
+impl Collider<BoxCollider> 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<Vec3<f32>> for SphereCollider
+{
+ fn intersects(&self, other: &Vec3<f32>) -> bool
+ {
+ (&self.center - other).length() <= self.radius
+ }
+}