1 |
|
|
/* |
2 |
|
|
* Software License Agreement (BSD License) |
3 |
|
|
* |
4 |
|
|
* Copyright (c) 2011-2014, Willow Garage, Inc. |
5 |
|
|
* Copyright (c) 2014-2016, Open Source Robotics Foundation |
6 |
|
|
* All rights reserved. |
7 |
|
|
* |
8 |
|
|
* Redistribution and use in source and binary forms, with or without |
9 |
|
|
* modification, are permitted provided that the following conditions |
10 |
|
|
* are met: |
11 |
|
|
* |
12 |
|
|
* * Redistributions of source code must retain the above copyright |
13 |
|
|
* notice, this list of conditions and the following disclaimer. |
14 |
|
|
* * Redistributions in binary form must reproduce the above |
15 |
|
|
* copyright notice, this list of conditions and the following |
16 |
|
|
* disclaimer in the documentation and/or other materials provided |
17 |
|
|
* with the distribution. |
18 |
|
|
* * Neither the name of Open Source Robotics Foundation nor the names of its |
19 |
|
|
* contributors may be used to endorse or promote products derived |
20 |
|
|
* from this software without specific prior written permission. |
21 |
|
|
* |
22 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
23 |
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
24 |
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
25 |
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
26 |
|
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
27 |
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
28 |
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
29 |
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
30 |
|
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
31 |
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
32 |
|
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
33 |
|
|
* POSSIBILITY OF SUCH DAMAGE. |
34 |
|
|
*/ |
35 |
|
|
|
36 |
|
|
/** @author Jia Pan */ |
37 |
|
|
|
38 |
|
|
#ifndef HPP_FCL_BROADPHASE_BROADPAHSESPATIALHASH_INL_H |
39 |
|
|
#define HPP_FCL_BROADPHASE_BROADPAHSESPATIALHASH_INL_H |
40 |
|
|
|
41 |
|
|
#include "hpp/fcl/broadphase/broadphase_spatialhash.h" |
42 |
|
|
|
43 |
|
|
namespace hpp { |
44 |
|
|
namespace fcl { |
45 |
|
|
|
46 |
|
|
//============================================================================== |
47 |
|
|
template <typename HashTable> |
48 |
|
51 |
SpatialHashingCollisionManager<HashTable>::SpatialHashingCollisionManager( |
49 |
|
|
FCL_REAL cell_size, const Vec3f& scene_min, const Vec3f& scene_max, |
50 |
|
|
unsigned int default_table_size) |
51 |
|
|
: scene_limit(AABB(scene_min, scene_max)), |
52 |
✓✗✓✗ ✓✗✓✗
|
51 |
hash_table(new HashTable(detail::SpatialHash(scene_limit, cell_size))) { |
53 |
✗✗ |
51 |
hash_table->init(default_table_size); |
54 |
|
51 |
} |
55 |
|
|
|
56 |
|
|
//============================================================================== |
57 |
|
|
template <typename HashTable> |
58 |
|
200 |
SpatialHashingCollisionManager<HashTable>::~SpatialHashingCollisionManager() { |
59 |
|
100 |
delete hash_table; |
60 |
✓✗ |
300 |
} |
61 |
|
|
|
62 |
|
|
//============================================================================== |
63 |
|
|
template <typename HashTable> |
64 |
|
12671 |
void SpatialHashingCollisionManager<HashTable>::registerObject( |
65 |
|
|
CollisionObject* obj) { |
66 |
✓✗ |
12671 |
objs.push_back(obj); |
67 |
|
|
|
68 |
|
12671 |
const AABB& obj_aabb = obj->getAABB(); |
69 |
✓✗ |
12671 |
AABB overlap_aabb; |
70 |
|
|
|
71 |
✓✗✓✗
|
12671 |
if (scene_limit.overlap(obj_aabb, overlap_aabb)) { |
72 |
✓✗✗✓
|
12671 |
if (!scene_limit.contain(obj_aabb)) |
73 |
|
|
objs_partially_penetrating_scene_limit.push_back(obj); |
74 |
|
|
|
75 |
✓✗✓✗
|
12671 |
hash_table->insert(overlap_aabb, obj); |
76 |
|
|
} else { |
77 |
|
|
objs_outside_scene_limit.push_back(obj); |
78 |
|
|
} |
79 |
|
|
|
80 |
✓✗✓✗
|
12671 |
obj_aabb_map[obj] = obj_aabb; |
81 |
|
12671 |
} |
82 |
|
|
|
83 |
|
|
//============================================================================== |
84 |
|
|
template <typename HashTable> |
85 |
|
|
void SpatialHashingCollisionManager<HashTable>::unregisterObject( |
86 |
|
|
CollisionObject* obj) { |
87 |
|
|
objs.remove(obj); |
88 |
|
|
|
89 |
|
|
const AABB& obj_aabb = obj->getAABB(); |
90 |
|
|
AABB overlap_aabb; |
91 |
|
|
|
92 |
|
|
if (scene_limit.overlap(obj_aabb, overlap_aabb)) { |
93 |
|
|
if (!scene_limit.contain(obj_aabb)) |
94 |
|
|
objs_partially_penetrating_scene_limit.remove(obj); |
95 |
|
|
|
96 |
|
|
hash_table->remove(overlap_aabb, obj); |
97 |
|
|
} else { |
98 |
|
|
objs_outside_scene_limit.remove(obj); |
99 |
|
|
} |
100 |
|
|
|
101 |
|
|
obj_aabb_map.erase(obj); |
102 |
|
|
} |
103 |
|
|
|
104 |
|
|
//============================================================================== |
105 |
|
|
template <typename HashTable> |
106 |
|
51 |
void SpatialHashingCollisionManager<HashTable>::setup() { |
107 |
|
|
// Do nothing |
108 |
|
51 |
} |
109 |
|
|
|
110 |
|
|
//============================================================================== |
111 |
|
|
template <typename HashTable> |
112 |
|
13 |
void SpatialHashingCollisionManager<HashTable>::update() { |
113 |
|
13 |
hash_table->clear(); |
114 |
|
13 |
objs_partially_penetrating_scene_limit.clear(); |
115 |
|
13 |
objs_outside_scene_limit.clear(); |
116 |
|
|
|
117 |
✓✓ |
1357 |
for (auto it = objs.cbegin(), end = objs.cend(); it != end; ++it) { |
118 |
|
1344 |
CollisionObject* obj = *it; |
119 |
|
1344 |
const AABB& obj_aabb = obj->getAABB(); |
120 |
✓✗ |
1344 |
AABB overlap_aabb; |
121 |
|
|
|
122 |
✓✗✓✓
|
1344 |
if (scene_limit.overlap(obj_aabb, overlap_aabb)) { |
123 |
✓✗✓✓
|
1255 |
if (!scene_limit.contain(obj_aabb)) |
124 |
✓✗ |
55 |
objs_partially_penetrating_scene_limit.push_back(obj); |
125 |
|
|
|
126 |
✓✗✓✗
|
1255 |
hash_table->insert(overlap_aabb, obj); |
127 |
|
|
} else { |
128 |
✓✗ |
89 |
objs_outside_scene_limit.push_back(obj); |
129 |
|
|
} |
130 |
|
|
|
131 |
✓✗✓✗
|
1344 |
obj_aabb_map[obj] = obj_aabb; |
132 |
|
|
} |
133 |
|
13 |
} |
134 |
|
|
|
135 |
|
|
//============================================================================== |
136 |
|
|
template <typename HashTable> |
137 |
|
|
void SpatialHashingCollisionManager<HashTable>::update( |
138 |
|
|
CollisionObject* updated_obj) { |
139 |
|
|
const AABB& new_aabb = updated_obj->getAABB(); |
140 |
|
|
const AABB& old_aabb = obj_aabb_map[updated_obj]; |
141 |
|
|
|
142 |
|
|
AABB old_overlap_aabb; |
143 |
|
|
const auto is_old_aabb_overlapping = |
144 |
|
|
scene_limit.overlap(old_aabb, old_overlap_aabb); |
145 |
|
|
if (is_old_aabb_overlapping) |
146 |
|
|
hash_table->remove(old_overlap_aabb, updated_obj); |
147 |
|
|
|
148 |
|
|
AABB new_overlap_aabb; |
149 |
|
|
const auto is_new_aabb_overlapping = |
150 |
|
|
scene_limit.overlap(new_aabb, new_overlap_aabb); |
151 |
|
|
if (is_new_aabb_overlapping) |
152 |
|
|
hash_table->insert(new_overlap_aabb, updated_obj); |
153 |
|
|
|
154 |
|
|
ObjectStatus old_status; |
155 |
|
|
if (is_old_aabb_overlapping) { |
156 |
|
|
if (scene_limit.contain(old_aabb)) |
157 |
|
|
old_status = Inside; |
158 |
|
|
else |
159 |
|
|
old_status = PartiallyPenetrating; |
160 |
|
|
} else { |
161 |
|
|
old_status = Outside; |
162 |
|
|
} |
163 |
|
|
|
164 |
|
|
if (is_new_aabb_overlapping) { |
165 |
|
|
if (scene_limit.contain(new_aabb)) { |
166 |
|
|
if (old_status == PartiallyPenetrating) { |
167 |
|
|
// Status change: PartiallyPenetrating --> Inside |
168 |
|
|
// Required action(s): |
169 |
|
|
// - remove object from "objs_partially_penetrating_scene_limit" |
170 |
|
|
|
171 |
|
|
auto find_it = std::find(objs_partially_penetrating_scene_limit.begin(), |
172 |
|
|
objs_partially_penetrating_scene_limit.end(), |
173 |
|
|
updated_obj); |
174 |
|
|
objs_partially_penetrating_scene_limit.erase(find_it); |
175 |
|
|
} else if (old_status == Outside) { |
176 |
|
|
// Status change: Outside --> Inside |
177 |
|
|
// Required action(s): |
178 |
|
|
// - remove object from "objs_outside_scene_limit" |
179 |
|
|
|
180 |
|
|
auto find_it = std::find(objs_outside_scene_limit.begin(), |
181 |
|
|
objs_outside_scene_limit.end(), updated_obj); |
182 |
|
|
objs_outside_scene_limit.erase(find_it); |
183 |
|
|
} |
184 |
|
|
} else { |
185 |
|
|
if (old_status == Inside) { |
186 |
|
|
// Status change: Inside --> PartiallyPenetrating |
187 |
|
|
// Required action(s): |
188 |
|
|
// - add object to "objs_partially_penetrating_scene_limit" |
189 |
|
|
|
190 |
|
|
objs_partially_penetrating_scene_limit.push_back(updated_obj); |
191 |
|
|
} else if (old_status == Outside) { |
192 |
|
|
// Status change: Outside --> PartiallyPenetrating |
193 |
|
|
// Required action(s): |
194 |
|
|
// - remove object from "objs_outside_scene_limit" |
195 |
|
|
// - add object to "objs_partially_penetrating_scene_limit" |
196 |
|
|
|
197 |
|
|
auto find_it = std::find(objs_outside_scene_limit.begin(), |
198 |
|
|
objs_outside_scene_limit.end(), updated_obj); |
199 |
|
|
objs_outside_scene_limit.erase(find_it); |
200 |
|
|
|
201 |
|
|
objs_partially_penetrating_scene_limit.push_back(updated_obj); |
202 |
|
|
} |
203 |
|
|
} |
204 |
|
|
} else { |
205 |
|
|
if (old_status == Inside) { |
206 |
|
|
// Status change: Inside --> Outside |
207 |
|
|
// Required action(s): |
208 |
|
|
// - add object to "objs_outside_scene_limit" |
209 |
|
|
|
210 |
|
|
objs_outside_scene_limit.push_back(updated_obj); |
211 |
|
|
} else if (old_status == PartiallyPenetrating) { |
212 |
|
|
// Status change: PartiallyPenetrating --> Outside |
213 |
|
|
// Required action(s): |
214 |
|
|
// - remove object from "objs_partially_penetrating_scene_limit" |
215 |
|
|
// - add object to "objs_outside_scene_limit" |
216 |
|
|
|
217 |
|
|
auto find_it = |
218 |
|
|
std::find(objs_partially_penetrating_scene_limit.begin(), |
219 |
|
|
objs_partially_penetrating_scene_limit.end(), updated_obj); |
220 |
|
|
objs_partially_penetrating_scene_limit.erase(find_it); |
221 |
|
|
|
222 |
|
|
objs_outside_scene_limit.push_back(updated_obj); |
223 |
|
|
} |
224 |
|
|
} |
225 |
|
|
|
226 |
|
|
obj_aabb_map[updated_obj] = new_aabb; |
227 |
|
|
} |
228 |
|
|
|
229 |
|
|
//============================================================================== |
230 |
|
|
template <typename HashTable> |
231 |
|
|
void SpatialHashingCollisionManager<HashTable>::update( |
232 |
|
|
const std::vector<CollisionObject*>& updated_objs) { |
233 |
|
|
for (size_t i = 0; i < updated_objs.size(); ++i) update(updated_objs[i]); |
234 |
|
|
} |
235 |
|
|
|
236 |
|
|
//============================================================================== |
237 |
|
|
template <typename HashTable> |
238 |
|
|
void SpatialHashingCollisionManager<HashTable>::clear() { |
239 |
|
|
objs.clear(); |
240 |
|
|
hash_table->clear(); |
241 |
|
|
objs_outside_scene_limit.clear(); |
242 |
|
|
obj_aabb_map.clear(); |
243 |
|
|
} |
244 |
|
|
|
245 |
|
|
//============================================================================== |
246 |
|
|
template <typename HashTable> |
247 |
|
|
void SpatialHashingCollisionManager<HashTable>::getObjects( |
248 |
|
|
std::vector<CollisionObject*>& objs_) const { |
249 |
|
|
objs_.resize(objs.size()); |
250 |
|
|
std::copy(objs.begin(), objs.end(), objs_.begin()); |
251 |
|
|
} |
252 |
|
|
|
253 |
|
|
//============================================================================== |
254 |
|
|
template <typename HashTable> |
255 |
|
3822 |
void SpatialHashingCollisionManager<HashTable>::collide( |
256 |
|
|
CollisionObject* obj, CollisionCallBackBase* callback) const { |
257 |
✓✓ |
3822 |
if (size() == 0) return; |
258 |
|
3762 |
collide_(obj, callback); |
259 |
|
|
} |
260 |
|
|
|
261 |
|
|
//============================================================================== |
262 |
|
|
template <typename HashTable> |
263 |
|
80 |
void SpatialHashingCollisionManager<HashTable>::distance( |
264 |
|
|
CollisionObject* obj, DistanceCallBackBase* callback) const { |
265 |
✓✗✗✓
|
80 |
if (size() == 0) return; |
266 |
|
80 |
FCL_REAL min_dist = (std::numeric_limits<FCL_REAL>::max)(); |
267 |
✓✗ |
80 |
distance_(obj, callback, min_dist); |
268 |
|
|
} |
269 |
|
|
|
270 |
|
|
//============================================================================== |
271 |
|
|
template <typename HashTable> |
272 |
|
3762 |
bool SpatialHashingCollisionManager<HashTable>::collide_( |
273 |
|
|
CollisionObject* obj, CollisionCallBackBase* callback) const { |
274 |
|
3762 |
const auto& obj_aabb = obj->getAABB(); |
275 |
✓✗ |
3762 |
AABB overlap_aabb; |
276 |
|
|
|
277 |
✓✗✓✓
|
3762 |
if (scene_limit.overlap(obj_aabb, overlap_aabb)) { |
278 |
✓✗✓✗
|
3453 |
const auto query_result = hash_table->query(overlap_aabb); |
279 |
✓✓ |
3642 |
for (const auto& obj2 : query_result) { |
280 |
✗✓ |
189 |
if (obj == obj2) continue; |
281 |
|
|
|
282 |
✓✗✗✓
|
189 |
if ((*callback)(obj, obj2)) return true; |
283 |
|
|
} |
284 |
|
|
|
285 |
✓✗✓✓
|
3453 |
if (!scene_limit.contain(obj_aabb)) { |
286 |
✓✓ |
851 |
for (const auto& obj2 : objs_outside_scene_limit) { |
287 |
✗✓ |
711 |
if (obj == obj2) continue; |
288 |
|
|
|
289 |
✓✗✗✓
|
711 |
if ((*callback)(obj, obj2)) return true; |
290 |
|
|
} |
291 |
|
|
} |
292 |
|
|
} else { |
293 |
✓✓ |
412 |
for (const auto& obj2 : objs_partially_penetrating_scene_limit) { |
294 |
✗✓ |
103 |
if (obj == obj2) continue; |
295 |
|
|
|
296 |
✓✗✗✓
|
103 |
if ((*callback)(obj, obj2)) return true; |
297 |
|
|
} |
298 |
|
|
|
299 |
✓✓ |
774 |
for (const auto& obj2 : objs_outside_scene_limit) { |
300 |
✗✓ |
465 |
if (obj == obj2) continue; |
301 |
|
|
|
302 |
✓✗✗✓
|
465 |
if ((*callback)(obj, obj2)) return true; |
303 |
|
|
} |
304 |
|
|
} |
305 |
|
|
|
306 |
|
3762 |
return false; |
307 |
|
|
} |
308 |
|
|
|
309 |
|
|
//============================================================================== |
310 |
|
|
template <typename HashTable> |
311 |
|
3070 |
bool SpatialHashingCollisionManager<HashTable>::distance_( |
312 |
|
|
CollisionObject* obj, DistanceCallBackBase* callback, |
313 |
|
|
FCL_REAL& min_dist) const { |
314 |
✓✗✓✗
|
3070 |
auto delta = (obj->getAABB().max_ - obj->getAABB().min_) * 0.5; |
315 |
✓✗ |
3070 |
auto aabb = obj->getAABB(); |
316 |
✓✓ |
3070 |
if (min_dist < (std::numeric_limits<FCL_REAL>::max)()) { |
317 |
✓✗ |
2984 |
Vec3f min_dist_delta(min_dist, min_dist, min_dist); |
318 |
✓✗ |
2984 |
aabb.expand(min_dist_delta); |
319 |
|
|
} |
320 |
|
|
|
321 |
✓✗ |
3070 |
AABB overlap_aabb; |
322 |
|
|
|
323 |
|
3070 |
auto status = 1; |
324 |
|
|
FCL_REAL old_min_distance; |
325 |
|
|
|
326 |
|
313 |
while (1) { |
327 |
|
3383 |
old_min_distance = min_dist; |
328 |
|
|
|
329 |
✓✗✓✓
|
3383 |
if (scene_limit.overlap(aabb, overlap_aabb)) { |
330 |
✓✗✓✗ ✓✗✗✓
|
3378 |
if (distanceObjectToObjects(obj, hash_table->query(overlap_aabb), |
331 |
|
|
callback, min_dist)) { |
332 |
|
|
return true; |
333 |
|
|
} |
334 |
|
|
|
335 |
✓✗✓✓
|
3378 |
if (!scene_limit.contain(aabb)) { |
336 |
✓✗✗✓
|
3092 |
if (distanceObjectToObjects(obj, objs_outside_scene_limit, callback, |
337 |
|
|
min_dist)) { |
338 |
|
|
return true; |
339 |
|
|
} |
340 |
|
|
} |
341 |
|
|
} else { |
342 |
✓✗✗✓
|
5 |
if (distanceObjectToObjects(obj, objs_partially_penetrating_scene_limit, |
343 |
|
|
callback, min_dist)) { |
344 |
|
|
return true; |
345 |
|
|
} |
346 |
|
|
|
347 |
✓✗✗✓
|
5 |
if (distanceObjectToObjects(obj, objs_outside_scene_limit, callback, |
348 |
|
|
min_dist)) { |
349 |
|
|
return true; |
350 |
|
|
} |
351 |
|
|
} |
352 |
|
|
|
353 |
✓✓ |
3383 |
if (status == 1) { |
354 |
✓✓ |
3297 |
if (old_min_distance < (std::numeric_limits<FCL_REAL>::max)()) { |
355 |
|
2984 |
break; |
356 |
|
|
} else { |
357 |
✓✓ |
313 |
if (min_dist < old_min_distance) { |
358 |
✓✗ |
86 |
Vec3f min_dist_delta(min_dist, min_dist, min_dist); |
359 |
✓✗✓✗
|
86 |
aabb = AABB(obj->getAABB(), min_dist_delta); |
360 |
|
86 |
status = 0; |
361 |
|
|
} else { |
362 |
✓✗✓✓
|
227 |
if (aabb == obj->getAABB()) |
363 |
✓✗✓✗
|
48 |
aabb.expand(delta); |
364 |
|
|
else |
365 |
✓✗ |
179 |
aabb.expand(obj->getAABB(), 2.0); |
366 |
|
|
} |
367 |
|
|
} |
368 |
✓✗ |
86 |
} else if (status == 0) { |
369 |
|
86 |
break; |
370 |
|
|
} |
371 |
|
|
} |
372 |
|
|
|
373 |
|
3070 |
return false; |
374 |
|
|
} |
375 |
|
|
|
376 |
|
|
//============================================================================== |
377 |
|
|
template <typename HashTable> |
378 |
|
37 |
void SpatialHashingCollisionManager<HashTable>::collide( |
379 |
|
|
CollisionCallBackBase* callback) const { |
380 |
✓✓ |
37 |
if (size() == 0) return; |
381 |
|
|
|
382 |
✓✓ |
2338 |
for (const auto& obj1 : objs) { |
383 |
|
2310 |
const auto& obj_aabb = obj1->getAABB(); |
384 |
✓✗ |
2310 |
AABB overlap_aabb; |
385 |
|
|
|
386 |
✓✗✓✓
|
2310 |
if (scene_limit.overlap(obj_aabb, overlap_aabb)) { |
387 |
✓✗✓✗
|
2221 |
auto query_result = hash_table->query(overlap_aabb); |
388 |
✓✓ |
4663 |
for (const auto& obj2 : query_result) { |
389 |
✓✓ |
2443 |
if (obj1 < obj2) { |
390 |
✓✗✓✓
|
112 |
if ((*callback)(obj1, obj2)) return; |
391 |
|
|
} |
392 |
|
|
} |
393 |
|
|
|
394 |
✓✗✓✓
|
2220 |
if (!scene_limit.contain(obj_aabb)) { |
395 |
✓✓ |
794 |
for (const auto& obj2 : objs_outside_scene_limit) { |
396 |
✓✓ |
739 |
if (obj1 < obj2) { |
397 |
✓✗✗✓
|
365 |
if ((*callback)(obj1, obj2)) return; |
398 |
|
|
} |
399 |
|
|
} |
400 |
|
|
} |
401 |
|
|
} else { |
402 |
✓✓ |
828 |
for (const auto& obj2 : objs_partially_penetrating_scene_limit) { |
403 |
✓✓ |
739 |
if (obj1 < obj2) { |
404 |
✓✗✗✓
|
374 |
if ((*callback)(obj1, obj2)) return; |
405 |
|
|
} |
406 |
|
|
} |
407 |
|
|
|
408 |
✓✓ |
1340 |
for (const auto& obj2 : objs_outside_scene_limit) { |
409 |
✓✓ |
1251 |
if (obj1 < obj2) { |
410 |
✓✗✗✓
|
581 |
if ((*callback)(obj1, obj2)) return; |
411 |
|
|
} |
412 |
|
|
} |
413 |
|
|
} |
414 |
|
|
} |
415 |
|
|
} |
416 |
|
|
|
417 |
|
|
//============================================================================== |
418 |
|
|
template <typename HashTable> |
419 |
|
6 |
void SpatialHashingCollisionManager<HashTable>::distance( |
420 |
|
|
DistanceCallBackBase* callback) const { |
421 |
✓✗✗✓
|
6 |
if (size() == 0) return; |
422 |
|
|
|
423 |
|
6 |
this->enable_tested_set_ = true; |
424 |
|
6 |
this->tested_set.clear(); |
425 |
|
|
|
426 |
|
6 |
FCL_REAL min_dist = (std::numeric_limits<FCL_REAL>::max)(); |
427 |
|
|
|
428 |
✓✓ |
2996 |
for (const auto& obj : objs) { |
429 |
✓✗✗✓
|
2990 |
if (distance_(obj, callback, min_dist)) break; |
430 |
|
|
} |
431 |
|
|
|
432 |
|
6 |
this->enable_tested_set_ = false; |
433 |
|
6 |
this->tested_set.clear(); |
434 |
|
|
} |
435 |
|
|
|
436 |
|
|
//============================================================================== |
437 |
|
|
template <typename HashTable> |
438 |
|
|
void SpatialHashingCollisionManager<HashTable>::collide( |
439 |
|
|
BroadPhaseCollisionManager* other_manager_, |
440 |
|
|
CollisionCallBackBase* callback) const { |
441 |
|
|
auto* other_manager = |
442 |
|
|
static_cast<SpatialHashingCollisionManager<HashTable>*>(other_manager_); |
443 |
|
|
|
444 |
|
|
if ((size() == 0) || (other_manager->size() == 0)) return; |
445 |
|
|
|
446 |
|
|
if (this == other_manager) { |
447 |
|
|
collide(callback); |
448 |
|
|
return; |
449 |
|
|
} |
450 |
|
|
|
451 |
|
|
if (this->size() < other_manager->size()) { |
452 |
|
|
for (const auto& obj : objs) { |
453 |
|
|
if (other_manager->collide_(obj, callback)) return; |
454 |
|
|
} |
455 |
|
|
} else { |
456 |
|
|
for (const auto& obj : other_manager->objs) { |
457 |
|
|
if (collide_(obj, callback)) return; |
458 |
|
|
} |
459 |
|
|
} |
460 |
|
|
} |
461 |
|
|
|
462 |
|
|
//============================================================================== |
463 |
|
|
template <typename HashTable> |
464 |
|
|
void SpatialHashingCollisionManager<HashTable>::distance( |
465 |
|
|
BroadPhaseCollisionManager* other_manager_, |
466 |
|
|
DistanceCallBackBase* callback) const { |
467 |
|
|
auto* other_manager = |
468 |
|
|
static_cast<SpatialHashingCollisionManager<HashTable>*>(other_manager_); |
469 |
|
|
|
470 |
|
|
if ((size() == 0) || (other_manager->size() == 0)) return; |
471 |
|
|
|
472 |
|
|
if (this == other_manager) { |
473 |
|
|
distance(callback); |
474 |
|
|
return; |
475 |
|
|
} |
476 |
|
|
|
477 |
|
|
FCL_REAL min_dist = (std::numeric_limits<FCL_REAL>::max)(); |
478 |
|
|
|
479 |
|
|
if (this->size() < other_manager->size()) { |
480 |
|
|
for (const auto& obj : objs) |
481 |
|
|
if (other_manager->distance_(obj, callback, min_dist)) return; |
482 |
|
|
} else { |
483 |
|
|
for (const auto& obj : other_manager->objs) |
484 |
|
|
if (distance_(obj, callback, min_dist)) return; |
485 |
|
|
} |
486 |
|
|
} |
487 |
|
|
|
488 |
|
|
//============================================================================== |
489 |
|
|
template <typename HashTable> |
490 |
|
|
bool SpatialHashingCollisionManager<HashTable>::empty() const { |
491 |
|
|
return objs.empty(); |
492 |
|
|
} |
493 |
|
|
|
494 |
|
|
//============================================================================== |
495 |
|
|
template <typename HashTable> |
496 |
|
3945 |
size_t SpatialHashingCollisionManager<HashTable>::size() const { |
497 |
|
3945 |
return objs.size(); |
498 |
|
|
} |
499 |
|
|
|
500 |
|
|
//============================================================================== |
501 |
|
|
template <typename HashTable> |
502 |
|
51 |
void SpatialHashingCollisionManager<HashTable>::computeBound( |
503 |
|
|
std::vector<CollisionObject*>& objs, Vec3f& l, Vec3f& u) { |
504 |
✓✗ |
51 |
AABB bound; |
505 |
✓✓✓✗
|
12722 |
for (unsigned int i = 0; i < objs.size(); ++i) bound += objs[i]->getAABB(); |
506 |
|
|
|
507 |
✓✗ |
51 |
l = bound.min_; |
508 |
✓✗ |
51 |
u = bound.max_; |
509 |
|
51 |
} |
510 |
|
|
|
511 |
|
|
//============================================================================== |
512 |
|
|
template <typename HashTable> |
513 |
|
|
template <typename Container> |
514 |
|
6480 |
bool SpatialHashingCollisionManager<HashTable>::distanceObjectToObjects( |
515 |
|
|
CollisionObject* obj, const Container& objs, DistanceCallBackBase* callback, |
516 |
|
|
FCL_REAL& min_dist) const { |
517 |
|
15302 |
for (auto& obj2 : objs) { |
518 |
|
8822 |
if (obj == obj2) continue; |
519 |
|
|
|
520 |
|
5794 |
if (!this->enable_tested_set_) { |
521 |
|
1322 |
if (obj->getAABB().distance(obj2->getAABB()) < min_dist) { |
522 |
|
716 |
if ((*callback)(obj, obj2, min_dist)) return true; |
523 |
|
|
} |
524 |
|
|
} else { |
525 |
|
4472 |
if (!this->inTestedSet(obj, obj2)) { |
526 |
|
2236 |
if (obj->getAABB().distance(obj2->getAABB()) < min_dist) { |
527 |
|
475 |
if ((*callback)(obj, obj2, min_dist)) return true; |
528 |
|
|
} |
529 |
|
|
|
530 |
|
2236 |
this->insertTestedSet(obj, obj2); |
531 |
|
|
} |
532 |
|
|
} |
533 |
|
|
} |
534 |
|
|
|
535 |
|
6480 |
return false; |
536 |
|
|
} |
537 |
|
|
|
538 |
|
|
} // namespace fcl |
539 |
|
|
|
540 |
|
|
} // namespace hpp |
541 |
|
|
|
542 |
|
|
#endif |