#ifndef OPENMW_COMPONENTS_TERRAIN_QUADTREENODE_H #define OPENMW_COMPONENTS_TERRAIN_QUADTREENODE_H #include #include #include "defs.hpp" namespace Terrain { class TerrainLineIntersector : public osgUtil::LineSegmentIntersector { public: TerrainLineIntersector(osgUtil::LineSegmentIntersector* intersector, osg::Matrix& matrix) : osgUtil::LineSegmentIntersector(intersector->getStart() * matrix, intersector->getEnd() * matrix) { setPrecisionHint(intersector->getPrecisionHint()); _intersectionLimit = intersector->getIntersectionLimit(); _parent = intersector; } bool intersectAndClip(const osg::BoundingBox& bbInput) { osg::Vec3d s(_start), e(_end); return osgUtil::LineSegmentIntersector::intersectAndClip(s, e, bbInput); } }; enum ChildDirection { NW = 0, NE = 1, SW = 2, SE = 3, Root }; class QuadTreeNode; class LodCallback : public osg::Referenced { public: virtual ~LodCallback() {} virtual bool isSufficientDetail(QuadTreeNode *node, float dist) = 0; }; class ViewDataMap; class ViewData; class QuadTreeNode : public osg::Group { public: QuadTreeNode(QuadTreeNode* parent, ChildDirection dir, float size, const osg::Vec2f& center); virtual ~QuadTreeNode(); inline QuadTreeNode* getParent() { return mParent; } inline QuadTreeNode* getChild(unsigned int i) { return static_cast(Group::getChild(i)); } inline unsigned int getNumChildren() const { return _children.size(); } // osg::Group::addChild() does a lot of unrelated stuff, but we just really want to add a child node. void addChildNode(QuadTreeNode* child) { // QuadTree node should not contain more than 4 child nodes. // Reserve enough space if this node is supposed to have child nodes. _children.reserve(4); _children.push_back(child); child->addParent(this); }; float distance(const osg::Vec3f& v) const; /// Returns our direction relative to the parent node, or Root if we are the root node. ChildDirection getDirection() { return mDirection; } /// Get neighbour node in this direction QuadTreeNode* getNeighbour (Direction dir); /// Initialize neighbours - do this after the quadtree is built void initNeighbours(); void setBoundingBox(const osg::BoundingBox& boundingBox); const osg::BoundingBox& getBoundingBox() const; bool hasValidBounds() const { return mValidBounds; } virtual osg::BoundingSphere computeBound() const; /// size in cell coordinates float getSize() const; /// center in cell coordinates const osg::Vec2f& getCenter() const; /// Traverse nodes according to LOD selection. void traverse(ViewData* vd, const osg::Vec3f& viewPoint, LodCallback* lodCallback, float maxDist); /// Traverse to a specific node and add only that node. void traverseTo(ViewData* vd, float size, const osg::Vec2f& center); /// Adds all leaf nodes which intersect the line from start to end void intersect(ViewData* vd, TerrainLineIntersector* intersector); private: QuadTreeNode* mParent; QuadTreeNode* mNeighbours[4]; ChildDirection mDirection; osg::BoundingBox mBoundingBox; bool mValidBounds; float mSize; osg::Vec2f mCenter; }; } #endif