shambler/
plane_3d.rs

1use crate::{vector3_from_point, Vector3, EPSILON};
2use shalrath::repr::{TexturePlane, TrianglePlane};
3
4#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd)]
5pub struct Plane3d {
6    pub n: Vector3,
7    pub d: f32,
8}
9
10impl Plane3d {
11    pub fn normal(&self) -> &Vector3 {
12        &self.n
13    }
14
15    pub fn distance(&self) -> f32 {
16        self.d
17    }
18
19    // Returns true if the two planes are parallel
20    pub fn is_parallel(&self, rhs: &Plane3d) -> bool {
21        let plane_dot = self.normal().dot(rhs.normal());
22        plane_dot <= -1.0 + EPSILON
23    }
24
25    // Returns true if the two planes are parallel and occupy the same position
26    pub fn opposes(&self, rhs: &Plane3d) -> bool {
27        if !self.is_parallel(rhs) {
28            return false;
29        }
30
31        // Distances should be the same with different signs
32        if self.distance().signum() == rhs.distance().signum() {
33            return false;
34        }
35
36        // Distances should be within EPSILON of one another
37        (self.distance().abs() - rhs.distance().abs()).abs() <= EPSILON
38    }
39}
40
41impl From<&TrianglePlane> for Plane3d {
42    fn from(t: &TrianglePlane) -> Self {
43        let v0 = vector3_from_point(t.v0);
44        let v1 = vector3_from_point(t.v1);
45        let v2 = vector3_from_point(t.v2);
46
47        let v0v1 = v1 - v0;
48        let v0v2 = v2 - v0;
49
50        let n = v0v2.cross(&v0v1).normalize();
51        let d = n.dot(&v0);
52
53        Plane3d { n, d }
54    }
55}
56
57impl From<&TexturePlane> for Plane3d {
58    fn from(p: &TexturePlane) -> Self {
59        let n = nalgebra::vector![p.x, p.y, p.z];
60        let d = p.d;
61        Plane3d { n, d }
62    }
63}