void BroadPhase2DHashGrid::_exit_grid( Element* p_elem, const Rect2& p_rect,bool p_static) { Point2i from = (p_rect.pos/cell_size).floor(); Point2i to = ((p_rect.pos+p_rect.size)/cell_size).floor(); for(int i=from.x;i<=to.x;i++) { for(int j=from.y;j<=to.y;j++) { PosKey pk; pk.x=i; pk.y=j; uint32_t idx = pk.hash() % hash_table_size; PosBin *pb = hash_table[idx]; while (pb) { if (pb->key == pk) { break; } pb=pb->next; } ERR_CONTINUE(!pb); //should exist!! bool exited=false; if (p_static) { if (pb->static_object_set[p_elem].dec()==0) { pb->static_object_set.erase(p_elem); exited=true; } } else { if (pb->object_set[p_elem].dec()==0) { pb->object_set.erase(p_elem); exited=true; } } if (exited) { for(Map<Element*,RC>::Element *E=pb->object_set.front();E;E=E->next()) { if (E->key()->owner==p_elem->owner) continue; _unpair_attempt(p_elem,E->key()); } if (!p_static) { for(Map<Element*,RC>::Element *E=pb->static_object_set.front();E;E=E->next()) { if (E->key()->owner==p_elem->owner) continue; _unpair_attempt(p_elem,E->key()); } } } if (pb->object_set.empty() && pb->static_object_set.empty()) { if (hash_table[idx]==pb) { hash_table[idx]=pb->next; } else { PosBin *px = hash_table[idx]; while (px) { if (px->next==pb) { px->next=pb->next; break; } px=px->next; } ERR_CONTINUE(!px); } memdelete(pb); } } } }
void BroadPhase2DHashGrid::_exit_grid(Element *p_elem, const Rect2 &p_rect, bool p_static) { Vector2 sz = (p_rect.size / cell_size * LARGE_ELEMENT_FI); if (sz.width * sz.height > large_object_min_surface) { //unpair all elements, instead of checking all, just check what is already paired, so we at least save from checking static vs static Map<Element *, PairData *>::Element *E = p_elem->paired.front(); while (E) { Map<Element *, PairData *>::Element *next = E->next(); _unpair_attempt(p_elem, E->key()); E = next; } if (large_elements[p_elem].dec() == 0) { large_elements.erase(p_elem); } return; } Point2i from = (p_rect.position / cell_size).floor(); Point2i to = ((p_rect.position + p_rect.size) / cell_size).floor(); for (int i = from.x; i <= to.x; i++) { for (int j = from.y; j <= to.y; j++) { PosKey pk; pk.x = i; pk.y = j; uint32_t idx = pk.hash() % hash_table_size; PosBin *pb = hash_table[idx]; while (pb) { if (pb->key == pk) { break; } pb = pb->next; } ERR_CONTINUE(!pb); //should exist!! bool exited = false; if (p_static) { if (pb->static_object_set[p_elem].dec() == 0) { pb->static_object_set.erase(p_elem); exited = true; } } else { if (pb->object_set[p_elem].dec() == 0) { pb->object_set.erase(p_elem); exited = true; } } if (exited) { for (Map<Element *, RC>::Element *E = pb->object_set.front(); E; E = E->next()) { if (E->key()->owner == p_elem->owner) continue; _unpair_attempt(p_elem, E->key()); } if (!p_static) { for (Map<Element *, RC>::Element *E = pb->static_object_set.front(); E; E = E->next()) { if (E->key()->owner == p_elem->owner) continue; _unpair_attempt(p_elem, E->key()); } } } if (pb->object_set.empty() && pb->static_object_set.empty()) { if (hash_table[idx] == pb) { hash_table[idx] = pb->next; } else { PosBin *px = hash_table[idx]; while (px) { if (px->next == pb) { px->next = pb->next; break; } px = px->next; } ERR_CONTINUE(!px); } memdelete(pb); } } } for (Map<Element *, RC>::Element *E = large_elements.front(); E; E = E->next()) { if (E->key() == p_elem) continue; // do not pair against itself if (E->key()->owner == p_elem->owner) continue; if (E->key()->_static && p_static) continue; //unpair from large elements _unpair_attempt(p_elem, E->key()); } }