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

osgEarth::Util::OceanSurfaceNode Class Reference

Collaboration diagram for osgEarth::Util::OceanSurfaceNode:

List of all members.

Public Member Functions

 OceanSurfaceNode ()
void setOceanMaskImageLayer (const ImageLayer *layer)
const ImageLayergetOceanMaskImageLayer () const
float getWaveHeight () const
void setWaveHeight (float waveHeight)
float getMaxRange () const
void setMaxRange (float maxRange)
float getPeriod () const
void setPeriod (float period)
bool getEnabled () const
void setEnabled (bool enabled)
bool getInvertMask () const
void setInvertMask (bool invertMask)
void setModulationColor (const osg::Vec4f &color)
osg::Vec4f getModulationColor () const
float getOceanAnimationPeriod () const
void setOceanAnimationPeriod (float oceanAnimationPeriod)
osg::Image * getOceanSurfaceImage () const
void setOceanSurfaceImage (osg::Image *image)
float getOceanSurfaceImageSizeRadians () const
void setOceanSurfaceImageSizeRadians (float size)
void setAdjustToMSL (bool adjustToMSL)
bool getAdjustToMSL () const
virtual void traverse (osg::NodeVisitor &nv)

Private Member Functions

void rebuildShaders ()
void shadersDirty (bool value)

Private Attributes

bool _shadersDirty
float _maxRange
UID _oceanMaskLayerUID
int _oceanSurfaceTextureUnit
bool _oceanSurfaceTextureApplied
float _waveHeight
float _period
bool _enabled
bool _invertMask
bool _adjustToMSL
osg::observer_ptr
< osg::CoordinateSystemNode > 
_csn
optional< osg::Vec4f > _oceanColor
float _oceanAnimationPeriod
float _oceanSurfaceImageSizeRadians
osg::ref_ptr< osg::Image > _oceanSurfaceImage
osg::ref_ptr< osg::Texture3D > _oceanSurfaceTexture
osg::observer_ptr< const
ImageLayer
_maskLayer

Detailed Description

OceanSurfaceNode is a decorator node that animates the surface of the globe to simulate simple waves. Note: This only works with multitextured maps, not multipass.

Definition at line 38 of file OceanSurfaceNode.


Constructor & Destructor Documentation

OceanSurfaceNode::OceanSurfaceNode ( )

Creates a new OceanSurfaceNode

Definition at line 43 of file OceanSurfaceNode.cpp.

                                   :
_shadersDirty(false),
_maxRange(800000),
_oceanMaskLayerUID(-1),
_oceanSurfaceTextureUnit(-1),
_oceanSurfaceTextureApplied(false),
_waveHeight(100),
_period(1024),
_enabled(true),
_invertMask(false),
_adjustToMSL(true),
_oceanColor(osg::Vec4f(0,0,1,0)),
_oceanAnimationPeriod(6.0),
_oceanSurfaceImageSizeRadians(osg::PI/500.0)
{
    rebuildShaders();
 
    getOrCreateStateSet()->getOrCreateUniform("osgearth_OceanPeriod", osg::Uniform::FLOAT)->set(_period);   
    getOrCreateStateSet()->getOrCreateUniform("osgearth_OceanAnimationPeriod", osg::Uniform::FLOAT)->set(_oceanAnimationPeriod); 

    osg::Uniform* oceanHeightUniform = getOrCreateStateSet()->getOrCreateUniform("osgearth_OceanHeight", osg::Uniform::FLOAT);
    oceanHeightUniform->set( _waveHeight);
    oceanHeightUniform->setDataVariance( osg::Object::DYNAMIC);

    //Initialize the ocean surface texture
    _oceanSurfaceTexture = new osg::Texture3D();
    _oceanSurfaceTexture->setWrap(osg::Texture::WRAP_S,osg::Texture::REPEAT);
    _oceanSurfaceTexture->setWrap(osg::Texture::WRAP_T,osg::Texture::REPEAT);
    _oceanSurfaceTexture->setWrap(osg::Texture::WRAP_R,osg::Texture::REPEAT);
    _oceanSurfaceTexture->setFilter(osg::Texture3D::MIN_FILTER,osg::Texture3D::LINEAR);
    _oceanSurfaceTexture->setFilter(osg::Texture3D::MAG_FILTER,osg::Texture3D::LINEAR);
}

Here is the call graph for this function:


Member Function Documentation

bool OceanSurfaceNode::getAdjustToMSL ( ) const

Gets whether or not to adjust the height of the ocean to always be at MSL 0 and ignore the current vert height

Definition at line 97 of file OceanSurfaceNode.cpp.

{
        return _adjustToMSL;
}
bool OceanSurfaceNode::getEnabled ( ) const

Gets whether the ocean effect is enabled

Definition at line 181 of file OceanSurfaceNode.cpp.

{
    return _enabled;
}
bool OceanSurfaceNode::getInvertMask ( ) const

Gets whether to invert the mask ocean mask.

Definition at line 197 of file OceanSurfaceNode.cpp.

{
    return _invertMask;
}
float OceanSurfaceNode::getMaxRange ( ) const

Gets the range at which the effect starts to show.

Definition at line 148 of file OceanSurfaceNode.cpp.

{
    return _maxRange;
}
osg::Vec4f OceanSurfaceNode::getModulationColor ( ) const

Definition at line 223 of file OceanSurfaceNode.cpp.

{
    return _oceanColor.value();
}

Here is the call graph for this function:

float OceanSurfaceNode::getOceanAnimationPeriod ( ) const

Gets the period of the ocean animation effect in seconds

Definition at line 229 of file OceanSurfaceNode.cpp.

const ImageLayer* osgEarth::Util::OceanSurfaceNode::getOceanMaskImageLayer ( ) const [inline]

Gets the image layer being used as an ocean mask.

Definition at line 54 of file OceanSurfaceNode.

{ return _maskLayer.get(); }
osg::Image * OceanSurfaceNode::getOceanSurfaceImage ( ) const

Gets the ocean surface image to the given 3D image.

Definition at line 113 of file OceanSurfaceNode.cpp.

{
    return _oceanSurfaceImage.get();
}
float OceanSurfaceNode::getOceanSurfaceImageSizeRadians ( ) const

Gets the size of the ocean surface image in radians

Definition at line 246 of file OceanSurfaceNode.cpp.

float OceanSurfaceNode::getPeriod ( ) const

Gets the period of the wave

Definition at line 164 of file OceanSurfaceNode.cpp.

{
    return _period;
}
float OceanSurfaceNode::getWaveHeight ( ) const

Gets the wave height

Definition at line 131 of file OceanSurfaceNode.cpp.

{
    return _waveHeight;
}
void OceanSurfaceNode::rebuildShaders ( ) [private]

Definition at line 276 of file OceanSurfaceNode.cpp.

{
    // need the terrain engine so we can get at the compositor.
    TerrainEngineNode* engine = osgEarth::findTopMostNodeOfType<TerrainEngineNode>( this );
    if ( !engine ) {
        OE_DEBUG << LC << "No terrain engine found in the map node; abort" << std::endl;
        return;
    }

    // access the compositor because we are going to be sampling map layers.
    TextureCompositor* comp = engine->getTextureCompositor();
    if ( !comp ) {
        OE_INFO << LC << "No texture compositor found in the terrain engine; abort" << std::endl;
        return;
    }

    // reserve a texture unit for the surface texture (if we haven't already)
    if ( !_oceanSurfaceTextureApplied && _oceanSurfaceTextureUnit < 0 && _oceanSurfaceTexture.valid() )
    {
        if ( comp->reserveTextureImageUnit( _oceanSurfaceTextureUnit ) )
        {
            getOrCreateStateSet()->setTextureAttributeAndModes(
                _oceanSurfaceTextureUnit, _oceanSurfaceTexture.get(), osg::StateAttribute::ON);
            _oceanSurfaceTextureApplied = true;
        }
        else
        {
            OE_WARN << LC << "Sorry, failed to allocate a texture image unit for the surface texture." << std::endl;
        }
    }

    // create a VP to store our custom shader components.
    osgEarth::VirtualProgram* vp = new osgEarth::VirtualProgram();
    getOrCreateStateSet()->setAttributeAndModes( vp, osg::StateAttribute::ON );

    // if the ocean is disabled, just return without injecting any shaders.
    if ( !_enabled )
        return;

    // build the sampler function if necessary
    osg::ref_ptr<const ImageLayer> safeMaskLayer = _maskLayer.get();
    osg::Shader* maskSampler = 0L;
    if ( safeMaskLayer.valid() )
    {
        maskSampler = comp->createSamplerFunction( safeMaskLayer->getUID(), MASK_SAMPLER_FUNC, osg::Shader::VERTEX );        
        if ( maskSampler )
            vp->setShader( MASK_SAMPLER_FUNC, maskSampler );
    }

    // make the helper functions.
    {
        std::stringstream buf;

        buf << "vec3 xyz_to_lat_lon_height(in vec3 xyz) \n"
            << "{ \n"
            << "    float X = xyz.x;\n"
            << "    float Y = xyz.y;\n"
            << "    float Z = xyz.z;\n"
            << "    float _radiusEquator = 6378137.0;\n"
            << "    float _radiusPolar   = 6356752.3142;\n"
            << "    float flattening = (_radiusEquator-_radiusPolar)/_radiusEquator;\n"
            << "    float _eccentricitySquared = 2.0*flattening - flattening*flattening;\n"
            << "    float p = sqrt(X*X + Y*Y);\n"
            << "    float theta = atan(Z*_radiusEquator , (p*_radiusPolar));\n"
            << "    float eDashSquared = (_radiusEquator*_radiusEquator - _radiusPolar*_radiusPolar)/(_radiusPolar*_radiusPolar);\n"
            << "    float sin_theta = sin(theta);\n"
            << "    float cos_theta = cos(theta);\n"
            << "    float latitude = atan( (Z + eDashSquared*_radiusPolar*sin_theta*sin_theta*sin_theta), (p - _eccentricitySquared*_radiusEquator*cos_theta*cos_theta*cos_theta) );\n"
            << "    float longitude = atan(Y,X);\n"
            << "    float sin_latitude = sin(latitude);\n"
            << "    float N = _radiusEquator / sqrt( 1.0 - _eccentricitySquared*sin_latitude*sin_latitude);\n"
            << "    float height = p/cos(latitude) - N;\n"
            << "    return vec3(longitude, latitude, height);\n"
            << "} \n"
            << "\n";

        std::string str = buf.str();
        vp->setShader( "xyz_to_lat_lon_height", new osg::Shader(osg::Shader::VERTEX, str) );
    }

    // next make the vertex shader function that will morph the ocean verts and prepare
    // the texture coordinates for the surface effects.
    {
        std::stringstream buf;

        buf << std::fixed;

        buf << "uniform float osg_SimulationTime; \n"
            << "uniform mat4  osg_ViewMatrixInverse;\n"
            << "uniform mat4  osg_ViewMatrix;\n"
            << "uniform float osgearth_OceanHeight;\n"
            << "uniform float osgearth_OceanPeriod;\n"
            << "uniform float osgearth_OceanAnimationPeriod;\n"
            << "varying float osgearth_OceanAlpha;\n"
            << "varying float osgearth_CameraRange; \n"

            << "vec3 xyz_to_lat_lon_height(in vec3 xyz); \n";

        if ( _oceanSurfaceTextureApplied )
        {
            buf << "varying vec3 osgearth_oceanSurfaceTexCoord; \n";
        }

        if ( maskSampler )
        {
            buf << "vec4 " << MASK_SAMPLER_FUNC << "(); \n";
        }

        buf << "void osgearth_ocean_morphSurface() \n"
            << "{ \n"
            << "   mat4 modelMatrix = osg_ViewMatrixInverse * gl_ModelViewMatrix; \n"
            << "   vec4 vert = modelMatrix  * gl_Vertex; \n"           
            << "   vec3 vert3 = vec3(vert.x, vert.y, vert.z); \n"
            << "   vec3 latlon = xyz_to_lat_lon_height(vert3); \n"
            << "   osgearth_OceanAlpha = 1.0; \n";

        if ( maskSampler )
        {
            buf << "    osgearth_OceanAlpha = 1.0 - (" << MASK_SAMPLER_FUNC << "()).a; \n";
        }

        if ( _invertMask )
            buf << "    osgearth_OceanAlpha = 1.0 - osgearth_OceanAlpha; \n";

        buf << "   if ( osgearth_CameraRange <= " << _maxRange << " ) \n"
            << "   { \n"
            << "       float s = mix(1.0, 0.0, osgearth_CameraRange / " << _maxRange << "); \n" //Invert so it's between 0 and 1
            << "       osgearth_OceanAlpha *= s; \n"
            << "   } \n"
            << "   else \n"
            << "   { \n"
            << "        osgearth_OceanAlpha = 0.0; \n"
            << "   } \n"

            << "   if (osgearth_OceanAlpha > 0.0) \n"
            << "   { \n"
            << "       float PI_2 = 3.14158 * 2.0; \n"
            << "       float period = PI_2/osgearth_OceanPeriod; \n"
            << "       float half_period = period / 2.0; \n"
            << "       vec3 n = normalize(vert3);\n"
            << "       float theta = (mod(latlon.x, period) / period) * PI_2; \n"  
            << "       float phi = (mod(latlon.y, half_period) / half_period) * PI_2; \n"
            << "       float phase1 = osg_SimulationTime * 2.0; \n"
            << "       float phase2 = osg_SimulationTime * 4.0; \n"
            << "       float waveHeight = (osgearth_OceanAlpha) * osgearth_OceanHeight; \n"
            << "       float scale1 = sin(theta + phase1) * waveHeight; \n"
            << "       float scale2 = cos(phi + phase2) * waveHeight; \n"
            << "       float scale3 = sin(theta + phase2) * cos(phi + phase1) * waveHeight * 1.6; \n"
            << "       float scale = (scale1 + scale2 + scale3)/3.0; \n";

        // flatten verts to MSL:
        if ( _adjustToMSL )
        {
            buf << "        vec3 offset = n * -latlon.z; \n"
                << "        vert += vec4( offset.xyz, 0 ); \n";
        }

        // apply the save scale:
        buf << "       n = n * scale; \n"
            << "       vert += vec4(n.x, n.y,n.z,0); \n"
            << "       vert = osg_ViewMatrix * vert; \n"
            << "       gl_Position = gl_ProjectionMatrix * vert; \n"
            << "   }\n";

        // set up the coords for the surface texture:
        if ( _oceanSurfaceTextureApplied )
        {
            buf << "   osgearth_oceanSurfaceTexCoord.x =  latlon.x / " << _oceanSurfaceImageSizeRadians << "; \n"
                << "   osgearth_oceanSurfaceTexCoord.y =  latlon.y / " << _oceanSurfaceImageSizeRadians << "; \n"
                << "   osgearth_oceanSurfaceTexCoord.z = fract(osg_SimulationTime/osgearth_OceanAnimationPeriod); \n";
        }

        buf << "}\n";

        // add as a custom user function in the shader composition:
        std::string vertSource = buf.str();
        vp->setFunction( "osgearth_ocean_morphSurface", vertSource, osgEarth::ShaderComp::LOCATION_VERTEX_PRE_TEXTURING );
    }
    
    // now we need a fragment function that will apply the ocean surface texture.
    if ( _oceanSurfaceTextureApplied )
    {
        getOrCreateStateSet()->getOrCreateUniform( "osgearth_oceanSurfaceTex", osg::Uniform::SAMPLER_3D )->set( _oceanSurfaceTextureUnit );

        std::stringstream buf;

        buf << "uniform sampler3D osgearth_oceanSurfaceTex; \n"
            << "varying vec3      osgearth_oceanSurfaceTexCoord; \n"
            << "varying float     osgearth_OceanAlpha; \n"

            << "void osgearth_ocean_applySurfaceTex( inout vec4 color ) \n"
            << "{ \n"
            << "    vec4 texel = texture3D(osgearth_oceanSurfaceTex, osgearth_oceanSurfaceTexCoord); \n"
            << "    color = vec4( mix( color.rgb, texel.rgb, texel.a * osgearth_OceanAlpha ), color.a); \n"
            << "} \n";

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

Here is the call graph for this function:

Here is the caller graph for this function:

void OceanSurfaceNode::setAdjustToMSL ( bool  adjustToMSL)

Sets whether or not to adjust the height of the ocean to always be at MSL 0 and ignore the current vert height

Definition at line 103 of file OceanSurfaceNode.cpp.

{
        if (_adjustToMSL != adjustToMSL)
        {
                _adjustToMSL = adjustToMSL;
        shadersDirty( true );
        }
}

Here is the call graph for this function:

void OceanSurfaceNode::setEnabled ( bool  enabled)

Sets whether the ocean effect is enabled

Definition at line 187 of file OceanSurfaceNode.cpp.

{
    if (_enabled != enabled)
    {
        _enabled = enabled;
        shadersDirty(true);
    }
}

Here is the call graph for this function:

void OceanSurfaceNode::setInvertMask ( bool  invertMask)

Sets whether to invert the mask ocean mask. Normally, transparant areas are considered ocean. When inverted, transparent areas are considered land.

Definition at line 203 of file OceanSurfaceNode.cpp.

{
    if (_invertMask != invertMask)
    {
        _invertMask = invertMask;
        shadersDirty( true );
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void OceanSurfaceNode::setMaxRange ( float  maxRange)

Sets the max range at which the effect starts to show

Definition at line 154 of file OceanSurfaceNode.cpp.

{
    if (_maxRange != maxRange)
    {
        _maxRange = maxRange;
        shadersDirty(true);
    }
}

Here is the call graph for this function:

void OceanSurfaceNode::setModulationColor ( const osg::Vec4f &  color)

Sets an optional ocean color. The ocean will take on this color based on the alpha values in the masking texture.

Definition at line 213 of file OceanSurfaceNode.cpp.

{
    if ( !_oceanColor.isSetTo( color ) )
    {
        _oceanColor = color;
        shadersDirty( true );
    }
}

Here is the call graph for this function:

void OceanSurfaceNode::setOceanAnimationPeriod ( float  oceanAnimationPeriod)

Sets the period of the ocean animation effect in seconds

Definition at line 235 of file OceanSurfaceNode.cpp.

{
    if (_oceanAnimationPeriod != oceanAnimationPeriod)
    {
        _oceanAnimationPeriod = oceanAnimationPeriod;
        getOrCreateStateSet()->getOrCreateUniform("osgearth_OceanAnimationPeriod", osg::Uniform::FLOAT)->set(oceanAnimationPeriod); 
        //TODO: consider rebuildShaders() instead..
    }
}
void OceanSurfaceNode::setOceanMaskImageLayer ( const ImageLayer layer)

Sets the image layer to use as an ocean mask.

Definition at line 87 of file OceanSurfaceNode.cpp.

{
    if ( _maskLayer.get() != layer )
    {
        _maskLayer = layer;
        shadersDirty(true);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void OceanSurfaceNode::setOceanSurfaceImage ( osg::Image *  image)

Sets the ocean surface image to the given 3D image.

Definition at line 119 of file OceanSurfaceNode.cpp.

{
    if (_oceanSurfaceImage.get() != image)
    {
        _oceanSurfaceImage = image;
        _oceanSurfaceTexture->setImage( _oceanSurfaceImage.get() );
        
        shadersDirty( true );
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void OceanSurfaceNode::setOceanSurfaceImageSizeRadians ( float  size)

Sets the size of the ocean surface image in radians

Definition at line 252 of file OceanSurfaceNode.cpp.

Here is the call graph for this function:

void OceanSurfaceNode::setPeriod ( float  period)

Sets the period of the wave

Definition at line 170 of file OceanSurfaceNode.cpp.

{
    if (_period !=period)
    {
        _period = period;
        getOrCreateStateSet()->getOrCreateUniform("osgearth_OceanPeriod", osg::Uniform::FLOAT)->set(_period); 
        //TODO: consider rebuildShaders() instead..    
    }
}
void OceanSurfaceNode::setWaveHeight ( float  waveHeight)

Sets the wave height

Definition at line 137 of file OceanSurfaceNode.cpp.

{
    if (_waveHeight != waveHeight)
    {
        _waveHeight = waveHeight;
        getOrCreateStateSet()->getOrCreateUniform("osgearth_OceanHeight", osg::Uniform::FLOAT)->set(_waveHeight);
        //TODO: consider rebuildShaders() instead..
    }
}
void OceanSurfaceNode::shadersDirty ( bool  value) [private]

Definition at line 77 of file OceanSurfaceNode.cpp.

{
    if ( _shadersDirty != value )
    {
        _shadersDirty = value;
        ADJUST_UPDATE_TRAV_COUNT( this, _shadersDirty ? 1 : -1 );
    }
}

Here is the caller graph for this function:

void OceanSurfaceNode::traverse ( osg::NodeVisitor &  nv) [virtual]

Definition at line 262 of file OceanSurfaceNode.cpp.

{
    if ( _shadersDirty && nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR )
    {
        rebuildShaders();
        shadersDirty( false );
    }

    osg::Group::traverse( nv );
}

Here is the call graph for this function:


Member Data Documentation

Definition at line 172 of file OceanSurfaceNode.

osg::observer_ptr<osg::CoordinateSystemNode> osgEarth::Util::OceanSurfaceNode::_csn [private]

Definition at line 173 of file OceanSurfaceNode.

Definition at line 170 of file OceanSurfaceNode.

Definition at line 171 of file OceanSurfaceNode.

osg::observer_ptr< const ImageLayer > osgEarth::Util::OceanSurfaceNode::_maskLayer [private]

Definition at line 179 of file OceanSurfaceNode.

Definition at line 164 of file OceanSurfaceNode.

Definition at line 175 of file OceanSurfaceNode.

Definition at line 174 of file OceanSurfaceNode.

Definition at line 165 of file OceanSurfaceNode.

osg::ref_ptr< osg::Image > osgEarth::Util::OceanSurfaceNode::_oceanSurfaceImage [private]

Definition at line 177 of file OceanSurfaceNode.

Definition at line 176 of file OceanSurfaceNode.

osg::ref_ptr< osg::Texture3D > osgEarth::Util::OceanSurfaceNode::_oceanSurfaceTexture [private]

Definition at line 178 of file OceanSurfaceNode.

Definition at line 167 of file OceanSurfaceNode.

Definition at line 166 of file OceanSurfaceNode.

Definition at line 169 of file OceanSurfaceNode.

Definition at line 162 of file OceanSurfaceNode.

Definition at line 168 of file OceanSurfaceNode.


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