| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- #ifndef ANKI_SCENE_OCTREE_H
- #define ANKI_SCENE_OCTREE_H
- #include "anki/collision/Aabb.h"
- #include "anki/util/Array.h"
- #include "anki/scene/Common.h"
- #include "anki/scene/Visibility.h"
- #include <memory>
- #if ANKI_CFG_OCTREE_THREAD_SAFE
- # include <mutex>
- #endif
- namespace anki {
- // Forward
- class Frustumable;
- class SceneNode;
- class Octree;
- class Sector;
- /// Octree node
- class OctreeNode
- {
- friend class Octree;
- public:
- typedef Array<OctreeNode*, 8> ChildrenContainer;
- OctreeNode(const Aabb& aabb, OctreeNode* parent,
- const SceneAllocator<U8>& alloc);
- ~OctreeNode();
- /// @name Accessors
- /// @{
- const OctreeNode* getChild(U id) const
- {
- return children[id];
- }
- const OctreeNode* getParent() const
- {
- return parent;
- }
- const Aabb& getAabb() const
- {
- return aabb;
- }
- SceneVector<SceneNode*>::iterator getSceneNodesBegin()
- {
- return sceneNodes.begin();
- }
- SceneVector<SceneNode*>::const_iterator getSceneNodesBegin() const
- {
- return sceneNodes.begin();
- }
- SceneVector<SceneNode*>::iterator getSceneNodesEnd()
- {
- return sceneNodes.end();
- }
- SceneVector<SceneNode*>::const_iterator getSceneNodesEnd() const
- {
- return sceneNodes.end();
- }
- /// @}
- Bool isRoot() const
- {
- return parent == nullptr;
- }
- void removeSceneNode(SceneNode* sn);
- /// @{
- /// Will traverse to find the octree
- const Octree& getOctree() const;
- Octree& getOctree();
- /// @}
- private:
- ChildrenContainer children;
- OctreeNode* parent;
- Aabb aabb; ///< Including AABB
- SceneVector<SceneNode*> sceneNodes;
- #if ANKI_CFG_OCTREE_THREAD_SAFE
- std::mutex mtx;
- #endif
- void addSceneNode(SceneNode* sn);
- void addChild(U pos, OctreeNode* child);
- };
- /// Root octree node. Its seperate because it holds pointer to the octree
- class RootOctreeNode: public OctreeNode
- {
- friend class OctreeNode;
- friend class Octree;
- public:
- RootOctreeNode(const Aabb& aabb, const SceneAllocator<U8>& alloc,
- Octree* octree_)
- : OctreeNode(aabb, nullptr, alloc), octree(octree_)
- {
- ANKI_ASSERT(octree != nullptr);
- }
- private:
- Octree* octree;
- };
- /// Octree
- class Octree
- {
- public:
- Octree(Sector* sector, const Aabb& aabb, U8 maxDepth, F32 looseness = 1.5);
- ~Octree();
- /// @name Accessors
- /// @{
- const OctreeNode& getRoot() const
- {
- return root;
- }
- OctreeNode& getRoot()
- {
- return root;
- }
- U getMaxDepth() const
- {
- return maxDepth;
- }
- Sector& getSector()
- {
- return *sector;
- }
- const Sector& getSector() const
- {
- return *sector;
- }
- /// @}
- /// Place a spatial in the tree
- void placeSceneNode(SceneNode* sn);
- /// Do the visibility tests
- void doVisibilityTests(SceneNode& frustumableSceneNode,
- VisibilityTest test, VisibilityTestResults& visibles);
- private:
- Sector* sector;
- U maxDepth;
- F32 looseness;
- RootOctreeNode root;
- OctreeNode* placeInternal(const Aabb& aabb, U depth, OctreeNode& node);
- /// Place an AABB inside the tree. The algorithm is pretty simple, find the
- /// node that completely includes the aabb. If found then go deeper into
- /// the node's children. The aabb will not be in more than one nodes. Also,
- /// if it is ourside the tree then return nullptr
- OctreeNode* place(const Aabb& aabb);
- /// Recursive method
- void doVisibilityTestsInternal(
- SceneNode& frustumableSceneNode,
- VisibilityTest test,
- VisibilityTestResults& visibles,
- OctreeNode& node);
- void createChildren(OctreeNode& parent);
- /// Calculate the AABB of a child given the parent's AABB and its
- /// position
- /// @param[in] i 0: left, 1: right
- /// @param[in] j 0: down, 1: up
- /// @param[in] k 0: back, 1: front
- /// @param[in] parentAabb The parent's AABB
- /// @param[out] out The out AABB
- void calcAabb(U i, U j, U k, const Aabb& parentAabb, Aabb& out) const;
- };
- } // end namespace anki
- #endif
|