ncollide3d/query/contact/
contact.rs

1use crate::math::{Point, Vector};
2use crate::query::ContactKinematic;
3use na::{self, RealField, Unit};
4use slotmap::Key;
5use std::mem;
6
7slotmap::new_key_type! {
8    /// A contact identifier which is unique within a contact manifold.
9    pub struct ContactId;
10}
11
12/// Geometric description of a contact.
13#[derive(Debug, PartialEq, Copy, Clone)]
14#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
15pub struct Contact<N: RealField + Copy> {
16    /// Position of the contact on the first object. The position is expressed in world space.
17    pub world1: Point<N>,
18
19    /// Position of the contact on the second object. The position is expressed in world space.
20    pub world2: Point<N>,
21
22    /// Contact normal
23    pub normal: Unit<Vector<N>>,
24
25    /// Penetration depth
26    pub depth: N,
27}
28
29impl<N: RealField + Copy> Contact<N> {
30    /// Creates a new contact.
31    #[inline]
32    pub fn new(world1: Point<N>, world2: Point<N>, normal: Unit<Vector<N>>, depth: N) -> Self {
33        Contact {
34            world1,
35            world2,
36            normal,
37            depth,
38        }
39    }
40
41    /// Creates a new contact, computing automatically the penetration depth.
42    #[inline]
43    pub fn new_wo_depth(world1: Point<N>, world2: Point<N>, normal: Unit<Vector<N>>) -> Contact<N> {
44        let depth = -normal.dot(&(world2 - world1));
45        Self::new(world1, world2, normal, depth)
46    }
47}
48
49impl<N: RealField + Copy> Contact<N> {
50    /// Reverts the contact normal and swaps `world1` and `world2`.
51    #[inline]
52    pub fn flip(&mut self) {
53        mem::swap(&mut self.world1, &mut self.world2);
54        self.normal = -self.normal;
55    }
56}
57
58/// A contact combined with contact kinematic information as well as a persistent identifier.
59///
60/// When ncollide is used to compute contact points between moving solids, it will attempt to
61/// match contact points found at successive frames. Two contact points are said to "match" if
62/// they can be seen as the same contact point that moved in-between frames. Two matching
63/// contact points are given the same `id` here.
64#[derive(Copy, Clone, Debug)]
65pub struct TrackedContact<N: RealField + Copy> {
66    /// The geometric contact information.
67    pub contact: Contact<N>,
68    /// The local contact kinematic.
69    pub kinematic: ContactKinematic<N>,
70    /// The identifier of this contact.
71    pub id: ContactId,
72}
73
74impl<N: RealField + Copy> TrackedContact<N> {
75    /// Creates a new tracked contact.
76    pub fn new(contact: Contact<N>, kinematic: ContactKinematic<N>) -> Self {
77        TrackedContact {
78            contact,
79            kinematic,
80            id: ContactId::null(),
81        }
82    }
83}
84
85/// The prediction parameters for contact determination.
86#[derive(Clone, Debug, PartialEq)]
87pub struct ContactPrediction<N: RealField + Copy> {
88    linear: N,
89    angular1: N,
90    angular2: N,
91    cos_angular1: N,
92    cos_angular2: N,
93    sin_angular1: N,
94    sin_angular2: N,
95}
96
97impl<N: RealField + Copy> ContactPrediction<N> {
98    /// Initialize prediction parameters.
99    pub fn new(linear: N, angular1: N, angular2: N) -> Self {
100        ContactPrediction {
101            linear,
102            angular1,
103            angular2,
104            cos_angular1: angular1.cos(),
105            cos_angular2: angular2.cos(),
106            sin_angular1: angular1.sin(),
107            sin_angular2: angular2.sin(),
108        }
109    }
110
111    /// The linear prediction.
112    #[inline]
113    pub fn linear(&self) -> N {
114        self.linear
115    }
116
117    /// Sets linear prediction.
118    #[inline]
119    pub fn set_linear(&mut self, val: N) {
120        self.linear = val
121    }
122
123    /// The angular regularization for the first solid.
124    #[inline]
125    pub fn angular1(&self) -> N {
126        self.angular1
127    }
128
129    /// The angular regularization for the second solid.
130    #[inline]
131    pub fn angular2(&self) -> N {
132        self.angular2
133    }
134
135    /// The cosine of angular regularization for the first solid.
136    #[inline]
137    pub fn cos_angular1(&self) -> N {
138        self.cos_angular1
139    }
140
141    /// The cosine angular regularization for the second solid.
142    #[inline]
143    pub fn cos_angular2(&self) -> N {
144        self.cos_angular2
145    }
146
147    /// The sine of angular regularization for the first solid.
148    #[inline]
149    pub fn sin_angular1(&self) -> N {
150        self.sin_angular1
151    }
152
153    /// The sine angular regularization for the second solid.
154    #[inline]
155    pub fn sin_angular2(&self) -> N {
156        self.sin_angular2
157    }
158}