16 static constexpr Int endOfList = std::numeric_limits<Int>::max();
17 static constexpr size_t elementSize =
sizeof(Type);
21 : firstFree(endOfList) {}
24 if (m_elements.size() + 1 >= endOfList)
27 if (firstFree == endOfList) {
28 m_elements.emplace_back();
29 firstFree = m_elements.size() - 1;
30 m_elements[firstFree].next = endOfList;
34 Node& node = m_elements[idx];
35 firstFree = node.next;
41 Int insert(Type&& obj) {
42 if (firstFree == endOfList) {
43 m_elements.emplace_back();
44 firstFree = m_elements.size() - 1;
45 m_elements[firstFree].next = endOfList;
49 Node& node = m_elements[idx];
50 firstFree = node.next;
51 node.emplace(std::forward<Type&&>(obj));
57 Node& node = m_elements[idx];
61 if (firstFree == endOfList) {
62 node.next = endOfList;
64 node.next = firstFree;
71 return *(Type*)m_elements[idx].element.data.data();
74 const Type& get(Int idx)
const {
75 return *(Type*)m_elements[idx].element.data.data();
78 Type& operator[](Int idx) {
82 const Type& operator[](Int idx)
const {
91 std::array<uint8_t, elementSize> data;
94 void emplace(Type&& obj) {
95 new(element.data.data())Type(obj);
99 new(element.data.data())Type();
102 void destroy()
noexcept {
103 Type* obj = (Type*)element.data.data();
109 std::vector<Node> m_elements;
119 static inline const boost::thread::id mainThreadId = boost::this_thread::get_id();
120 using ivec2 =
typename glm::vec<2, Int, glm::packed_lowp>;
128 void insert(uint16_t idx) {
129 elements.push_back(idx);
132 void erase(uint16_t idx) {
133 elements.erase(std::find(elements.begin(), elements.end(), idx));
136 std::vector<uint16_t> elements;
139 using GridMap = boost::unordered_flat_map<ivec2, ParentCell>;
146 Grid(Float cellSize = (Float)tcW)
147 : m_cellSize(cellSize), m_invCellSize(1.0f / cellSize) {
159 uint16_t idx = m_elementList.insert();
164 const ivec2& min = getCellCoords(aabb.min());
165 const ivec2& max = getCellCoords(aabb.max());
167 for (
auto y = min.y; y <= max.y; y++) {
168 for (
auto x = min.x; x <= max.x; x++) {
169 m_cells[{x, y}].insert(idx);
186 const ivec2& oldMin = getCellCoords(element.aabb.min());
187 const ivec2& oldMax = getCellCoords(element.aabb.max());
188 ivec2 newMin = getCellCoords(newAABB.min());
189 ivec2 newMax = getCellCoords(newAABB.max());
191 for (
auto y = oldMin.y; y <= oldMax.y; y++) {
192 for (
auto x = oldMin.x; x <= oldMax.x; x++) {
193 if (contains(newMin, newMax, { x, y }))
196 auto iter = m_cells.find({ x, y });
197 iter->second.erase(idx);
198 if (iter->second.elements.size() == 0)
199 m_possiblyEmptyCells.push_back({ x, y });
203 for (
auto y = newMin.y; y <= newMax.y; y++) {
204 for (
auto x = newMin.x; x <= newMax.x; x++) {
205 if (contains(oldMin, oldMax, { x, y }))
208 m_cells[{x, y}].insert(idx);
212 element.aabb = newAABB;
222 const ivec2& min = getCellCoords(element.aabb.min());
223 const ivec2& max = getCellCoords(element.aabb.max());
225 for (
auto y = min.y; y <= max.y; y++) {
226 for (
auto x = min.x; x <= max.x; x++) {
227 m_cells[{x, y}].erase(idx);
231 m_elementList.erase(idx);
234 template<
typename Callback>
235 void queryIntersects(
const AABB<Float>& area, Callback&& clbk)
const {
236 const ivec2 min = getCellCoords(area.min());
237 const ivec2 max = getCellCoords(area.max());
239 for (
auto y = min.y; y <= max.y; y++) {
240 for (
auto x = min.x; x <= max.x; x++) {
243 auto iter = m_cells.find(coord);
244 if (iter == m_cells.end())
247 for (uint16_t idx : iter->second.elements) {
248 const GridElement& element = m_elementList.get(idx);
250 if (element.aabb.intersects(area)) {
262 for (
const ivec2& coord : m_possiblyEmptyCells) {
263 if (m_cells[coord].elements.size() == 0) {
264 m_cells.erase(coord);
268 m_possiblyEmptyCells.clear();
281 inline ivec2 getCellCoords(
const vec2& coords)
const {
283 icoords.x = floor<Int>(coords.x * m_invCellSize);
284 icoords.y = floor<Int>(coords.y * m_invCellSize);
289 bool contains(
const Int& min,
const Int& max,
const Int& point) {
290 return min <= point && point <= max;
293 bool contains(
const ivec2& min,
const ivec2& max,
const ivec2& point) {
294 return contains(min.x, max.x, point.x) && contains(min.y, max.y, point.y);
303 std::vector<ivec2> m_possiblyEmptyCells;
uint16_t insert(const AABB< Float > &aabb, const T &data)
Inserts a new element into the grid.
Definition spatial.hpp:158
void relocate(uint16_t idx, const AABB< Float > &newAABB)
Relocates an already existing element within the grid.
Definition spatial.hpp:183