38 #ifndef FCL_BROAD_PHASE_INTERVAL_TREE_INL_H
39 #define FCL_BROAD_PHASE_INTERVAL_TREE_INL_H
58 p.value =
obj->getAABB().min_[0];
60 p.value =
obj->getAABB().max_[0];
61 auto end1 = std::upper_bound(start1,
endpoints[0].end(), p);
65 unsigned int start_id = start1 -
endpoints[0].begin();
66 unsigned int end_id = end1 -
endpoints[0].begin();
67 unsigned int cur_id = start_id;
68 for(
unsigned int i = start_id; i < end_id; ++i)
72 if(i == cur_id) cur_id++;
84 p.value =
obj->getAABB().min_[1];
86 p.value =
obj->getAABB().max_[1];
87 auto end2 = std::upper_bound(start2,
endpoints[1].end(), p);
91 unsigned int start_id = start2 -
endpoints[1].begin();
92 unsigned int end_id = end2 -
endpoints[1].begin();
93 unsigned int cur_id = start_id;
94 for(
unsigned int i = start_id; i < end_id; ++i)
98 if(i == cur_id) cur_id++;
111 p.value =
obj->getAABB().min_[2];
113 p.value =
obj->getAABB().max_[2];
114 auto end3 = std::upper_bound(start3,
endpoints[2].end(), p);
118 unsigned int start_id = start3 -
endpoints[2].begin();
119 unsigned int end_id = end3 -
endpoints[2].begin();
120 unsigned int cur_id = start_id;
121 for(
unsigned int i = start_id; i < end_id; ++i)
125 if(i == cur_id) cur_id++;
159 template <
typename S>
162 for(
int i = 0; i < 3; ++i)
163 interval_trees[i] =
nullptr;
167 template <
typename S>
168 IntervalTreeCollisionManager<S>::~IntervalTreeCollisionManager()
174 template <
typename S>
175 void IntervalTreeCollisionManager<S>::registerObject(CollisionObject<S>*
obj)
183 p.value =
obj->getAABB().min_[0];
184 q.value =
obj->getAABB().max_[0];
185 endpoints[0].push_back(p);
186 endpoints[0].push_back(q);
188 p.value =
obj->getAABB().min_[1];
189 q.value =
obj->getAABB().max_[1];
190 endpoints[1].push_back(p);
191 endpoints[1].push_back(q);
193 p.value =
obj->getAABB().min_[2];
194 q.value =
obj->getAABB().max_[2];
195 endpoints[2].push_back(p);
196 endpoints[2].push_back(q);
201 template <
typename S>
202 void IntervalTreeCollisionManager<S>::setup()
206 std::sort(endpoints[0].begin(), endpoints[0].end());
207 std::sort(endpoints[1].begin(), endpoints[1].end());
208 std::sort(endpoints[2].begin(), endpoints[2].end());
210 for(
int i = 0; i < 3; ++i)
211 delete interval_trees[i];
213 for(
int i = 0; i < 3; ++i)
214 interval_trees[i] =
new detail::IntervalTree<S>;
216 for(
unsigned int i = 0, size = endpoints[0].size(); i < size; ++i)
218 EndPoint p = endpoints[0][i];
219 CollisionObject<S>*
obj = p.obj;
222 SAPInterval* ivl1 =
new SAPInterval(
obj->getAABB().min_[0],
obj->getAABB().max_[0],
obj);
223 SAPInterval* ivl2 =
new SAPInterval(
obj->getAABB().min_[1],
obj->getAABB().max_[1],
obj);
224 SAPInterval* ivl3 =
new SAPInterval(
obj->getAABB().min_[2],
obj->getAABB().max_[2],
obj);
226 interval_trees[0]->insert(ivl1);
227 interval_trees[1]->insert(ivl2);
228 interval_trees[2]->insert(ivl3);
230 obj_interval_maps[0][
obj] = ivl1;
231 obj_interval_maps[1][
obj] = ivl2;
232 obj_interval_maps[2][
obj] = ivl3;
241 template <
typename S>
242 void IntervalTreeCollisionManager<S>::update()
246 for(
unsigned int i = 0, size = endpoints[0].size(); i < size; ++i)
248 if(endpoints[0][i].
minmax == 0)
249 endpoints[0][i].value = endpoints[0][i].obj->getAABB().min_[0];
251 endpoints[0][i].value = endpoints[0][i].obj->getAABB().max_[0];
254 for(
unsigned int i = 0, size = endpoints[1].size(); i < size; ++i)
256 if(endpoints[1][i].
minmax == 0)
257 endpoints[1][i].value = endpoints[1][i].obj->getAABB().min_[1];
259 endpoints[1][i].value = endpoints[1][i].obj->getAABB().max_[1];
262 for(
unsigned int i = 0, size = endpoints[2].size(); i < size; ++i)
264 if(endpoints[2][i].
minmax == 0)
265 endpoints[2][i].value = endpoints[2][i].obj->getAABB().min_[2];
267 endpoints[2][i].value = endpoints[2][i].obj->getAABB().max_[2];
275 template <
typename S>
276 void IntervalTreeCollisionManager<S>::update(CollisionObject<S>* updated_obj)
279 const AABB<S>& new_aabb = updated_obj->getAABB();
280 for(
int i = 0; i < 3; ++i)
282 const auto it = obj_interval_maps[i].find(updated_obj);
283 interval_trees[i]->deleteNode(it->second);
284 old_aabb.min_[i] = it->second->low;
285 old_aabb.max_[i] = it->second->high;
286 it->second->low = new_aabb.min_[i];
287 it->second->high = new_aabb.max_[i];
288 interval_trees[i]->insert(it->second);
292 typename std::vector<EndPoint>::iterator it;
293 for(
int i = 0; i < 3; ++i)
295 dummy.value = old_aabb.min_[i];
296 it = std::lower_bound(endpoints[i].begin(), endpoints[i].end(), dummy);
297 for(; it != endpoints[i].end(); ++it)
299 if(it->obj == updated_obj && it->minmax == 0)
301 it->value = new_aabb.min_[i];
306 dummy.value = old_aabb.max_[i];
307 it = std::lower_bound(endpoints[i].begin(), endpoints[i].end(), dummy);
308 for(; it != endpoints[i].end(); ++it)
310 if(it->obj == updated_obj && it->minmax == 0)
312 it->value = new_aabb.max_[i];
317 std::sort(endpoints[i].begin(), endpoints[i].end());
322 template <
typename S>
323 void IntervalTreeCollisionManager<S>::update(
const std::vector<CollisionObject<S>*>& updated_objs)
325 for(
size_t i = 0; i < updated_objs.size(); ++i)
326 update(updated_objs[i]);
330 template <
typename S>
331 void IntervalTreeCollisionManager<S>::clear()
333 endpoints[0].clear();
334 endpoints[1].clear();
335 endpoints[2].clear();
337 delete interval_trees[0]; interval_trees[0] =
nullptr;
338 delete interval_trees[1]; interval_trees[1] =
nullptr;
339 delete interval_trees[2]; interval_trees[2] =
nullptr;
341 for(
int i = 0; i < 3; ++i)
343 for(
auto it = obj_interval_maps[i].cbegin(), end = obj_interval_maps[i].cend();
350 for(
int i = 0; i < 3; ++i)
351 obj_interval_maps[i].clear();
357 template <
typename S>
358 void IntervalTreeCollisionManager<S>::getObjects(std::vector<CollisionObject<S>*>& objs)
const
360 objs.resize(endpoints[0].size() / 2);
362 for(
unsigned int i = 0, size = endpoints[0].size(); i < size; ++i)
364 if(endpoints[0][i].
minmax == 0)
366 objs[j] = endpoints[0][i].obj; j++;
372 template <
typename S>
375 if(size() == 0)
return;
376 collide_(
obj, cdata, callback);
380 template <
typename S>
381 bool IntervalTreeCollisionManager<S>::collide_(CollisionObject<S>*
obj,
void* cdata, CollisionCallBack<S> callback)
const
383 static const unsigned int CUTOFF = 100;
385 std::deque<detail::SimpleInterval<S>*> results0, results1, results2;
387 results0 = interval_trees[0]->query(
obj->getAABB().min_[0],
obj->getAABB().max_[0]);
388 if(results0.size() > CUTOFF)
390 results1 = interval_trees[1]->query(
obj->getAABB().min_[1],
obj->getAABB().max_[1]);
391 if(results1.size() > CUTOFF)
393 results2 = interval_trees[2]->query(
obj->getAABB().min_[2],
obj->getAABB().max_[2]);
394 if(results2.size() > CUTOFF)
396 int d1 = results0.size();
397 int d2 = results1.size();
398 int d3 = results2.size();
400 if(d1 >= d2 && d1 >= d3)
401 return checkColl(results0.begin(), results0.end(),
obj, cdata, callback);
402 else if(d2 >= d1 && d2 >= d3)
403 return checkColl(results1.begin(), results1.end(),
obj, cdata, callback);
405 return checkColl(results2.begin(), results2.end(),
obj, cdata, callback);
408 return checkColl(results2.begin(), results2.end(),
obj, cdata, callback);
411 return checkColl(results1.begin(), results1.end(),
obj, cdata, callback);
414 return checkColl(results0.begin(), results0.end(),
obj, cdata, callback);
418 template <
typename S>
421 if(size() == 0)
return;
423 distance_(
obj, cdata, callback, min_dist);
427 template <
typename S>
428 bool IntervalTreeCollisionManager<S>::distance_(CollisionObject<S>*
obj,
void* cdata, DistanceCallBack<S> callback, S& min_dist)
const
430 static const unsigned int CUTOFF = 100;
432 Vector3<S> delta = (
obj->getAABB().max_ -
obj->getAABB().min_) * 0.5;
436 Vector3<S> min_dist_delta(min_dist, min_dist, min_dist);
437 aabb.expand(min_dist_delta);
445 bool dist_res =
false;
447 old_min_distance = min_dist;
449 std::deque<detail::SimpleInterval<S>*> results0, results1, results2;
451 results0 = interval_trees[0]->query(
aabb.min_[0],
aabb.max_[0]);
452 if(results0.size() > CUTOFF)
454 results1 = interval_trees[1]->query(
aabb.min_[1],
aabb.max_[1]);
455 if(results1.size() > CUTOFF)
457 results2 = interval_trees[2]->query(
aabb.min_[2],
aabb.max_[2]);
458 if(results2.size() > CUTOFF)
460 int d1 = results0.size();
461 int d2 = results1.size();
462 int d3 = results2.size();
464 if(d1 >= d2 && d1 >= d3)
465 dist_res = checkDist(results0.begin(), results0.end(),
obj, cdata, callback, min_dist);
466 else if(d2 >= d1 && d2 >= d3)
467 dist_res = checkDist(results1.begin(), results1.end(),
obj, cdata, callback, min_dist);
469 dist_res = checkDist(results2.begin(), results2.end(),
obj, cdata, callback, min_dist);
472 dist_res = checkDist(results2.begin(), results2.end(),
obj, cdata, callback, min_dist);
475 dist_res = checkDist(results1.begin(), results1.end(),
obj, cdata, callback, min_dist);
478 dist_res = checkDist(results0.begin(), results0.end(),
obj, cdata, callback, min_dist);
480 if(dist_res)
return true;
492 if(min_dist < old_min_distance)
494 Vector3<S> min_dist_delta(min_dist, min_dist, min_dist);
495 aabb = AABB<S>(
obj->getAABB(), min_dist_delta);
503 aabb.expand(
obj->getAABB(), 2.0);
515 template <
typename S>
518 if(size() == 0)
return;
520 std::set<CollisionObject<S>*> active;
521 std::set<std::pair<CollisionObject<S>*, CollisionObject<S>*> >
overlap;
522 unsigned int n = endpoints[0].size();
523 S diff_x = endpoints[0][0].value - endpoints[0][n-1].value;
524 S diff_y = endpoints[1][0].value - endpoints[1][n-1].value;
525 S diff_z = endpoints[2][0].value - endpoints[2][n-1].value;
528 if(diff_y > diff_x && diff_y > diff_z)
530 else if(diff_z > diff_y && diff_z > diff_x)
533 for(
unsigned int i = 0; i < n; ++i)
535 const EndPoint& endpoint = endpoints[axis][i];
536 CollisionObject<S>* index = endpoint.obj;
537 if(endpoint.minmax == 0)
539 auto iter = active.begin();
540 auto end = active.end();
541 for(; iter != end; ++iter)
543 CollisionObject<S>* active_index = *iter;
544 const AABB<S>& b0 = active_index->getAABB();
545 const AABB<S>& b1 = index->getAABB();
547 int axis2 = (axis + 1) % 3;
548 int axis3 = (axis + 2) % 3;
550 if(b0.axisOverlap(b1, axis2) && b0.axisOverlap(b1, axis3))
552 std::pair<typename std::set<std::pair<CollisionObject<S>*, CollisionObject<S>*> >::iterator,
bool> insert_res;
553 if(active_index < index)
554 insert_res =
overlap.insert(std::make_pair(active_index, index));
556 insert_res =
overlap.insert(std::make_pair(index, active_index));
558 if(insert_res.second)
560 if(callback(active_index, index, cdata))
565 active.insert(index);
574 template <
typename S>
577 if(size() == 0)
return;
579 this->enable_tested_set_ =
true;
580 this->tested_set.clear();
583 for(
size_t i = 0; i < endpoints[0].size(); ++i)
584 if(distance_(endpoints[0][i].
obj, cdata, callback, min_dist))
break;
586 this->enable_tested_set_ =
false;
587 this->tested_set.clear();
591 template <
typename S>
594 IntervalTreeCollisionManager* other_manager =
static_cast<IntervalTreeCollisionManager*
>(other_manager_);
596 if((size() == 0) || (other_manager->size() == 0))
return;
598 if(
this == other_manager)
604 if(this->size() < other_manager->size())
606 for(
size_t i = 0, size = endpoints[0].size(); i < size; ++i)
607 if(other_manager->collide_(endpoints[0][i].obj, cdata, callback))
return;
611 for(
size_t i = 0, size = other_manager->endpoints[0].size(); i < size; ++i)
612 if(collide_(other_manager->endpoints[0][i].obj, cdata, callback))
return;
617 template <
typename S>
620 IntervalTreeCollisionManager* other_manager =
static_cast<IntervalTreeCollisionManager*
>(other_manager_);
622 if((size() == 0) || (other_manager->size() == 0))
return;
624 if(
this == other_manager)
632 if(this->size() < other_manager->size())
634 for(
size_t i = 0, size = endpoints[0].size(); i < size; ++i)
635 if(other_manager->distance_(endpoints[0][i].obj, cdata, callback, min_dist))
return;
639 for(
size_t i = 0, size = other_manager->endpoints[0].size(); i < size; ++i)
640 if(distance_(other_manager->endpoints[0][i].obj, cdata, callback, min_dist))
return;
645 template <
typename S>
646 bool IntervalTreeCollisionManager<S>::empty()
const
648 return endpoints[0].empty();
652 template <
typename S>
653 size_t IntervalTreeCollisionManager<S>::size()
const
655 return endpoints[0].size() / 2;
659 template <
typename S>
660 bool IntervalTreeCollisionManager<S>::checkColl(
661 typename std::deque<detail::SimpleInterval<S>*>::const_iterator pos_start,
662 typename std::deque<detail::SimpleInterval<S>*>::const_iterator pos_end,
663 CollisionObject<S>*
obj,
665 CollisionCallBack<S> callback)
const
667 while(pos_start < pos_end)
669 SAPInterval* ivl =
static_cast<SAPInterval*
>(*pos_start);
672 if(ivl->obj->getAABB().overlap(
obj->getAABB()))
674 if(callback(ivl->obj,
obj, cdata))
686 template <
typename S>
687 bool IntervalTreeCollisionManager<S>::checkDist(
688 typename std::deque<detail::SimpleInterval<S>*>::const_iterator pos_start,
689 typename std::deque<detail::SimpleInterval<S>*>::const_iterator pos_end,
690 CollisionObject<S>*
obj,
692 DistanceCallBack<S> callback,
695 while(pos_start < pos_end)
697 SAPInterval* ivl =
static_cast<SAPInterval*
>(*pos_start);
700 if(!this->enable_tested_set_)
702 if(ivl->obj->getAABB().distance(
obj->getAABB()) < min_dist)
704 if(callback(ivl->obj,
obj, cdata, min_dist))
710 if(!this->inTestedSet(ivl->obj,
obj))
712 if(ivl->obj->getAABB().distance(
obj->getAABB()) < min_dist)
714 if(callback(ivl->obj,
obj, cdata, min_dist))
718 this->insertTestedSet(ivl->obj,
obj);
730 template <
typename S>
731 bool IntervalTreeCollisionManager<S>::EndPoint::operator<(
732 const typename IntervalTreeCollisionManager<S>::EndPoint& p)
const
734 return value < p.value;
738 template <
typename S>
739 IntervalTreeCollisionManager<S>::SAPInterval::SAPInterval(
740 S low_, S high_, CollisionObject<S>* obj_)
741 : detail::SimpleInterval<S>()