1use std::fmt::Debug;
2use std::ops::{Add, Mul, Sub};
3
4use cgmath::{
5 BaseFloat, Basis2, EuclideanSpace, InnerSpace, Matrix3, Point2, Point3, Quaternion, Rotation,
6 Transform, Vector3, Zero,
7};
8use collision::dbvt::TreeValue;
9use collision::{Bound, ComputeBound, Contains, Discrete, HasBound, SurfaceArea, Union};
10use core::{
11 ApplyAngular, BroadPhase, GetId, Inertia, NarrowPhase, PartialCrossProduct, PhysicsTime, Pose,
12 Primitive,
13};
14use specs::prelude::{Component, DispatcherBuilder, Entity, Tracked};
15
16pub fn setup_dispatch<'a, 'b, P, T, B, D, Y, V, N, R, A, I, DT, O>(
40 dispatcher: &mut DispatcherBuilder<'a, 'b>,
41 broad_phase: V,
42 narrow_phase: N,
43 spatial: bool,
44) where
45 V: BroadPhase<D> + BroadPhase<(usize, D)> + 'static,
46 N: NarrowPhase<P, T, B, Y> + 'static,
47 P: Primitive + ComputeBound<B> + Send + Sync + 'static,
48 P::Point: Debug + Send + Sync + 'static,
49 <P::Point as EuclideanSpace>::Scalar: BaseFloat + Send + Sync + 'static,
50 <P::Point as EuclideanSpace>::Diff:
51 InnerSpace
52 + PartialCrossProduct<<P::Point as EuclideanSpace>::Diff, Output = O>
53 + Debug
54 + Send
55 + Sync
56 + 'static,
57 T: Debug + Component + Pose<P::Point, R> + Transform<P::Point> + Send + Sync + Clone + 'static,
58 T::Storage: Tracked,
59 Y: Default + Send + Sync + 'static,
60 B: Bound<Point = P::Point>
61 + Send
62 + Sync
63 + 'static
64 + Union<B, Output = B>
65 + Clone
66 + Contains<B>
67 + SurfaceArea<Scalar = <P::Point as EuclideanSpace>::Scalar>
68 + Discrete<B>
69 + Debug,
70 (usize, D): HasBound<Bound = B>,
71 D: TreeValue<Bound = B>
72 + HasBound<Bound = B>
73 + From<(Entity, B)>
74 + GetId<Entity>
75 + Send
76 + Sync
77 + 'static,
78 R: Rotation<P::Point>
79 + ApplyAngular<<P::Point as EuclideanSpace>::Scalar, A>
80 + Send
81 + Sync
82 + 'static,
83 I: Inertia<Orientation = R> + Mul<A, Output = A> + Mul<O, Output = O> + Send + Sync + 'static,
84 A: Mul<<P::Point as EuclideanSpace>::Scalar, Output = A>
85 + PartialCrossProduct<
86 <P::Point as EuclideanSpace>::Diff,
87 Output = <P::Point as EuclideanSpace>::Diff,
88 > + Zero
89 + Clone
90 + Copy
91 + Send
92 + Sync
93 + 'static,
94 DT: PhysicsTime<<P::Point as EuclideanSpace>::Scalar> + Default + Send + Sync + 'static,
95 O: PartialCrossProduct<
96 <P::Point as EuclideanSpace>::Diff,
97 Output = <P::Point as EuclideanSpace>::Diff,
98 > + Send
99 + Sync
100 + 'static,
101 for<'c> &'c A: Sub<O, Output = A> + Add<O, Output = A>,
102{
103 use {
104 BasicCollisionSystem, ContactResolutionSystem, CurrentFrameUpdateSystem,
105 NextFrameSetupSystem, SpatialCollisionSystem, SpatialSortingSystem,
106 };
107 dispatcher.add(
108 CurrentFrameUpdateSystem::<P::Point, R, A, T>::new(),
109 "physics_solver_system",
110 &[],
111 );
112 dispatcher.add(
113 NextFrameSetupSystem::<P::Point, R, I, A, T, DT>::new(),
114 "next_frame_setup",
115 &["physics_solver_system"],
116 );
117 if spatial {
118 dispatcher.add(
119 SpatialSortingSystem::<P, T, D, B, Y>::new(),
120 "spatial_sorting_system",
121 &["next_frame_setup"],
122 );
123 dispatcher.add(
124 SpatialCollisionSystem::<P, T, (usize, D), B, Y>::new()
125 .with_broad_phase(broad_phase)
126 .with_narrow_phase(narrow_phase),
127 "collision_system",
128 &["spatial_sorting_system"],
129 );
130 } else {
131 dispatcher.add(
132 BasicCollisionSystem::<P, T, D, B, Y>::new()
133 .with_broad_phase(broad_phase)
134 .with_narrow_phase(narrow_phase),
135 "collision_system",
136 &["next_frame_setup"],
137 );
138 }
139 dispatcher.add(
140 ContactResolutionSystem::<P::Point, R, I, A, O, T>::new(),
141 "contact_resolution",
142 &["collision_system"],
143 );
144}
145
146pub fn setup_dispatch_2d<'a, 'b, S, P, T, B, D, Y, V, N, DT>(
167 dispatcher: &mut DispatcherBuilder<'a, 'b>,
168 broad_phase: V,
169 narrow_phase: N,
170 spatial: bool,
171) where
172 V: BroadPhase<D> + BroadPhase<(usize, D)> + 'static,
173 N: NarrowPhase<P, T, B, Y> + 'static,
174 P: Primitive<Point = Point2<S>> + ComputeBound<B> + Send + Sync + 'static,
175 S: Inertia<Orientation = Basis2<S>> + BaseFloat + Send + Sync + 'static,
176 T: Component
177 + Pose<Point2<S>, Basis2<S>>
178 + Debug
179 + Transform<Point2<S>>
180 + Send
181 + Sync
182 + Clone
183 + 'static,
184 T::Storage: Tracked,
185 Y: Default + Send + Sync + 'static,
186 B: Bound<Point = Point2<S>>
187 + Send
188 + Sync
189 + 'static
190 + Union<B, Output = B>
191 + Clone
192 + Contains<B>
193 + SurfaceArea<Scalar = S>
194 + Discrete<B>
195 + Debug,
196 (usize, D): HasBound<Bound = B>,
197 D: TreeValue<Bound = B>
198 + HasBound<Bound = B>
199 + From<(Entity, B)>
200 + GetId<Entity>
201 + Send
202 + Sync
203 + 'static,
204 DT: PhysicsTime<S> + Default + Send + Sync + 'static,
205 for<'c> &'c S: Sub<S, Output = S> + Add<S, Output = S>,
206{
207 setup_dispatch::<P, T, B, D, Y, V, N, Basis2<S>, S, S, DT, S>(
208 dispatcher,
209 broad_phase,
210 narrow_phase,
211 spatial,
212 );
213}
214
215pub fn setup_dispatch_3d<S, P, T, B, D, Y, V, N, DT>(
236 dispatcher: &mut DispatcherBuilder,
237 broad_phase: V,
238 narrow_phase: N,
239 spatial: bool,
240) where
241 V: BroadPhase<D> + BroadPhase<(usize, D)> + 'static,
242 N: NarrowPhase<P, T, B, Y> + 'static,
243 P: Primitive<Point = Point3<S>> + ComputeBound<B> + Send + Sync + 'static,
244 S: BaseFloat + Send + Sync + 'static,
245 T: Component
246 + Pose<Point3<S>, Quaternion<S>>
247 + Transform<Point3<S>>
248 + Debug
249 + Send
250 + Sync
251 + Clone
252 + 'static,
253 T::Storage: Tracked,
254 Y: Default + Send + Sync + 'static,
255 B: Bound<Point = Point3<S>>
256 + Send
257 + Sync
258 + 'static
259 + Union<B, Output = B>
260 + Clone
261 + Contains<B>
262 + SurfaceArea<Scalar = S>
263 + Discrete<B>
264 + Debug,
265 (usize, D): HasBound<Bound = B>,
266 D: TreeValue<Bound = B>
267 + HasBound<Bound = B>
268 + From<(Entity, B)>
269 + GetId<Entity>
270 + Send
271 + Sync
272 + 'static,
273 DT: PhysicsTime<S> + Default + Send + Sync + 'static,
274{
275 setup_dispatch::<P, T, B, D, Y, V, N, Quaternion<S>, Vector3<S>, Matrix3<S>, DT, Vector3<S>>(
276 dispatcher,
277 broad_phase,
278 narrow_phase,
279 spatial,
280 );
281}
282
283#[cfg(test)]
284mod tests {
285
286 use super::*;
287 use collide2d::{BodyPose2, SweepAndPrune2, GJK2};
288 use collide3d::{BodyPose3, SweepAndPrune3, GJK3};
289 use collision::dbvt::TreeValueWrapped;
290 use collision::primitive::{Primitive2, Primitive3};
291 use collision::{Aabb2, Aabb3};
292 use DeltaTime;
293
294 #[test]
295 fn test_dispatch() {
296 let mut builder = DispatcherBuilder::new();
297 setup_dispatch::<
298 Primitive2<f32>,
299 BodyPose2<f32>,
300 Aabb2<f32>,
301 TreeValueWrapped<Entity, Aabb2<f32>>,
302 (),
303 _,
304 _,
305 _,
306 _,
307 f32,
308 DeltaTime<f32>,
309 _,
310 >(&mut builder, SweepAndPrune2::new(), GJK2::new(), false);
311 }
312
313 #[test]
314 fn test_dispatch_2d() {
315 let mut builder = DispatcherBuilder::new();
316 setup_dispatch_2d::<
317 _,
318 Primitive2<f32>,
319 BodyPose2<f32>,
320 Aabb2<f32>,
321 TreeValueWrapped<Entity, Aabb2<f32>>,
322 (),
323 _,
324 _,
325 DeltaTime<f32>,
326 >(&mut builder, SweepAndPrune2::new(), GJK2::new(), false);
327 }
328
329 #[test]
330 fn test_dispatch_3d() {
331 let mut builder = DispatcherBuilder::new();
332 setup_dispatch_3d::<
333 _,
334 Primitive3<f32>,
335 BodyPose3<f32>,
336 Aabb3<f32>,
337 TreeValueWrapped<Entity, Aabb3<f32>>,
338 (),
339 _,
340 _,
341 DeltaTime<f32>,
342 >(&mut builder, SweepAndPrune3::new(), GJK3::new(), false);
343 }
344}