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);