osgEarth 2.1.1
Public Member Functions | Protected Member Functions | Protected Attributes

osgEarth::Features::StencilVolumeNode Class Reference

Inheritance diagram for osgEarth::Features::StencilVolumeNode:
Collaboration diagram for osgEarth::Features::StencilVolumeNode:

List of all members.

Public Member Functions

 StencilVolumeNode (bool preRenderChildrenToDepthBuffer=false, bool inverted=false)
 StencilVolumeNode (const StencilVolumeNode &rhs, const osg::CopyOp &op=osg::CopyOp::DEEP_COPY_ALL)
 META_Node (osgEarth::Features, StencilVolumeNode)
virtual void traverse (osg::NodeVisitor &nv)
int setBaseRenderBin (int bin)
void addVolumes (osg::Node *node)
virtual bool addChild (Node *child)
virtual bool insertChild (unsigned int index, Node *child)
virtual bool removeChildren (unsigned int pos, unsigned int numChildrenToRemove)
virtual bool replaceChild (Node *origChild, Node *newChild)
virtual bool setChild (unsigned int i, Node *node)
virtual osg::BoundingSphere computeBound () const

Protected Member Functions

void init ()

Protected Attributes

osg::ref_ptr< osg::Group > _root
osg::Group * _stencilGroup1
osg::Group * _stencilGroup2
osg::Group * _depthPass
osg::Group * _renderPass
bool _inverted
bool _preRenderChildrenToDepthBuffer

Detailed Description

Definition at line 31 of file StencilVolumeNode.


Constructor & Destructor Documentation

StencilVolumeNode::StencilVolumeNode ( bool  preRenderChildrenToDepthBuffer = false,
bool  inverted = false 
)

Constructs a stencil masking node.

Parameters:
preRenderChildrenToDepthBufferNormally, this node will render the stencil volumes first and then render the children (which will be masked by the stencil). If you need to pre-render the children to the depth buffer, set this to TRUE. You need to do this is you are creating a straight render mask.
invertedInverts the stencil buffer, masking the opposite pixels that would normally be masked.

Definition at line 41 of file StencilVolumeNode.cpp.

                                                                                         :
osgEarth::MaskNode(),
_preRenderChildrenToDepthBuffer( preRenderChildrenToDepthBuffer ),
_inverted( inverted ),
_stencilGroup1( 0L ),
_stencilGroup2( 0L ),
_depthPass( 0L ),
_renderPass( 0L )
{
    init();
}

Here is the call graph for this function:

StencilVolumeNode::StencilVolumeNode ( const StencilVolumeNode rhs,
const osg::CopyOp &  op = osg::CopyOp::DEEP_COPY_ALL 
)

Definition at line 47 of file StencilUtils.cpp.

                                                          :
osg::Group( rhs, op ),
_stencilGroup1( rhs._stencilGroup1 ),
_stencilGroup2( rhs._stencilGroup2 ),
_maskGroup( rhs._maskGroup ),
_maskColorArray( rhs._maskColorArray )
{
    //nop
}

Member Function Documentation

bool StencilVolumeNode::addChild ( Node *  child) [virtual]

Override all the osg::Group methods:

Definition at line 101 of file StencilVolumeNode.cpp.

                                         {
    if ( !child ) return false;
    dirtyBound();
    if ( _depthPass )  _depthPass->addChild( child );
    return _renderPass->addChild( child );
}

Here is the caller graph for this function:

void StencilVolumeNode::addVolumes ( osg::Node *  node)

Definition at line 84 of file StencilUtils.cpp.

{
    if ( _stencilGroup1 )
        _stencilGroup1->addChild( node );
    if ( _stencilGroup2 )
        _stencilGroup2->addChild( node );
}

Here is the caller graph for this function:

osg::BoundingSphere StencilVolumeNode::computeBound ( ) const [virtual]

Definition at line 134 of file StencilVolumeNode.cpp.

                                      {
    if ( _depthPass ) return _depthPass->computeBound();
    else return _renderPass->computeBound();
}
void StencilVolumeNode::init ( ) [protected]

Definition at line 93 of file StencilUtils.cpp.

{
    // FIRST create the stenciled geometry pass:

    // For now we are hard-coding these to what are hopefully "safe" values.
    // In the future we hope to rewrite this as a custom StencilVolumeNode that 
    // will automatically detect extension availability at draw time and choose
    // the optimal GL rendering path.
    static bool s_EXT_stencil_wrap     = true; //osg::isGLExtensionSupported(0, "GL_EXT_stencil_wrap");
    static bool s_EXT_stencil_two_side = false; //osg::isGLExtensionSupported(0, "GL_EXT_stencil_two_side");


    // zFail=true if more compute intensive, but lets you get inside the volume.
    // Again, a custom node will give us a better opportunity to choose between zFail and zPass based on
    // the eye location (you only need zFail if you camera is inside the volume).
    bool zFail = true;
    int baseBin = 100;

    osg::notify(osg::INFO) << "[osgEarth] Stencil buffer wrap = " << s_EXT_stencil_wrap << std::endl;

    if ( s_EXT_stencil_two_side )
    {
        osg::notify(osg::INFO) << "[osgEarth] Two-sided stenciling" << std::endl;

        osg::StencilTwoSided::Operation incrOp = s_EXT_stencil_wrap ? osg::StencilTwoSided::INCR_WRAP : osg::StencilTwoSided::INCR;
        osg::StencilTwoSided::Operation decrOp = s_EXT_stencil_wrap ? osg::StencilTwoSided::DECR_WRAP : osg::StencilTwoSided::DECR;
        _stencilGroup1 = new osg::Group();
        //osg::Group* stencil_group = new osg::Group();
        osg::StateSet* ss = _stencilGroup1->getOrCreateStateSet();
        ss->setRenderBinDetails( baseBin++, "RenderBin" );

        if ( zFail )
        {
            osg::StencilTwoSided* stencil = new osg::StencilTwoSided();
            stencil->setFunction(osg::StencilTwoSided::BACK, osg::StencilTwoSided::ALWAYS, 1, ~0u); 
            stencil->setOperation(osg::StencilTwoSided::BACK, osg::StencilTwoSided::KEEP, incrOp, osg::StencilTwoSided::KEEP);

            stencil->setFunction(osg::StencilTwoSided::FRONT, osg::StencilTwoSided::ALWAYS, 1, ~0u); 
            stencil->setOperation(osg::StencilTwoSided::FRONT, osg::StencilTwoSided::KEEP, decrOp, osg::StencilTwoSided::KEEP);
            ss->setAttributeAndModes( stencil, ON_AND_PROTECTED );
        }
        else
        {
            osg::StencilTwoSided* stencil = new osg::StencilTwoSided();
            stencil->setFunction(osg::StencilTwoSided::FRONT, osg::StencilTwoSided::ALWAYS, 1, ~0u); 
            stencil->setOperation(osg::StencilTwoSided::FRONT, osg::StencilTwoSided::KEEP, osg::StencilTwoSided::KEEP, incrOp);

            stencil->setFunction(osg::StencilTwoSided::BACK, osg::StencilTwoSided::ALWAYS, 1, ~0u); 
            stencil->setOperation(osg::StencilTwoSided::BACK, osg::StencilTwoSided::KEEP, osg::StencilTwoSided::KEEP, decrOp);
            ss->setAttributeAndModes( stencil, ON_AND_PROTECTED );
        }

        ss->setAttributeAndModes(new osg::ColorMask(false,false,false,false), ON_AND_PROTECTED);
        ss->setAttributeAndModes(new osg::Depth(osg::Depth::LESS,0,1,false), ON_AND_PROTECTED);
        //stencil_group->addChild( geometry );

        this->addChild( _stencilGroup1 );
        //root->addChild( stencil_group );
    }
    else
    {
        osg::notify(osg::INFO) << "[osgEarth] One-sided stenciling" << std::endl;

        if ( !zFail )  // Z-Pass
        {
            _stencilGroup1 = new osg::Group();
            osg::StateSet* front_ss = _stencilGroup1->getOrCreateStateSet();
            front_ss->setRenderBinDetails( baseBin++, "RenderBin" );

            // incrementing stencil op for front faces:
            osg::Stencil* front_stencil = new osg::Stencil();
            front_stencil->setFunction( osg::Stencil::ALWAYS, 1, ~0u );
            osg::Stencil::Operation incrOp = s_EXT_stencil_wrap ? osg::Stencil::INCR_WRAP : osg::Stencil::INCR;
            front_stencil->setOperation( osg::Stencil::KEEP, osg::Stencil::KEEP, incrOp );
            front_ss->setAttributeAndModes( front_stencil, ON_AND_PROTECTED );

            front_ss->setAttributeAndModes( new osg::ColorMask(false,false,false,false), ON_AND_PROTECTED);
            front_ss->setAttributeAndModes( new osg::CullFace(osg::CullFace::BACK), ON_AND_PROTECTED);
            front_ss->setAttributeAndModes( new osg::Depth(osg::Depth::LESS,0,1,false), ON_AND_PROTECTED);

            //front_group->addChild( geometry );
            this->addChild( _stencilGroup1 );
            //root->addChild( front_group );

            // decrementing stencil op for back faces:
            _stencilGroup2 = new osg::Group();
            osg::StateSet* back_ss = _stencilGroup2->getOrCreateStateSet();
            back_ss->setRenderBinDetails( baseBin++, "RenderBin" );

            osg::Stencil* back_stencil = new osg::Stencil();
            back_stencil->setFunction( osg::Stencil::ALWAYS, 1, ~0u );
            osg::Stencil::Operation decrOp = s_EXT_stencil_wrap ? osg::Stencil::DECR_WRAP : osg::Stencil::DECR;
            back_stencil->setOperation( osg::Stencil::KEEP, osg::Stencil::KEEP, decrOp );
            back_ss->setAttributeAndModes( back_stencil, ON_AND_PROTECTED );

            back_ss->setAttributeAndModes( new osg::ColorMask(false,false,false,false), ON_AND_PROTECTED);
            back_ss->setAttributeAndModes( new osg::CullFace(osg::CullFace::FRONT), ON_AND_PROTECTED);
            back_ss->setAttributeAndModes( new osg::Depth(osg::Depth::LESS,0,1,false), ON_AND_PROTECTED);

            //back_group->addChild( geometry );
            this->addChild( _stencilGroup2 );
            //root->addChild( back_group );       
        }
        else
        {
            // incrementing stencil op for back faces:
            {
                _stencilGroup1 = new osg::Group();
                osg::StateSet* front_ss = _stencilGroup1->getOrCreateStateSet();
                front_ss->setRenderBinDetails( baseBin++, "RenderBin" );

                osg::Stencil* front_stencil = new osg::Stencil();
                front_stencil->setFunction( osg::Stencil::ALWAYS ); //, 1, ~0u );
                osg::Stencil::Operation incrOp = s_EXT_stencil_wrap ? osg::Stencil::INCR_WRAP : osg::Stencil::INCR;
                front_stencil->setOperation( osg::Stencil::KEEP, incrOp, osg::Stencil::KEEP );
                front_ss->setAttributeAndModes( front_stencil, ON_AND_PROTECTED );

                front_ss->setAttributeAndModes( new osg::ColorMask(false,false,false,false), ON_AND_PROTECTED);
                front_ss->setAttributeAndModes( new osg::CullFace(osg::CullFace::FRONT), ON_AND_PROTECTED);
                front_ss->setAttributeAndModes( new osg::Depth(osg::Depth::LESS,0,1,false), ON_AND_PROTECTED);

                //front_group->addChild( geometry );
                this->addChild( _stencilGroup1 );
                //root->addChild( front_group );
            }

            // decrementing stencil buf for front faces
            {
                _stencilGroup2 = new osg::Group();
                osg::StateSet* back_ss = _stencilGroup2->getOrCreateStateSet();
                back_ss->setRenderBinDetails( baseBin++, "RenderBin" );

                osg::Stencil* back_stencil = new osg::Stencil();
                back_stencil->setFunction( osg::Stencil::ALWAYS ); //, 1, ~0u );
                osg::Stencil::Operation decrOp = s_EXT_stencil_wrap ? osg::Stencil::DECR_WRAP : osg::Stencil::DECR;
                back_stencil->setOperation( osg::Stencil::KEEP, decrOp, osg::Stencil::KEEP );
                back_ss->setAttributeAndModes( back_stencil, ON_AND_PROTECTED );

                back_ss->setAttributeAndModes( new osg::ColorMask(false,false,false,false), ON_AND_PROTECTED);
                back_ss->setAttributeAndModes( new osg::CullFace(osg::CullFace::BACK), ON_AND_PROTECTED);
                back_ss->setAttributeAndModes( new osg::Depth(osg::Depth::LESS,0,1,false), ON_AND_PROTECTED);

                //back_group->addChild( geometry );
                this->addChild( _stencilGroup2 );
                //root->addChild( back_group );
            }
        }
    }
    

    // NOW built the full-screen quad mask that will paint the volume:

    _maskGroup = new osg::Group();

    // make a full screen quad:
    osg::Geometry* quad = new osg::Geometry();
    osg::Vec3Array* verts = new osg::Vec3Array(4);
    (*verts)[0].set( 0, 1, 0 );
    (*verts)[1].set( 0, 0, 0 );
    (*verts)[2].set( 1, 0, 0 );
    (*verts)[3].set( 1, 1, 0 );
    quad->setVertexArray( verts );
    quad->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, 4 ) );
    _maskColorArray = new osg::Vec4Array(1);
    (*_maskColorArray)[0] = osg::Vec4f(1,1,1,1);
    quad->setColorArray( _maskColorArray );
    quad->setColorBinding( osg::Geometry::BIND_OVERALL );
    osg::Geode* quad_geode = new osg::Geode();
    quad_geode->addDrawable( quad );

    osg::StateSet* quad_ss = quad->getOrCreateStateSet();
    quad_ss->setMode( GL_CULL_FACE, OFF_AND_PROTECTED );
    quad_ss->setMode( GL_DEPTH_TEST, OFF_AND_PROTECTED );
    quad_ss->setMode( GL_LIGHTING, OFF_AND_PROTECTED );

    osg::Stencil* quad_stencil = new osg::Stencil();
    quad_stencil->setFunction( osg::Stencil::NOTEQUAL, 128, (unsigned int)~0 );
    // this will conveniently re-clear the stencil buffer in prep for the next pass:
    quad_stencil->setOperation( osg::Stencil::REPLACE, osg::Stencil::REPLACE, osg::Stencil::REPLACE );
    quad_ss->setAttributeAndModes( quad_stencil, ON_AND_PROTECTED );

    osg::MatrixTransform* abs = new osg::MatrixTransform();
    abs->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
    abs->setMatrix( osg::Matrix::identity() );
    abs->addChild( quad_geode );

    osg::Projection* proj = new osg::Projection();
    proj->setMatrix( osg::Matrix::ortho(0, 1, 0, 1, 0, -1) );
    proj->addChild( abs );

    _maskGroup->addChild( proj );
    _maskGroup->getOrCreateStateSet()->setMode( GL_BLEND, 1 );    
    _maskGroup->getOrCreateStateSet()->setRenderBinDetails( baseBin++, "RenderBin" );

    this->addChild( _maskGroup );
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool StencilVolumeNode::insertChild ( unsigned int  index,
Node *  child 
) [virtual]

Definition at line 108 of file StencilVolumeNode.cpp.

                                                                {
    if ( !child ) return false;
    dirtyBound();
    if ( _depthPass ) _depthPass->insertChild( index, child );
    return _renderPass->insertChild( index, child );
}
osgEarth::Features::StencilVolumeNode::META_Node ( osgEarth::Features  ,
StencilVolumeNode   
)
bool StencilVolumeNode::removeChildren ( unsigned int  pos,
unsigned int  numChildrenToRemove 
) [virtual]

Definition at line 115 of file StencilVolumeNode.cpp.

                                                                                   {
    dirtyBound();
    if ( _depthPass ) _depthPass->removeChildren( pos, numChildrenToRemove );
    return _renderPass->removeChildren( pos, numChildrenToRemove );
}
bool StencilVolumeNode::replaceChild ( Node *  origChild,
Node *  newChild 
) [virtual]

Definition at line 121 of file StencilVolumeNode.cpp.

                                                                 {
    dirtyBound();
    if ( _depthPass ) _depthPass->replaceChild( origChild, newChild );
    return _renderPass->replaceChild( origChild, newChild );
}
int StencilVolumeNode::setBaseRenderBin ( int  bin)

Definition at line 59 of file StencilUtils.cpp.

{
    if ( _stencilGroup1 )
    {
        _stencilGroup1->getOrCreateStateSet()->setRenderBinDetails( bin++, "RenderBin" );
    }
    if ( _stencilGroup2 )
    {
        _stencilGroup2->getOrCreateStateSet()->setRenderBinDetails( bin++, "RenderBin" );
    }
    if ( _maskGroup )
    {
        _maskGroup->getOrCreateStateSet()->setRenderBinDetails( bin++, "RenderBin" );
    }
    return bin;
}

Here is the caller graph for this function:

bool StencilVolumeNode::setChild ( unsigned int  i,
Node *  node 
) [virtual]

Definition at line 127 of file StencilVolumeNode.cpp.

                                                         {
    dirtyBound();
    if ( _depthPass ) _depthPass->setChild( i, node );
    return _renderPass->setChild( i, node );
}
void StencilVolumeNode::traverse ( osg::NodeVisitor &  nv) [virtual]

Definition at line 141 of file StencilVolumeNode.cpp.

{
    _root->accept( nv );
}

Member Data Documentation

Definition at line 83 of file StencilVolumeNode.

Definition at line 85 of file StencilVolumeNode.

Definition at line 86 of file StencilVolumeNode.

Definition at line 84 of file StencilVolumeNode.

osg::ref_ptr<osg::Group> osgEarth::Features::StencilVolumeNode::_root [protected]

Definition at line 80 of file StencilVolumeNode.

Definition at line 81 of file StencilVolumeNode.

Definition at line 82 of file StencilVolumeNode.


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