rg3d_physics/
static_geometry.rs1use rg3d_core::{
2 math::{
3 vec3::Vec3,
4 plane::Plane
5 },
6 visitor::{Visit, VisitResult, Visitor, VisitError},
7 octree::Octree
8};
9
10#[derive(Default, Clone, Debug)]
11pub struct StaticGeometry {
12 pub(in crate) triangles: Vec<StaticTriangle>,
13 pub(in crate) octree: Octree,
14 save_triangles: bool
15}
16
17impl StaticGeometry {
18 pub const OCTREE_THRESHOLD: usize = 64;
19
20 pub fn new(triangles: Vec<StaticTriangle>, save_triangles: bool) -> Self {
21 let raw_triangles: Vec<[Vec3; 3]> = triangles.iter().map(|st| st.points).collect();
22
23 Self {
24 octree: Octree::new(&raw_triangles, Self::OCTREE_THRESHOLD),
25 triangles,
26 save_triangles
27 }
28 }
29
30 pub fn set_save_triangles(&mut self, save_triangles: bool) {
31 self.save_triangles = save_triangles;
32 }
33
34 pub fn save_triangles(&self) -> bool {
35 self.save_triangles
36 }
37}
38
39impl Visit for StaticGeometry {
40 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
41 visitor.enter_region(name)?;
42
43 if !visitor.is_reading() {
44 if self.save_triangles {
45 self.triangles.visit("Triangles", visitor)?;
46 } else {
47 let mut empty: Vec<StaticTriangle> = Vec::new();
48 empty.visit("Triangles", visitor)?;
49 }
50 } else {
51 self.triangles.visit("Triangles", visitor)?;
52 }
53
54 if visitor.is_reading() {
55 let raw_triangles: Vec<[Vec3; 3]> = self.triangles.iter().map(|st| st.points).collect();
56 self.octree = Octree::new(&raw_triangles, Self::OCTREE_THRESHOLD);
57 }
58
59 let _ = self.save_triangles.visit("SaveTriangles", visitor);
60
61 visitor.leave_region()
62 }
63}
64
65#[derive(Clone, Debug)]
66pub struct StaticTriangle {
67 pub points: [Vec3; 3],
68 pub ca: Vec3,
69 pub ba: Vec3,
70 pub ca_dot_ca: f32,
71 pub ca_dot_ba: f32,
72 pub ba_dot_ba: f32,
73 pub inv_denom: f32,
74 pub plane: Plane,
75}
76
77impl Default for StaticTriangle {
78 fn default() -> Self {
79 Self {
80 points: Default::default(),
81 ca: Default::default(),
82 ba: Default::default(),
83 ca_dot_ca: 0.0,
84 ca_dot_ba: 0.0,
85 ba_dot_ba: 0.0,
86 inv_denom: 0.0,
87 plane: Default::default(),
88 }
89 }
90}
91
92impl Visit for StaticTriangle {
93 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
94 visitor.enter_region(name)?;
95
96 let mut a = self.points[0];
97 a.visit("A", visitor)?;
98
99 let mut b = self.points[1];
100 b.visit("B", visitor)?;
101
102 let mut c = self.points[2];
103 c.visit("C", visitor)?;
104
105 *self = match Self::from_points(&a, &b, &c) {
106 None => return Err(VisitError::User(String::from("invalid triangle"))),
107 Some(triangle) => triangle,
108 };
109
110 visitor.leave_region()
111 }
112}
113
114impl StaticTriangle {
115 pub fn from_points(a: &Vec3, b: &Vec3, c: &Vec3) -> Option<StaticTriangle> {
121 let ca = *c - *a;
122 let ba = *b - *a;
123 let ca_dot_ca = ca.dot(&ca);
124 let ca_dot_ba = ca.dot(&ba);
125 let ba_dot_ba = ba.dot(&ba);
126 if let Ok(plane) = Plane::from_normal_and_point(&ba.cross(&ca), a) {
127 return Some(StaticTriangle {
128 points: [*a, *b, *c],
129 ba,
130 ca: *c - *a,
131 ca_dot_ca,
132 ca_dot_ba,
133 ba_dot_ba,
134 inv_denom: 1.0 / (ca_dot_ca * ba_dot_ba - ca_dot_ba * ca_dot_ba),
135 plane,
136 });
137 }
138
139 None
140 }
141
142 pub fn contains_point(&self, p: Vec3) -> bool {
144 let vp = p - self.points[0];
145 let dot02 = self.ca.dot(&vp);
146 let dot12 = self.ba.dot(&vp);
147 let u = (self.ba_dot_ba * dot02 - self.ca_dot_ba * dot12) * self.inv_denom;
148 let v = (self.ca_dot_ca * dot12 - self.ca_dot_ba * dot02) * self.inv_denom;
149 u >= 0.0 && v >= 0.0 && u + v < 1.0
150 }
151}