38 #ifndef FCL_BROADPHASE_BROADPAHSESPATIALHASH_INL_H
39 #define FCL_BROADPHASE_BROADPAHSESPATIALHASH_INL_H
48 class FCL_EXPORT SpatialHashingCollisionManager<
50 detail::SimpleHashTable<
54 template<
typename S,
typename HashTable>
59 unsigned int default_table_size)
60 : scene_limit(
AABB<S>(scene_min, scene_max)),
61 hash_table(new HashTable(detail::SpatialHash<S>(scene_limit, cell_size)))
67 template<
typename S,
typename HashTable>
74 template<
typename S,
typename HashTable>
83 if(scene_limit.overlap(obj_aabb, overlap_aabb))
85 if(!scene_limit.contain(obj_aabb))
86 objs_partially_penetrating_scene_limit.push_back(
obj);
88 hash_table->insert(overlap_aabb,
obj);
92 objs_outside_scene_limit.push_back(
obj);
95 obj_aabb_map[
obj] = obj_aabb;
99 template<
typename S,
typename HashTable>
107 if(scene_limit.overlap(obj_aabb, overlap_aabb))
109 if(!scene_limit.contain(obj_aabb))
110 objs_partially_penetrating_scene_limit.remove(
obj);
112 hash_table->remove(overlap_aabb,
obj);
116 objs_outside_scene_limit.remove(
obj);
119 obj_aabb_map.erase(
obj);
123 template<
typename S,
typename HashTable>
130 template<
typename S,
typename HashTable>
134 objs_partially_penetrating_scene_limit.clear();
135 objs_outside_scene_limit.clear();
137 for(
auto it = objs.cbegin(), end = objs.cend(); it != end; ++it)
143 if(scene_limit.overlap(obj_aabb, overlap_aabb))
145 if(!scene_limit.contain(obj_aabb))
146 objs_partially_penetrating_scene_limit.push_back(
obj);
148 hash_table->insert(overlap_aabb,
obj);
152 objs_outside_scene_limit.push_back(
obj);
155 obj_aabb_map[
obj] = obj_aabb;
160 template<
typename S,
typename HashTable>
164 const AABB<S>& old_aabb = obj_aabb_map[updated_obj];
167 const auto is_old_aabb_overlapping
168 = scene_limit.
overlap(old_aabb, old_overlap_aabb);
169 if(is_old_aabb_overlapping)
170 hash_table->remove(old_overlap_aabb, updated_obj);
173 const auto is_new_aabb_overlapping
174 = scene_limit.
overlap(new_aabb, new_overlap_aabb);
175 if(is_new_aabb_overlapping)
176 hash_table->insert(new_overlap_aabb, updated_obj);
179 if(is_old_aabb_overlapping)
181 if(scene_limit.contain(old_aabb))
184 old_status = PartiallyPenetrating;
188 old_status = Outside;
191 if(is_new_aabb_overlapping)
193 if(scene_limit.contain(new_aabb))
195 if (old_status == PartiallyPenetrating)
201 auto find_it = std::find(objs_partially_penetrating_scene_limit.begin(),
202 objs_partially_penetrating_scene_limit.end(),
204 objs_partially_penetrating_scene_limit.erase(find_it);
206 else if (old_status == Outside)
212 auto find_it = std::find(objs_outside_scene_limit.begin(),
213 objs_outside_scene_limit.end(),
215 objs_outside_scene_limit.erase(find_it);
220 if (old_status == Inside)
226 objs_partially_penetrating_scene_limit.push_back(updated_obj);
228 else if (old_status == Outside)
235 auto find_it = std::find(objs_outside_scene_limit.begin(),
236 objs_outside_scene_limit.end(),
238 objs_outside_scene_limit.erase(find_it);
240 objs_partially_penetrating_scene_limit.push_back(updated_obj);
246 if (old_status == Inside)
252 objs_outside_scene_limit.push_back(updated_obj);
254 else if (old_status == PartiallyPenetrating)
261 auto find_it = std::find(objs_partially_penetrating_scene_limit.begin(),
262 objs_partially_penetrating_scene_limit.end(),
264 objs_partially_penetrating_scene_limit.erase(find_it);
266 objs_outside_scene_limit.push_back(updated_obj);
270 obj_aabb_map[updated_obj] = new_aabb;
274 template<
typename S,
typename HashTable>
277 for(
size_t i = 0; i < updated_objs.size(); ++i)
278 update(updated_objs[i]);
282 template<
typename S,
typename HashTable>
287 objs_outside_scene_limit.clear();
288 obj_aabb_map.clear();
292 template<
typename S,
typename HashTable>
295 objs_.resize(objs.size());
296 std::copy(objs.begin(), objs.end(), objs_.begin());
300 template<
typename S,
typename HashTable>
303 if(size() == 0)
return;
304 collide_(
obj, cdata, callback);
308 template<
typename S,
typename HashTable>
311 if(size() == 0)
return;
313 distance_(
obj, cdata, callback, min_dist);
317 template<
typename S,
typename HashTable>
321 const auto& obj_aabb =
obj->getAABB();
324 if(scene_limit.overlap(obj_aabb, overlap_aabb))
326 const auto query_result = hash_table->query(overlap_aabb);
327 for(
const auto&
obj2 : query_result)
336 if(!scene_limit.contain(obj_aabb))
338 for(
const auto&
obj2 : objs_outside_scene_limit)
350 for(
const auto&
obj2 : objs_partially_penetrating_scene_limit)
359 for(
const auto&
obj2 : objs_outside_scene_limit)
373 template<
typename S,
typename HashTable>
377 auto delta = (
obj->getAABB().max_ -
obj->getAABB().min_) * 0.5;
381 Vector3<S> min_dist_delta(min_dist, min_dist, min_dist);
382 aabb.expand(min_dist_delta);
392 old_min_distance = min_dist;
394 if(scene_limit.overlap(
aabb, overlap_aabb))
396 if (distanceObjectToObjects(
397 obj, hash_table->query(overlap_aabb), cdata, callback, min_dist))
402 if(!scene_limit.contain(
aabb))
404 if (distanceObjectToObjects(
405 obj, objs_outside_scene_limit, cdata, callback, min_dist))
413 if (distanceObjectToObjects(
414 obj, objs_partially_penetrating_scene_limit, cdata, callback, min_dist))
419 if (distanceObjectToObjects(
420 obj, objs_outside_scene_limit, cdata, callback, min_dist))
434 if(min_dist < old_min_distance)
436 Vector3<S> min_dist_delta(min_dist, min_dist, min_dist);
445 aabb.expand(
obj->getAABB(), 2.0);
459 template<
typename S,
typename HashTable>
466 for(
const auto&
obj1 : objs)
468 const auto& obj_aabb =
obj1->getAABB();
471 if(scene_limit.overlap(obj_aabb, overlap_aabb))
473 auto query_result = hash_table->query(overlap_aabb);
474 for(
const auto&
obj2 : query_result)
483 if(!scene_limit.contain(obj_aabb))
485 for(
const auto&
obj2 : objs_outside_scene_limit)
497 for(
const auto&
obj2 : objs_partially_penetrating_scene_limit)
506 for(
const auto&
obj2 : objs_outside_scene_limit)
519 template<
typename S,
typename HashTable>
526 this->enable_tested_set_ =
true;
527 this->tested_set.clear();
531 for(
const auto&
obj : objs)
533 if(distance_(
obj, cdata, callback, min_dist))
537 this->enable_tested_set_ =
false;
538 this->tested_set.clear();
542 template<
typename S,
typename HashTable>
547 if((size() == 0) || (other_manager->size() == 0))
550 if(
this == other_manager)
556 if(this->size() < other_manager->size())
558 for(
const auto&
obj : objs)
560 if(other_manager->collide_(
obj, cdata, callback))
566 for(
const auto&
obj : other_manager->objs)
568 if(collide_(
obj, cdata, callback))
575 template<
typename S,
typename HashTable>
580 if((size() == 0) || (other_manager->size() == 0))
583 if(
this == other_manager)
591 if(this->size() < other_manager->size())
593 for(
const auto&
obj : objs)
594 if(other_manager->distance_(
obj, cdata, callback, min_dist))
return;
598 for(
const auto&
obj : other_manager->objs)
599 if(distance_(
obj, cdata, callback, min_dist))
return;
604 template<
typename S,
typename HashTable>
611 template<
typename S,
typename HashTable>
618 template<
typename S,
typename HashTable>
623 for(
unsigned int i = 0; i < objs.size(); ++i)
624 bound += objs[i]->getAABB();
631 template<
typename S,
typename HashTable>
632 template<
typename Container>
635 const Container& objs,
640 for(
auto&
obj2 : objs)
645 if(!this->enable_tested_set_)
647 if(
obj->getAABB().distance(
obj2->getAABB()) < min_dist)
649 if(callback(
obj,
obj2, cdata, min_dist))
655 if(!this->inTestedSet(
obj,
obj2))
657 if(
obj->getAABB().distance(
obj2->getAABB()) < min_dist)
659 if(callback(
obj,
obj2, cdata, min_dist))
663 this->insertTestedSet(
obj,
obj2);