38 #ifndef COAL_BROADPHASE_BROADPAHSESPATIALHASH_INL_H
39 #define COAL_BROADPHASE_BROADPAHSESPATIALHASH_INL_H
46 template <
typename HashTable>
49 unsigned int default_table_size)
50 : scene_limit(
AABB(scene_min, scene_max)),
51 hash_table(new HashTable(detail::SpatialHash(scene_limit, cell_size))) {
56 template <
typename HashTable>
62 template <
typename HashTable>
70 if (scene_limit.overlap(obj_aabb, overlap_aabb)) {
71 if (!scene_limit.contain(obj_aabb))
72 objs_partially_penetrating_scene_limit.push_back(obj);
74 hash_table->insert(overlap_aabb, obj);
76 objs_outside_scene_limit.push_back(obj);
79 obj_aabb_map[obj] = obj_aabb;
83 template <
typename HashTable>
91 if (scene_limit.overlap(obj_aabb, overlap_aabb)) {
92 if (!scene_limit.contain(obj_aabb))
93 objs_partially_penetrating_scene_limit.remove(obj);
95 hash_table->remove(overlap_aabb, obj);
97 objs_outside_scene_limit.remove(obj);
100 obj_aabb_map.erase(obj);
104 template <
typename HashTable>
110 template <
typename HashTable>
113 objs_partially_penetrating_scene_limit.clear();
114 objs_outside_scene_limit.clear();
116 for (
auto it = objs.cbegin(), end = objs.cend(); it != end; ++it) {
121 if (scene_limit.overlap(obj_aabb, overlap_aabb)) {
122 if (!scene_limit.contain(obj_aabb))
123 objs_partially_penetrating_scene_limit.push_back(obj);
125 hash_table->insert(overlap_aabb, obj);
127 objs_outside_scene_limit.push_back(obj);
130 obj_aabb_map[obj] = obj_aabb;
135 template <
typename HashTable>
139 const AABB& old_aabb = obj_aabb_map[updated_obj];
141 AABB old_overlap_aabb;
142 const auto is_old_aabb_overlapping =
143 scene_limit.
overlap(old_aabb, old_overlap_aabb);
144 if (is_old_aabb_overlapping)
145 hash_table->remove(old_overlap_aabb, updated_obj);
147 AABB new_overlap_aabb;
148 const auto is_new_aabb_overlapping =
149 scene_limit.
overlap(new_aabb, new_overlap_aabb);
150 if (is_new_aabb_overlapping)
151 hash_table->insert(new_overlap_aabb, updated_obj);
154 if (is_old_aabb_overlapping) {
155 if (scene_limit.contain(old_aabb))
158 old_status = PartiallyPenetrating;
160 old_status = Outside;
163 if (is_new_aabb_overlapping) {
164 if (scene_limit.contain(new_aabb)) {
165 if (old_status == PartiallyPenetrating) {
170 auto find_it = std::find(objs_partially_penetrating_scene_limit.begin(),
171 objs_partially_penetrating_scene_limit.end(),
173 objs_partially_penetrating_scene_limit.erase(find_it);
174 }
else if (old_status == Outside) {
179 auto find_it = std::find(objs_outside_scene_limit.begin(),
180 objs_outside_scene_limit.end(), updated_obj);
181 objs_outside_scene_limit.erase(find_it);
184 if (old_status == Inside) {
189 objs_partially_penetrating_scene_limit.push_back(updated_obj);
190 }
else if (old_status == Outside) {
196 auto find_it = std::find(objs_outside_scene_limit.begin(),
197 objs_outside_scene_limit.end(), updated_obj);
198 objs_outside_scene_limit.erase(find_it);
200 objs_partially_penetrating_scene_limit.push_back(updated_obj);
204 if (old_status == Inside) {
209 objs_outside_scene_limit.push_back(updated_obj);
210 }
else if (old_status == PartiallyPenetrating) {
217 std::find(objs_partially_penetrating_scene_limit.begin(),
218 objs_partially_penetrating_scene_limit.end(), updated_obj);
219 objs_partially_penetrating_scene_limit.erase(find_it);
221 objs_outside_scene_limit.push_back(updated_obj);
225 obj_aabb_map[updated_obj] = new_aabb;
229 template <
typename HashTable>
231 const std::vector<CollisionObject*>& updated_objs) {
232 for (
size_t i = 0; i < updated_objs.size(); ++i) update(updated_objs[i]);
236 template <
typename HashTable>
240 objs_outside_scene_limit.clear();
241 obj_aabb_map.clear();
245 template <
typename HashTable>
247 std::vector<CollisionObject*>& objs_)
const {
248 objs_.resize(objs.size());
249 std::copy(objs.begin(), objs.end(), objs_.begin());
253 template <
typename HashTable>
256 if (size() == 0)
return;
261 template <
typename HashTable>
264 if (size() == 0)
return;
265 CoalScalar min_dist = (std::numeric_limits<CoalScalar>::max)();
270 template <
typename HashTable>
273 const auto& obj_aabb = obj->
getAABB();
276 if (scene_limit.overlap(obj_aabb, overlap_aabb)) {
277 const auto query_result = hash_table->query(overlap_aabb);
278 for (
const auto& obj2 : query_result) {
279 if (obj == obj2)
continue;
281 if ((*
callback)(obj, obj2))
return true;
284 if (!scene_limit.contain(obj_aabb)) {
285 for (
const auto& obj2 : objs_outside_scene_limit) {
286 if (obj == obj2)
continue;
288 if ((*
callback)(obj, obj2))
return true;
292 for (
const auto& obj2 : objs_partially_penetrating_scene_limit) {
293 if (obj == obj2)
continue;
295 if ((*
callback)(obj, obj2))
return true;
298 for (
const auto& obj2 : objs_outside_scene_limit) {
299 if (obj == obj2)
continue;
301 if ((*
callback)(obj, obj2))
return true;
309 template <
typename HashTable>
315 if (min_dist < (std::numeric_limits<CoalScalar>::max)()) {
316 Vec3s min_dist_delta(min_dist, min_dist, min_dist);
317 aabb.expand(min_dist_delta);
326 old_min_distance = min_dist;
328 if (scene_limit.overlap(aabb, overlap_aabb)) {
329 if (distanceObjectToObjects(obj, hash_table->query(overlap_aabb),
334 if (!scene_limit.contain(aabb)) {
335 if (distanceObjectToObjects(obj, objs_outside_scene_limit,
callback,
341 if (distanceObjectToObjects(obj, objs_partially_penetrating_scene_limit,
346 if (distanceObjectToObjects(obj, objs_outside_scene_limit,
callback,
353 if (old_min_distance < (std::numeric_limits<CoalScalar>::max)()) {
356 if (min_dist < old_min_distance) {
357 Vec3s min_dist_delta(min_dist, min_dist, min_dist);
364 aabb.expand(obj->
getAABB(), 2.0);
367 }
else if (status == 0) {
376 template <
typename HashTable>
379 if (size() == 0)
return;
381 for (
const auto& obj1 : objs) {
382 const auto& obj_aabb = obj1->getAABB();
385 if (scene_limit.overlap(obj_aabb, overlap_aabb)) {
386 auto query_result = hash_table->query(overlap_aabb);
387 for (
const auto& obj2 : query_result) {
389 if ((*
callback)(obj1, obj2))
return;
393 if (!scene_limit.contain(obj_aabb)) {
394 for (
const auto& obj2 : objs_outside_scene_limit) {
396 if ((*
callback)(obj1, obj2))
return;
401 for (
const auto& obj2 : objs_partially_penetrating_scene_limit) {
403 if ((*
callback)(obj1, obj2))
return;
407 for (
const auto& obj2 : objs_outside_scene_limit) {
409 if ((*
callback)(obj1, obj2))
return;
417 template <
typename HashTable>
420 if (size() == 0)
return;
422 this->enable_tested_set_ =
true;
423 this->tested_set.clear();
425 CoalScalar min_dist = (std::numeric_limits<CoalScalar>::max)();
427 for (
const auto& obj : objs) {
428 if (distance_(obj,
callback, min_dist))
break;
431 this->enable_tested_set_ =
false;
432 this->tested_set.clear();
436 template <
typename HashTable>
440 auto* other_manager =
443 if ((size() == 0) || (other_manager->size() == 0))
return;
445 if (
this == other_manager) {
450 if (this->size() < other_manager->size()) {
451 for (
const auto& obj : objs) {
452 if (other_manager->collide_(obj,
callback))
return;
455 for (
const auto& obj : other_manager->objs) {
456 if (collide_(obj,
callback))
return;
462 template <
typename HashTable>
466 auto* other_manager =
469 if ((size() == 0) || (other_manager->size() == 0))
return;
471 if (
this == other_manager) {
476 CoalScalar min_dist = (std::numeric_limits<CoalScalar>::max)();
478 if (this->size() < other_manager->size()) {
479 for (
const auto& obj : objs)
480 if (other_manager->distance_(obj,
callback, min_dist))
return;
482 for (
const auto& obj : other_manager->objs)
483 if (distance_(obj,
callback, min_dist))
return;
488 template <
typename HashTable>
494 template <
typename HashTable>
500 template <
typename HashTable>
502 std::vector<CollisionObject*>& objs,
Vec3s& l,
Vec3s& u) {
504 for (
unsigned int i = 0; i < objs.size(); ++i) bound += objs[i]->getAABB();
511 template <
typename HashTable>
512 template <
typename Container>
516 for (
auto& obj2 : objs) {
517 if (obj == obj2)
continue;
519 if (!this->enable_tested_set_) {
521 if ((*
callback)(obj, obj2, min_dist))
return true;
524 if (!this->inTestedSet(obj, obj2)) {
526 if ((*
callback)(obj, obj2, min_dist))
return true;
529 this->insertTestedSet(obj, obj2);