Skip to content

Commit

Permalink
[WIP] Template dimension and flatten
Browse files Browse the repository at this point in the history
Signed-off-by: Squareys <[email protected]>
  • Loading branch information
Squareys committed Apr 14, 2018
1 parent 888fba1 commit fc7855a
Show file tree
Hide file tree
Showing 6 changed files with 314 additions and 276 deletions.
125 changes: 44 additions & 81 deletions src/Magnum/Octree/Octree.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
#include <Magnum/Math/Vector3.h>
#include <Magnum/Math/Vector4.h>

#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/ArrayView.h>

#include <vector>
#include "Magnum/Octree/visibility.h"

Expand All @@ -56,84 +59,45 @@ An octree is a cubic structure, which is subdivided in up to 8 smaller cubes,
called octants. Each octant can be seen as an octree itself. Data is stored
in the leaf octants (octants without children).
*/
template<typename T>
class Octree {
template<UnsignedInt dimensions, class T, class Data>
class Tree {
public:

enum {
NodesPerLevel = 1 << dimensions
};

/** @brief Default constructor */
Octree() :
_children{}
{}
Tree()=default;

/** @brief Copying is not allowed */
Octree(const Octree&)=delete;
Tree(const Tree<dimensions, T, Data>&)=delete;

/** @brief Default destructor */
~Octree()=default;

/** @brief Get the center of the octree */
const Vector3& center() const { return _center; }

/** @brief Get the radius of the octree. */
Float radius() const { return _radius; }

/** @brief Get the depth of the octree */
Int depth() const { return _depth; }
~Tree()=default;

/** @brief Get the bounding boxes in this octree node */
const std::vector<Range3D>& entries() const { return _entries; }
const Containers::ArrayView<const Math::Range3D<T>> boundingBoxes() const { return _boundingBoxes; }

/** @brief Get the data contained in this octree node */
const std::vector<T>& data() const { return _data; }

/** @brief Get the i-th child of this octree */
Octree<T>* child(int i) const { return _children[i]; }
const Containers::ArrayView<const Data> data() const { return _data; }

/**
* @brief Check if the octree is a leaf node.
*
* An octree is a leaf node if it has no children.
*/
bool isLeafNode() const { return _isLeafNode; }

/**
* @brief Set if octree is a leaf node.
*
* An octree is a leaf node if it has no children.
*/
void setLeafNode(bool isLeafNode) {
_isLeafNode = isLeafNode;
}
bool isLeafNode(Int nodeIndex) const { return _childrenStart[nodeIndex] == 0; }

/** @brief Whether this node is empty */
bool empty() const { return _data.empty(); }

/**
* @brief Build the octree for points and a maximal depth
* @param points The points that should get stored in the octree
* @param maxDepth The maximal depth of the octree
* @return Reference to self (for method chaining)
*/
Octree<T>& build(const std::vector<Range3D>& entries, const std::vector<T>& data, const Int maxDepth) {
CORRADE_ASSERT(data.size() == entries.size(), "Entries and data need to be same size.", *this);

createInitialBounds(entries, maxDepth);

auto dataItor = data.begin();
for(const auto& entry : entries) {
insert(entry, *dataItor);
++dataItor;
}

return *this;
}

/**
* @brief Get the child of the octree in which the point is stored, if the point exists
* @param point The point that should be found
* @return The index of the child potentially containing the point
*/
Int octantContainingBox(const Range3D& point) const;
Int octantContainingBox(Int nodeIndex, const Math::Range3D<T>& point) const;

/**
* @brief Get all points contained of the octree within given bounds
Expand All @@ -142,39 +106,38 @@ class Octree {
* @param max The maximal corner of the search bounds
* @return Reference to self (for method chaining)
*/
const Octree<T>& points(std::vector<T>& resultData, const Range3D& range) const;
const Octree<T>& points(std::vector<T>& resultData, const Math::Frustum<Float>& frustum) const;
const Octree<T>& points(std::vector<T>& resultData) const;
const Tree<dimensions, T, Data>& points(std::vector<Data>& resultData, const Math::Range3D<T>& range, Int nodeIndex=0) const;
const Tree<dimensions, T, Data>& points(std::vector<Data>& resultData, const Math::Frustum<T>& frustum, Int nodeIndex=0) const;
const Tree<dimensions, T, Data>& points(std::vector<Data>& resultData, Int nodeIndex=0) const;
Tree<dimensions, T, Data>& build(const Containers::ArrayView<Math::Range3D<T>> entries, const Containers::ArrayView<Data> data, const Int maxDepth);

private:
/**
* @brief Private constructor for setting the center, radius and depth of the octree manually
* @param center The center of the octree
* @param radius The radius of the octree
* @param depth The depth of the octree
*/
Octree(const Vector3& center, Float radius, Int depth, bool isLeafNode) :
_center{center},
_radius(radius),
_depth(depth),
_isLeafNode(isLeafNode),
_children{}
{}

void createInitialBounds(const std::vector<Range3D>& points, Int maxDepth);
void insert(const Range3D& point, T data);
OctantStatus cubeInFrustum(const Math::Frustum<Float>& frustum) const;

Vector3 _center;
Float _radius;
Int _depth;
bool _isLeafNode;

Octree<T>* _children[8];
std::vector<Range3D> _entries;
std::vector<T> _data;

OctantStatus cubeInFrustum(const Math::Frustum<T>& frustum, Int nodeIndex=0) const;

/* Find node which should hold entry with given bounding box.
@returns Depth, and Index of that node as well as the child subindex this
entry would belong into, if the found node is a leaf node and finally
the depth in the tree the node is at */
std::tuple<Int, Int, Int, Int> findNodeFor(const Math::Range3D<T> boundingBox) const;

Containers::Array<Math::Vector3<T>> _centers;
Containers::Array<T> _radii;

Containers::Array<Math::Range3D<T>> _boundingBoxes;
Containers::Array<Data> _data;
/* Range of data entries in _data associated with each node */
Containers::Array<Math::Vector2<UnsignedInt>> _perNodeData;

Containers::Array<Int> _childrenStart;
};

template<class Data> using Quadtree = Tree<2, Float, Data>;
template<class Data> using Quadtreed = Tree<2, Double, Data>;

template<class Data> using Octree = Tree<3, Float, Data>;
template<class Data> using Octreed = Tree<3, Double, Data>;

}}

#endif
Loading

0 comments on commit fc7855a

Please sign in to comment.