mini_collide/
triangle.rs

1use crate::Plane;
2use mini_math::{Point, Vector3};
3
4/// A triangle
5#[derive(Debug)]
6pub struct Triangle {
7    pub a: Point,
8    pub b: Point,
9    pub c: Point,
10}
11
12impl Triangle {
13    /// Construct a new triangle from three vertices
14    pub fn new(a: Point, b: Point, c: Point) -> Self {
15        Self { a, b, c }
16    }
17
18    /// Barycentric coordinates of the given point
19    pub(crate) fn barycentric_coordinates(&self, p: Point) -> Vector3 {
20        let e0 = self.b - self.a;
21        let e1 = self.c - self.a;
22        let e2 = p - self.a;
23
24        let d00 = e0.dot(e0);
25        let d01 = e0.dot(e1);
26        let d11 = e1.dot(e1);
27        let d20 = e2.dot(e0);
28        let d21 = e2.dot(e1);
29        let denom = 1.0 / (d00 * d11 - d01 * d01);
30        let v = (d11 * d20 - d01 * d21) * denom;
31        let w = (d00 * d21 - d01 * d20) * denom;
32        let u = 1.0 - v - w;
33
34        Vector3::new(u, v, w)
35    }
36
37    /// Test if a coplanar point is inside the triangle
38    pub(crate) fn coplanar_point_inside(&self, p: Point) -> bool {
39        let plane = Plane::from(self);
40
41        let edge_cross = (self.b - self.a).cross(p - self.a);
42        // reject if intersection is outside of edge
43        if plane.normal.dot(edge_cross) > 0.0 {
44            return false;
45        }
46
47        let edge_cross = (self.c - self.b).cross(p - self.b);
48        // reject if intersection is outside of edge
49        if plane.normal.dot(edge_cross) > 0.0 {
50            return false;
51        }
52
53        let edge_cross = (self.a - self.c).cross(p - self.c);
54        // reject if intersection is outside of edge
55        if plane.normal.dot(edge_cross) > 0.0 {
56            return false;
57        }
58
59        true
60    }
61}