Browse Source

Replace lol::array with std::vector in aabb_tree.h.

wip/core-clipp
Sam Hocevar 5 years ago
parent
commit
c1aac56766
2 changed files with 118 additions and 96 deletions
  1. +0
    -1
      TODO.md
  2. +118
    -95
      legacy/lol/algorithm/aabb_tree.h

+ 0
- 1
TODO.md View File

@@ -47,7 +47,6 @@
## headers to remove one day ## headers to remove one day


src/lol/algorithm/sort.h (there’s plenty of stuff in libc++) src/lol/algorithm/sort.h (there’s plenty of stuff in libc++)
src/lol/base/array.h (use std::vector)
src/lol/base/enum.h (can’t see the point) src/lol/base/enum.h (can’t see the point)
src/lol/base/tuple.h (use std::tuple) src/lol/base/tuple.h (use std::tuple)



+ 118
- 95
legacy/lol/algorithm/aabb_tree.h View File

@@ -13,10 +13,12 @@


#pragma once #pragma once


#include <lol/base/array.h>
#include <lol/debug/lines.h> #include <lol/debug/lines.h>
#include <lol/image/color.h> #include <lol/image/color.h>


#include <vector> // std::vector
#include <tuple> // std::tuple

namespace lol namespace lol
{ {


@@ -29,37 +31,61 @@ template <typename TE> class Octree;
namespace Debug { 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> 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; 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; done = true;
break; break;
} }
} }
if (!done) 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++) 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); boxes.push(bbox, color);
} }
} }
@@ -71,76 +97,70 @@ void DrawInner(TREE *tree, array<TBB, vec4> &boxes,
template <typename TE, typename TV = void> template <typename TE, typename TV = void>
void Draw(Quadtree<TE>* tree, vec4 color) 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); DrawInner<Quadtree<TE>, TE, box2>(tree, boxes, elements, leaves, 4, color);


vec3 off = vec3(0.0f, 0.1f, 0.0f); vec3 off = vec3(0.0f, 0.1f, 0.0f);
//vec3 add = 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> template <typename TE, typename TV = void>
void Draw(Octree<TE>* tree, vec4 color) 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); DrawInner<Octree<TE>, TE, box3>(tree, boxes, elements, leaves, 8, color);


vec3 off = vec3(0.0f, 0.1f, 0.0f); vec3 off = vec3(0.0f, 0.1f, 0.0f);
//vec3 add = 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; //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; //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> template <typename TE, typename TV, typename TB, size_t child_nb>
@@ -148,11 +168,11 @@ class AABBTree
{ {
struct NodeLeaf struct NodeLeaf
{ {
int m_parent;
int m_parent;
//Children pos in the list //Children pos in the list
int m_children[child_nb];
size_t m_children[child_nb];
//Element list //Element list
array<int> m_elements;
std::vector<int> m_elements;


NodeLeaf(int parent) NodeLeaf(int parent)
{ {
@@ -164,8 +184,8 @@ class AABBTree


struct TreeElement 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; } inline bool operator==(const TE*& element) { return m_element == element; }
}; };
@@ -208,9 +228,9 @@ private:
{ {
for (size_t i = 0; i < child_nb; ++i) 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) if (old_leaf != 0)
m_free_leaves << old_leaf;
m_free_leaves.push_back(old_leaf);
m_tree[leaf].m_children[i] = 0; m_tree[leaf].m_children[i] = 0;
} }
return true; return true;
@@ -221,7 +241,7 @@ private:
void RemoveElement(TE* element) void RemoveElement(TE* element)
{ {
int idx = INDEX_NONE; 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) if (m_elements[i].m_element == element)
idx = i; idx = i;


@@ -229,8 +249,8 @@ private:
return; return;


//Remove item from tree leaves //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 //Try leaves cleanup
CleanupEmptyLeaves(); CleanupEmptyLeaves();
@@ -238,32 +258,32 @@ private:
//-- //--
int AddElement(TE* element) 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) if (m_elements[i].m_element == element)
return i;
return int(i);


TreeElement new_element; TreeElement new_element;
new_element.m_element = 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 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); m_tree[idx] = NodeLeaf(parent);
} }
else else
m_tree << NodeLeaf(parent);
m_tree.push_back(NodeLeaf(parent));
return idx; 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; bool result = false;
if (TestAABBVsAABB(leaf_bb, test_bb)) if (TestAABBVsAABB(leaf_bb, test_bb))
@@ -278,7 +298,7 @@ private:
} }
else 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); elements.push_unique(m_elements[node.m_elements[j]].m_element);
result = true; result = true;
} }
@@ -303,23 +323,26 @@ private:
if (found_child) if (found_child)
return true; 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) depth < m_max_depth)
{ {
//Extract elements //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(); m_tree[leaf].m_elements.clear();
//Add children //Add children
for (size_t j = 0; j < child_nb; ++j) for (size_t j = 0; j < child_nb; ++j)
m_tree[leaf].m_children[j] = AddLeaf(leaf); m_tree[leaf].m_children[j] = AddLeaf(leaf);
//Re-run extracted elements //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 add to list.
else else
@@ -336,7 +359,7 @@ private:
public: public:
void RegisterElement(TE* element) { RegisterElement(element, 0, GetAABB(), 0); } void RegisterElement(TE* element) { RegisterElement(element, 0, GetAABB(), 0); }
void UnregisterElement(TE* element) { RemoveElement(element); } 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() void Clear()
{ {
m_tree.clear(); m_tree.clear();
@@ -362,23 +385,23 @@ public:
void SetMaxDepth(int max_depth) { m_max_depth = max_depth; } void SetMaxDepth(int max_depth) { m_max_depth = max_depth; }
void SetMaxElement(int max_element) { m_max_element = max_element; } void SetMaxElement(int max_element) { m_max_element = max_element; }


array<NodeLeaf> const & GetTree() const
std::vector<NodeLeaf> const & GetTree() const
{ {
return m_tree; return m_tree;
} }


array<TreeElement> const & GetElements() const
std::vector<TreeElement> const & GetElements() const
{ {
return m_elements; return m_elements;
} }


protected: 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
}; };


//-- //--


Loading…
Cancel
Save