collision_detection/
lib.rs1#![deny(missing_docs)]
2
3use array_linked_list::ArrayLinkedList;
17use collide::{Collider, CollisionInfo};
18use vector_space::VectorSpace;
19
20pub struct Body<C: Collider> {
23 pub colliders: Vec<C>,
25}
26
27impl<C: Collider> Body<C> {
28 pub fn new() -> Self {
30 Self {
31 colliders: Vec::new(),
32 }
33 }
34
35 pub fn with_collider(mut self, collider: C) -> Self {
37 self.colliders.push(collider);
38 self
39 }
40}
41
42#[derive(Copy, Clone)]
44pub enum ObjectIndex<S, D> {
45 Static(S),
47 Dynamic(D),
49}
50
51pub struct IndexedCollisionInfo<V: VectorSpace, S, D> {
53 pub index: ObjectIndex<S, D>,
55 pub info: CollisionInfo<V>,
57}
58
59struct Static<C: Collider, I> {
60 collider: C,
61 index: I,
62}
63
64struct Dynamic<C: Collider, I> {
65 body: Body<C>,
66 index: I,
67}
68
69pub struct CollisionManager<C: Collider, S, D> {
73 bodies: ArrayLinkedList<Dynamic<C, D>>,
74 colliders: ArrayLinkedList<Static<C, S>>,
75}
76
77impl<C: Collider, S: Copy, D: Copy> CollisionManager<C, S, D> {
78 pub fn new() -> Self {
80 Self {
81 bodies: ArrayLinkedList::new(),
82 colliders: ArrayLinkedList::new(),
83 }
84 }
85
86 pub fn with_capacity(capacity: usize) -> Self {
88 Self {
89 bodies: ArrayLinkedList::with_capacity(capacity),
90 colliders: ArrayLinkedList::new(),
91 }
92 }
93
94 pub fn insert_collider(&mut self, collider: C, index: S) -> usize {
97 self.colliders.push_back(Static { collider, index })
98 }
99
100 pub fn insert_body(&mut self, body: Body<C>, index: D) -> usize {
103 self.bodies.push_back(Dynamic { body, index })
104 }
105
106 pub fn replace_collider(&mut self, index: usize, collider: C) {
108 self.colliders[index].as_mut().unwrap().collider = collider;
109 }
110
111 pub fn replace_body(&mut self, index: usize, body: Body<C>) {
113 self.bodies[index].as_mut().unwrap().body = body;
114 }
115
116 pub fn remove_collider(&mut self, index: usize) {
118 self.colliders.remove(index);
119 }
120
121 pub fn remove_body(&mut self, index: usize) {
123 self.bodies.remove(index);
124 }
125
126 pub fn collider(&self, index: usize) -> &C {
128 &self.colliders[index].as_ref().unwrap().collider
129 }
130
131 pub fn collider_mut(&mut self, index: usize) -> &mut C {
133 &mut self.colliders[index].as_mut().unwrap().collider
134 }
135
136 pub fn body(&self, index: usize) -> &Body<C> {
138 &self.bodies[index].as_ref().unwrap().body
139 }
140
141 pub fn body_mut(&mut self, index: usize) -> &mut Body<C> {
143 &mut self.bodies[index].as_mut().unwrap().body
144 }
145
146 pub fn find_static_collision(&self, collider: &C) -> Option<S> {
148 for collider_static in &self.colliders {
149 if collider.check_collision(&collider_static.collider) {
150 return Some(collider_static.index);
151 }
152 }
153 None
154 }
155
156 pub fn find_dynamic_collision(&self, collider: &C) -> Option<D> {
158 for body_dynamic in &self.bodies {
159 for dynamic_collider in &body_dynamic.body.colliders {
160 if collider.check_collision(dynamic_collider) {
161 return Some(body_dynamic.index);
162 }
163 }
164 }
165 None
166 }
167
168 pub fn find_collision(&self, collider: &C) -> Option<ObjectIndex<S, D>> {
170 if let Some(index) = self.find_dynamic_collision(collider) {
171 Some(ObjectIndex::Dynamic(index))
172 } else if let Some(index) = self.find_static_collision(collider) {
173 Some(ObjectIndex::Static(index))
174 } else {
175 None
176 }
177 }
178
179 pub fn compute_collisions(
182 &self,
183 ) -> ArrayLinkedList<Vec<IndexedCollisionInfo<C::Vector, S, D>>> {
184 let mut result = ArrayLinkedList::with_capacity(self.bodies.capacity());
185 for body_index in self.bodies.indices() {
186 result.replace_front(body_index, Vec::new());
187 }
188 for (body_index, body_dynamic) in self.bodies.indexed() {
189 let infos = result[body_index].as_mut().unwrap();
190 for collider_static in &self.colliders {
192 for body_collider in &body_dynamic.body.colliders {
193 if let Some(info) = body_collider.collision_info(&collider_static.collider) {
194 infos.push(IndexedCollisionInfo {
195 index: ObjectIndex::Static(collider_static.index),
196 info,
197 });
198 }
199 }
200 }
201 let infos = infos as *mut _;
202 for (other_index, other_dynamic) in self.bodies.indexed_after(body_index) {
204 let other_infos = result[other_index].as_mut().unwrap();
205 for dynamic_collider in &other_dynamic.body.colliders {
206 for body_collider in &body_dynamic.body.colliders {
207 if let Some(info) = body_collider.collision_info(dynamic_collider) {
208 other_infos.push(IndexedCollisionInfo {
209 index: ObjectIndex::Dynamic(body_dynamic.index),
210 info: -info,
211 });
212 unsafe {
213 std::mem::transmute::<
214 _,
215 &mut Vec<IndexedCollisionInfo<C::Vector, S, D>>,
216 >(infos)
217 }
218 .push(IndexedCollisionInfo {
219 index: ObjectIndex::Dynamic(other_dynamic.index),
220 info,
221 });
222 }
223 }
224 }
225 }
226 }
227 result
228 }
229}