1use std::f32;
20use std::fmt;
21use std::mem;
22use std::collections::HashMap;
23
24use cgmath::prelude::*;
25use cgmath::{EuclideanSpace, InnerSpace, Point3, Vector3};
26use crate::geom::*;
27use crate::collision::*;
28use crate::pool::*;
29
30pub struct Simplex<Point = Point3<f32>>
31where
32 Point: Into<Point3<f32>> + From<Point3<f32>> + Copy + Clone + 'static
33{
34 points: [Point; 4],
35 state: &'static SimplexState<Point>,
36}
37
38impl<Point> fmt::Debug for Simplex<Point>
39where
40 Point: Into<Point3<f32>> + From<Point3<f32>> + Copy + Clone + 'static + fmt::Debug
41{
42 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
43 #[derive(Debug)]
44 enum StateName {
45 Vertex,
46 Edge,
47 Face,
48 Volume
49 };
50 let (state, points) = if self.state as *const _ == &VERTEX_DATAPTRLOC as *const _ {
51 (StateName::Vertex, &self.points[..1])
52 } else if self.state as *const _ == &EDGE_DATAPTRLOC as * const _ {
53 (StateName::Edge, &self.points[..2])
54 } else if self.state as * const _ == &FACE_DATAPTRLOC as * const _ {
55 (StateName::Face, &self.points[..3])
56 } else {
57 (StateName::Volume, &self.points[..4])
58 };
59 write!(f, "Simplex {{ state: {:?}, points: {:?} }}", state, points)
60 }
61}
62
63impl<Point> From<[Point; 1]> for Simplex<Point>
64where
65 Point: Into<Point3<f32>> + From<Point3<f32>> + Copy + Clone + 'static
66{
67 fn from(p: [Point; 1]) -> Self {
68 Self::from(p[0])
69 }
70}
71
72impl<Point> From<Point> for Simplex<Point>
73where
74 Point: Into<Point3<f32>> + From<Point3<f32>> + Copy + Clone + 'static
75{
76 fn from(p: Point) -> Self {
77 Simplex {
78 points: [
79 p,
80 Point::from(Point3::new(0.0, 0.0, 0.0)),
81 Point::from(Point3::new(0.0, 0.0, 0.0)),
82 Point::from(Point3::new(0.0, 0.0, 0.0)),
83 ],
84 state: &VERTEX_DATAPTRLOC,
85 }
86 }
87}
88
89impl<Point> From<[Point; 2]> for Simplex<Point>
90where
91 Point: Into<Point3<f32>> + From<Point3<f32>> + Copy + Clone + 'static
92{
93 fn from(p: [Point; 2]) -> Self {
94 Self::from((p[0], p[1]))
95 }
96}
97
98impl<Point> From<(Point, Point)> for Simplex<Point>
99where
100 Point: Into<Point3<f32>> + From<Point3<f32>> + Copy + Clone + 'static
101{
102 fn from(p: (Point, Point)) -> Self {
103 Simplex {
104 points: [
105 p.0,
106 p.1,
107 Point::from(Point3::new(0.0, 0.0, 0.0)),
108 Point::from(Point3::new(0.0, 0.0, 0.0)),
109 ],
110 state: &EDGE_DATAPTRLOC,
111 }
112 }
113}
114
115impl<Point> From<[Point; 3]> for Simplex<Point>
116where
117 Point: Into<Point3<f32>> + From<Point3<f32>> + Copy + Clone + 'static
118{
119 fn from(p: [Point; 3]) -> Self {
120 Self::from((p[0], p[1], p[2]))
121 }
122}
123
124impl<Point> From<(Point, Point, Point)> for Simplex<Point>
125where
126 Point: Into<Point3<f32>> + From<Point3<f32>> + Copy + Clone + 'static
127{
128 fn from(p: (Point, Point, Point)) -> Self {
129 Simplex {
130 points: [
131 p.0,
132 p.1,
133 p.2,
134 Point::from(Point3::new(0.0, 0.0, 0.0)),
135 ],
136 state: &FACE_DATAPTRLOC,
137 }
138 }
139}
140
141impl<Point> From<[Point; 4]> for Simplex<Point>
142where
143 Point: Into<Point3<f32>> + From<Point3<f32>> + Copy + Clone + 'static
144{
145 fn from(p: [Point; 4]) -> Self {
146 Self::from((p[0], p[1], p[2], p[3]))
147 }
148}
149
150impl<Point> From<(Point, Point, Point, Point)> for Simplex<Point>
151where
152 Point: Into<Point3<f32>> + From<Point3<f32>> + Copy + Clone + 'static
153{
154 fn from(p: (Point, Point, Point, Point)) -> Self {
155 Simplex {
156 points: [
157 p.0,
158 p.1,
159 p.2,
160 p.3,
161 ],
162 state: &VOLUME_DATAPTRLOC,
163 }
164 }
165}
166
167impl<Point> Simplex<Point>
168where
169 Point: Into<Point3<f32>> + From<Point3<f32>> + Copy + Clone + 'static + fmt::Debug
170{
171 pub fn closest_point_to_origin<S>(&mut self, shape: &S) -> Point3<f32>
173 where
174 S: Convex<Point>
175 {
176 let mut prev_norm = Vector3::zero();
177 loop {
178 let (min_norm, next_state) = self.state.min_norm(&mut self.points);
179 if min_norm.magnitude2() < COLLISION_EPSILON {
180 for i in self.state.len()..4 {
183 let min_norm = -Vector3::new(prev_norm.z, prev_norm.x, prev_norm.y);
184 let support = shape.support(-min_norm.normalize());
185 prev_norm = -min_norm.normalize();
186 self.points[i] = support;
187 }
188 self.state = &VOLUME_DATAPTRLOC;
189 return Point3::new(0.0, 0.0, 0.0);
190 }
191 let support = shape.support(-min_norm.normalize());
192 let support_v = support.into().to_vec();
193 prev_norm = min_norm;
194 if min_norm.magnitude2() >= support_v.magnitude2() {
195 return Point3::from_vec(min_norm);
196 }
197 self.state = next_state;
198 self.state.add_point(&mut self.points, support);
199 }
200 }
201}
202
203trait SimplexState<Point>
204where
205 Point: Into<Point3<f32>> + Copy + Clone + 'static
206{
207 fn min_norm(&self, _: &mut [Point; 4]) -> (Vector3<f32>, &'static SimplexState<Point>);
208
209 fn add_point(&self, _: &mut [Point; 4], _: Point);
210
211 fn len(&self) -> usize;
212}
213
214struct VertexSimplex{}
215struct EdgeSimplex{}
216struct FaceSimplex{}
217struct VolumeSimplex{}
218
219static VERTEX_DATAPTRLOC: VertexSimplex = VertexSimplex{};
220static EDGE_DATAPTRLOC: EdgeSimplex = EdgeSimplex{};
221static FACE_DATAPTRLOC: FaceSimplex = FaceSimplex{};
222static VOLUME_DATAPTRLOC: VolumeSimplex = VolumeSimplex{};
223
224impl<Point> SimplexState<Point> for VertexSimplex
225where
226 Point: Into<Point3<f32>> + Copy + Clone + 'static
227{
228 fn min_norm(&self, simp: &mut [Point; 4]) -> (Vector3<f32>, &'static SimplexState<Point>) {
229 (simp[0].into().to_vec(), &EDGE_DATAPTRLOC)
230 }
231
232 fn add_point(&self, simp: &mut [Point; 4], p: Point) {
233 simp[0] = p
234 }
235
236 fn len(&self) -> usize { 1 }
237}
238
239impl<Point> SimplexState<Point> for EdgeSimplex
240where
241 Point: Into<Point3<f32>> + Copy + Clone + 'static
242{
243 fn min_norm(&self, simp: &mut [Point; 4]) -> (Vector3<f32>, &'static SimplexState<Point>) {
244 let ab = simp[1].into() - simp[0].into();
245 let t = ab.dot(-simp[0].into().to_vec());
246 if t <= 0.0 {
247 (simp[0].into().to_vec(), &EDGE_DATAPTRLOC)
248 } else {
249 let denom = ab.dot(ab);
250 if t >= denom {
251 simp[0] = simp[1];
252 (simp[1].into().to_vec(), &EDGE_DATAPTRLOC)
253 } else {
254 (simp[0].into().to_vec() + ab * (t / denom), &FACE_DATAPTRLOC)
255 }
256 }
257 }
258
259 fn add_point(&self, simp: &mut [Point; 4], p: Point) {
260 simp[1] = p
261 }
262
263 fn len(&self) -> usize { 2 }
264}
265
266
267impl<Point> SimplexState<Point> for FaceSimplex
268where
269 Point: Into<Point3<f32>> + Copy + Clone + 'static
270{
271 fn min_norm(&self, simp: &mut [Point; 4]) -> (Vector3<f32>, &'static SimplexState<Point>) {
272 let (a, b, c): (Point3<f32>, Point3<f32>, Point3<f32>) = (
273 simp[0].into(), simp[1].into(), simp[2].into()
274 );
275 let ab = b - a;
276 let ac = c - a;
277 let ap = -a.to_vec();
278 let d1 = ab.dot(ap);
279 let d2 = ac.dot(ap);
280
281 if d1 <= 0.0 && d2 <= 0.0 {
283 return (simp[0].into().to_vec(), &EDGE_DATAPTRLOC);
284 }
285
286 let bp = -b.to_vec();
288 let d3 = ab.dot(bp);
289 let d4 = ac.dot(bp);
290 if d3 >= 0.0 && d4 <= d3 {
291 simp[0] = simp[1];
292 return (simp[1].into().to_vec(), &EDGE_DATAPTRLOC);
293 }
294
295 let vc = d1 * d4 - d3 * d2;
297 if vc <= 0.0 && d1 >= 0.0 && d3 <= 0.0 {
298 let v = d1 / (d1 - d3);
299 return ((simp[0].into().to_vec() + ab * v), &FACE_DATAPTRLOC);
300 }
301
302 let cp = -c.to_vec();
304 let d5 = ab.dot(cp);
305 let d6 = ac.dot(cp);
306 if d6 >= 0.0 && d5 <= d6 {
307 simp[0] = simp[2];
308 return (simp[2].into().to_vec(), &EDGE_DATAPTRLOC);
309 }
310
311 let vb = d5 * d2 - d1 * d6;
313 if vb <= 0.0 && d2 >= 0.0 && d6 <= 0.0 {
314 let w = d2 / (d2 - d6);
315 simp[1] = simp[2];
316 return ((simp[0].into().to_vec() + ac * w), &FACE_DATAPTRLOC);
317 }
318
319 let va = d3 * d6 - d5 * d4;
321 if va <= 0.0 && (d4 - d3) >= 0.0 && (d5 - d6) >= 0.0 {
322 let w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
323 simp[0] = simp[2];
324 return ((simp[1].into().to_vec() + (simp[2].into() - simp[1].into()) * w), &FACE_DATAPTRLOC);
325 }
326
327 let denom = 1.0 / (va + vb + vc);
328 let v = vb * denom;
329 let w = vc * denom;
330 ((simp[0].into().to_vec() + ab * v + ac * w), &VOLUME_DATAPTRLOC)
331 }
332
333 fn add_point(&self, simp: &mut [Point; 4], p: Point) {
334 simp[2] = p;
335 }
336
337 fn len(&self) -> usize { 3 }
338}
339
340fn origin_outside_plane(
341 a: Vector3<f32>, b: Vector3<f32>, c: Vector3<f32>, d: Vector3<f32>
342) -> bool {
343 let ab_x_ac = (b - a).cross(c - a);
344 let sign_p = (-a).dot(ab_x_ac);
345 let sign_d = (d - a).dot(ab_x_ac);
346 sign_p * sign_d < 0.0
347}
348
349impl<Point> SimplexState<Point> for VolumeSimplex
350where
351 Point: Into<Point3<f32>> + Copy + Clone + 'static
352{
353 fn min_norm(&self, simp: &mut [Point; 4]) -> (Vector3<f32>, &'static SimplexState<Point>) {
354 let mut closest_pt: Vector3<f32> = Vector3::zero();
355 let mut best_dist: f32 = f32::INFINITY;
356 let mut next_state: &'static SimplexState<Point> = &VERTEX_DATAPTRLOC;
357 let (a, b, c, d) = (simp[0], simp[1], simp[2], simp[3]);
358 let (av, bv, cv, dv) = (a.into().to_vec(), b.into().to_vec(), c.into().to_vec(), d.into().to_vec());
359 if origin_outside_plane(av, bv, cv, dv) {
361 let mut new_simp = [ a, b, c, d ];
362 let (p, new_state) = FACE_DATAPTRLOC.min_norm(&mut new_simp);
363 let new_dist = p.magnitude2();
364 if new_dist < best_dist {
365 closest_pt = p;
366 best_dist = new_dist;
367 next_state = new_state;
368 *simp = new_simp;
369 }
370 }
371 if origin_outside_plane(av, cv, dv, bv) {
373 let mut new_simp = [ a, c, d, b ];
374 let (p, new_state) = FACE_DATAPTRLOC.min_norm(&mut new_simp);
375 let new_dist = p.magnitude2();
376 if new_dist < best_dist {
377 closest_pt = p;
378 best_dist = new_dist;
379 next_state = new_state;
380 *simp = new_simp;
381 }
382 }
383 if origin_outside_plane(av, dv, bv, cv) {
385 let mut new_simp = [ a, d, b, c ];
386 let (p, new_state) = FACE_DATAPTRLOC.min_norm(&mut new_simp);
387 let new_dist = p.magnitude2();
388 if new_dist < best_dist {
389 closest_pt = p;
390 best_dist = new_dist;
391 next_state = new_state;
392 *simp = new_simp;
393 }
394 }
395 if origin_outside_plane(bv, dv, cv, av) {
397 let mut new_simp = [ b, d, c, a ];
398 let (p, new_state) = FACE_DATAPTRLOC.min_norm(&mut new_simp);
399 let new_dist = p.magnitude2();
400 if new_dist < best_dist {
401 closest_pt = p;
402 next_state = new_state;
403 *simp = new_simp;
404 }
405 }
406
407 (closest_pt, next_state)
408 }
409
410 fn add_point(&self, simp: &mut [Point; 4], p: Point) {
411 simp[3] = p
412 }
413
414 fn len(&self) -> usize { 4 }
415}
416
417#[derive(Default)]
418struct EdgeMap {
419 map: HashMap<[ (u32, u32, u32); 2 ], [ (Point3<f32>, Point3<f32>); 2 ]>,
420}
421
422impl EdgeMap {
423 fn add_edge(&mut self, a: SupportPoint, b: SupportPoint) {
424 let la = (a.a, a.b);
425 let lb = (b.a, b.b);
426 let a = unsafe {
427 (
428 mem::transmute::<f32, u32>(a.p.x),
429 mem::transmute::<f32, u32>(a.p.y),
430 mem::transmute::<f32, u32>(a.p.z),
431 )
432 };
433 let b = unsafe {
434 (
435 mem::transmute::<f32, u32>(b.p.x),
436 mem::transmute::<f32, u32>(b.p.y),
437 mem::transmute::<f32, u32>(b.p.z),
438 )
439 };
440 let ba = [ b, a ];
441 if self.map.contains_key(&ba) {
442 self.map.remove(&ba);
443 return;
444 }
445 self.map.insert(
446 [ a, b ],
447 [ la, lb ]
448 );
449 }
450}
451
452
453impl Simplex<SupportPoint> {
454 pub fn compute_contact<S1, S2>(&self, s1: &S1, s2: &S2) -> Contact
457 where
458 S1: Convex,
459 S2: Convex
460 {
461 if self.state.len() != 4 {
462 panic!("simplex is too small");
463 }
464 let diff = MinkowskiDiff{ s1, s2 };
465 let [ a, b, c, d ] = self.points;
466 let mut tris = Pool::from(
467 vec![
468 (a, b, c),
469 (a, c, d),
470 (a, d, b),
471 (b, d, c)
472 ]
473 );
474 let mut edges = EdgeMap::default();
475 const MAX_ITERATIONS: usize = 100;
476 for iter in 0..=MAX_ITERATIONS {
477 let (closest_dist, closest_i, closest_n) = {
478 let mut closest_dist = f32::INFINITY;
479 let mut closest_i = 0usize;
480 let mut closest_n = Vector3::zero();
481 for (i, (a, b, c)) in tris.iter() {
482 let tri = Triangle::from((a.p, b.p, c.p));
483 let n = tri.normal();
484 let dist = n.dot(a.p.to_vec()).abs();
485 if closest_dist > dist {
486 closest_dist = dist;
487 closest_i = i;
488 closest_n = n;
489 }
490 }
491 (closest_dist, closest_i, closest_n)
492 };
493 let closest_tri = {
494 let (a, b, c) = tris[closest_i];
495 ( Triangle::from((a.p, b.p, c.p)), Triangle::from((a.a, b.a, c.a)) )
496 };
497 let support: SupportPoint = diff.support(closest_n);
498 let v = closest_n.dot(support.p.to_vec()) - closest_dist;
499 if v < COLLISION_EPSILON || iter == MAX_ITERATIONS {
500 let (u, v, w ) = closest_tri.0.barycentric(Point3::from_vec(closest_dist * closest_n));
501 let a = u * closest_tri.1.a + v * closest_tri.1.b + w * closest_tri.1.c;
502 return Contact {
503 a: Point3::from_vec(a),
504 b: Point3::from_vec(a - closest_dist*closest_n),
505 n: closest_n,
506 t: 0.0
507 };
508 }
509 let mut to_remove = Vec::new();
511 for (i, (a, b, c)) in tris.iter() {
512 let n = Triangle::from((a.p, b.p, c.p)).normal();
513 if n.dot(support.p - a.p) > 0.0 {
514 edges.add_edge(*a, *b);
515 edges.add_edge(*b, *c);
516 edges.add_edge(*c, *a);
517 to_remove.push(i);
518 }
519 }
520 for i in to_remove {
521 tris.remove(i);
522 }
523 for ([( apx, apy, apz ), ( bpx, bpy, bpz ) ], [ la, lb ]) in edges.map.iter() {
524 let a = unsafe {
525 (
526 mem::transmute::<u32, f32>(*apx),
527 mem::transmute::<u32, f32>(*apy),
528 mem::transmute::<u32, f32>(*apz)
529 )
530 };
531 let b = unsafe {
532 (
533 mem::transmute::<u32, f32>(*bpx),
534 mem::transmute::<u32, f32>(*bpy),
535 mem::transmute::<u32, f32>(*bpz)
536 )
537 };
538 let a = SupportPoint {
539 p: Point3::new(a.0, a.1, a.2),
540 a: la.0,
541 b: la.1
542 };
543 let b = SupportPoint {
544 p: Point3::new(b.0, b.1, b.2),
545 a: lb.0,
546 b: lb.1
547 };
548 tris.push((support, a, b));
549 }
550 edges.map.clear();
551 }
552 unreachable!()
553 }
554}
555