Browse Source

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

wip/core-clipp
Sam Hocevar 4 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

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/tuple.h (use std::tuple)


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

@@ -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
};

//--


Loading…
Cancel
Save