237 lines
9.1 KiB
Plaintext
237 lines
9.1 KiB
Plaintext
|
/* -*-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 <http://www.gnu.org/licenses/>
|
||
|
*/
|
||
|
#ifndef OSGEARTH_OVERLAY_DECORATOR
|
||
|
#define OSGEARTH_OVERLAY_DECORATOR
|
||
|
|
||
|
#include <osgEarth/Common>
|
||
|
#include <osgEarth/Threading>
|
||
|
#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;
|
||
|
}
|
||
|
|
||
|
namespace osgEarth { namespace Util
|
||
|
{
|
||
|
class OverlayDecorator;
|
||
|
class OverlayTechnique;
|
||
|
|
||
|
/**
|
||
|
* Overlays geometry onto the terrain using various techniques.
|
||
|
*/
|
||
|
class OSGEARTH_EXPORT OverlayDecorator : public osg::Group
|
||
|
{
|
||
|
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 );
|
||
|
|
||
|
/**
|
||
|
* Sets the maximum horizon distance to enforce when calculating
|
||
|
* the draping extents. Constraining the distance will mean that you won't
|
||
|
* see draped geometry past a certain point, but you will potentially get
|
||
|
* higher quality for the geometry you do see (with fewer aliasing artifacts).
|
||
|
*/
|
||
|
double getMaxHorizonDistance() const;
|
||
|
void setMaxHorizonDistance( double horizonDistance );
|
||
|
|
||
|
/**
|
||
|
* Maximum height (above and below) the terrain MSL/ellipsoid at which
|
||
|
* to drape geometry. Geometry above the max or below the -max will not
|
||
|
* appear. This is only important to maintain Z buffering precision in the
|
||
|
* draped geometry; however, it is usually a better idea to draw draped
|
||
|
* geometry without blending or z-testing anyway.
|
||
|
* Default is 500,000 meters.
|
||
|
*/
|
||
|
void setMaximumHeight(double value) { _maxHeight = value; }
|
||
|
double getMaximumHeight() const { return _maxHeight; }
|
||
|
|
||
|
/**
|
||
|
* Initializes the decorator with a terrain engine
|
||
|
*/
|
||
|
void setTerrainEngine(TerrainEngineNode*);
|
||
|
|
||
|
public: // osg::Node
|
||
|
void traverse( osg::NodeVisitor& nv );
|
||
|
|
||
|
public: // osg::Object
|
||
|
void resizeGLObjectBuffers(unsigned maxSize);
|
||
|
void releaseGLObjects(osg::State* state) const;
|
||
|
|
||
|
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::Object> _techniqueData; // technique sets this if needed
|
||
|
const double* _horizonDistance; // points to the PVD horizon distance
|
||
|
TerrainResources* _terrainResources; // for accessing image units
|
||
|
osg::Vec3d _eyeWorld; // eyepoint in world coords
|
||
|
osgShadow::ConvexPolyhedron _visibleFrustumPH; // polyhedron representing the frustum
|
||
|
osg::ref_ptr<osg::Uniform> _rttToPrimaryMatrixUniform; // xform from RTT cam to primary cam
|
||
|
};
|
||
|
|
||
|
// 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 _isGeocentric;
|
||
|
unsigned _rttTraversalMask;
|
||
|
double _maxHeight;
|
||
|
double _maxHorizonDistance;
|
||
|
unsigned _totalOverlayChildren;
|
||
|
|
||
|
osg::ref_ptr<const SpatialReference> _srs;
|
||
|
Ellipsoid _ellipsoid;
|
||
|
osg::observer_ptr<TerrainEngineNode> _engine;
|
||
|
|
||
|
// Mapping of each RTT camera params vector to a Camera (per view data)
|
||
|
using PerViewDataMap = std::unordered_map<osg::Camera*, PerViewData>;
|
||
|
|
||
|
PerViewDataMap _perViewData;
|
||
|
mutable 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 constrainOrthoZ() const { return false; }
|
||
|
|
||
|
virtual bool hasData(
|
||
|
OverlayDecorator::TechRTTParams& params) const { return true; }
|
||
|
|
||
|
virtual const osg::BoundingSphere& getBound(
|
||
|
OverlayDecorator::TechRTTParams& params) const { return params._group->getBound(); }
|
||
|
|
||
|
virtual bool optimizeToVisibleBound() const { return false; }
|
||
|
|
||
|
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 ) { }
|
||
|
|
||
|
virtual void resizeGLObjectBuffers(unsigned maxSize) { }
|
||
|
virtual void releaseGLObjects(osg::State* state) const { }
|
||
|
};
|
||
|
|
||
|
} } // namespace osgEarth
|
||
|
|
||
|
#endif //OSGEARTH_OVERLAY_DECORATOR
|