38 #ifndef FCL_BROAD_PHASE_SAP_INL_H
39 #define FCL_BROAD_PHASE_SAP_INL_H
55 for(
auto end =
AABB_arr.end(); it != end; ++it)
70 for(
int coord = 0; coord < 3; ++coord)
73 if(curr->lo->prev[coord] ==
nullptr)
74 elist[coord] = curr->lo->next[coord];
76 curr->lo->prev[coord]->next[coord] = curr->lo->next[coord];
78 curr->lo->next[coord]->prev[coord] = curr->lo->prev[coord];
81 if(curr->hi->prev[coord] ==
nullptr)
82 elist[coord] = curr->hi->next[coord];
84 curr->hi->prev[coord]->next[coord] = curr->hi->next[coord];
86 if(curr->hi->next[coord] !=
nullptr)
87 curr->hi->next[coord]->prev[coord] = curr->hi->prev[coord];
109 template <
typename S>
116 template <
typename S>
119 if(other_objs.empty())
return;
125 std::vector<EndPoint*> endpoints(2 * other_objs.size());
127 for(
size_t i = 0; i < other_objs.size(); ++i)
129 SaPAABB* sapaabb =
new SaPAABB();
130 sapaabb->obj = other_objs[i];
131 sapaabb->lo =
new EndPoint();
132 sapaabb->hi =
new EndPoint();
133 sapaabb->cached = other_objs[i]->getAABB();
134 endpoints[2 * i] = sapaabb->lo;
135 endpoints[2 * i + 1] = sapaabb->hi;
136 sapaabb->lo->minmax = 0;
137 sapaabb->hi->minmax = 1;
138 sapaabb->lo->aabb = sapaabb;
139 sapaabb->hi->aabb = sapaabb;
146 for(
size_t coord = 0; coord < 3; ++coord)
148 std::sort(endpoints.begin(), endpoints.end(),
149 std::bind(std::less<S>(),
150 std::bind(
static_cast<S (EndPoint::*)(
size_t)
const >(&EndPoint::getVal), std::placeholders::_1, coord),
151 std::bind(
static_cast<S (EndPoint::*)(
size_t)
const >(&EndPoint::getVal), std::placeholders::_2, coord)));
153 endpoints[0]->prev[coord] =
nullptr;
154 endpoints[0]->next[coord] = endpoints[1];
155 for(
size_t i = 1; i < endpoints.size() - 1; ++i)
157 endpoints[i]->prev[coord] = endpoints[i-1];
158 endpoints[i]->next[coord] = endpoints[i+1];
160 endpoints[endpoints.size() - 1]->prev[coord] = endpoints[endpoints.size() - 2];
161 endpoints[endpoints.size() - 1]->next[coord] =
nullptr;
163 elist[coord] = endpoints[0];
165 scale[coord] = endpoints.back()->aabb->cached.max_[coord] - endpoints[0]->aabb->cached.min_[coord];
169 if(scale[axis] < scale[1]) axis = 1;
170 if(scale[axis] < scale[2]) axis = 2;
172 EndPoint* pos =
elist[axis];
174 while(pos !=
nullptr)
176 EndPoint* pos_next =
nullptr;
177 SaPAABB*
aabb = pos->aabb;
178 EndPoint* pos_it = pos->next[axis];
180 while(pos_it !=
nullptr)
182 if(pos_it->aabb ==
aabb)
184 if(pos_next ==
nullptr) pos_next = pos_it;
188 if(pos_it->minmax == 0)
190 if(pos_next ==
nullptr) pos_next = pos_it;
191 if(pos_it->aabb->cached.overlap(
aabb->cached))
194 pos_it = pos_it->next[axis];
205 template <
typename S>
208 SaPAABB* curr =
new SaPAABB;
209 curr->cached =
obj->getAABB();
211 curr->lo =
new EndPoint;
212 curr->lo->minmax = 0;
213 curr->lo->aabb = curr;
215 curr->hi =
new EndPoint;
216 curr->hi->minmax = 1;
217 curr->hi->aabb = curr;
219 for(
int coord = 0; coord < 3; ++coord)
221 EndPoint* current =
elist[coord];
224 if(current ==
nullptr)
226 elist[coord] = curr->lo;
227 curr->lo->prev[coord] = curr->lo->next[coord] =
nullptr;
231 EndPoint* curr_lo = curr->lo;
232 S curr_lo_val = curr_lo->getVal()[coord];
233 while((current->getVal()[coord] < curr_lo_val) && (current->next[coord] !=
nullptr))
234 current = current->next[coord];
236 if(current->getVal()[coord] >= curr_lo_val)
238 curr_lo->prev[coord] = current->prev[coord];
239 curr_lo->next[coord] = current;
240 if(current->prev[coord] ==
nullptr)
241 elist[coord] = curr_lo;
243 current->prev[coord]->next[coord] = curr_lo;
245 current->prev[coord] = curr_lo;
249 curr_lo->prev[coord] = current;
250 curr_lo->next[coord] =
nullptr;
251 current->next[coord] = curr_lo;
258 EndPoint* curr_hi = curr->hi;
259 S curr_hi_val = curr_hi->getVal()[coord];
263 while((current->getVal()[coord] < curr_hi_val) && (current->next[coord] !=
nullptr))
265 if(current != curr->lo)
266 if(current->aabb->cached.overlap(curr->cached))
269 current = current->next[coord];
274 while((current->getVal()[coord] < curr_hi_val) && (current->next[coord] !=
nullptr))
275 current = current->next[coord];
278 if(current->getVal()[coord] >= curr_hi_val)
280 curr_hi->prev[coord] = current->prev[coord];
281 curr_hi->next[coord] = current;
282 if(current->prev[coord] ==
nullptr)
283 elist[coord] = curr_hi;
285 current->prev[coord]->next[coord] = curr_hi;
287 current->prev[coord] = curr_hi;
291 curr_hi->prev[coord] = current;
292 curr_hi->next[coord] =
nullptr;
293 current->next[coord] = curr_hi;
305 template <
typename S>
308 if(
size() == 0)
return;
311 scale[0] = (
velist[0].back())->getVal(0) -
velist[0][0]->getVal(0);
312 scale[1] = (
velist[1].back())->getVal(1) -
velist[1][0]->getVal(1);;
313 scale[2] = (
velist[2].back())->getVal(2) -
velist[2][0]->getVal(2);
315 if(scale[axis] < scale[1]) axis = 1;
316 if(scale[axis] < scale[2]) axis = 2;
321 template <
typename S>
324 if(updated_aabb->cached.equal(updated_aabb->obj->getAABB()))
327 SaPAABB* current = updated_aabb;
329 Vector3<S> new_min = current->obj->getAABB().min_;
330 Vector3<S> new_max = current->obj->getAABB().max_;
333 dummy.cached = current->obj->getAABB();
335 for(
int coord = 0; coord < 3; ++coord)
340 if(current->lo->getVal(coord) > new_min[coord])
342 else if(current->lo->getVal(coord) < new_min[coord])
349 if(current->lo->prev[coord] !=
nullptr)
352 while((temp !=
nullptr) && (temp->getVal(coord) > new_min[coord]))
354 if(temp->minmax == 1)
355 if(temp->aabb->cached.overlap(dummy.cached))
357 temp = temp->prev[coord];
362 current->lo->prev[coord]->next[coord] = current->lo->next[coord];
363 current->lo->next[coord]->prev[coord] = current->lo->prev[coord];
364 current->lo->prev[coord] =
nullptr;
365 current->lo->next[coord] =
elist[coord];
366 elist[coord]->prev[coord] = current->lo;
367 elist[coord] = current->lo;
371 current->lo->prev[coord]->next[coord] = current->lo->next[coord];
372 current->lo->next[coord]->prev[coord] = current->lo->prev[coord];
373 current->lo->prev[coord] = temp;
374 current->lo->next[coord] = temp->next[coord];
375 temp->next[coord]->prev[coord] = current->lo;
376 temp->next[coord] = current->lo;
380 current->lo->getVal(coord) = new_min[coord];
384 while(temp->getVal(coord) > new_max[coord])
386 if((temp->minmax == 0) && (temp->aabb->cached.overlap(current->cached)))
388 temp = temp->prev[coord];
391 current->hi->prev[coord]->next[coord] = current->hi->next[coord];
392 if(current->hi->next[coord] !=
nullptr)
393 current->hi->next[coord]->prev[coord] = current->hi->prev[coord];
394 current->hi->prev[coord] = temp;
395 current->hi->next[coord] = temp->next[coord];
396 if(temp->next[coord] !=
nullptr)
397 temp->next[coord]->prev[coord] = current->hi;
398 temp->next[coord] = current->hi;
400 current->hi->getVal(coord) = new_max[coord];
402 else if(direction == 1)
405 if(current->hi->next[coord] !=
nullptr)
408 while((temp->next[coord] !=
nullptr) && (temp->getVal(coord) < new_max[coord]))
410 if(temp->minmax == 0)
411 if(temp->aabb->cached.overlap(dummy.cached))
413 temp = temp->next[coord];
416 if(temp->getVal(coord) < new_max[coord])
418 current->hi->prev[coord]->next[coord] = current->hi->next[coord];
419 current->hi->next[coord]->prev[coord] = current->hi->prev[coord];
420 current->hi->prev[coord] = temp;
421 current->hi->next[coord] =
nullptr;
422 temp->next[coord] = current->hi;
426 current->hi->prev[coord]->next[coord] = current->hi->next[coord];
427 current->hi->next[coord]->prev[coord] = current->hi->prev[coord];
428 current->hi->prev[coord] = temp->prev[coord];
429 current->hi->next[coord] = temp;
430 temp->prev[coord]->next[coord] = current->hi;
431 temp->prev[coord] = current->hi;
435 current->hi->getVal(coord) = new_max[coord];
440 while(temp->getVal(coord) < new_min[coord])
442 if((temp->minmax == 1) && (temp->aabb->cached.overlap(current->cached)))
444 temp = temp->next[coord];
447 if(current->lo->prev[coord] !=
nullptr)
448 current->lo->prev[coord]->next[coord] = current->lo->next[coord];
450 elist[coord] = current->lo->next[coord];
451 current->lo->next[coord]->prev[coord] = current->lo->prev[coord];
452 current->lo->prev[coord] = temp->prev[coord];
453 current->lo->next[coord] = temp;
454 if(temp->prev[coord] !=
nullptr)
455 temp->prev[coord]->next[coord] = current->lo;
457 elist[coord] = current->lo;
458 temp->prev[coord] = current->lo;
459 current->lo->getVal(coord) = new_min[coord];
465 template <
typename S>
468 for(
int coord = 0; coord < 3; ++coord)
471 EndPoint* current =
elist[coord];
475 velist[coord][id] = current;
476 current = current->next[coord];
483 template <
typename S>
494 template <
typename S>
497 for(
size_t i = 0; i < updated_objs.size(); ++i)
506 template <
typename S>
520 template <
typename S>
546 template <
typename S>
551 for(
auto it =
AABB_arr.cbegin(), end =
AABB_arr.cend(); it != end; ++it, ++i)
553 objs[i] = (*it)->obj;
558 template <
typename S>
562 const AABB<S>& obj_aabb =
obj->getAABB();
564 S min_val = obj_aabb.min_[axis];
569 dummy_aabb.cached = obj_aabb;
571 dummy.aabb = &dummy_aabb;
574 const auto res_it = std::upper_bound(
velist[axis].begin(),
velist[axis].end(), &dummy,
575 std::bind(std::less<S>(),
576 std::bind(
static_cast<S (EndPoint::*)(
size_t) const
>(&EndPoint::getVal), std::placeholders::_1, axis),
577 std::bind(
static_cast<S (EndPoint::*)(
size_t) const
>(&EndPoint::getVal), std::placeholders::_2, axis)));
579 EndPoint* end_pos =
nullptr;
580 if(res_it !=
velist[axis].end())
583 EndPoint* pos =
elist[axis];
585 while(pos != end_pos)
587 if(pos->aabb->obj !=
obj)
589 if((pos->minmax == 0) && (pos->aabb->hi->getVal(axis) >= min_val))
591 if(pos->aabb->cached.overlap(
obj->getAABB()))
592 if(callback(
obj, pos->aabb->obj, cdata))
596 pos = pos->next[axis];
603 template <
typename S>
605 const typename SaPCollisionManager<S>::SaPPair& p)
607 bool repeated =
false;
622 template <
typename S>
624 const typename SaPCollisionManager<S>::SaPPair& p)
641 template <
typename S>
644 if(
size() == 0)
return;
650 template <
typename S>
653 Vector3<S> delta = (
obj->getAABB().max_ -
obj->getAABB().min_) * 0.5;
658 Vector3<S> min_dist_delta(min_dist, min_dist, min_dist);
659 aabb.expand(min_dist_delta);
667 EndPoint* start_pos =
elist[axis];
671 old_min_distance = min_dist;
672 S min_val =
aabb.min_[axis];
677 dummy_aabb.cached =
aabb;
679 dummy.aabb = &dummy_aabb;
682 const auto res_it = std::upper_bound(
velist[axis].begin(),
velist[axis].end(), &dummy,
683 std::bind(std::less<S>(),
684 std::bind(
static_cast<S (EndPoint::*)(
size_t) const
>(&EndPoint::getVal), std::placeholders::_1, axis),
685 std::bind(
static_cast<S (EndPoint::*)(
size_t) const
>(&EndPoint::getVal), std::placeholders::_2, axis)));
687 EndPoint* end_pos =
nullptr;
688 if(res_it !=
velist[axis].end())
691 EndPoint* pos = start_pos;
693 while(pos != end_pos)
697 if((pos->minmax == 0) && (pos->aabb->hi->getVal(axis) >= min_val))
699 CollisionObject<S>* curr_obj = pos->aabb->obj;
704 if(pos->aabb->cached.distance(
obj->getAABB()) < min_dist)
706 if(callback(curr_obj,
obj, cdata, min_dist))
714 if(pos->aabb->cached.distance(
obj->getAABB()) < min_dist)
716 if(callback(curr_obj,
obj, cdata, min_dist))
726 pos = pos->next[axis];
735 if(min_dist < old_min_distance)
737 Vector3<S> min_dist_delta(min_dist, min_dist, min_dist);
738 aabb = AABB<S>(
obj->getAABB(), min_dist_delta);
746 aabb.expand(
obj->getAABB(), 2.0);
758 template <
typename S>
761 if(
size() == 0)
return;
769 template <
typename S>
772 if(
size() == 0)
return;
776 CollisionObject<S>*
obj1 = it->obj1;
777 CollisionObject<S>*
obj2 = it->obj2;
785 template <
typename S>
788 if(
size() == 0)
return;
797 if(
distance_((*it)->obj, cdata, callback, min_dist))
806 template <
typename S>
811 if((
size() == 0) || (other_manager->size() == 0))
return;
813 if(
this == other_manager)
819 if(this->
size() < other_manager->size())
823 if(other_manager->collide_((*it)->obj, cdata, callback))
829 for(
auto it = other_manager->AABB_arr.cbegin(), end = other_manager->AABB_arr.cend(); it != end; ++it)
831 if(
collide_((*it)->obj, cdata, callback))
838 template <
typename S>
843 if((
size() == 0) || (other_manager->size() == 0))
return;
845 if(
this == other_manager)
853 if(this->
size() < other_manager->size())
857 if(other_manager->distance_((*it)->obj, cdata, callback, min_dist))
863 for(
auto it = other_manager->AABB_arr.cbegin(), end = other_manager->AABB_arr.cend(); it != end; ++it)
865 if(
distance_((*it)->obj, cdata, callback, min_dist))
872 template <
typename S>
879 template <
typename S>
886 template <
typename S>
887 const Vector3<S>&SaPCollisionManager<S>::EndPoint::getVal()
const
890 else return aabb->cached.min_;
894 template <
typename S>
895 Vector3<S>&SaPCollisionManager<S>::EndPoint::getVal()
898 else return aabb->cached.min_;
902 template <
typename S>
903 S SaPCollisionManager<S>::EndPoint::getVal(
size_t i)
const
906 return aabb->cached.max_[i];
908 return aabb->cached.min_[i];
912 template <
typename S>
913 S& SaPCollisionManager<S>::EndPoint::getVal(
size_t i)
916 return aabb->cached.max_[i];
918 return aabb->cached.min_[i];
922 template <
typename S>
923 SaPCollisionManager<S>::SaPPair::SaPPair(CollisionObject<S>* a, CollisionObject<S>* b)
938 template <
typename S>
939 bool SaPCollisionManager<S>::SaPPair::operator ==(
const typename SaPCollisionManager<S>::SaPPair& other)
const
941 return ((
obj1 == other.obj1) && (
obj2 == other.obj2));
945 template <
typename S>
946 SaPCollisionManager<S>::isUnregistered::isUnregistered(CollisionObject<S>* obj_) :
obj(obj_)
950 template <
typename S>
951 bool SaPCollisionManager<S>::isUnregistered::operator()(
const SaPPair& pair)
const
953 return (pair.obj1 ==
obj) || (pair.obj2 ==
obj);
957 template <
typename S>
958 SaPCollisionManager<S>::isNotValidPair::isNotValidPair(CollisionObject<S>* obj1_, CollisionObject<S>* obj2_) :
obj1(obj1_),
965 template <
typename S>
966 bool SaPCollisionManager<S>::isNotValidPair::operator()(
const SaPPair& pair)
968 return (pair.obj1 ==
obj1) && (pair.obj2 ==
obj2);