ncollide3d/pipeline/object/
collision_object.rs1use crate::bounding_volume::{self, BoundingVolume, AABB};
2use crate::math::Isometry;
3use crate::pipeline::broad_phase::BroadPhaseProxyHandle;
4use crate::pipeline::narrow_phase::CollisionObjectGraphIndex;
5use crate::pipeline::object::CollisionGroups;
6use crate::pipeline::object::GeometricQueryType;
7use crate::shape::{Shape, ShapeHandle};
8use simba::scalar::RealField;
9
10bitflags! {
11 #[derive(Default)]
12 pub struct CollisionObjectUpdateFlags: u8 {
14 const POSITION_CHANGED = 0b00000001;
16 const PREDICTED_POSITION_CHANGED = 0b00000010;
18 const SHAPE_CHANGED = 0b000100;
20 const COLLISION_GROUPS_CHANGED = 0b001000;
22 const QUERY_TYPE_CHANGED = 0b0010000;
24 }
25}
26
27impl CollisionObjectUpdateFlags {
28 pub fn needs_broad_phase_update(&self) -> bool {
30 !self.is_empty()
31 }
32
33 pub fn needs_narrow_phase_update(&self) -> bool {
35 self.intersects(
38 Self::POSITION_CHANGED
39 | Self::SHAPE_CHANGED
40 | Self::COLLISION_GROUPS_CHANGED
41 | Self::QUERY_TYPE_CHANGED,
42 )
43 }
44
45 pub fn needs_bounding_volume_update(&self) -> bool {
47 self.intersects(Self::POSITION_CHANGED | Self::SHAPE_CHANGED | Self::QUERY_TYPE_CHANGED)
50 }
51
52 pub fn needs_broad_phase_redispatch(&self) -> bool {
55 self.intersects(
56 Self::SHAPE_CHANGED | Self::COLLISION_GROUPS_CHANGED | Self::QUERY_TYPE_CHANGED,
57 )
58 }
59}
60
61pub trait CollisionObjectRef<N: RealField + Copy> {
63 fn graph_index(&self) -> Option<CollisionObjectGraphIndex>;
67 fn proxy_handle(&self) -> Option<BroadPhaseProxyHandle>;
71 fn position(&self) -> &Isometry<N>;
73 fn predicted_position(&self) -> Option<&Isometry<N>>;
79 fn shape(&self) -> &dyn Shape<N>;
81 fn collision_groups(&self) -> &CollisionGroups;
83 fn query_type(&self) -> GeometricQueryType<N>;
85 fn update_flags(&self) -> CollisionObjectUpdateFlags;
87
88 fn compute_aabb(&self) -> AABB<N> {
90 let mut aabb = bounding_volume::aabb(self.shape(), self.position());
91 aabb.loosen(self.query_type().query_limit());
92 aabb
93 }
94
95 fn compute_swept_aabb(&self) -> AABB<N> {
101 if let Some(predicted_pos) = self.predicted_position() {
102 let shape = self.shape();
103 let mut aabb1 = bounding_volume::aabb(shape, self.position());
104 let mut aabb2 = bounding_volume::aabb(shape, predicted_pos);
105 let margin = self.query_type().query_limit();
106 aabb1.loosen(margin);
107 aabb2.loosen(margin);
108 aabb1.merge(&aabb2);
109 aabb1
110 } else {
111 self.compute_aabb()
112 }
113 }
114}
115
116#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
118#[repr(transparent)]
119#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
120pub struct CollisionObjectSlabHandle(pub usize);
121
122impl CollisionObjectSlabHandle {
123 #[inline]
125 pub fn uid(&self) -> usize {
126 self.0
127 }
128}
129
130pub struct CollisionObject<N: RealField + Copy, T> {
132 proxy_handle: Option<BroadPhaseProxyHandle>,
133 graph_index: Option<CollisionObjectGraphIndex>,
134 position: Isometry<N>,
135 predicted_position: Option<Isometry<N>>,
136 shape: ShapeHandle<N>,
137 collision_groups: CollisionGroups,
138 query_type: GeometricQueryType<N>,
139 update_flags: CollisionObjectUpdateFlags,
140 data: T,
141}
142
143impl<N: RealField + Copy, T> CollisionObject<N, T> {
144 pub fn new(
146 proxy_handle: Option<BroadPhaseProxyHandle>,
147 graph_index: Option<CollisionObjectGraphIndex>,
148 position: Isometry<N>,
149 shape: ShapeHandle<N>,
150 groups: CollisionGroups,
151 query_type: GeometricQueryType<N>,
152 data: T,
153 ) -> CollisionObject<N, T> {
154 CollisionObject {
155 proxy_handle,
156 graph_index,
157 position,
158 predicted_position: None,
159 shape,
160 collision_groups: groups,
161 data,
162 query_type,
163 update_flags: CollisionObjectUpdateFlags::all(),
164 }
165 }
166
167 #[inline]
171 pub fn graph_index(&self) -> Option<CollisionObjectGraphIndex> {
172 self.graph_index
173 }
174
175 #[inline]
177 pub fn set_graph_index(&mut self, index: Option<CollisionObjectGraphIndex>) {
178 self.graph_index = index
179 }
180
181 pub fn update_flags_mut(&mut self) -> &mut CollisionObjectUpdateFlags {
183 &mut self.update_flags
184 }
185
186 pub fn clear_update_flags(&mut self) {
188 self.update_flags = CollisionObjectUpdateFlags::empty()
189 }
190
191 #[inline]
193 pub fn proxy_handle(&self) -> Option<BroadPhaseProxyHandle> {
194 self.proxy_handle
195 }
196
197 #[inline]
199 pub fn set_proxy_handle(&mut self, handle: Option<BroadPhaseProxyHandle>) {
200 self.proxy_handle = handle
201 }
202
203 #[inline]
205 pub fn position(&self) -> &Isometry<N> {
206 &self.position
207 }
208
209 #[inline]
211 pub fn predicted_position(&self) -> Option<&Isometry<N>> {
212 self.predicted_position.as_ref()
213 }
214
215 #[inline]
217 pub fn set_position(&mut self, pos: Isometry<N>) {
218 self.update_flags |= CollisionObjectUpdateFlags::POSITION_CHANGED;
219 self.update_flags |= CollisionObjectUpdateFlags::PREDICTED_POSITION_CHANGED;
220 self.position = pos;
221 self.predicted_position = None;
222 }
223
224 #[inline]
226 pub fn set_position_with_prediction(&mut self, pos: Isometry<N>, prediction: Isometry<N>) {
227 self.update_flags |= CollisionObjectUpdateFlags::POSITION_CHANGED;
228 self.update_flags |= CollisionObjectUpdateFlags::PREDICTED_POSITION_CHANGED;
229 self.position = pos;
230 self.predicted_position = Some(prediction);
231 }
232
233 #[inline]
235 pub fn set_predicted_position(&mut self, pos: Option<Isometry<N>>) {
236 self.update_flags |= CollisionObjectUpdateFlags::PREDICTED_POSITION_CHANGED;
237 self.predicted_position = pos;
238 }
239
240 #[inline]
244 pub fn set_deformations(&mut self, coords: &[N]) {
245 self.update_flags |= CollisionObjectUpdateFlags::POSITION_CHANGED;
246 self.shape
247 .make_mut()
248 .as_deformable_shape_mut()
249 .expect("Attempting to deform a non-deformable shape.")
250 .set_deformations(coords)
251 }
252
253 #[inline]
255 pub fn shape(&self) -> &ShapeHandle<N> {
256 &self.shape
257 }
258
259 #[inline]
261 pub fn set_shape(&mut self, shape: ShapeHandle<N>) {
262 self.update_flags |= CollisionObjectUpdateFlags::SHAPE_CHANGED;
263 self.shape = shape
264 }
265
266 #[inline]
268 pub fn collision_groups(&self) -> &CollisionGroups {
269 &self.collision_groups
270 }
271
272 #[inline]
274 pub fn set_collision_groups(&mut self, groups: CollisionGroups) {
275 self.update_flags |= CollisionObjectUpdateFlags::COLLISION_GROUPS_CHANGED;
276 self.collision_groups = groups
277 }
278
279 #[inline]
281 pub fn query_type(&self) -> GeometricQueryType<N> {
282 self.query_type
283 }
284
285 #[inline]
288 pub fn set_query_type(&mut self, query_type: GeometricQueryType<N>) {
289 self.update_flags |= CollisionObjectUpdateFlags::QUERY_TYPE_CHANGED;
290 self.query_type = query_type;
291 }
292
293 #[inline]
295 pub fn data(&self) -> &T {
296 &self.data
297 }
298
299 #[inline]
301 pub fn data_mut(&mut self) -> &mut T {
302 &mut self.data
303 }
304}
305
306impl<N: RealField + Copy, T> CollisionObjectRef<N> for CollisionObject<N, T> {
307 fn graph_index(&self) -> Option<CollisionObjectGraphIndex> {
308 self.graph_index()
309 }
310
311 fn proxy_handle(&self) -> Option<BroadPhaseProxyHandle> {
312 self.proxy_handle()
313 }
314
315 fn position(&self) -> &Isometry<N> {
316 self.position()
317 }
318
319 fn predicted_position(&self) -> Option<&Isometry<N>> {
320 self.predicted_position()
321 }
322
323 fn shape(&self) -> &dyn Shape<N> {
324 self.shape().as_ref()
325 }
326
327 fn collision_groups(&self) -> &CollisionGroups {
328 self.collision_groups()
329 }
330
331 fn query_type(&self) -> GeometricQueryType<N> {
332 self.query_type()
333 }
334
335 fn update_flags(&self) -> CollisionObjectUpdateFlags {
336 self.update_flags
337 }
338}