|
|
@@ -13,10 +13,12 @@ |
|
|
|
|
|
|
|
#pragma once |
|
|
|
|
|
|
|
#include <lol/base/array.h> |
|
|
|
#include <lol/debug/lines.h> |
|
|
|
#include <lol/image/color.h> |
|
|
|
|
|
|
|
#include <vector> // std::vector |
|
|
|
#include <tuple> // std::tuple |
|
|
|
|
|
|
|
namespace lol |
|
|
|
{ |
|
|
|
|
|
|
@@ -29,37 +31,61 @@ template <typename TE> class Octree; |
|
|
|
namespace Debug { |
|
|
|
//-- |
|
|
|
|
|
|
|
template<typename TBB> |
|
|
|
struct box_t |
|
|
|
{ |
|
|
|
TBB bbox; |
|
|
|
vec4 color; |
|
|
|
}; |
|
|
|
|
|
|
|
template<typename TE> |
|
|
|
struct elem_t |
|
|
|
{ |
|
|
|
TE *elem; |
|
|
|
int shadow; |
|
|
|
vec4 color; |
|
|
|
}; |
|
|
|
|
|
|
|
template<typename TBB> |
|
|
|
struct leaf_t |
|
|
|
{ |
|
|
|
int id; |
|
|
|
TBB bbox; |
|
|
|
}; |
|
|
|
|
|
|
|
template<typename TREE, typename TE, typename TBB> |
|
|
|
void DrawInner(TREE *tree, array<TBB, vec4> &boxes, |
|
|
|
array<TE *, int, vec4> &elements, |
|
|
|
array<int, TBB> &leaves, int children, vec4 color) |
|
|
|
void DrawInner(TREE *tree, |
|
|
|
std::vector<box_t<TBB>> &boxes, |
|
|
|
std::vector<elem_t<TE>> &elements, |
|
|
|
std::vector<leaf_t<TBB>> &leaves, int children, vec4 color) |
|
|
|
{ |
|
|
|
boxes.push(tree->GetAABB(), color::white); |
|
|
|
leaves.push(0, boxes.last().m1); |
|
|
|
while (leaves.count() > 0) |
|
|
|
boxes.push_back(box_t<TBB> { tree->GetAABB(), color::white }); |
|
|
|
leaves.push_back(leaf_t<TBB> { 0, boxes.last().bbox }); |
|
|
|
|
|
|
|
while (leaves.size() > 0) |
|
|
|
{ |
|
|
|
for (int j = 0; j < tree->GetTree()[leaves[0].m1].m_elements.count(); j++) |
|
|
|
for (auto const eid : tree->GetTree()[leaves[0].id].m_elements) |
|
|
|
{ |
|
|
|
bool done = false; |
|
|
|
for (int k = 0; k < elements.count(); k++) |
|
|
|
for (size_t k = 0; k < elements.size(); k++) |
|
|
|
{ |
|
|
|
if (elements[k].m1 == tree->GetElements()[tree->GetTree()[leaves[0].m1].m_elements[j]].m_element) |
|
|
|
if (elements[k].elem == tree->GetElements()[eid].m_element) |
|
|
|
{ |
|
|
|
elements[k].m2++; |
|
|
|
elements[k].shadow++; |
|
|
|
done = true; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
if (!done) |
|
|
|
elements.push(tree->GetElements()[tree->GetTree()[leaves[0].m1].m_elements[j]].m_element, 1, color::red); |
|
|
|
elements.push(tree->GetElements()[eid].m_element, 1, color::red); |
|
|
|
} |
|
|
|
|
|
|
|
for (int i = 0; i < children; i++) |
|
|
|
{ |
|
|
|
if (tree->GetTree()[leaves[0].m1].m_children[i] != 0) |
|
|
|
if (tree->GetTree()[leaves[0].id].m_children[i] != 0) |
|
|
|
{ |
|
|
|
TBB bbox = tree->GetSubAABB(leaves[0].m2, i); |
|
|
|
leaves.push(tree->GetTree()[leaves[0].m1].m_children[i], bbox); |
|
|
|
TBB bbox = tree->GetSubAABB(leaves[0].bbox, i); |
|
|
|
leaves.push(tree->GetTree()[leaves[0].id].m_children[i], bbox); |
|
|
|
boxes.push(bbox, color); |
|
|
|
} |
|
|
|
} |
|
|
@@ -71,76 +97,70 @@ void DrawInner(TREE *tree, array<TBB, vec4> &boxes, |
|
|
|
template <typename TE, typename TV = void> |
|
|
|
void Draw(Quadtree<TE>* tree, vec4 color) |
|
|
|
{ |
|
|
|
array<box2, vec4> boxes; |
|
|
|
array<TE*, int, vec4> elements; |
|
|
|
array<int, box2> leaves; |
|
|
|
std::vector<box_t<box2>> boxes; |
|
|
|
std::vector<elem_t<TE>> elements; |
|
|
|
std::vector<leaf_t<box2>> leaves; |
|
|
|
|
|
|
|
DrawInner<Quadtree<TE>, TE, box2>(tree, boxes, elements, leaves, 4, color); |
|
|
|
|
|
|
|
vec3 off = vec3(0.0f, 0.1f, 0.0f); |
|
|
|
//vec3 add = vec3(0.0f, 0.1f, 0.0f); |
|
|
|
while (boxes.count() > 0) |
|
|
|
for (auto const &b : boxes) |
|
|
|
{ |
|
|
|
auto const &box = std::get<0>(boxes[0]); |
|
|
|
auto const &col = std::get<1>(boxes[0]); |
|
|
|
Debug::DrawBox(vec3(box.aa.x, tree->m_debug_y_offset, box.aa.y), |
|
|
|
vec3(box.bb.x, tree->m_debug_y_offset, box.bb.y), |
|
|
|
col); |
|
|
|
boxes.remove(0); |
|
|
|
Debug::DrawBox(vec3(b.bbox.aa.x, tree->m_debug_y_offset, b.bbox.aa.y), |
|
|
|
vec3(b.bbox.bb.x, tree->m_debug_y_offset, b.bbox.bb.y), |
|
|
|
b.color); |
|
|
|
} |
|
|
|
while (elements.count() > 0) |
|
|
|
boxes.clear(); |
|
|
|
|
|
|
|
for (auto const &e : elements) |
|
|
|
{ |
|
|
|
auto const *e = std::get<0>(elements[0]); |
|
|
|
int shadow = std::get<1>(elements[0]); |
|
|
|
while (shadow) |
|
|
|
while (e.shadow) |
|
|
|
{ |
|
|
|
Debug::DrawBox(vec3(e->GetAABB().aa.x, tree->m_debug_y_offset, e->GetAABB().aa.y) + off * (float)shadow, |
|
|
|
vec3(e->GetAABB().bb.x, tree->m_debug_y_offset, e->GetAABB().bb.y) + off * (float)shadow, |
|
|
|
elements[0].m3); |
|
|
|
--shadow; |
|
|
|
Debug::DrawBox(vec3(e.elem->GetAABB().aa.x, tree->m_debug_y_offset, e.elem->GetAABB().aa.y) + off * (float)e.shadow, |
|
|
|
vec3(e.elem->GetAABB().bb.x, tree->m_debug_y_offset, e.elem->GetAABB().bb.y) + off * (float)e.shadow, |
|
|
|
e.color); |
|
|
|
--e.shadow; |
|
|
|
} |
|
|
|
elements.remove(0); |
|
|
|
} |
|
|
|
elements.clear(); |
|
|
|
} |
|
|
|
//-- |
|
|
|
|
|
|
|
template <typename TE, typename TV = void> |
|
|
|
void Draw(Octree<TE>* tree, vec4 color) |
|
|
|
{ |
|
|
|
array<box3, vec4> boxes; |
|
|
|
array<TE*, int, vec4> elements; |
|
|
|
array<int, box3> leaves; |
|
|
|
std::vector<box_t<box3>> boxes; |
|
|
|
std::vector<elem_t<TE>> elements; |
|
|
|
std::vector<leaf_t<box3>> leaves; |
|
|
|
|
|
|
|
DrawInner<Octree<TE>, TE, box3>(tree, boxes, elements, leaves, 8, color); |
|
|
|
|
|
|
|
vec3 off = vec3(0.0f, 0.1f, 0.0f); |
|
|
|
//vec3 add = vec3(0.0f, 0.1f, 0.0f); |
|
|
|
while (boxes.count() > 0) |
|
|
|
for (auto const &b : boxes) |
|
|
|
{ |
|
|
|
auto const &box = std::get<0>(boxes[0]); |
|
|
|
auto const &col = std::get<1>(boxes[0]); |
|
|
|
//float size = box.bb.x - box.aa.x; |
|
|
|
Debug::DrawBox(box.aa, /* + off * (m_size.x / size) */ |
|
|
|
box.bb, /* + off * (m_size.x / size) */ |
|
|
|
col); |
|
|
|
Debug::DrawBox(b.bbox.aa, /* + off * (m_size.x / size) */ |
|
|
|
b.bbox.bb, /* + off * (m_size.x / size) */ |
|
|
|
b.color); |
|
|
|
//off += add; |
|
|
|
boxes.remove(0); |
|
|
|
} |
|
|
|
while (elements.count() > 0) |
|
|
|
boxes.clear(); |
|
|
|
|
|
|
|
for (auto const &e : elements) |
|
|
|
{ |
|
|
|
auto const *e = std::get<0>(elements[0]); |
|
|
|
int shadow = std::get<1>(elements[0]); |
|
|
|
while (shadow) |
|
|
|
while (e.shadow) |
|
|
|
{ |
|
|
|
Debug::DrawBox(e->GetAABB().aa + off * (float)shadow, |
|
|
|
e->GetAABB().bb + off * (float)shadow, |
|
|
|
elements[0].m3); |
|
|
|
--shadow; |
|
|
|
Debug::DrawBox(e.elem->GetAABB().aa + off * (float)e.shadow, |
|
|
|
e.elem->GetAABB().bb + off * (float)e.shadow, |
|
|
|
e.color); |
|
|
|
--e.shadow; |
|
|
|
} |
|
|
|
elements.remove(0); |
|
|
|
} |
|
|
|
elements.clear(); |
|
|
|
} |
|
|
|
//-- |
|
|
|
} |
|
|
|
|
|
|
|
} // namespace Debug |
|
|
|
|
|
|
|
//-- |
|
|
|
template <typename TE, typename TV, typename TB, size_t child_nb> |
|
|
@@ -148,11 +168,11 @@ class AABBTree |
|
|
|
{ |
|
|
|
struct NodeLeaf |
|
|
|
{ |
|
|
|
int m_parent; |
|
|
|
int m_parent; |
|
|
|
//Children pos in the list |
|
|
|
int m_children[child_nb]; |
|
|
|
size_t m_children[child_nb]; |
|
|
|
//Element list |
|
|
|
array<int> m_elements; |
|
|
|
std::vector<int> m_elements; |
|
|
|
|
|
|
|
NodeLeaf(int parent) |
|
|
|
{ |
|
|
@@ -164,8 +184,8 @@ class AABBTree |
|
|
|
|
|
|
|
struct TreeElement |
|
|
|
{ |
|
|
|
TE* m_element; |
|
|
|
array<int> m_leaves; |
|
|
|
TE *m_element; |
|
|
|
std::vector<int> m_leaves; |
|
|
|
|
|
|
|
inline bool operator==(const TE*& element) { return m_element == element; } |
|
|
|
}; |
|
|
@@ -208,9 +228,9 @@ private: |
|
|
|
{ |
|
|
|
for (size_t i = 0; i < child_nb; ++i) |
|
|
|
{ |
|
|
|
int old_leaf = m_tree[leaf].m_children[i]; |
|
|
|
size_t old_leaf = m_tree[leaf].m_children[i]; |
|
|
|
if (old_leaf != 0) |
|
|
|
m_free_leaves << old_leaf; |
|
|
|
m_free_leaves.push_back(old_leaf); |
|
|
|
m_tree[leaf].m_children[i] = 0; |
|
|
|
} |
|
|
|
return true; |
|
|
@@ -221,7 +241,7 @@ private: |
|
|
|
void RemoveElement(TE* element) |
|
|
|
{ |
|
|
|
int idx = INDEX_NONE; |
|
|
|
for (int i = 0; i < m_elements.count(); ++i) |
|
|
|
for (size_t i = 0; i < m_elements.size(); ++i) |
|
|
|
if (m_elements[i].m_element == element) |
|
|
|
idx = i; |
|
|
|
|
|
|
@@ -229,8 +249,8 @@ private: |
|
|
|
return; |
|
|
|
|
|
|
|
//Remove item from tree leaves |
|
|
|
for (int i = 0; i < m_elements[idx].m_leaves.count(); i++) |
|
|
|
m_tree[m_elements[idx].m_leaves[i]].m_elements.removeItem(idx); |
|
|
|
for (auto const &lid : m_elements[idx].m_leaves) |
|
|
|
m_tree[lid].m_elements.removeItem(idx); |
|
|
|
|
|
|
|
//Try leaves cleanup |
|
|
|
CleanupEmptyLeaves(); |
|
|
@@ -238,32 +258,32 @@ private: |
|
|
|
//-- |
|
|
|
int AddElement(TE* element) |
|
|
|
{ |
|
|
|
for (int i = 0; i < m_elements.count(); ++i) |
|
|
|
for (size_t i = 0; i < m_elements.size(); ++i) |
|
|
|
if (m_elements[i].m_element == element) |
|
|
|
return i; |
|
|
|
return int(i); |
|
|
|
|
|
|
|
TreeElement new_element; |
|
|
|
new_element.m_element = element; |
|
|
|
new_element.m_leaves = array<int>(); |
|
|
|
m_elements << new_element; |
|
|
|
return m_elements.count() - 1; |
|
|
|
new_element.m_leaves.clear(); |
|
|
|
m_elements.push_back(new_element); |
|
|
|
return int(m_elements.size()) - 1; |
|
|
|
} |
|
|
|
//-- |
|
|
|
int AddLeaf(int parent) |
|
|
|
{ |
|
|
|
int idx = m_tree.count(); |
|
|
|
if (m_free_leaves.count()) |
|
|
|
int idx(m_tree.size()); |
|
|
|
if (m_free_leaves.size()) |
|
|
|
{ |
|
|
|
idx = m_free_leaves.pop(); |
|
|
|
idx = m_free_leaves.pop_back(); |
|
|
|
m_tree[idx] = NodeLeaf(parent); |
|
|
|
} |
|
|
|
else |
|
|
|
m_tree << NodeLeaf(parent); |
|
|
|
m_tree.push_back(NodeLeaf(parent)); |
|
|
|
return idx; |
|
|
|
} |
|
|
|
|
|
|
|
//-- |
|
|
|
bool TestLeaf(int leaf, const TB& leaf_bb, const TB& test_bb, array<TE*>& elements) |
|
|
|
bool TestLeaf(int leaf, const TB& leaf_bb, const TB& test_bb, std::vector<TE*>& elements) |
|
|
|
{ |
|
|
|
bool result = false; |
|
|
|
if (TestAABBVsAABB(leaf_bb, test_bb)) |
|
|
@@ -278,7 +298,7 @@ private: |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
for (int j = 0; j < node.m_elements.count(); j++) |
|
|
|
for (size_t j = 0; j < node.m_elements.size(); j++) |
|
|
|
elements.push_unique(m_elements[node.m_elements[j]].m_element); |
|
|
|
result = true; |
|
|
|
} |
|
|
@@ -303,23 +323,26 @@ private: |
|
|
|
if (found_child) |
|
|
|
return true; |
|
|
|
|
|
|
|
//Too much elements, we need to re-dispatch the elements |
|
|
|
if (m_tree[leaf].m_elements.count() + 1 > m_max_element && |
|
|
|
//Too many elements, we need to re-dispatch the elements |
|
|
|
if (int(m_tree[leaf].m_elements.size()) >= m_max_element && |
|
|
|
depth < m_max_depth) |
|
|
|
{ |
|
|
|
//Extract elements |
|
|
|
array<int> elements = m_tree[leaf].m_elements; |
|
|
|
elements.push_unique(AddElement(element)); |
|
|
|
std::vector<int> elements = m_tree[leaf].m_elements; |
|
|
|
int new_eid = AddElement(element); |
|
|
|
// Add new element to list if not already here |
|
|
|
for (auto const eid : elements) |
|
|
|
if (eid == new_eid) |
|
|
|
new_eid = -1; |
|
|
|
if (new_eid != -1) |
|
|
|
elements.push_back(new_eid); |
|
|
|
m_tree[leaf].m_elements.clear(); |
|
|
|
//Add children |
|
|
|
for (size_t j = 0; j < child_nb; ++j) |
|
|
|
m_tree[leaf].m_children[j] = AddLeaf(leaf); |
|
|
|
//Re-run extracted elements |
|
|
|
while (elements.count()) |
|
|
|
{ |
|
|
|
RegisterElement(m_elements[elements[0]].m_element, leaf, leaf_bb, depth); |
|
|
|
elements.remove(0); |
|
|
|
} |
|
|
|
for (auto const eid : elements) |
|
|
|
RegisterElement(m_elements[eid].m_element, leaf, leaf_bb, depth); |
|
|
|
} |
|
|
|
//else add to list. |
|
|
|
else |
|
|
@@ -336,7 +359,7 @@ private: |
|
|
|
public: |
|
|
|
void RegisterElement(TE* element) { RegisterElement(element, 0, GetAABB(), 0); } |
|
|
|
void UnregisterElement(TE* element) { RemoveElement(element); } |
|
|
|
bool FindElements(const TB& bbox, array<TE*>& elements) { return TestLeaf(0, GetAABB(), bbox, elements); } |
|
|
|
bool FindElements(const TB& bbox, std::vector<TE*>& elements) { return TestLeaf(0, GetAABB(), bbox, elements); } |
|
|
|
void Clear() |
|
|
|
{ |
|
|
|
m_tree.clear(); |
|
|
@@ -362,23 +385,23 @@ public: |
|
|
|
void SetMaxDepth(int max_depth) { m_max_depth = max_depth; } |
|
|
|
void SetMaxElement(int max_element) { m_max_element = max_element; } |
|
|
|
|
|
|
|
array<NodeLeaf> const & GetTree() const |
|
|
|
std::vector<NodeLeaf> const & GetTree() const |
|
|
|
{ |
|
|
|
return m_tree; |
|
|
|
} |
|
|
|
|
|
|
|
array<TreeElement> const & GetElements() const |
|
|
|
std::vector<TreeElement> const & GetElements() const |
|
|
|
{ |
|
|
|
return m_elements; |
|
|
|
} |
|
|
|
|
|
|
|
protected: |
|
|
|
array<NodeLeaf> m_tree; //actual tree |
|
|
|
array<TreeElement> m_elements; //elements to leaves |
|
|
|
array<int> m_free_leaves; //leaves removed from tree |
|
|
|
TV m_size; //Main tree size |
|
|
|
int m_max_depth; //Maximum depth possible |
|
|
|
int m_max_element; //Maximum element per leaf |
|
|
|
std::vector<NodeLeaf> m_tree; // actual tree |
|
|
|
std::vector<TreeElement> m_elements; // elements to leaves |
|
|
|
std::vector<int> m_free_leaves; // leaves removed from tree |
|
|
|
TV m_size; // Main tree size |
|
|
|
int m_max_depth; // Maximum depth possible |
|
|
|
int m_max_element; // Maximum element per leaf |
|
|
|
}; |
|
|
|
|
|
|
|
//-- |
|
|
|