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

osgEarth::Util::SkyNode Class Reference

Collaboration diagram for osgEarth::Util::SkyNode:

List of all members.

Classes

struct  PerViewData
struct  StarData

Public Member Functions

 SkyNode (Map *map, const std::string &starFile="")
void attach (osg::View *view, int lightNum=0)
void setSunPosition (const osg::Vec3 &pos, osg::View *view=0L)
void setSunPosition (double lat_degrees, double lon_degrees, osg::View *view=0L)
void setDateTime (int year, int month, int date, double hoursUTC, osg::View *view=0L)
void setAmbientBrightness (float value, osg::View *view=0L)
float getAmbientBrightness (osg::View *view=0L) const
void setStarsVisible (bool value, osg::View *view=0L)
bool getStarsVisible (osg::View *view=0L) const
virtual void traverse (osg::NodeVisitor &nv)
virtual osg::BoundingSphere computeBound () const

Private Types

typedef std::map< osg::View
*, PerViewData
PerViewDataMap

Private Member Functions

void makeAtmosphere (const osg::EllipsoidModel *)
void makeSun ()
void makeStars (const std::string &starFile)
osg::Geode * buildStarGeometry (const std::vector< StarData > &stars)
void getDefaultStars (std::vector< StarData > &out_stars)
bool parseStarFile (const std::string &starFile, std::vector< StarData > &out_stars)
void setAmbientBrightness (PerViewData &data, float value)
void setSunPosition (PerViewData &data, const osg::Vec3 &pos)

Private Attributes

PerViewData _defaultPerViewData
PerViewDataMap _perViewData
float _innerRadius
float _outerRadius
float _sunDistance
float _starRadius
osg::ref_ptr< osg::Node > _sun
osg::ref_ptr< osg::Node > _stars
osg::ref_ptr< osg::Node > _atmosphere
osg::ref_ptr< osg::Uniform > _starAlpha
osg::ref_ptr< osg::Uniform > _starPointSize
osg::ref_ptr< const
osg::EllipsoidModel > 
_ellipsoidModel

Detailed Description

A sky model.

Definition at line 36 of file SkyNode.


Member Typedef Documentation

typedef std::map<osg::View*, PerViewData> osgEarth::Util::SkyNode::PerViewDataMap [private]

Definition at line 97 of file SkyNode.


Constructor & Destructor Documentation

SkyNode::SkyNode ( Map map,
const std::string &  starFile = "" 
)

Creates a new sky node based on the provided map.

Definition at line 583 of file SkyNode.cpp.

{
    // intialize the default settings:
    _defaultPerViewData._lightPos.set( osg::Vec3f(0.0f, 1.0f, 0.0f) );
    _defaultPerViewData._light = new osg::Light( 0 );  
    _defaultPerViewData._light->setPosition( osg::Vec4( _defaultPerViewData._lightPos, 0 ) );
    _defaultPerViewData._light->setAmbient( osg::Vec4(0.4f, 0.4f, 0.4f ,1.0) );
    _defaultPerViewData._light->setDiffuse( osg::Vec4(1,1,1,1) );
    _defaultPerViewData._light->setSpecular( osg::Vec4(0,0,0,1) );
    _defaultPerViewData._starsVisible = true;
    
    // set up the astronomical parameters:
    _ellipsoidModel =  map->getProfile()->getSRS()->getGeographicSRS()->getEllipsoid();
    _innerRadius = _ellipsoidModel->getRadiusPolar();
    _outerRadius = _innerRadius * 1.025f;
    _sunDistance = _innerRadius * 12000.0f;

    // make the ephemeris (note: order is important here)
    makeAtmosphere( _ellipsoidModel.get() );
    makeSun();
    makeStars(starFile);
}

Here is the call graph for this function:


Member Function Documentation

void SkyNode::attach ( osg::View *  view,
int  lightNum = 0 
)

Attached this sky node to a view (placing a sky light).

Definition at line 640 of file SkyNode.cpp.

{
    if ( !view ) return;

    // creates the new per-view if it does not already exist
    PerViewData& data = _perViewData[view];

    data._light = osg::clone( _defaultPerViewData._light.get() );
    data._light->setLightNum( lightNum );
    data._light->setAmbient( _defaultPerViewData._light->getAmbient() );
    data._lightPos = _defaultPerViewData._lightPos;

    // the cull callback has to be on a parent group-- won't work on the xforms themselves.
    data._cullContainer = new osg::Group();

    data._sunXform = new osg::MatrixTransform();
    data._sunMatrix = osg::Matrixd::translate(
        _sunDistance * data._lightPos.x(),
        _sunDistance * data._lightPos.y(),
        _sunDistance * data._lightPos.z() );
    data._sunXform->setMatrix( data._sunMatrix );
    data._sunXform->addChild( _sun.get() );
    data._cullContainer->addChild( data._sunXform.get() );

    data._starsXform = new osg::MatrixTransform();
    data._starsMatrix = _defaultPerViewData._starsMatrix;
    data._starsXform->setMatrix( _defaultPerViewData._starsMatrix );
    data._starsXform->addChild( _stars.get() );
    data._cullContainer->addChild( data._starsXform.get() );

    data._starsVisible = true;

    data._cullContainer->addChild( _atmosphere.get() );
    data._lightPosUniform = osg::clone( _defaultPerViewData._lightPosUniform.get() );

    view->setLightingMode( osg::View::SKY_LIGHT );
    view->setLight( data._light.get() );
    view->getCamera()->setClearColor( osg::Vec4(0,0,0,1) );
}

Here is the caller graph for this function:

osg::Geode * SkyNode::buildStarGeometry ( const std::vector< StarData > &  stars) [private]

Definition at line 989 of file SkyNode.cpp.

{
  double minMag = DBL_MAX, maxMag = DBL_MIN;

  osg::Vec3Array* coords = new osg::Vec3Array();
  std::vector<StarData>::const_iterator p;
  for( p = stars.begin(); p != stars.end(); p++ )
  {
    osg::Vec3 v = osg::Vec3(0,_starRadius,0) * 
      osg::Matrix::rotate( p->declination, 1, 0, 0 ) * 
      osg::Matrix::rotate( p->right_ascension, 0, 0, 1 );

    coords->push_back( v );

    if ( p->magnitude < minMag ) minMag = p->magnitude;
    if ( p->magnitude > maxMag ) maxMag = p->magnitude;
  }

  osg::Vec4Array* colors = new osg::Vec4Array();
  for( p = stars.begin(); p != stars.end(); p++ )
  {
      //float c = 0.5f + 0.5f * ( (p->magnitude-minMag) / (maxMag-minMag) );
      float c = ( (p->magnitude-minMag) / (maxMag-minMag) );
      colors->push_back( osg::Vec4(c,c,c,1.0f) );
  }

  osg::Geometry* geometry = new osg::Geometry;
  geometry->setUseVertexBufferObjects( true );
  geometry->setVertexArray( coords );
  geometry->setColorArray( colors );
  geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
  geometry->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, coords->size()));

  osg::StateSet* sset = new osg::StateSet;

  sset->setMode( GL_VERTEX_PROGRAM_POINT_SIZE, osg::StateAttribute::ON );
  osg::Program* program = new osg::Program;
  program->addShader( new osg::Shader(osg::Shader::VERTEX, s_starVertexSource) );
  program->addShader( new osg::Shader(osg::Shader::FRAGMENT, s_starFragmentSource) );
  sset->setAttributeAndModes( program, osg::StateAttribute::ON );

  sset->setRenderBinDetails( BIN_STARS, "RenderBin");
  sset->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS, 0, 1, false), osg::StateAttribute::ON );
  geometry->setStateSet( sset );

  osg::Geode* starGeode = new osg::Geode;
  starGeode->addDrawable( geometry );

  return starGeode;
}
osg::BoundingSphere SkyNode::computeBound ( ) const [virtual]

Definition at line 607 of file SkyNode.cpp.

{
    return osg::BoundingSphere();
}
float SkyNode::getAmbientBrightness ( osg::View *  view = 0L) const

Definition at line 697 of file SkyNode.cpp.

{
    if ( view )
    {
        PerViewDataMap::const_iterator i = _perViewData.find(view);
        if ( i != _perViewData.end() )
            return i->second._light->getAmbient().r();
    }
    return _defaultPerViewData._light->getAmbient().r();
}
void SkyNode::getDefaultStars ( std::vector< StarData > &  out_stars) [private]

Definition at line 1041 of file SkyNode.cpp.

{
  out_stars.clear();

  for(const char **sptr = s_defaultStarData; *sptr; sptr++)
  {
    std::stringstream ss(*sptr);
    out_stars.push_back(StarData(ss));
  }
}
bool SkyNode::getStarsVisible ( osg::View *  view = 0L) const

Definition at line 820 of file SkyNode.cpp.

{
    PerViewDataMap::const_iterator i = _perViewData.find(view);

    if ( !view || i == _perViewData.end() )
    {
        return _defaultPerViewData._starsVisible;
    }
    else
    {
        return i->second._starsVisible;
    }
}
void SkyNode::makeAtmosphere ( const osg::EllipsoidModel *  em) [private]

Definition at line 835 of file SkyNode.cpp.

{
    // create some skeleton geometry to shade:
    osg::Geometry* drawable = s_makeEllipsoidGeometry( em, _outerRadius );

    osg::Geode* geode = new osg::Geode();
    geode->addDrawable( drawable );

    osg::StateSet* set = geode->getOrCreateStateSet();

    // configure the state set:
    set->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
    set->setMode( GL_CULL_FACE, osg::StateAttribute::ON );
    set->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
    //set->setBinNumber( 65 ); // todo, what?
    set->setBinNumber( BIN_ATMOSPHERE );
    set->setAttributeAndModes( new osg::Depth( osg::Depth::LESS, 0, 1, false ) ); // no depth write
    set->setAttributeAndModes( new osg::BlendFunc( GL_ONE, GL_ONE ), osg::StateAttribute::ON );
    set->setAttributeAndModes( new osg::FrontFace( osg::FrontFace::CLOCKWISE ), osg::StateAttribute::ON );

    // next, create and add the shaders:
    osg::Program* program = new osg::Program();
    osg::Shader* vs = new osg::Shader( osg::Shader::VERTEX, s_atmosphereVertexSource );
    program->addShader( vs );
    osg::Shader* fs = new osg::Shader( osg::Shader::FRAGMENT, s_atmosphereFragmentSource );
    program->addShader( fs );
    set->setAttributeAndModes( program, osg::StateAttribute::ON );

    // apply the uniforms:
    float r_wl   = ::powf( .65f, 4.0f );
    float g_wl = ::powf( .57f, 4.0f );
    float b_wl  = ::powf( .475f, 4.0f );
    osg::Vec3 RGB_wl( 1.0f/r_wl, 1.0f/g_wl, 1.0f/b_wl );
    float Kr = 0.0025f;
    float Kr4PI = Kr * 4.0f * osg::PI;
    float Km = 0.0015f;
    float Km4PI = Km * 4.0f * osg::PI;
    float ESun = 15.0f;
    float MPhase = -.095f;
    float RayleighScaleDepth = 0.25f;
    int   Samples = 2;
    float Weather = 1.0f;
    
    float Scale = 1.0f / (_outerRadius - _innerRadius);

    _defaultPerViewData._lightPosUniform = set->getOrCreateUniform( "atmos_v3LightPos", osg::Uniform::FLOAT_VEC3 );
    _defaultPerViewData._lightPosUniform->set( _defaultPerViewData._lightPos / _defaultPerViewData._lightPos.length() );

    set->getOrCreateUniform( "atmos_v3InvWavelength", osg::Uniform::FLOAT_VEC3 )->set( RGB_wl );
    set->getOrCreateUniform( "atmos_fInnerRadius",    osg::Uniform::FLOAT )->set( _innerRadius );
    set->getOrCreateUniform( "atmos_fInnerRadius2",   osg::Uniform::FLOAT )->set( _innerRadius * _innerRadius );
    set->getOrCreateUniform( "atmos_fOuterRadius",    osg::Uniform::FLOAT )->set( _outerRadius );
    set->getOrCreateUniform( "atmos_fOuterRadius2",   osg::Uniform::FLOAT )->set( _outerRadius * _outerRadius );
    set->getOrCreateUniform( "atmos_fKrESun",         osg::Uniform::FLOAT )->set( Kr * ESun );
    set->getOrCreateUniform( "atmos_fKmESun",         osg::Uniform::FLOAT )->set( Km * ESun );
    set->getOrCreateUniform( "atmos_fKr4PI",          osg::Uniform::FLOAT )->set( Kr4PI );
    set->getOrCreateUniform( "atmos_fKm4PI",          osg::Uniform::FLOAT )->set( Km4PI );
    set->getOrCreateUniform( "atmos_fScale",          osg::Uniform::FLOAT )->set( Scale );
    set->getOrCreateUniform( "atmos_fScaleDepth",     osg::Uniform::FLOAT )->set( RayleighScaleDepth );
    set->getOrCreateUniform( "atmos_fScaleOverScaleDepth", osg::Uniform::FLOAT )->set( Scale / RayleighScaleDepth );
    set->getOrCreateUniform( "atmos_g",               osg::Uniform::FLOAT )->set( MPhase );
    set->getOrCreateUniform( "atmos_g2",              osg::Uniform::FLOAT )->set( MPhase * MPhase );
    set->getOrCreateUniform( "atmos_nSamples",        osg::Uniform::INT )->set( Samples );
    set->getOrCreateUniform( "atmos_fSamples",        osg::Uniform::FLOAT )->set( (float)Samples );
    set->getOrCreateUniform( "atmos_fWeather",        osg::Uniform::FLOAT )->set( Weather );
    
    //geode->setCullCallback( new DoNotIncludeInNearFarComputationCallback() );
    AddCallbackToDrawablesVisitor visitor( _innerRadius );
    geode->accept( visitor );

    _atmosphere = geode;
}

Here is the call graph for this function:

void SkyNode::makeStars ( const std::string &  starFile) [private]

Definition at line 966 of file SkyNode.cpp.

{
  _starRadius = 20000.0 * (_sunDistance > 0.0 ? _sunDistance : _outerRadius);

  std::vector<StarData> stars;

  if( starFile.empty() || parseStarFile(starFile, stars) == false )
  {
    if( !starFile.empty() )
      OE_WARN << "Warning: Unable to use star field defined in file \"" << starFile << "\", using default star data." << std::endl;

    getDefaultStars(stars);
  }

  osg::Node* starNode = buildStarGeometry(stars);

  AddCallbackToDrawablesVisitor visitor(_starRadius);
  starNode->accept(visitor);

  _stars = starNode;
}
void SkyNode::makeSun ( ) [private]

Definition at line 909 of file SkyNode.cpp.

{
    osg::Billboard* sun = new osg::Billboard();
    sun->setMode( osg::Billboard::POINT_ROT_EYE );
    sun->setNormal( osg::Vec3(0, 0, 1) );

    float sunRadius = _innerRadius * 100.0f;

    sun->addDrawable( s_makeDiscGeometry( sunRadius*80.0f ) ); 

    osg::StateSet* set = sun->getOrCreateStateSet();

    set->getOrCreateUniform( "sunAlpha", osg::Uniform::FLOAT )->set( 1.0f );

    // configure the stateset
    set->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
    set->setMode( GL_CULL_FACE, osg::StateAttribute::OFF );
    set->setRenderBinDetails( BIN_SUN, "RenderBin" );
    set->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS, 0, 1, false), osg::StateAttribute::ON );
    set->setAttributeAndModes( new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA), osg::StateAttribute::ON );

    // create shaders
    osg::Program* program = new osg::Program();
    osg::Shader* vs = new osg::Shader( osg::Shader::VERTEX, s_sunVertexSource );
    program->addShader( vs );
    osg::Shader* fs = new osg::Shader( osg::Shader::FRAGMENT, s_sunFragmentSource );
    program->addShader( fs );
    set->setAttributeAndModes( program, osg::StateAttribute::ON );

    // make the sun's transform:
    // todo: move this?
    _defaultPerViewData._sunXform = new osg::MatrixTransform();
    _defaultPerViewData._sunXform->setMatrix( osg::Matrix::translate( 
        _sunDistance * _defaultPerViewData._lightPos.x(), 
        _sunDistance * _defaultPerViewData._lightPos.y(), 
        _sunDistance * _defaultPerViewData._lightPos.z() ) );
    _defaultPerViewData._sunXform->addChild( sun );
    
    AddCallbackToDrawablesVisitor visitor( _sunDistance );
    sun->accept( visitor );

    _sun = sun;
}

Here is the call graph for this function:

bool SkyNode::parseStarFile ( const std::string &  starFile,
std::vector< StarData > &  out_stars 
) [private]

Definition at line 1053 of file SkyNode.cpp.

{
  out_stars.clear();

  std::fstream in(starFile.c_str());
  if (!in)
  {
    OE_WARN <<  "Warning: Unable to open file star file \"" << starFile << "\"" << std::endl;
    return false ;
  }

  while (!in.eof())
  {
    std::string line;

    std::getline(in, line);
    if (in.eof())
      break;

    if (line.empty() || line[0] == '#') 
      continue;

    std::stringstream ss(line);
    out_stars.push_back(StarData(ss));
  }

  in.close();

  return true;
}

Here is the call graph for this function:

void SkyNode::setAmbientBrightness ( float  value,
osg::View *  view = 0L 
)

The minimum brightness for non-sunlit areas.

Definition at line 681 of file SkyNode.cpp.

{
    if ( !view )
    {
        setAmbientBrightness( _defaultPerViewData, value );

        for( PerViewDataMap::iterator i = _perViewData.begin(); i != _perViewData.end(); ++i )
            setAmbientBrightness( i->second, value );
    }
    else if ( _perViewData.find(view) != _perViewData.end() )
    {
        setAmbientBrightness( _perViewData[view], value );
    }
}
void SkyNode::setAmbientBrightness ( PerViewData data,
float  value 
) [private]

Definition at line 709 of file SkyNode.cpp.

{
    value = osg::clampBetween( value, 0.0f, 1.0f );
    data._light->setAmbient( osg::Vec4f(value, value, value, 1.0f) );
}
void SkyNode::setDateTime ( int  year,
int  month,
int  date,
double  hoursUTC,
osg::View *  view = 0L 
)

Sets the sun's position based on a julian date.

Definition at line 767 of file SkyNode.cpp.

{
    if ( _ellipsoidModel.valid() )
    {
        // position the sun:
        Sun sun;
        osg::Vec3d pos = sun.getPosition( year, month, date, hoursUTC );
        pos.normalize();
        setSunPosition( pos, view );

        // position the stars:
        double time_r = hoursUTC/24.0; // 0..1
        double rot_z = -osg::PI + TWO_PI*time_r;

        osg::Matrixd starsMatrix = osg::Matrixd::rotate( -rot_z, 0, 0, 1 );
        if ( !view )
        {
            _defaultPerViewData._starsMatrix = starsMatrix;
            for( PerViewDataMap::iterator i = _perViewData.begin(); i != _perViewData.end(); ++i )
            {
                i->second._starsMatrix = starsMatrix;
                i->second._starsXform->setMatrix( starsMatrix );
            }
        }
        else if ( _perViewData.find(view) != _perViewData.end() )
        {
            PerViewData& data = _perViewData[view];
            data._starsMatrix = starsMatrix;
            data._starsXform->setMatrix( starsMatrix );
        }
    }
}

Here is the caller graph for this function:

void SkyNode::setStarsVisible ( bool  value,
osg::View *  view = 0L 
)

Whether the stars are visible

Definition at line 801 of file SkyNode.cpp.

{
    if ( !view )
    {
        _defaultPerViewData._starsVisible = value;
        for( PerViewDataMap::iterator i = _perViewData.begin(); i != _perViewData.end(); ++i )
        {
            i->second._starsVisible = value;
            i->second._starsXform->setNodeMask( value ? ~0 : 0 );
        }
    }
    else if ( _perViewData.find(view) != _perViewData.end() )
    {
        _perViewData[view]._starsVisible = value;
        _perViewData[view]._starsXform->setNodeMask( value ? ~0 : 0 );
    }
}
void SkyNode::setSunPosition ( PerViewData data,
const osg::Vec3 &  pos 
) [private]

Definition at line 731 of file SkyNode.cpp.

{
    data._lightPos = pos;

    if ( data._light.valid() )
        data._light->setPosition( osg::Vec4( data._lightPos, 0 ) );

    if ( data._lightPosUniform.valid() )
        data._lightPosUniform->set( data._lightPos / data._lightPos.length() );

    if ( data._sunXform.valid() )
    {
        data._sunXform->setMatrix( osg::Matrix::translate( 
            _sunDistance * data._lightPos.x(), 
            _sunDistance * data._lightPos.y(),
            _sunDistance * data._lightPos.z() ) );
    }
}
void SkyNode::setSunPosition ( const osg::Vec3 &  pos,
osg::View *  view = 0L 
)

Sets the sun's position as a unit vector.

Definition at line 716 of file SkyNode.cpp.

{
    if ( !view )
    {
        setSunPosition( _defaultPerViewData, pos );
        for( PerViewDataMap::iterator i = _perViewData.begin(); i != _perViewData.end(); ++i )
            setSunPosition( i->second, pos );
    }
    else if ( _perViewData.find(view) != _perViewData.end() )
    {
        setSunPosition( _perViewData[view], pos );
    }
}
void SkyNode::setSunPosition ( double  lat_degrees,
double  lon_degrees,
osg::View *  view = 0L 
)

Sets the sun's position as a latitude and longitude.

Definition at line 751 of file SkyNode.cpp.

{
    if (_ellipsoidModel.valid())
    {
        double x, y, z;
        _ellipsoidModel->convertLatLongHeightToXYZ(
            osg::RadiansToDegrees(lat_degrees),
            osg::RadiansToDegrees(long_degrees),
            0, 
            x, y, z);
        osg::Vec3d up  = _ellipsoidModel->computeLocalUpVector(x, y, z);
        setSunPosition( up, view );
    }
}
void SkyNode::traverse ( osg::NodeVisitor &  nv) [virtual]

Definition at line 613 of file SkyNode.cpp.

{
    osg::CullSettings::ComputeNearFarMode saveMode;

    osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>( &nv );
    if ( cv )
    {
        saveMode = cv->getComputeNearFarMode();
        cv->setComputeNearFarMode( osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR );

        osg::View* view = cv->getCurrentCamera()->getView();
        PerViewDataMap::iterator i = _perViewData.find( view );
        if ( i != _perViewData.end() )
        {
            i->second._cullContainer->accept( nv );
        }
    }

    osg::Group::traverse( nv );

    if ( cv )
    {
        cv->setComputeNearFarMode( saveMode );
    }
}

Member Data Documentation

osg::ref_ptr<osg::Node> osgEarth::Util::SkyNode::_atmosphere [private]

Definition at line 101 of file SkyNode.

Definition at line 96 of file SkyNode.

osg::ref_ptr< const osg::EllipsoidModel > osgEarth::Util::SkyNode::_ellipsoidModel [private]

Definition at line 105 of file SkyNode.

Definition at line 100 of file SkyNode.

Definition at line 100 of file SkyNode.

Definition at line 98 of file SkyNode.

osg::ref_ptr<osg::Uniform> osgEarth::Util::SkyNode::_starAlpha [private]

Definition at line 102 of file SkyNode.

osg::ref_ptr<osg::Uniform> osgEarth::Util::SkyNode::_starPointSize [private]

Definition at line 103 of file SkyNode.

Definition at line 100 of file SkyNode.

osg::ref_ptr<osg::Node> osgEarth::Util::SkyNode::_stars [private]

Definition at line 101 of file SkyNode.

osg::ref_ptr<osg::Node> osgEarth::Util::SkyNode::_sun [private]

Definition at line 101 of file SkyNode.

Definition at line 100 of file SkyNode.


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