X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2FMoof%2FOctree.hh;h=cdac62a29071f4eeaeb51c48c055e84db1a029dc;hb=d5b4262bc0c6cea41c603e8a3a85ab93adfdc36b;hp=d896844f0379a4ab7ca1cebe32d52cb5a719a775;hpb=bfa6212d09d8735d8fd5e2638188e4a99f21ada4;p=chaz%2Fyoink diff --git a/src/Moof/Octree.hh b/src/Moof/Octree.hh index d896844..cdac62a 100644 --- a/src/Moof/Octree.hh +++ b/src/Moof/Octree.hh @@ -39,6 +39,8 @@ #include #include #include +#include +#include #include #include @@ -46,115 +48,261 @@ namespace Mf { -class Camera; +//class Octree; +//typedef boost::shared_ptr OctreeP; +//class Octree::Node; +//typedef stlplus::ntree::iterator OctreeNodeP; -struct OctreeNode : public Entity + +struct OctreeInsertable { - std::list objects; + virtual ~OctreeInsertable() {} - OctreeNode() - { - aabb_.min = Vector3(-1.0, -1.0, -1.0); - aabb_.max = Vector3(1.0, 1.0, 1.0); - sphere_.init(Vector3(0.0, 0.0, 0.0), 1.41421); - } + virtual bool isInsideAabb(const Aabb& aabb) const = 0; + virtual int getOctant(const Aabb& aabb) const = 0; +}; - OctreeNode(const Aabb& aabb) - { - aabb_ = aabb; - sphere_.point = aabb.getCenter(); - sphere_.radius = (aabb.min - sphere_.point).length(); - } - void draw(Scalar alpha) const +template +class Octree : public Entity +{ + typedef boost::shared_ptr InsertableP; + + struct Node : public Entity { - std::list::const_iterator it; + std::list objects; + + Aabb aabb; + Sphere sphere; + + Node(const Aabb& box) : + aabb(box) + { + sphere.point = aabb.getCenter(); + sphere.radius = (aabb.min - sphere.point).length(); + } + + void draw(Scalar alpha) const + { + typename std::list::const_iterator it; + + for (it = objects.begin(); it != objects.end(); ++it) + { + (*it)->draw(alpha); + } + + if (!objects.empty()) + aabb.draw(); // temporary + } + + void drawIfVisible(Scalar alpha, const Frustum& frustum) const + { + typename std::list::const_iterator it; + + for (it = objects.begin(); it != objects.end(); ++it) + { + (*it)->drawIfVisible(alpha, frustum); + } + + if (!objects.empty()) + { + //aabb.draw(); + //sphere.draw(); + } + } + - for (it = objects.begin(); it != objects.end(); ++it) + bool isVisible(const Frustum& frustum) const { - (*it)->draw(alpha); + if (sphere.isVisible(frustum)) + { + return aabb.isVisible(frustum); + } + + return false; } + }; + + +public: + + typedef boost::shared_ptr Ptr; + typedef typename stlplus::ntree::iterator NodeP; + +private: + - //if (!objects.empty()) - //aabb_.draw(); // temporary + NodeP insert(InsertableP entity, NodeP node) + { + ASSERT(node.valid() && "invalid node passed"); + ASSERT(entity && "null entity passed"); + + if (entity->isInsideAabb(node->aabb)) + { + return insert_recurse(entity, node); + } + else + { + node->objects.push_back(entity); + return node; + } } - void drawIfVisible(Scalar alpha, const Camera& cam) const + NodeP insert_recurse(InsertableP entity, NodeP node) { - std::list::const_iterator it; + ASSERT(node.valid() && "invalid node passed"); + ASSERT(entity && "null entity passed"); - for (it = objects.begin(); it != objects.end(); ++it) + int octantNum = entity->getOctant(node->aabb); + if (octantNum == -1) { - (*it)->drawIfVisible(alpha, cam); + node->objects.push_back(entity); + return node; } + else + { + if ((int)tree_.children(node) <= octantNum) + { + addChild(node, octantNum); + } - //if (!objects.empty()) - //aabb_.draw(); - } + NodeP child = tree_.child(node, octantNum); + ASSERT(child.valid() && "expected valid child node"); + return insert(entity, child); + } + } - bool isVisible(const Camera& cam) const + void addChild(NodeP node, int index) { - if (sphere_.isVisible(cam)) + ASSERT(node.valid() && "invalid node passed"); + + Aabb octant; + + for (int i = tree_.children(node); i <= index; ++i) { - return aabb_.isVisible(cam); + node->aabb.getOctant(octant, i); + tree_.append(node, octant); } - - return false; } - static bool compareZOrder(EntityPtr a, EntityPtr b) + void draw(Scalar alpha, NodeP node) const { - return a->getSphere().point[2] < b->getSphere().point[2]; + ASSERT(node.valid() && "invalid node passed"); + + node->draw(alpha); + + for (unsigned i = 0; i < tree_.children(node); ++i) + { + NodeP child = tree_.child(node, i); + ASSERT(child.valid() && "expected valid child node"); + + draw(alpha, child); + } } - void sort() + void drawIfVisible(Scalar alpha, const Frustum& frustum, NodeP node) const { - //std::sort(objects.begin(), objects.end(), compareZOrder); - objects.sort(compareZOrder); + ASSERT(node.valid() && "invalid node passed"); + + // try to cull by sphere + Frustum::Collision collision = frustum.contains(node->sphere); + if (collision == Frustum::OUTSIDE) return; + + // try to cull by aabb + collision = frustum.contains(node->aabb); + if (collision == Frustum::OUTSIDE) return; + + + if (collision == Frustum::INSIDE) + { + node->draw(alpha); + } + else // collision == Frustum::INTERSECT + { + node->drawIfVisible(alpha, frustum); + } + + if (tree_.children(node) > 0) + { + if (collision == Frustum::INSIDE) + { + for (unsigned i = 0; i < tree_.children(node); ++i) + { + NodeP child = tree_.child(node, i); + ASSERT(child.valid() && "expected valid child node"); + + draw(alpha, child); + } + } + else // collision == Frustum::INTERSECT + { + for (unsigned i = 0; i < tree_.children(node); ++i) + { + NodeP child = tree_.child(node, i); + ASSERT(child.valid() && "expected valid child node"); + + drawIfVisible(alpha, frustum, child); + } + } + } } -}; + + mutable stlplus::ntree tree_; -class Octree -{ public: - explicit Octree(const OctreeNode& rootNode) + void print(NodeP node) { - tree_.insert(rootNode); + //logDebug("-----"); + //logDebug("depth to node: %d", tree_.depth(node)); + //logDebug("size of node: %d", tree_.size(node)); } - stlplus::ntree::iterator insert(EntityPtr entity) + static Ptr alloc(const Node& rootNode) { - return insert(tree_.root(), entity); + return Ptr(new Octree(rootNode)); } - stlplus::ntree::iterator reinsert(EntityPtr entity, - stlplus::ntree::iterator node); + explicit Octree(const Node& rootNode) + { + tree_.insert(rootNode); + } - void drawIfVisible(Scalar alpha, const Camera& cam) + NodeP insert(InsertableP entity) { - drawIfVisible(tree_.root(), alpha, cam); + return insert(entity, tree_.root()); } - void sort(); + NodeP reinsert(InsertableP entity, NodeP node) + { + ASSERT(entity && "null entity passed"); + ASSERT(node.valid() && "invalid node passed"); -private: - stlplus::ntree::iterator insert(stlplus::ntree::iterator node, EntityPtr entity); - - void addChild(stlplus::ntree::iterator node, int index); + typename std::list::iterator it; + it = std::find(node->objects.begin(), node->objects.end(), entity); + + if (it != node->objects.end()) + { + node->objects.erase(it); + } - void draw(stlplus::ntree::iterator node, Scalar alpha); - void drawIfVisible(stlplus::ntree::iterator node, - Scalar alpha, const Camera& cam); + return insert(entity); + } - stlplus::ntree tree_; -}; + void draw(Scalar alpha) const + { + draw(alpha, tree_.root()); + } -typedef boost::shared_ptr OctreePtr; + void drawIfVisible(Scalar alpha, const Frustum& frustum) const + { + drawIfVisible(alpha, frustum, tree_.root()); + } +}; } // namespace Mf