/* -*-c++-*- */ /* osgEarth - Geospatial SDK for OpenSceneGraph * Copyright 2020 Pelican Mapping * http://osgearth.org * * osgEarth is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see */ #ifndef OSGEARTH_UTIL_HTM_H #define OSGEARTH_UTIL_HTM_H 1 #include #include #include #include #include #include #include namespace osgEarth { namespace Contrib { using namespace osgEarth; struct HTMSettings { unsigned _maxObjectsPerCell; Distance _threshold; float _minCellSize; float _maxCellSize; bool _storeObjectsInLeavesOnly; int _debugCount; int _debugFrame; bool _debugGeom; }; /** * Hierarchical Triangular Mesh group - for geocentric maps only * http://www.geog.ucsb.edu/~hu/papers/spatialIndex.pdf * * An osg::Group that automatically organizes its contents spatially * in order to improve culling performance. */ class OSGEARTH_EXPORT HTMGroup : public osg::Group { public: HTMGroup(); //! Sets the maximum number of objects that can live in a single cell. void setMaximumObjectsPerCell(unsigned value) { _settings._maxObjectsPerCell = value; } float getMaximumObjectsPerCell() const { return _settings._maxObjectsPerCell; } //! Minimum size (bounding radius*2) of an HTM cell. void setMinimumCellSize(double value) { _settings._minCellSize = value; } double getMinimumCellSize() const { return _settings._minCellSize; } //! Maximum size (bounding radius*2) of an HTM cell that can contain objects. void setMaximumCellSize(double value) { _settings._maxCellSize = value; } double getMaximumCellSize() const { return _settings._maxCellSize; } //! Range at which objects become visible. //! If in linear units, treat as a max distance; if pixels, treat as a min SSE void setThreshold(const Distance& value) { _settings._threshold = value; } //! If true, only store objects in the leaf nodes (defaults to false) void setStoreObjectsInLeavesOnly(bool value) { _settings._storeObjectsInLeavesOnly = value; } //! Enable debugging geometry void setDebug(bool value) { _settings._debugGeom = value; } bool getDebug() const { return _settings._debugGeom; } public: // osg::Group /** Add a node to the group. */ virtual bool addChild(osg::Node* child); /** Add a node to the group. Ignores the "index". */ virtual bool insertChild(unsigned index, osg::Node* child); public: // osg::Group (internal) /** These methods are derived from Group but are NOOPs for the HTMGroup. */ virtual bool removeChildren(unsigned pos, unsigned numChildrenToRemove); virtual bool replaceChild(osg::Node* origChild, osg::Node* newChild); virtual bool setChild(unsigned index, osg::Node* node); protected: virtual ~HTMGroup() { } bool insert(osg::Node* node); void reinitialize(); HTMSettings _settings; }; /** * Internal index cell for the HTMGroup (do not use directly). */ class HTMNode : public osg::Group { public: HTMNode(HTMSettings& settings, const osg::Vec3d& v0, const osg::Vec3d& v1, const osg::Vec3d& v2, const std::string& id = ""); bool contains(const osg::Vec3d& p) const { return _tri.contains(p); } void insert(osg::Node* node); public: void traverse(osg::NodeVisitor& nv); protected: virtual ~HTMNode() { } void split(); // test whether the node's triangle lies entirely within a frustum bool entirelyWithin(const osg::Polytope& tope) const; // test whether the node's triangle intersects a frustum bool intersects(const osg::Polytope& tope) const; private: struct PolytopeDP : public osg::Polytope { bool contains(const osg::Vec3d& p) const; bool containsAnyOf(const std::vector& p) const; }; struct Triangle { std::vector _v; PolytopeDP _tope; void set(const osg::Vec3d& v0, const osg::Vec3d& v1, const osg::Vec3d& v2); void getMidpoints(osg::Vec3d* w) const; bool contains(const osg::Vec3d& p) const { return _tope.contains(p); } }; Triangle _tri; bool _isLeaf; HTMSettings& _settings; osg::ref_ptr _debug; }; } } // namesapce osgEarth::Util #endif // OSGEARTH_UTIL_HTM_H