/* -*-c++-*- */ /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph * Copyright 2015 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 <http://www.gnu.org/licenses/> */ #ifndef OSGEARTH_OVERLAY_DECORATOR #define OSGEARTH_OVERLAY_DECORATOR #include <osgEarth/Common> #include <osgEarth/ThreadingUtils> #include <osgEarth/TerrainEngineNode> #include <osg/Camera> #include <osg/CoordinateSystemNode> #include <osg/TexGenNode> #include <osg/Uniform> #include <osgUtil/CullVisitor> #include <osgShadow/ConvexPolyhedron> namespace osgEarth { class TerrainEngineNode; class OverlayDecorator; class OverlayTechnique; /** * Overlays geometry onto the terrain using various techniques. */ class OSGEARTH_EXPORT OverlayDecorator : public TerrainDecorator { public: OverlayDecorator(); /** * Adds a new overlay technique to the decorator. */ void addTechnique( OverlayTechnique* technique ); /** * Gets the group for nodes that are to be overlaid with * the specified Technique. */ template<typename T> osg::Group* getGroup() { for(unsigned i=0; i<_techniques.size(); ++i ) { if ( dynamic_cast<T*>(_techniques[i].get()) ) return _overlayGroups[i].get(); } return 0L; } /** * The traversal mask to use when traversing the overlay groups. */ void setOverlayGraphTraversalMask( unsigned mask ); double getMaxHorizonDistance() const; void setMaxHorizonDistance( double horizonDistance ); public: // TerrainDecorator virtual void onInstall( TerrainEngineNode* engine ); virtual void onUninstall( TerrainEngineNode* engine ); public: // osg::Node void traverse( osg::NodeVisitor& nv ); public: // NotiferGroup listener interface void onGroupChanged(osg::Group* group); protected: virtual ~OverlayDecorator() { } public: // RTT camera parameters for an overlay technique. There will be // one of these per technique, per view. struct TechRTTParams { osg::Camera* _mainCamera; // Camera to which this per-view data is attached osg::ref_ptr<osg::Camera> _rttCamera; // RTT camera. osg::Matrixd _rttViewMatrix; // View matrix of RTT camera osg::Matrixd _rttProjMatrix; // Projection matrix of RTT camera osg::Group* _group; // contains the overlay graphics osg::StateSet* _terrainStateSet; // same object as in PerViewData (shared across techniques) osg::ref_ptr<osg::Referenced> _techniqueData; // technique sets this if needed const double* _horizonDistance; // points to the PVD horizon distance. osg::Group* _terrainParent; // the terrain is in getChild(0). osg::Vec3d _eyeWorld; // eyepoint in world coords osgShadow::ConvexPolyhedron _visibleFrustumPH; // polyhedron representing the frustum }; // One of these per view (camera). The terrain state set // if Shared almong all the techniques under a view. struct PerViewData { osg::Camera* _camera; // Camera to which this per-view data is attached std::vector<TechRTTParams> _techParams; // Pre-view data for each technique osg::ref_ptr<osg::StateSet> _sharedTerrainStateSet; // shared state set to apply to the terrain traversal double _sharedHorizonDistance; // horizon distnace (not used?) osg::Matrix _prevViewMatrix; // last frame's view matrix }; private: optional<int> _explicitTextureUnit; optional<int> _textureUnit; optional<int> _textureSize; bool _useShaders; bool _isGeocentric; bool _mipmapping; bool _rttBlending; bool _updatePending; unsigned _rttTraversalMask; double _maxHorizonDistance; bool _attachStencil; unsigned _totalOverlayChildren; osg::ref_ptr<const SpatialReference> _srs; osg::ref_ptr<const osg::EllipsoidModel> _ellipsoid; osg::observer_ptr<TerrainEngineNode> _engine; // Mapping of each RTT camera params vector to a Camera (per view data) typedef std::map<osg::Camera*, PerViewData> PerViewDataMap; PerViewDataMap _perViewData; Threading::ReadWriteMutex _perViewDataMutex; typedef std::vector< osg::ref_ptr<OverlayTechnique> > Techniques; Techniques _techniques; Techniques _unsupportedTechniques; typedef std::vector< osg::ref_ptr<osg::Group> > Groups; Groups _overlayGroups; private: void cullTerrainAndCalculateRTTParams( osgUtil::CullVisitor* cv, PerViewData& pvd ); void initializePerViewData( PerViewData&, osg::Camera* ); PerViewData& getPerViewData( osg::Camera* key ); public: // marker class for DrapeableNode support. struct InternalNodeVisitor : public osg::NodeVisitor { InternalNodeVisitor(const osg::NodeVisitor::TraversalMode& mode =osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) : osg::NodeVisitor(mode) { } }; //debugging: void requestDump() { _dumpRequested = true; } osg::Node* getDump() { osg::Node* r = _dump.release(); _dump = 0L; return r; } osg::ref_ptr<osg::Node> _dump; bool _dumpRequested; }; /** * Abstract interface for an overlay technique implementation */ class OverlayTechnique : public osg::Referenced { protected: bool _supported; OverlayTechnique() : _supported(true) { } virtual ~OverlayTechnique() { } public: virtual bool supported() { return _supported; } virtual bool hasData( OverlayDecorator::TechRTTParams& params) const { return true; } virtual void onInstall( TerrainEngineNode* engine ) { } virtual void onUninstall( TerrainEngineNode* engine ) { } virtual void reestablish( TerrainEngineNode* engine ) { } virtual void preCullTerrain( OverlayDecorator::TechRTTParams& params, osgUtil::CullVisitor* cv ) { } virtual void cullOverlayGroup( OverlayDecorator::TechRTTParams& params, osgUtil::CullVisitor* cv ) { } }; } // namespace osgEarth #endif //OSGEARTH_OVERLAY_DECORATOR