X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2FOctree.hh;h=1c57ff2d3317fe83d10aa6972093683cb634556f;hp=2ee617f3744f0baa6155c15df3a767617cb35c56;hb=329a48e4c4c2f5f2904b913938fc53154c48b825;hpb=29e3d45f7bbbf31eadf793c41ff2b3d9c47b7539 diff --git a/src/Moof/Octree.hh b/src/Moof/Octree.hh index 2ee617f..1c57ff2 100644 --- a/src/Moof/Octree.hh +++ b/src/Moof/Octree.hh @@ -33,52 +33,323 @@ #include +#include + +#include +#include +#include #include -#include +#include namespace Mf { -class Entity; +struct OctreeNode : public Entity +{ + std::list objects; + + 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); + } + + OctreeNode(const Aabb& aabb) + { + aabb_ = aabb; + sphere_.point = aabb.getCenter(); + sphere_.radius = (aabb.min - sphere_.point).length(); + } + + void draw(Scalar alpha) const + { + 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 Camera& cam) const + { + std::list::const_iterator it; + + for (it = objects.begin(); it != objects.end(); ++it) + { + (*it)->drawIfVisible(alpha, cam); + } + if (!objects.empty()) + aabb_.draw(); + } + + + bool isVisible(const Camera& cam) const + { + if (sphere_.isVisible(cam)) + { + return aabb_.isVisible(cam); + } + + return false; + } +}; +class Octree; +typedef boost::shared_ptr OctreePtr; + class Octree { + + stlplus::ntree root_; + public: - class Node + explicit Octree(const OctreeNode& rootNode) + { + root_.insert(rootNode); + } + + void insert(EntityPtr entity) + { + insert(root_.root(), entity); + } + + void insert(stlplus::ntree::iterator node, EntityPtr entity) + { + Plane::Halfspace halfspace; + int octantNum = -1; + + if (!node.valid()) + { + std::cerr << "cannot insert into invalid node" << std::endl; + return; + } + + Plane xy = node->getAabb().getPlaneXY(); + halfspace = xy.intersectsSphere(entity->getSphere()); + + if (halfspace == Plane::POSITIVE) + { + Plane xz = node->getAabb().getPlaneXZ(); + halfspace = xz.intersectsSphere(entity->getSphere()); + + if (halfspace == Plane::POSITIVE) + { + Plane yz = node->getAabb().getPlaneYZ(); + halfspace = yz.intersectsSphere(entity->getSphere()); + + if (halfspace == Plane::POSITIVE) + { + octantNum = 2; + } + else if (halfspace == Plane::NEGATIVE) + { + octantNum = 3; + } + } + else if (halfspace == Plane::NEGATIVE) + { + Plane yz = node->getAabb().getPlaneYZ(); + halfspace = yz.intersectsSphere(entity->getSphere()); + + if (halfspace == Plane::POSITIVE) + { + octantNum = 1; + } + else if (halfspace == Plane::NEGATIVE) + { + octantNum = 0; + } + } + } + else if (halfspace == Plane::NEGATIVE) + { + Plane xz = node->getAabb().getPlaneXZ(); + halfspace = xz.intersectsSphere(entity->getSphere()); + + if (halfspace == Plane::POSITIVE) + { + Plane yz = node->getAabb().getPlaneYZ(); + halfspace = yz.intersectsSphere(entity->getSphere()); + + if (halfspace == Plane::POSITIVE) + { + octantNum = 6; + } + else if (halfspace == Plane::NEGATIVE) + { + octantNum = 7; + } + } + else if (halfspace == Plane::NEGATIVE) + { + Plane yz = node->getAabb().getPlaneYZ(); + halfspace = yz.intersectsSphere(entity->getSphere()); + + if (halfspace == Plane::POSITIVE) + { + octantNum = 5; + } + else if (halfspace == Plane::NEGATIVE) + { + octantNum = 4; + } + } + } + + if (octantNum == -1) + { + node->objects.push_front(entity); + //return node; + } + else + { + if (root_.children(node) == 0) + { + addChildren(node); + } + + stlplus::ntree::iterator child = root_.child(node, octantNum); + + if (child.valid()) + { + return insert(child, entity); + } + else + { + std::cerr << "expected but found no child at index " << octantNum << std::endl; + //return stlplus::ntree::iterator(); + } + //return WeakPtr(); + } + } + + void addChildren(stlplus::ntree::iterator node) + { + Aabb octant; + + if (!node.valid()) + { + std::cerr << "cannot add children to invalid node" << std::endl; + return; + } + + for (int i = 0; i < 8; ++i) + { + node->getAabb().getOctant(octant, i); + //OctreeNode octantNode(octant); + + root_.append(node, octant); + } + } + + void draw(stlplus::ntree::iterator node, Scalar alpha) { - Aabb aabb_; - Vector3 center_; + if (!node.valid()) + { + std::cerr << "cannot draw null child node :-(" << std::endl; + return; + } - std::list > objects_; + node->draw(alpha); - public: + for (unsigned i = 0; i < root_.children(node); ++i) + { + stlplus::ntree::iterator child = root_.child(node, i); - Node() : - aabb_(-1.0, -1.0, -1.0, 1.0, 1.0, 1.0), - center_(0.0, 0.0, 0.0) {} + if (child.valid()) + { + draw(child, alpha); + } + else + { + std::cerr << "node is not a leaf, but has an invalid child" << std::endl; + } + + } + } + + void drawIfVisible(stlplus::ntree::iterator node, + Scalar alpha, const Camera& cam) + { + //node.drawIfVisible(alpha, cam); + + if (!node.valid()) + { + std::cerr << "invalid child while drawing :-(" << std::endl; + return; + } - Node(const Aabb& aabb) : - aabb_(aabb), - center_(aabb.getCenter()) {} - }; + Frustum::Collision collision = + cam.getFrustum().containsSphere(node->getSphere()); + if (collision == Frustum::OUTSIDE) return; - Octree() : - root_(new Tree()) {} + collision = cam.getFrustum().containsAabb(node->getAabb()); + if (collision == Frustum::OUTSIDE) return; - Octree(const Aabb& aabb) : - root_(new Tree(Node(aabb))) {} + if (collision == Frustum::INSIDE) + { + node->draw(alpha); + } + else // collision == Frustum::INTERSECT + { + node->drawIfVisible(alpha, cam); + } - Tree::WeakPtr add(EntityPtr object); + if (root_.children(node) > 0) + { + if (collision == Frustum::INSIDE) + { + for (unsigned i = 0; i < root_.children(node); ++i) + { + stlplus::ntree::iterator child = root_.child(node, i); + + if (child.valid()) + { + draw(child, alpha); + } + else + { + std::cerr << "node is not a leaf, but has an invalid child" << std::endl; + } + + } + } + else // collision == Frustum::INTERSECT + { + for (unsigned i = 0; i < root_.children(node); ++i) + { + stlplus::ntree::iterator child = root_.child(node, i); + + if (child.valid()) + { + drawIfVisible(child, alpha, cam); + } + else + { + std::cerr << "node is not a leaf, but has an invalid child" << std::endl; + } + } + } + } + } + + void drawIfVisible(Scalar alpha, const Camera& cam) + { + drawIfVisible(root_.root(), alpha, cam); + } -private: - Tree::Ptr root_; }; + } // namespace Mf #endif // _MOOF_OCTREE_HH_