osgEarth 2.1.1
Public Member Functions | Private Member Functions | Private Attributes

osgEarth::OverlayDecorator Class Reference

Inheritance diagram for osgEarth::OverlayDecorator:
Collaboration diagram for osgEarth::OverlayDecorator:

List of all members.

Public Member Functions

 OverlayDecorator ()
void setOverlayGraph (osg::Node *node)
osg::Node * getOverlayGraph () const
void setTextureUnit (int unit)
int getTextureUnit () const
void setTextureSize (int texSize)
int getTextureSize () const
void setMipmapping (bool value)
bool getMipmapping () const
void setVertexWarping (bool value)
bool getVertexWarping () const
void setOverlayBlending (bool value)
bool getOverlayBlending () const
virtual void onInstall (TerrainEngineNode *engine)
virtual void onUninstall (TerrainEngineNode *engine)
void traverse (osg::NodeVisitor &nv)

Private Member Functions

void updateRTTCamera (osg::NodeVisitor &nv)
void cull (osgUtil::CullVisitor *cv)
void reinit ()
void initSubgraphShaders (osg::StateSet *set)
void initRTTShaders (osg::StateSet *set)

Private Attributes

osg::ref_ptr< osg::Node > _overlayGraph
osg::ref_ptr< osg::Camera > _rttCamera
osg::ref_ptr< osg::Texture2D > _projTexture
osg::ref_ptr< osg::TexGenNode > _texGenNode
osg::ref_ptr< osg::Uniform > _texGenUniform
osg::ref_ptr< osg::Uniform > _warpUniform
osg::ref_ptr< osg::StateSet > _subgraphStateSet
optional< int > _explicitTextureUnit
optional< int > _textureUnit
optional< int > _textureSize
bool _useShaders
bool _useWarping
float _warp
bool _warping
bool _visualizeWarp
bool _isGeocentric
double _maxProjectedMapExtent
bool _mipmapping
bool _rttBlending
osg::Matrixd _rttViewMatrix
osg::Matrixd _rttProjMatrix
osg::Matrixd _projectorViewMatrix
osg::Matrixd _projectorProjMatrix
osg::ref_ptr< const
osg::EllipsoidModel > 
_ellipsoid
osg::ref_ptr
< osgEarth::VirtualProgram
_vp
osg::ref_ptr< TerrainEngineNode_engine

Detailed Description

Projects an overlay scene graph onto the main model.

The OverlayDecorator is automatically installed in the MapNode and is used to display ModelLayer's whose "overlay" property is set to true.

This class is similar in scope to osgSim::OverlayNode, but is optimized for use with osgEarth and geocentric terrains.

Definition at line 43 of file OverlayDecorator.


Constructor & Destructor Documentation

OverlayDecorator::OverlayDecorator ( )

Definition at line 218 of file OverlayDecorator.cpp.

                                   :
_textureUnit  ( 1 ),
_textureSize  ( 1024 ),
_useShaders   ( false ),
_useWarping   ( false ),
_warp         ( 1.0f ),
_visualizeWarp( false ),
_mipmapping   ( true ),
_rttBlending  ( true )
{
    // nop
}

Member Function Documentation

void OverlayDecorator::cull ( osgUtil::CullVisitor *  cv) [private]

Definition at line 646 of file OverlayDecorator.cpp.

{
    static int s_frame = 1;

    osg::Vec3 eye = cv->getEyePoint();

    double eyeLen;
    osg::Vec3d worldUp;

    // height above sea level
    double hasl;

    // weight of the HASL value when calculating extent compensation
    double haslWeight;

    // approximate distance to the visible horizon
    double horizonDistance; 

    // distance to the horizon, projected into the RTT camera's tangent plane.
    double horizonDistanceInRTTPlane;

    if ( _isGeocentric )
    {
        double lat, lon;
        _ellipsoid->convertXYZToLatLongHeight( eye.x(), eye.y(), eye.z(), lat, lon, hasl );
        hasl = osg::maximum( hasl, 100.0 );

        worldUp = _ellipsoid->computeLocalUpVector(eye.x(), eye.y(), eye.z());

        eyeLen = eye.length();

        // radius of the earth under the eyepoint
        double radius = eyeLen - hasl; 
        horizonDistance = sqrt( 2.0 * radius * hasl ); 
    
        // calculate the distance to the horizon, projected into the RTT camera plane.
        // This is the maximum limit of eMax since there is no point in drawing overlay
        // data beyond the visible horizon.
        double pitchAngleOfHorizon_rad = acos( horizonDistance/eyeLen );
        horizonDistanceInRTTPlane = horizonDistance * sin( pitchAngleOfHorizon_rad );
    }
    else // projected map
    {
        hasl = eye.z();
        hasl = osg::maximum( hasl, 100.0 );
        worldUp.set( 0.0, 0.0, 1.0 );
        eyeLen = hasl * 2.0;

        // there is no maximum horizon distance in a projected map
        horizonDistance = DBL_MAX;
        horizonDistanceInRTTPlane = DBL_MAX;

        _rttViewMatrix = osg::Matrixd::lookAt( eye, eye-worldUp*hasl, osg::Vec3(0,1,0) );
    }

    // create a "weighting" that weights HASL against the camera's pitch.
    osg::Vec3d lookVector = cv->getLookVectorLocal();
    haslWeight = osg::absolute(worldUp * lookVector);

    // unit look-vector of the eye:
    osg::Vec3d from, to, up;
    const osg::Matrix& mvMatrix = *cv->getModelViewMatrix();
    mvMatrix.getLookAt( from, to, up, eyeLen);
    osg::Vec3 camLookVec = to-from;
    camLookVec.normalize();

    // unit look-vector of the RTT camera:
    osg::Vec3d rttLookVec = -worldUp;

    // the minimum and maximum extents of the overlay ortho projector:
    double eMin = 0.1;
    double eMax = DBL_MAX;

    // Save and reset the current near/far planes before traversing the subgraph.
    // We do this because we want a projection matrix that includes ONLY the clip
    // planes from the subgraph, and not anything traversed up to this point.
    double zSavedNear = cv->getCalculatedNearPlane();
    double zSavedFar  = cv->getCalculatedFarPlane();

    cv->setCalculatedNearPlane( FLT_MAX );
    cv->setCalculatedFarPlane( -FLT_MAX );

    // cull the subgraph here. This doubles as the subgraph's official cull traversal
    // and a gathering of its clip planes.
    cv->pushStateSet( _subgraphStateSet.get() );
    osg::Group::traverse( *cv );
    cv->popStateSet();

    // Pull a copy of the projection matrix; we will use this to calculate the optimum
    // projected texture extent
    osg::Matrixd projMatrix = *cv->getProjectionMatrix();

    // Clamp the projection matrix to the newly calculated clip planes. This prevents
    // any "leakage" from outside the subraph.
    double zNear = cv->getCalculatedNearPlane();
    double zFar  = cv->getCalculatedFarPlane();
    cv->clampProjectionMatrix( projMatrix, zNear, zFar );

    //OE_NOTICE << std::fixed << "zNear = " << zNear << ", zFar = " << zFar << std::endl;

    if ( _isGeocentric )
    {
        // in geocentric mode, clamp the far clip plane to the horizon.
        double maxDistance = (1.0 - haslWeight)  * horizonDistance  + haslWeight * hasl;
        maxDistance *= 1.5;
        if (zFar - zNear >= maxDistance)
            zFar = zNear + maxDistance;

        cv->clampProjectionMatrix( projMatrix, zNear, zFar );
    }

    // restore the clip planes in the cull visitor, now that we have our subgraph
    // projection matrix.
    cv->setCalculatedNearPlane( osg::minimum(zSavedNear, zNear) );
    cv->setCalculatedFarPlane( osg::maximum(zSavedFar, zFar) );
       
    // contruct the polyhedron representing the viewing frustum.
    //osgShadow::ConvexPolyhedron frustumPH;
    MyConvexPolyhedron frustumPH;
    frustumPH.setToUnitFrustum( true, true );
    osg::Matrixd MVP = *cv->getModelViewMatrix() * projMatrix;
    osg::Matrixd inverseMVP;
    inverseMVP.invert(MVP);
    frustumPH.transform( inverseMVP, MVP );

    // make a polyhedron representing the viewing frustum of the overlay, and cut it to
    // intersect the viewing frustum:
    osgShadow::ConvexPolyhedron visiblePH;

    // get the bounds of the overlay graph model. 
    osg::BoundingBox visibleOverlayBBox;
    CoarsePolytopeIntersector cpi( frustumPH, visibleOverlayBBox );
    _overlayGraph->accept( cpi );
    visiblePH.setToBoundingBox( visibleOverlayBBox );

    // this intersects the viewing frustum with the subgraph's bounding box, basically giving us
    // a "minimal" polyhedron containing all potentially visible geometry. (It can't be truly 
    // minimal without clipping at the geometry level, but that would probably be too expensive.)
    visiblePH.cut( frustumPH );

    // calculate the extents for our orthographic RTT camera (clamping it to the
    // visible horizon)
    std::vector<osg::Vec3d> verts;
    visiblePH.getPoints( verts );

    if ( _isGeocentric )
    {
        // for a geocentric map, try to place the RTT camera position at an optimal point
        // that will minimize the span of the RTT texture. Take the centroid of the 
        // visible polyhedron and clamp it's distance to the eyepoint by half the horizon
        // distance.
        osg::BoundingBox box = visiblePH.computeBoundingBox();
        osg::Vec3d bc = box.center();
        osg::Vec3d eye2bc = eye - bc;
        if ( eye2bc.length() > horizonDistance )
        {
            eye2bc.normalize();
            bc = eye + eye2bc * 0.5*horizonDistance;
        }
        
        rttLookVec = -bc;
        rttLookVec.normalize();

        double new_eMax;
        getMinMaxExtentInSilhouette( bc, rttLookVec, verts, eMin, new_eMax );
        eMax = std::min( eMax, new_eMax );
        _rttViewMatrix = osg::Matrixd::lookAt( bc, osg::Vec3d(0,0,0), osg::Vec3d(0,0,1) );
        _rttProjMatrix = osg::Matrixd::ortho( -eMax, eMax, -eMax, eMax, -eyeLen, bc.length() );

        //OE_INFO << std::fixed << std::setprecision(1)
        //    << "eMax = " << eMax
        //    << ", bc = " << bc.x() << ", " << bc.y() << ", " << bc.z()
        //    << ", eye = " << eye.x() << ", " << eye.y() << ", " << eye.z()
        //    << ", eyeLen = " << eyeLen
        //    << std::endl;
    }
    else
    {
        // for a projected map, just point the RTT straight down at the camera position.
        // TODO: this could be optimized, probably.
        double new_eMax;
        getMinMaxExtentInSilhouette( from, osg::Vec3d(0,0,-1), verts, eMin, new_eMax );   
        eMax = std::min( eMax, new_eMax ); 
        _rttProjMatrix = osg::Matrix::ortho( -eMax, eMax, -eMax, eMax, -eyeLen, eyeLen );
    }

    //OE_NOTICE << LC << "EMIN = " << eMin << ", EMAX = " << eMax << std::endl;

    if ( _useWarping )
    {
        // calculate the warping paramaters. This uses shaders to warp the verts and
        // tex coords to favor data closer to the camera when necessary.

    #define WARP_LIMIT 3.0

        double pitchStrength = ( camLookVec * rttLookVec ); // eye pitch relative to rtt pitch
        double devStrength = 1.0 - (pitchStrength*pitchStrength);
        double haslStrength = 1.0 - osg::clampBetween( hasl/1e6, 0.0, 1.0 );

        _warp = 1.0 + devStrength * haslStrength * WARP_LIMIT;

        if ( _visualizeWarp )
            _warp = 4.0;

#if 0
        OE_INFO << LC << std::fixed
            << "hasl=" << hasl
            << ", eMin=" << eMin
            << ", eMax=" << eMax
            << ", eyeLen=" << eyeLen
            //<< ", ratio=" << ratio
            //<< ", dev=" << devStrength
            //<< ", has=" << haeStrength
            << ", warp=" << _warp
            << std::endl;
#endif
    }

#if 0
    if ( s_frame++ % 100 == 0 )
    {
        osgShadow::ConvexPolyhedron rttPH;
        rttPH.setToUnitFrustum( true, true );
        osg::Matrixd MVP = _rttViewMatrix * _rttProjMatrix;
        osg::Matrixd inverseMVP;
        inverseMVP.invert(MVP);
        rttPH.transform( inverseMVP, MVP );
        rttPH.dumpGeometry();
    }
#endif

    // projector matrices are the same as for the RTT camera. Tim was right.
    _projectorViewMatrix = _rttViewMatrix;
    _projectorProjMatrix = _rttProjMatrix;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool osgEarth::OverlayDecorator::getMipmapping ( ) const [inline]

Definition at line 76 of file OverlayDecorator.

{ return _mipmapping; }
bool osgEarth::OverlayDecorator::getOverlayBlending ( ) const [inline]

Definition at line 93 of file OverlayDecorator.

{ return _rttBlending; }
osg::Node* osgEarth::OverlayDecorator::getOverlayGraph ( ) const [inline]

Definition at line 52 of file OverlayDecorator.

{ return _overlayGraph.get(); }
int osgEarth::OverlayDecorator::getTextureSize ( ) const [inline]

Definition at line 68 of file OverlayDecorator.

{ return *_textureSize; }
int osgEarth::OverlayDecorator::getTextureUnit ( ) const [inline]

Definition at line 60 of file OverlayDecorator.

{ return *_textureUnit; }
bool osgEarth::OverlayDecorator::getVertexWarping ( ) const [inline]

Definition at line 84 of file OverlayDecorator.

{ return _warping; }
void OverlayDecorator::initRTTShaders ( osg::StateSet *  set) [private]

Definition at line 348 of file OverlayDecorator.cpp.

{
    //TODO: convert this to VP so the overlay graph can use shadercomp too.
    osg::Program* program = new osg::Program();
    program->setName( "OverlayDecorator RTT shader" );
    set->setAttributeAndModes( program, osg::StateAttribute::ON );

    std::stringstream buf;
    buf << "#version 110 \n";

    if ( _useWarping )
    {
        buf << "uniform float warp; \n"

            // because the built-in pow() is busted
            << "float mypow( in float x, in float y ) \n"
            << "{ \n"
            << "    return x/(x+y-y*x); \n"
            << "} \n"

            << "vec4 warpVertex( in vec4 src ) \n"
            << "{ \n"
            //      normalize to [-1..1], then take the absolute values since we
            //      want to apply the warping in [0..1] on each side of zero:
            << "    vec2 srct = vec2( abs(src.x)/src.w, abs(src.y)/src.w ); \n"
            << "    vec2 sign = vec2( src.x > 0.0 ? 1.0 : -1.0, src.y > 0.0 ? 1.0 : -1.0 ); \n"

            //      apply the deformation using a "deceleration" curve:
            << "    vec2 srcp = vec2( 1.0-mypow(1.0-srct.x,warp), 1.0-mypow(1.0-srct.y,warp) ); \n"

            //      re-apply the sign. no need to un-normalize, just use w=1 instead
            << "    return vec4( sign.x*srcp.x, sign.y*srcp.y, src.z/src.w, 1.0 ); \n"
            << "} \n"

            << "void main() \n"
            << "{ \n"
            << "    gl_Position = warpVertex( gl_ModelViewProjectionMatrix * gl_Vertex ); \n"
            << "    gl_FrontColor = gl_Color; \n"
            << "    gl_TexCoord[0] = gl_MultiTexCoord0;\n"
            << "} \n";
    }

    else // no vertex warping
    {
        buf << "void main() \n"
            << "{ \n"
            << "    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; \n"
            << "    gl_FrontColor = gl_Color; \n"
            << "    gl_TexCoord[0] = gl_MultiTexCoord0;\n"
            << "} \n";
    }

    std::string vertSource = buf.str();
    program->addShader( new osg::Shader( osg::Shader::VERTEX, vertSource ) );

    std::stringstream fragBuf;
    fragBuf    << "#version 110 \n"
               << "uniform sampler2D texture_0; \n"
               << "void main() \n"
               << "{\n"                              
               << "    vec4 tex = texture2D(texture_0, gl_TexCoord[0].xy);\n"
               << "    vec3 mixed_color = mix(gl_Color.rgb, tex.rgb, tex.a);\n"
               //<< "    gl_FragColor = vec4(mixed_color, gl_Color.a); \n"
               << "    gl_FragColor = vec4(mixed_color, gl_Color.a); \n"
               << "}\n";
    
    std::string fragSource = fragBuf.str();
    
    program->addShader( new osg::Shader( osg::Shader::FRAGMENT, fragSource ) );
    set->addUniform(new osg::Uniform("texture_0",0));
}

Here is the caller graph for this function:

void OverlayDecorator::initSubgraphShaders ( osg::StateSet *  set) [private]

Definition at line 421 of file OverlayDecorator.cpp.

{
    VirtualProgram* vp = new VirtualProgram();
    vp->setName( "OverlayDecorator subgraph shader" );
    set->setAttributeAndModes( vp, osg::StateAttribute::ON );

    // sampler for projected texture:
    set->getOrCreateUniform( "osgearth_overlay_ProjTex", osg::Uniform::SAMPLER_2D )->set( *_textureUnit );

    // the texture projection matrix uniform.
    _texGenUniform = set->getOrCreateUniform( "osgearth_overlay_TexGenMatrix", osg::Uniform::FLOAT_MAT4 );

    std::stringstream buf;

    // vertex shader - subgraph
    buf << "#version 110 \n"
        << "uniform mat4 osgearth_overlay_TexGenMatrix; \n"
        << "uniform mat4 osg_ViewMatrixInverse; \n"

        << "void osgearth_overlay_vertex(void) \n"
        << "{ \n"
        << "    gl_TexCoord["<< *_textureUnit << "] = osgearth_overlay_TexGenMatrix * osg_ViewMatrixInverse * gl_ModelViewMatrix * gl_Vertex; \n"
        << "} \n";

    std::string vertexSource = buf.str();
    vp->setFunction( "osgearth_overlay_vertex", vertexSource, ShaderComp::LOCATION_VERTEX_POST_LIGHTING );

    // fragment shader - subgraph
    buf.str("");
    buf << "#version 110 \n"
        << "uniform sampler2D osgearth_overlay_ProjTex; \n";

    if ( _useWarping )
    {
        buf << "uniform float warp; \n"

            // because the built-in pow() is busted
            << "float mypow( in float x, in float y ) \n"
            << "{ \n"
            << "    return x/(x+y-y*x); \n"
            << "} \n"

            << "vec2 warpTexCoord( in vec2 src ) \n"
            << "{ \n"
            //      incoming tex coord is [0..1], so we scale to [-1..1]
            << "    vec2 srcn = vec2( src.x*2.0 - 1.0, src.y*2.0 - 1.0 ); \n" 

            //      we want to work in the [0..1] space on each side of 0, so can the abs
            //      and store the signs for later:
            << "    vec2 srct = vec2( abs(srcn.x), abs(srcn.y) ); \n"
            << "    vec2 sign = vec2( srcn.x > 0.0 ? 1.0 : -1.0, srcn.y > 0.0 ? 1.0 : -1.0 ); \n"

            //      apply the deformation using a deceleration curve:
            << "    vec2 srcp = vec2( 1.0-mypow(1.0-srct.x,warp), 1.0-mypow(1.0-srct.y,warp) ); \n"

            //      reapply the sign, and scale back to [0..1]:
            << "    vec2 srcr = vec2( sign.x*srcp.x, sign.y*srcp.y ); \n"
            << "    return vec2( 0.5*(srcr.x + 1.0), 0.5*(srcr.y + 1.0) ); \n"
            << "} \n";
    }

    buf << "void osgearth_overlay_fragment( inout vec4 color ) \n"
        << "{ \n"
        << "    vec2 texCoord = gl_TexCoord["<< *_textureUnit << "].xy / gl_TexCoord["<< *_textureUnit << "].q; \n";

    if ( _useWarping && !_visualizeWarp )
        buf  << "    texCoord = warpTexCoord( texCoord ); \n";

    buf << "    vec4 texel = texture2D(osgearth_overlay_ProjTex, texCoord); \n"  
        << "    color = vec4( mix( color.rgb, texel.rgb, texel.a ), color.a); \n"
        << "} \n";

    std::string fragmentSource = buf.str();
    vp->setFunction( "osgearth_overlay_fragment", fragmentSource, ShaderComp::LOCATION_FRAGMENT_PRE_LIGHTING );
}

Here is the call graph for this function:

Here is the caller graph for this function:

void OverlayDecorator::onInstall ( TerrainEngineNode engine) [virtual]

Reimplemented from osgEarth::TerrainDecorator.

Definition at line 576 of file OverlayDecorator.cpp.

{
    _engine = engine;

    // establish the earth's major axis:
    MapInfo info(engine->getMap());
    _isGeocentric = info.isGeocentric();
    _ellipsoid = info.getProfile()->getSRS()->getEllipsoid();

    // the maximum extent (for projected maps only)
    if ( !_isGeocentric )
    {
        const GeoExtent& extent = info.getProfile()->getExtent();
        _maxProjectedMapExtent = osg::maximum( extent.width(), extent.height() );
    }

    // see whether we want shader support:
    // TODO: this is not stricty correct; you might still want to use shader overlays
    // in multipass mode, AND you might want FFP overlays in multitexture-FFP mode.
    _useShaders = engine->getTextureCompositor()->usesShaderComposition();

    if ( !_textureSize.isSet() )
    {
        unsigned maxSize = Registry::instance()->getCapabilities().getMaxFastTextureSize();
        _textureSize.init( osg::minimum( 4096u, maxSize ) );

        OE_INFO << LC << "Using texture size = " << *_textureSize << std::endl;
    }

    // rebuild dynamic elements.
    reinit();
}

Here is the call graph for this function:

void OverlayDecorator::onUninstall ( TerrainEngineNode engine) [virtual]

Reimplemented from osgEarth::TerrainDecorator.

Definition at line 610 of file OverlayDecorator.cpp.

{
    if ( !_explicitTextureUnit.isSet() && _textureUnit.isSet() )
    {
        _engine->getTextureCompositor()->releaseTextureImageUnit( *_textureUnit );
        _textureUnit.unset();
    }

    _engine = 0L;
}

Here is the call graph for this function:

void OverlayDecorator::reinit ( ) [private]

Definition at line 232 of file OverlayDecorator.cpp.

{
    if ( !_engine.valid() ) return;

    if ( _overlayGraph.valid() )
    {
        // apply the user-request texture unit, if applicable:
        if ( _explicitTextureUnit.isSet() )
        {
            if ( !_textureUnit.isSet() || *_textureUnit != *_explicitTextureUnit )
            {
                _textureUnit = *_explicitTextureUnit;
            }
        }

        // otherwise, automatically allocate a texture unit if necessary:
        else if ( !_textureUnit.isSet() && _useShaders )
        {
            int texUnit;
            if ( _engine->getTextureCompositor()->reserveTextureImageUnit( texUnit ) )
            {
                _textureUnit = texUnit;
                OE_INFO << LC << "Reserved texture image unit " << *_textureUnit << std::endl;
            }
            else
            {
                OE_WARN << LC << "Uh oh, no texture image units available." << std::endl;
            }
        }

        if ( _textureUnit.isSet() )
        {
            _projTexture = new osg::Texture2D();
            _projTexture->setTextureSize( *_textureSize, *_textureSize );
            _projTexture->setInternalFormat( GL_RGBA8 );
            _projTexture->setSourceFormat( GL_RGBA );
            _projTexture->setSourceType( GL_UNSIGNED_BYTE );
            _projTexture->setFilter( osg::Texture::MIN_FILTER, _mipmapping? osg::Texture::LINEAR_MIPMAP_LINEAR : osg::Texture::LINEAR );
            _projTexture->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );
            _projTexture->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_BORDER );
            _projTexture->setWrap( osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_BORDER );
            _projTexture->setWrap( osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_BORDER );
            _projTexture->setBorderColor( osg::Vec4(0,0,0,0) );

            // set up the RTT camera:
            _rttCamera = new osg::Camera();
            _rttCamera->setClearColor( osg::Vec4f(0,0,0,0) );
            // this ref frame causes the RTT to inherit its viewpoint from above (in order to properly
            // process PagedLOD's etc. -- it doesn't affect the perspective of the RTT camera though)
            _rttCamera->setReferenceFrame( osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT );
            _rttCamera->setViewport( 0, 0, *_textureSize, *_textureSize );
            _rttCamera->setComputeNearFarMode( osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR );
            _rttCamera->setRenderOrder( osg::Camera::PRE_RENDER );
            _rttCamera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
            _rttCamera->attach( osg::Camera::COLOR_BUFFER, _projTexture.get(), 0, 0, _mipmapping );
            _rttCamera->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );

            if ( _rttBlending )
            {
                osg::BlendFunc* blendFunc = new osg::BlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
                _rttCamera->getOrCreateStateSet()->setAttributeAndModes(blendFunc, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
            }
            else
            {
                _rttCamera->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);
            }
            //Enable blending on the RTT camera with pre-multiplied alpha.
            //osg::BlendFunc* blendFunc = new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
                

            // texture coordinate generator:
            _texGenNode = new osg::TexGenNode();
            _texGenNode->setTextureUnit( *_textureUnit );
            _texGenNode->getTexGen()->setMode( osg::TexGen::EYE_LINEAR );
            
            // attach the overlay graph to the RTT camera.
            if ( _overlayGraph.valid() && ( _overlayGraph->getNumParents() == 0 || _overlayGraph->getParent(0) != _rttCamera.get() ))
            {
                if ( _rttCamera->getNumChildren() > 0 )
                    _rttCamera->replaceChild( 0, _overlayGraph.get() );
                else
                    _rttCamera->addChild( _overlayGraph.get() );
            }
        }
    }

    // assemble the subgraph stateset:
    _subgraphStateSet = new osg::StateSet();

    if ( _overlayGraph.valid() && _textureUnit.isSet() )
    {
        // set up the subgraph to receive the projected texture:
        _subgraphStateSet->setTextureMode( *_textureUnit, GL_TEXTURE_GEN_S, osg::StateAttribute::ON );
        _subgraphStateSet->setTextureMode( *_textureUnit, GL_TEXTURE_GEN_T, osg::StateAttribute::ON );
        _subgraphStateSet->setTextureMode( *_textureUnit, GL_TEXTURE_GEN_R, osg::StateAttribute::ON );
        _subgraphStateSet->setTextureMode( *_textureUnit, GL_TEXTURE_GEN_Q, osg::StateAttribute::ON );
        _subgraphStateSet->setTextureAttributeAndModes( *_textureUnit, _projTexture.get(), osg::StateAttribute::ON );

        // decalling (note: this has no effect when using shaders.. remove? -gw)
        //osg::TexEnv* env = new osg::TexEnv();
        //env->setMode( osg::TexEnv::DECAL );
        //_subgraphStateSet->setTextureAttributeAndModes( *_textureUnit, env, osg::StateAttribute::ON );
        
        // set up the shaders
        if ( _useShaders )
        {            
            initSubgraphShaders( _subgraphStateSet.get() );
            initRTTShaders( _rttCamera->getOrCreateStateSet() );

            _warpUniform = this->getOrCreateStateSet()->getOrCreateUniform( "warp", osg::Uniform::FLOAT );
            _warpUniform->set( 1.0f );
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void OverlayDecorator::setMipmapping ( bool  value)

Whether mipmapping is enabled on the projected overlay texture. Mapmapping will improve the visual appearance, but will use more memory, and may affect performance for overlays that are dynamic.

Definition at line 537 of file OverlayDecorator.cpp.

{
    if ( value != _mipmapping )
    {
        _mipmapping = value;
        reinit();

        if ( _mipmapping )
            OE_INFO << LC << "Overlay mipmapping " << (value?"enabled":"disabled") << std::endl;
    }
}

Here is the call graph for this function:

void OverlayDecorator::setOverlayBlending ( bool  value)

Whether to enable blending on the RTT camera graph. Default = true. You might want to disable this is you are draping polygons that cover a very large area and curve around the globe; sometimes they suffer from tessellation artifacts when draped.

Definition at line 563 of file OverlayDecorator.cpp.

{
    if ( value != _rttBlending )
    {
        _rttBlending = value;
        reinit();
        
        if ( _rttBlending )
            OE_INFO << LC << "Overlay blending " << (value?"enabled":"disabled")<< std::endl;
    }
}

Here is the call graph for this function:

void OverlayDecorator::setOverlayGraph ( osg::Node *  node)

The scene graph to be sampled an overlaid on the terrain.

Definition at line 498 of file OverlayDecorator.cpp.

{
    if ( _overlayGraph.get() != node )
    {
        if ( _overlayGraph.valid() && node == 0L )
        {
            ADJUST_UPDATE_TRAV_COUNT( this, -1 );
        }
        else if ( !_overlayGraph.valid() && node != 0L )
        {
            ADJUST_UPDATE_TRAV_COUNT( this, 1 );
        }

        _overlayGraph = node;
        reinit();
    }
}

Here is the call graph for this function:

void OverlayDecorator::setTextureSize ( int  texSize)

The size (resolution in both directions) of the overlay texture. By default, this defaults to 4096 or your hardware's maximum supported texture size, whichever is less.

Definition at line 517 of file OverlayDecorator.cpp.

{
    if ( texSize != _textureSize.value() )
    {
        _textureSize = texSize;
        reinit();
    }
}

Here is the call graph for this function:

void OverlayDecorator::setTextureUnit ( int  unit)

Explicity sets the texture unit to use. Note! When you add this class to a MapNode, it will automatically allocate a free texture unit; so you usually do NOT need to call this method.

Definition at line 527 of file OverlayDecorator.cpp.

{
    if ( !_explicitTextureUnit.isSet() || texUnit != _explicitTextureUnit.value() )
    {
        _explicitTextureUnit = texUnit;
        reinit();
    }
}

Here is the call graph for this function:

void OverlayDecorator::setVertexWarping ( bool  value)

Whether to employ overlay warping. Warping can help increase the apparent resolution of the overlay image. But it can cause artifacts when you zoom in very close. Default = true

Definition at line 550 of file OverlayDecorator.cpp.

{
    if ( value != _useWarping )
    {
        _useWarping = value;
        reinit();
        
        if ( _useWarping )
            OE_INFO << LC << "Vertex warping " << (value?"enabled":"disabled")<< std::endl;
    }
}

Here is the call graph for this function:

void OverlayDecorator::traverse ( osg::NodeVisitor &  nv)

Definition at line 883 of file OverlayDecorator.cpp.

{
    bool isCull = nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR;

    if ( _overlayGraph.valid() && _textureUnit.isSet() )
    {
        if ( isCull )
        {
            osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>( &nv );
            if ( cv )
            {
                cull( cv );
            }
            _rttCamera->accept( nv );
            
            // note: texgennode doesn't need a cull, and the subgraph
            // is traversed in cull().
        }

        else
        {
            if ( nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR )
            {
                updateRTTCamera( nv );
            }
            _rttCamera->accept( nv );
            _texGenNode->accept( nv );

            osg::Group::traverse( nv );
        }    
    }
    else
    {
        osgUtil::CullVisitor* cv = 0L;
        if ( isCull )
            cv = dynamic_cast<osgUtil::CullVisitor*>( &nv );

        if ( cv )
            cv->pushStateSet( _subgraphStateSet.get() );

        osg::Group::traverse( nv );

        if ( cv )
            cv->popStateSet();
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void OverlayDecorator::updateRTTCamera ( osg::NodeVisitor &  nv) [private]

Definition at line 622 of file OverlayDecorator.cpp.

{
    static osg::Matrix normalizeMatrix = 
        osg::Matrix::translate(1.0,1.0,1.0) * osg::Matrix::scale(0.5,0.5,0.5);

    // configure the RTT camera:
    _rttCamera->setViewMatrix( _rttViewMatrix );
    _rttCamera->setProjectionMatrix( _rttProjMatrix );

    osg::Matrix MVPT = _projectorViewMatrix * _projectorProjMatrix * normalizeMatrix;

    //_texGenNode->getTexGen()->setMode( osg::TexGen::EYE_LINEAR ); // moved to initialization
    _texGenNode->getTexGen()->setPlanesFromMatrix( MVPT );
    
    // uniform update:
    if ( _useShaders )
    {
        _texGenUniform->set( MVPT );
        if ( _useWarping )
            _warpUniform->set( _warp );
    }
}

Here is the caller graph for this function:


Member Data Documentation

osg::ref_ptr<const osg::EllipsoidModel> osgEarth::OverlayDecorator::_ellipsoid [private]

Definition at line 134 of file OverlayDecorator.

Definition at line 136 of file OverlayDecorator.

Definition at line 117 of file OverlayDecorator.

Definition at line 125 of file OverlayDecorator.

Definition at line 126 of file OverlayDecorator.

Definition at line 127 of file OverlayDecorator.

osg::ref_ptr<osg::Node> osgEarth::OverlayDecorator::_overlayGraph [private]

Definition at line 110 of file OverlayDecorator.

Definition at line 132 of file OverlayDecorator.

Definition at line 131 of file OverlayDecorator.

osg::ref_ptr<osg::Texture2D> osgEarth::OverlayDecorator::_projTexture [private]

Definition at line 112 of file OverlayDecorator.

Definition at line 128 of file OverlayDecorator.

osg::ref_ptr<osg::Camera> osgEarth::OverlayDecorator::_rttCamera [private]

Definition at line 111 of file OverlayDecorator.

Definition at line 130 of file OverlayDecorator.

Definition at line 129 of file OverlayDecorator.

osg::ref_ptr<osg::StateSet> osgEarth::OverlayDecorator::_subgraphStateSet [private]

Definition at line 116 of file OverlayDecorator.

osg::ref_ptr<osg::TexGenNode> osgEarth::OverlayDecorator::_texGenNode [private]

Definition at line 113 of file OverlayDecorator.

osg::ref_ptr<osg::Uniform> osgEarth::OverlayDecorator::_texGenUniform [private]

Definition at line 114 of file OverlayDecorator.

Definition at line 119 of file OverlayDecorator.

Definition at line 118 of file OverlayDecorator.

Definition at line 120 of file OverlayDecorator.

Definition at line 121 of file OverlayDecorator.

Definition at line 124 of file OverlayDecorator.

Definition at line 135 of file OverlayDecorator.

Definition at line 122 of file OverlayDecorator.

Definition at line 123 of file OverlayDecorator.

osg::ref_ptr<osg::Uniform> osgEarth::OverlayDecorator::_warpUniform [private]

Definition at line 115 of file OverlayDecorator.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines