Hi Roger,

Moving a class definition into a function implementation makes me
nervous about the possibile consequence for older compilers handling
this.  I don't know whether it would be supported or not, but... given
it's not a technique used in the rest the OSG I don't have a prior art
to confirm that it's OK to roll out.

Would enclosing the class in a local namespace be sufficient?

Robert.

On Thu, Jan 22, 2009 at 2:23 PM, Roger James
<[email protected]> wrote:
> Robert,
>
> This fix moves a couple of debug callback functions that have the same name
> from the global context into the local function context where they are used.
> This avoids some obscure problems when they used in DLLs generated by MS
> VC8.1.
>
> Roger
>
> /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
>  *
>  * This library is open source and may be redistributed and/or modified
> under
>  * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
>  * (at your option) any later version.  The full license is in LICENSE file
>  * included with this distribution, and on the openscenegraph.org website.
>  *
>  * This library is distributed in the hope that it will be useful,
>  * but WITHOUT ANY WARRANTY; without even the implied warranty of
>  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>  * OpenSceneGraph Public License for more details.
>  *
>  * ViewDependentShadow codes Copyright (C) 2008 Wojciech Lewandowski
>  * Thanks to to my company http://www.ai.com.pl for allowing me free this
> work.
> */
>
> #include <osgShadow/DebugShadowMap>
> #include <osgShadow/ConvexPolyhedron>
> #include <osgUtil/RenderLeaf>
> #include <osg/Geometry>
> #include <osg/PrimitiveSet>
> #include <osg/MatrixTransform>
> #include <osg/Depth>
> #include <iostream>
> #include <iomanip>
>
> using namespace osgShadow;
>
>
> #define VECTOR_LENGTH( v ) ( sizeof(v)/sizeof(v[0]) )
>
> #define DEFAULT_DEBUG_HUD_SIZE_X 256
> #define DEFAULT_DEBUG_HUD_SIZE_Y 256
> #define DEFAULT_DEBUG_HUD_ORIGIN_X 8
> #define DEFAULT_DEBUG_HUD_ORIGIN_Y 8
>
> DebugShadowMap::DebugShadowMap():
>    BaseClass(),
>    _hudSize( 2, 2 ),
>    _hudOrigin( -1, -1 ),
>    _viewportSize( DEFAULT_DEBUG_HUD_SIZE_X, DEFAULT_DEBUG_HUD_SIZE_Y ),
>    _viewportOrigin( DEFAULT_DEBUG_HUD_ORIGIN_X, DEFAULT_DEBUG_HUD_ORIGIN_Y
> ),
>    _orthoSize( 2, 2 ),
>    _orthoOrigin( -1, -1 ),
>    _doDebugDraw( false )
> {
>
>    // Why this fancy 24 bit depth to 24 bit rainbow colors shader ?
>    //
>    // Depth values cannot be easily cast on color component because they
> are:
>    // a) 24 or 32 bit and we loose lots of precision when cast on 8 bit
>    // b) depth value distribution is non linear due to projection division
>    // when cast on componenent color there is usually very minor shade
> variety
>    // and its often difficult to notice that there is anything in the buffer
>    //
>    // Shader looks complex but it is used only for debug head-up rectangle
>    // so performance impact is not significant.
>
>    _depthColorFragmentShader = new osg::Shader( osg::Shader::FRAGMENT,
> #if 0
>        "uniform sampler2D texture;
>    \n"
>        "
>    \n"
>        "void main(void)
>     \n"
>        "{
>     \n"
>        "    float f = texture2D( texture, vec3( gl_TexCoord[0].xy, 1.0).xy
> ).r; \n"
>        "    gl_FragColor =  vec4( 0.0, 1.0 - f,  0.5 - f, 0.5 );
>    \n"
>        "}
>     \n"
> #else
>        "uniform sampler2D texture;
>    \n"
>        "
>    \n"
>        "void main(void)
>     \n"
>        "{
>     \n"
>        "    float f = texture2D( texture, vec3( gl_TexCoord[0].xy, 1.0).xy
> ).r; \n"
>        "
>    \n"
>        "    f = 256.0 * f;
>    \n"
>        "    float fC = floor( f ) / 256.0;
>    \n"
>        "
>    \n"
>        "    f = 256.0 * fract( f );
>     \n"
>        "    float fS = floor( f ) / 256.0;
>    \n"
>        "
>    \n"
>        "    f = 256.0 * fract( f );
>     \n"
>        "    float fH = floor( f ) / 256.0;
>    \n"
>        "
>    \n"
>        "    fS *= 0.5;
>    \n"
>        "    fH = ( fH  * 0.34 + 0.66 ) * ( 1.0 - fS );
>    \n"
>        "
>    \n"
>        "    vec3 rgb = vec3( ( fC > 0.5 ? ( 1.0 - fC ) : fC ),
>    \n"
>        "                     abs( fC - 0.333333 ),
>    \n"
>        "                     abs( fC - 0.666667 ) );
>    \n"
>        "
>    \n"
>        "    rgb = min( vec3( 1.0, 1.0, 1.0 ), 3.0 * rgb );
>    \n"
>        "
>    \n"
>        "    float fMax = max( max( rgb.r, rgb.g ), rgb.b );
>     \n"
>        "    fMax = 1.0 / fMax;
>    \n"
>        "
>    \n"
>        "    vec3 color = fMax * rgb;
>    \n"
>        "
>    \n"
>        "    gl_FragColor =  vec4( fS + fH * color, 1 ) * gl_Color;
>    \n"
>        "}
>     \n"
> #endif
>    ); // end _depthColorFragmentShader
> }
>
> DebugShadowMap::DebugShadowMap
> (const DebugShadowMap& copy, const osg::CopyOp& copyop) :
>    BaseClass(copy,copyop),
>    _hudSize( copy._hudSize ),
>    _hudOrigin( copy._hudOrigin ),
>    _viewportSize( copy._viewportSize ),
>    _viewportOrigin( copy._viewportOrigin ),
>    _orthoSize( copy._viewportOrigin ),
>    _orthoOrigin( copy._viewportOrigin ),
>    _doDebugDraw( copy._doDebugDraw )
> {
>    if( copy._depthColorFragmentShader.valid() )
>        _depthColorFragmentShader =
>            dynamic_cast<osg::Shader*>
>                ( copy._depthColorFragmentShader->clone(copyop) );
> }
>
> DebugShadowMap::~DebugShadowMap()
> {
> }
>
> void DebugShadowMap::ViewData::cull( void )
> {
>    if( getDebugDraw() && !_cameraDebugHUD.valid() )
>        createDebugHUD();
>
>    BaseClass::ViewData::cull( );
>
>    cullDebugGeometry( );
> }
>
> bool DebugShadowMap::ViewData::DebugBoundingBox
>    ( const osg::BoundingBox & bb, const char * name )
> {
>    bool result = false;
> #if defined( _DEBUG    ) || defined( DEBUG )
>    if( !name ) name = "";
>
>    osg::BoundingBox & bb_prev = _boundingBoxMap[ std::string( name ) ];
>
>    result = bb.center() != bb_prev.center() || bb.radius() !=
> bb_prev.radius();
>    if( result )
>        std::cout << "Box<" << name << "> ("
>                  << ( bb._max._v[0] + bb._min._v[0] ) * 0.5 << " "
>                  << ( bb._max._v[1] + bb._min._v[1] ) * 0.5 << " "
>                  << ( bb._max._v[2] + bb._min._v[2] ) * 0.5 << ") ["
>                  << ( bb._max._v[0] - bb._min._v[0] ) << " "
>                  << ( bb._max._v[1] - bb._min._v[1] ) << " "
>                  << ( bb._max._v[2] - bb._min._v[2] ) << "] "
>                  << std::endl;
>
>    bb_prev = bb;
> #endif
>    return result;
> }
>
> bool DebugShadowMap::ViewData::DebugPolytope
> ( const osg::Polytope & p, const char * name )
> {
>    bool result = false;
> #if defined( _DEBUG    ) || defined( DEBUG )
>    if( !name ) name = "";
>
>    osg::Polytope & p_prev = _polytopeMap[ std::string( name ) ];
>
>    result = ( p.getPlaneList() != p_prev.getPlaneList() );
>
>    if( result ) {
>        std::cout << "Polytope<" << name
>                  << "> size(" << p.getPlaneList().size() << ")"
>                  << std::endl;
>
>        if( p.getPlaneList().size() == p_prev.getPlaneList().size() ) {
>            for( unsigned i = 0; i < p.getPlaneList().size(); ++i )
>            {
>                if( p.getPlaneList()[i] != p_prev.getPlaneList()[i] )
>                {
>                    std::cout << "Plane<" << i
>                        << "> ("
>                        << p.getPlaneList()[i].asVec4()[0] << ", "
>                        << p.getPlaneList()[i].asVec4()[1] << ", "
>                        << p.getPlaneList()[i].asVec4()[2] << ", "
>                        << p.getPlaneList()[i].asVec4()[3] << ")"
>                        << std::endl;
>                }
>            }
>        }
>    }
>
>    p_prev = p;
> #endif
>    return result;
> }
>
> bool DebugShadowMap::ViewData::DebugMatrix
>    ( const osg::Matrix & m, const char * name )
> {
>    bool result = false;
> #if defined( _DEBUG    ) || defined( DEBUG )
>    if( !name ) name = "";
>
>    osg::Matrix & m_prev = _matrixMap[ std::string( name ) ];
>
>    result = ( m != m_prev );
>
>    if( result )
>        std::cout << "Matrix<" << name << "> " << std::endl
>            <<"[ " << m(0,0) << " " << m(0,1) << " " << m(0,2) << " " <<
> m(0,3) << " ]  " << std::endl
>            <<"[ " << m(1,0) << " " << m(1,1) << " " << m(1,2) << " " <<
> m(1,3) << " ]  " << std::endl
>            <<"[ " << m(2,0) << " " << m(2,1) << " " << m(2,2) << " " <<
> m(2,3) << " ]  " << std::endl
>            <<"[ " << m(3,0) << " " << m(3,1) << " " << m(3,2) << " " <<
> m(3,3) << " ]  " << std::endl;
>
>    m_prev = m;
> #endif
>    return result;
> }
>
> void DebugShadowMap::ViewData::setDebugPolytope
>    ( const char * name, const ConvexPolyhedron & polytope,
>      osg::Vec4 colorOutline, osg::Vec4 colorInside )
> {
>    if( !getDebugDraw() ) return;
>
>    if( &polytope == NULL ) { // delete
>        PolytopeGeometry & pg = _polytopeGeometryMap[ std::string( name ) ];
>        for( unsigned int i = 0; i < VECTOR_LENGTH( pg._geometry ) ; i++ )
>        {
>            if( pg._geometry[i].valid() ) {
>                if( _geode[i].valid() &&
>                    _geode[i]->containsDrawable( pg._geometry[i].get() ) )
>                        _geode[i]->removeDrawable( pg._geometry[i].get() );
>
>                pg._geometry[i] = NULL;
>            }
>        }
>        _polytopeGeometryMap.erase( std::string( name ) );
>    } else { // update
>        PolytopeGeometry & pg = _polytopeGeometryMap[ std::string( name ) ];
>
>        pg._polytope = polytope;
>        if( colorOutline.a() > 0 )
>            pg._colorOutline = colorOutline;
>        if( colorInside.a() > 0 )
>            pg._colorInside = colorInside;
>
>        for( unsigned int i = 0; i < VECTOR_LENGTH( pg._geometry ) ; i++ )
>        {
>            if( !pg._geometry[i].valid() ) {
>                pg._geometry[i] = new osg::Geometry;
>                pg._geometry[i]->setDataVariance( osg::Object::DYNAMIC );
>                pg._geometry[i]->setUseDisplayList( false );
>                pg._geometry[i]->setSupportsDisplayList( false );
>            }
>
>            if( _geode[i].valid() &&
>                  !_geode[i]->containsDrawable( pg._geometry[i].get() ) ) {
>                        osg::Geode::DrawableList & dl =
>                           const_cast< osg::Geode::DrawableList &>
>                              ( _geode[i]->getDrawableList() );
>                        dl.insert( dl.begin(), pg._geometry[i].get() );
>            }
>        }
>    }
> }
>
> void DebugShadowMap::ViewData::updateDebugGeometry
>    ( const osg::Camera * viewCam, const osg::Camera * shadowCam )
> {
>    if( !getDebugDraw() ) return;
>    if( _polytopeGeometryMap.empty() ) return;
>
>    const int num = 2; // = VECTOR_LENGTH( PolytopeGeometry::_geometry );
>
>    osg::Matrix
>        transform[ num ] =
>            { viewCam->getViewMatrix() *
>                // use near far clamped projection ( precomputed in
> cullDebugGeometry )
>                ( viewCam == _viewCamera ? _viewProjection :
> viewCam->getProjectionMatrix() ),
>              shadowCam->getViewMatrix() * shadowCam->getProjectionMatrix()
> },
>        inverse[ num ] =
>            { osg::Matrix::inverse( transform[0] ),
>              osg::Matrix::inverse( transform[1] ) };
>
> #if 0
>    ConvexPolyhedron frustum[ num ];
>    for( int i = 0; i < num; i++ ) {
>        frustum[i].setToUnitFrustum( );
> #if 1
>        frustum[i].transform( inverse[i], transform[i] );
> #else
>        frustum[i].transform
>            ( osg::Matrix::inverse( camera[i]->getProjectionMatrix() ),
>              camera[i]->getProjectionMatrix() );
>        frustum[i].transform
>            ( osg::Matrix::inverse( camera[i]->getViewMatrix() ),
>              camera[i]->getViewMatrix() );
> #endif
>    };
> #else
>    osg::Polytope frustum[ num ];
>    for( int i = 0; i < num; i++ ) {
>        frustum[i].setToUnitFrustum( );
>        frustum[i].transformProvidingInverse( transform[i] );
>    }
> #endif
>
>    transform[0] = viewCam->getViewMatrix();
>    inverse[0] = viewCam->getInverseViewMatrix();
>
>    for( PolytopeGeometryMap::iterator itr = _polytopeGeometryMap.begin();
>         itr != _polytopeGeometryMap.end();
>         ++itr )
>    {
>        PolytopeGeometry & pg = itr->second;
>
>        for( int i = 0; i < num ; i++ )
>        {
>
>            ConvexPolyhedron cp( pg._polytope );
>            cp.cut( frustum[i] );
>            cp.transform( transform[i], inverse[i] );
>
>            pg._geometry[i] = cp.buildGeometry
>                ( pg._colorOutline, pg._colorInside, pg._geometry[i].get() );
>        }
>    }
> }
>
> void DebugShadowMap::ViewData::cullDebugGeometry( )
> {
>    if( !getDebugDraw() ) return;
>    if( !_camera.valid() ) return;
>
>    // View camera may use clamping projection matrix after traversal.
>    // Since we need to know exact matrix for drawing the frusta,
>    // we have to compute it here in exactly the same way as cull visitor
>    // will after cull traversal completes view camera subgraph.
>    {
>        _viewProjection = *_cv->getProjectionMatrix();
>        _viewCamera = _cv->getRenderStage()->getCamera();
>
>        if( _cv->getComputeNearFarMode() ) {
>
>            // Redo steps from CullVisitor::popProjectionMatrix()
>            // which clamps projection matrix when Camera & Projection
>            // completes traversal of their children
>
>            // We have to do this now manually
>            // because we did not complete camera traversal yet but
>            // we need to know how this clamped projection matrix will be
>
>            _cv->computeNearPlane();
>
>            osgUtil::CullVisitor::value_type n =
> _cv->getCalculatedNearPlane();
>            osgUtil::CullVisitor::value_type f =
> _cv->getCalculatedFarPlane();
>
>            if( n < f )
>                _cv->clampProjectionMatrix( _viewProjection, n, f );
>        }
>    }
>
>    updateDebugGeometry( _viewCamera, _camera.get() );
>
> #if 1 // Add geometries of polytopes to main cam Render Stage
>    _transform[0]->accept( *_cv );
> #else
>    for( PolytopeGeometryMap::iterator itr = _polytopeGeometryMap.begin();
>         itr != _polytopeGeometryMap.end();
>         ++itr )
>    {
>        PolytopeGeometry & pg = itr->second;
>        _cv->pushStateSet( _geode[0]->getStateSet() );
>        _cv->addDrawableAndDepth( pg._geometry[0].get(), NULL, FLT_MAX );
>        _cv->popStateSet( );
>    }
> #endif
>
>    // Add geometries of polytopes to hud cam Render Stage
>    _cameraDebugHUD->accept( *_cv );
> }
>
> void DebugShadowMap::ViewData::init( ThisClass *st, osgUtil::CullVisitor *cv
> )
> {
>    BaseClass::ViewData::init( st, cv );
>
>    _doDebugDrawPtr           = &st->_doDebugDraw;
>
>    _hudSize                  = st->_hudSize;
>    _hudOrigin                = st->_hudOrigin;
>    _viewportSize             = st->_viewportSize;
>    _viewportOrigin           = st->_viewportOrigin;
>    _orthoSize                = st->_orthoSize;
>    _orthoOrigin              = st->_orthoOrigin;
>
>    _depthColorFragmentShader = st->_depthColorFragmentShader;
>
>    // create placeholder geodeds for polytope geometries
>    // rest of their initialization will be performed during camera hud init
>    _geode[0] = new osg::Geode;
>    _geode[1] = new osg::Geode;
>
>    _cameraDebugHUD           = NULL;//Force debug HUD rebuild ( if needed )
> }
>
> void DebugShadowMap::ViewData::createDebugHUD( )
> {
>        // Callback used by debugging hud to display Shadow Map to color
> buffer
>        // Had to do it this way because OSG does not allow to use
>        // the same GL Texture Id with different glTexParams.
>        // Callback simply turns compare mode off via GL while rendering hud
> and
>        // restores it before rendering the scene with shadows.
>        class DrawableDrawWithDepthShadowComparisonOffCallback:
>                public osg::Drawable::DrawCallback
>        {
>        public:
>                DrawableDrawWithDepthShadowComparisonOffCallback(
> osg::Texture2D *pTex )
>                        : _pTexture( pTex )
>                {
>                }
>
>                virtual void drawImplementation
>                        ( osg::RenderInfo & ri,const osg::Drawable* drawable
> ) const
>                {
>                        ri.getState()->applyTextureAttribute( 0,
> _pTexture.get() );
>
>                        // Turn off depth comparison mode
>                        glTexParameteri( GL_TEXTURE_2D,
> GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE );
>
>                        drawable->drawImplementation(ri);
>
>                        // Turn it back on
>                        glTexParameteri( GL_TEXTURE_2D,
> GL_TEXTURE_COMPARE_MODE_ARB,
>                                GL_COMPARE_R_TO_TEXTURE_ARB );
>                }
>
>                osg::ref_ptr< osg::Texture2D > _pTexture;
>        };
>
>    _cameraDebugHUD = new osg::Camera;
>
>    { // Make sure default HUD layout makes sense
>        if( _hudSize[0] <= 0 ) _hudSize[0] = DEFAULT_DEBUG_HUD_SIZE_X;
>        if( _hudSize[1] <= 0 ) _hudSize[1] = DEFAULT_DEBUG_HUD_SIZE_Y;
>
>        if( _viewportSize[0] <= 0 ) _viewportSize[0] = _hudSize[0];
>        if( _viewportSize[1] <= 0 ) _viewportSize[1] = _hudSize[1];
>
>        if( _orthoSize[0] <= 0 ) _orthoSize[0] = _viewportSize[0];
>        if( _orthoSize[1] <= 0 ) _orthoSize[1] = _viewportSize[1];
>    }
>
>    { // Initialize hud camera
>        osg::Camera * camera = _cameraDebugHUD.get();
>        camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
>        camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
>        camera->setViewMatrix(osg::Matrix::identity());
>        camera->setViewport( _viewportOrigin[0], _viewportOrigin[1],
>                             _viewportSize[0], _viewportSize[1] );
>
>        camera->setProjectionMatrixAsOrtho(
>                _orthoOrigin[0], _orthoOrigin[0] + _orthoSize[0],
>                _orthoOrigin[1], _orthoOrigin[1] + _orthoSize[1],
>                -10, 10 );
>
>        camera->setClearMask(GL_DEPTH_BUFFER_BIT);
>        camera->setRenderOrder(osg::Camera::POST_RENDER);
>    }
>
>    { // Add geode and drawable with BaseClass display
>        // create geode to contain hud drawables
>        osg::Geode* geode = new osg::Geode;
>        _cameraDebugHUD->addChild(geode);
>
>        // finally create and attach hud geometry
>        osg::Geometry* geometry = osg::createTexturedQuadGeometry
>            ( osg::Vec3(_hudOrigin[0],_hudOrigin[1],0),
>              osg::Vec3(_hudSize[0],0,0),
>              osg::Vec3(0,_hudSize[1],0) );
>
>        osg::StateSet* stateset = _cameraDebugHUD->getOrCreateStateSet();
>
>  
> stateset->setTextureAttributeAndModes(0,_texture.get(),osg::StateAttribute::ON
> );
>        stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
> //        stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
>        stateset->setAttributeAndModes
>            ( new osg::Depth( osg::Depth::ALWAYS, 0, 1, false ) );
>        stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
>
>        osg::Program* program = new osg::Program;
>        program->addShader( _depthColorFragmentShader.get() );
>        stateset->setAttribute( program );
>        stateset->addUniform( new osg::Uniform( "texture" , 0 ) );
>
>        geometry->setDrawCallback
>            ( new DrawableDrawWithDepthShadowComparisonOffCallback(
> _texture.get() ) );
>
>        geode->addDrawable( geometry );
>    }
>
>    { // Create transforms and geodes to manage polytope drawing
>        osg::StateSet * stateset = new osg::StateSet;
>        stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
>        stateset->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::OFF);
>        stateset->setTextureMode(1, GL_TEXTURE_2D, osg::StateAttribute::OFF);
>        stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
>        stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
>        stateset->setAttribute( new osg::Program() );
>        stateset->setAttributeAndModes
>            ( new osg::Depth( osg::Depth::LEQUAL, 0, 1, false ) );
>
>        for( int i = 0; i < 2; i++ ) {
>            _geode[i]->setStateSet( stateset );
>            _transform[i] = new osg::MatrixTransform;
>            _transform[i]->addChild( _geode[i].get() );
>            _transform[i]->setMatrix( osg::Matrix::identity() );
>            _transform[i]->setReferenceFrame(
> osg::MatrixTransform::ABSOLUTE_RF );
>        }
>
>        _transform[1]->setMatrix
>            ( osg::Matrix::translate( 1, 1, 0 ) *
>              osg::Matrix::scale( 0.5, 0.5, 1 ) *
>              osg::Matrix::scale( _hudSize[0], _hudSize[1], 1 ) *
>              osg::Matrix::translate( _hudOrigin[0], _hudOrigin[1], 0 ) );
>
>        _cameraDebugHUD->addChild( _transform[1].get() );
>    }
> }
>
> osg::Vec3d DebugShadowMap::ViewData::computeShadowTexelToPixelError
>     ( const osg::Matrix & mvpwView,
>       const osg::Matrix & mvpwShadow,
>       const osg::Vec3d & vWorld,
>       const osg::Vec3d & vDelta )
> {
>    osg::Vec3d vS0 = mvpwShadow * vWorld;
>    osg::Vec3d vS1 = mvpwShadow * ( vWorld + vDelta );
>
>    osg::Vec3d vV0 = mvpwView * vWorld;
>    osg::Vec3d vV1 = mvpwView * ( vWorld + vDelta );
>
>    osg::Vec3d dV = vV1 - vV0;
>    osg::Vec3d dS = vS1 - vS0;
>
>    return osg::Vec3( dS[0] / dV[0], dS[1] / dV[1], dS[2] / dV[2] );
> }
>
> void DebugShadowMap::ViewData::displayShadowTexelToPixelErrors
>  ( const osg::Camera* viewCamera,
>    const osg::Camera* shadowCamera,
>    const ConvexPolyhedron* hull )
> {
>    osg::Matrix mvpwMain  =
>        viewCamera->getViewMatrix() *
>        viewCamera->getProjectionMatrix() *
>        viewCamera->getViewport()->computeWindowMatrix();
>
>    osg::Matrix mvpwShadow  =
>        shadowCamera->getViewMatrix() *
>        shadowCamera->getProjectionMatrix() *
>        shadowCamera->getViewport()->computeWindowMatrix();
>
>    osg::BoundingBox bb =
>        hull->computeBoundingBox( viewCamera->getViewMatrix() );
>
>    osg::Matrix m = viewCamera->getInverseViewMatrix();
>
>    osg::Vec3d vn = osg::Vec3d( 0, 0, bb._max[2] ) * m;
>    osg::Vec3d vf = osg::Vec3d( 0, 0, bb._min[2] ) * m;
>    osg::Vec3d vm = osg::Vec3d( 0, 0, ( bb._max[2] + bb._min[2] ) * 0.5 ) *
> m;
>
>    osg::Vec3d vne = computeShadowTexelToPixelError( mvpwMain, mvpwShadow, vn
> );
>    osg::Vec3d vfe = computeShadowTexelToPixelError( mvpwMain, mvpwShadow, vf
> );
>    osg::Vec3d vme = computeShadowTexelToPixelError( mvpwMain, mvpwShadow, vm
> );
>
>    std::cout << std::setprecision( 3 ) << " "
>        << "ne=(" << vne[0] << "," << vne[1] << "," << vne[2] << ")  "
>        << "fe=(" << vfe[0] << "," << vfe[1] << "," << vfe[2] << ")  "
>        << "me=(" << vme[0] << "," << vme[1] << "," << vme[2] << ")  "
>        <<
> "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
>        <<
> "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
>        <<
> "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
>        << std::flush;
> }
>
>
> /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
>  *
>  * This library is open source and may be redistributed and/or modified
> under
>  * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
>  * (at your option) any later version.  The full license is in LICENSE file
>  * included with this distribution, and on the openscenegraph.org website.
>  *
>  * This library is distributed in the hope that it will be useful,
>  * but WITHOUT ANY WARRANTY; without even the implied warranty of
>  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>  * OpenSceneGraph Public License for more details.
> */
>
> #include <osgShadow/ShadowMap>
> #include <osgShadow/ShadowedScene>
> #include <osg/Notify>
> #include <osg/ComputeBoundsVisitor>
> #include <osg/PolygonOffset>
> #include <osg/CullFace>
> #include <osg/io_utils>
>
> using namespace osgShadow;
>
> #include <iostream>
> //for debug
> #include <osg/LightSource>
> #include <osg/PolygonMode>
> #include <osg/Geometry>
> #include <osgDB/ReadFile>
> #include <osgText/Text>
>
> #define IMPROVE_TEXGEN_PRECISION 1
>
> //////////////////////////////////////////////////////////////////
> // fragment shader
> //
> static const char fragmentShaderSource_noBaseTexture[] =
>    "uniform sampler2DShadow osgShadow_shadowTexture; \n"
>    "uniform vec2 osgShadow_ambientBias; \n"
>    "\n"
>    "void main(void) \n"
>    "{ \n"
>    "    gl_FragColor = gl_Color * (osgShadow_ambientBias.x + shadow2DProj(
> osgShadow_shadowTexture, gl_TexCoord[0] ) * osgShadow_ambientBias.y); \n"
>    "}\n";
>
> //////////////////////////////////////////////////////////////////
> // fragment shader
> //
> static const char fragmentShaderSource_withBaseTexture[] =
>    "uniform sampler2D osgShadow_baseTexture; \n"
>    "uniform sampler2DShadow osgShadow_shadowTexture; \n"
>    "uniform vec2 osgShadow_ambientBias; \n"
>    "\n"
>    "void main(void) \n"
>    "{ \n"
>    "    vec4 color = gl_Color * texture2D( osgShadow_baseTexture,
> gl_TexCoord[0].xy ); \n"
>    "    gl_FragColor = color * (osgShadow_ambientBias.x + shadow2DProj(
> osgShadow_shadowTexture, gl_TexCoord[1] ) * osgShadow_ambientBias.y); \n"
>    "}\n";
>
> //////////////////////////////////////////////////////////////////
> // fragment shader
> //
> static const char fragmentShaderSource_debugHUD_texcoord[] =
>    "uniform sampler2D osgShadow_shadowTexture; \n"
>    " \n"
>    "void main(void) \n"
>    "{ \n"
>    "   vec4 texCoord = gl_TexCoord[1].xyzw; \n"
>    "   float value = texCoord.z / texCoord.w; \n"
>    "   gl_FragColor = vec4( value, value, value, 1.0 ); \n"
>    "} \n";
>
> static const char fragmentShaderSource_debugHUD[] =
>    "uniform sampler2D osgShadow_shadowTexture; \n"
>    " \n"
>    "void main(void) \n"
>    "{ \n"
>    "   vec4 texResult = texture2D(osgShadow_shadowTexture, gl_TexCoord[0].st
> ); \n"
>    "   float value = texResult.r; \n"
>    "   gl_FragColor = vec4( value, value, value, 0.8 ); \n"
>    "} \n";
>
> ShadowMap::ShadowMap():
>    _baseTextureUnit(0),
>    _shadowTextureUnit(1),
>    _polyOffset(1.0,1.0),
>    _ambientBias(0.5f,0.5f),
>    _textureSize(1024,1024)
> {
> }
>
> ShadowMap::ShadowMap(const ShadowMap& copy, const osg::CopyOp& copyop):
> ShadowTechnique(copy,copyop),
>    _baseTextureUnit(copy._baseTextureUnit),
>    _shadowTextureUnit(copy._shadowTextureUnit),
>    _polyOffset(copy._polyOffset),
>    _ambientBias(copy._ambientBias),
>    _textureSize(copy._textureSize)
> {
> }
>
> void ShadowMap::setTextureUnit(unsigned int unit)
> {
>    _shadowTextureUnit = unit;
> }
>
> void ShadowMap::setPolygonOffset(const osg::Vec2& polyOffset)
> {
>    _polyOffset = polyOffset;
> }
>
> void ShadowMap::setAmbientBias(const osg::Vec2& ambientBias)
> {
>    _ambientBias = ambientBias;
>    if (_ambientBiasUniform.valid()) _ambientBiasUniform->set(_ambientBias);
> }
>
> void ShadowMap::setTextureSize(const osg::Vec2s& textureSize)
> {
>    _textureSize = textureSize;
>    dirty();
> }
>
> void ShadowMap::setLight(osg::Light* light)
> {
>    _light = light;
> }
>
>
> void ShadowMap::setLight(osg::LightSource* ls)
> {
>    _ls = ls;
>    _light = _ls->getLight();
> }
>
> void ShadowMap::createUniforms()
> {
>    _uniformList.clear();
>
>    osg::Uniform* baseTextureSampler = new
> osg::Uniform("osgShadow_baseTexture",(int)_baseTextureUnit);
>    _uniformList.push_back(baseTextureSampler);
>
>    osg::Uniform* shadowTextureSampler = new
> osg::Uniform("osgShadow_shadowTexture",(int)_shadowTextureUnit);
>    _uniformList.push_back(shadowTextureSampler);
>
>    _ambientBiasUniform = new
> osg::Uniform("osgShadow_ambientBias",_ambientBias);
>    _uniformList.push_back(_ambientBiasUniform.get());
>
> }
>
> void ShadowMap::createShaders()
> {
>    // if we are not given shaders, use the default
>    if( _shaderList.empty() )
>    {
>        if (_shadowTextureUnit==0)
>        {
>            osg::Shader* fragment_shader = new
> osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_noBaseTexture);
>            _shaderList.push_back(fragment_shader);
>        }
>        else
>        {
>            osg::Shader* fragment_shader = new
> osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_withBaseTexture);
>            _shaderList.push_back(fragment_shader);
>
>        }
>    }
> }
>
> void ShadowMap::init()
> {
>    if (!_shadowedScene) return;
>
>    _texture = new osg::Texture2D;
>    _texture->setTextureSize(_textureSize.x(), _textureSize.y());
>    _texture->setInternalFormat(GL_DEPTH_COMPONENT);
>    _texture->setShadowComparison(true);
>    _texture->setShadowTextureMode(osg::Texture2D::LUMINANCE);
>    _texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
>    _texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
>
>    // the shadow comparison should fail if object is outside the texture
>
>  _texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER);
>
>  _texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER);
>    _texture->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
>
>    // set up the render to texture camera.
>    {
>        // create the camera
>        _camera = new osg::Camera;
>
>
>  _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT);
>
>        _camera->setCullCallback(new CameraCullCallback(this));
>
>        _camera->setClearMask(GL_DEPTH_BUFFER_BIT);
>        //_camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
>        _camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
>        _camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
>
>        // set viewport
>        _camera->setViewport(0,0,_textureSize.x(),_textureSize.y());
>
>        // set the camera to render before the main camera.
>        _camera->setRenderOrder(osg::Camera::PRE_RENDER);
>
>        // tell the camera to use OpenGL frame buffer object where supported.
>
>  _camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
>
>  //_camera->setRenderTargetImplementation(osg::Camera::SEPERATE_WINDOW);
>
>        // attach the texture and use it as the color buffer.
>        _camera->attach(osg::Camera::DEPTH_BUFFER, _texture.get());
>
>        osg::StateSet* stateset = _camera->getOrCreateStateSet();
>
>
> #if 1
>        // cull front faces so that only backfaces contribute to depth map
>
>
>        osg::ref_ptr<osg::CullFace> cull_face = new osg::CullFace;
>        cull_face->setMode(osg::CullFace::FRONT);
>        stateset->setAttribute(cull_face.get(), osg::StateAttribute::ON |
> osg::StateAttribute::OVERRIDE);
>        stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON |
> osg::StateAttribute::OVERRIDE);
>
>        // negative polygonoffset - move the backface nearer to the eye point
> so that backfaces
>        // shadow themselves
>        float factor = -_polyOffset[0];
>        float units =  -_polyOffset[1];
>
>        osg::ref_ptr<osg::PolygonOffset> polygon_offset = new
> osg::PolygonOffset;
>        polygon_offset->setFactor(factor);
>        polygon_offset->setUnits(units);
>        stateset->setAttribute(polygon_offset.get(), osg::StateAttribute::ON
> | osg::StateAttribute::OVERRIDE);
>        stateset->setMode(GL_POLYGON_OFFSET_FILL, osg::StateAttribute::ON |
> osg::StateAttribute::OVERRIDE);
> #else
>        // disabling cull faces so that only front and backfaces contribute
> to depth map
>        stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF |
> osg::StateAttribute::OVERRIDE);
>
>        // negative polygonoffset - move the backface nearer to the eye point
>        // so that front faces do not shadow themselves.
>        float factor = _polyOffset[0];
>        float units =  _polyOffset[1];
>
>        osg::ref_ptr<osg::PolygonOffset> polygon_offset = new
> osg::PolygonOffset;
>        polygon_offset->setFactor(factor);
>        polygon_offset->setUnits(units);
>        stateset->setAttribute(polygon_offset.get(), osg::StateAttribute::ON
> | osg::StateAttribute::OVERRIDE);
>        stateset->setMode(GL_POLYGON_OFFSET_FILL, osg::StateAttribute::ON |
> osg::StateAttribute::OVERRIDE);
> #endif
>    }
>
>    {
>        _stateset = new osg::StateSet;
>
>  
> _stateset->setTextureAttributeAndModes(_shadowTextureUnit,_texture.get(),osg::StateAttribute::ON
> | osg::StateAttribute::OVERRIDE);
>
>  
> _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON);
>
>  
> _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON);
>
>  
> _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON);
>
>  
> _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON);
>
>        _texgen = new osg::TexGen;
>
>        // add Program, when empty of Shaders then we are using fixed
> functionality
>        _program = new osg::Program;
>        _stateset->setAttribute(_program.get());
>
>        // create default shaders if needed
>        createShaders();
>
>        // add the shader list to the program
>        for(ShaderList::const_iterator itr=_shaderList.begin();
>            itr!=_shaderList.end();
>            ++itr)
>        {
>            _program->addShader(itr->get());
>        }
>
>        // create own uniforms
>        createUniforms();
>
>        // add the uniform list to the stateset
>        for(UniformList::const_iterator itr=_uniformList.begin();
>            itr!=_uniformList.end();
>            ++itr)
>        {
>            _stateset->addUniform(itr->get());
>        }
>
>        {
>            // fake texture for baseTexture, add a fake texture
>            // we support by default at least one texture layer
>            // without this fake texture we can not support
>            // textured and not textured scene
>
>            // TODO: at the moment the PSSM supports just one texture layer
> in the GLSL shader, multitexture are
>            //       not yet supported !
>
>            osg::Image* image = new osg::Image;
>            // allocate the image data, noPixels x 1 x 1 with 4 rgba floats -
> equivilant to a Vec4!
>            int noPixels = 1;
>            image->allocateImage(noPixels,1,1,GL_RGBA,GL_FLOAT);
>            image->setInternalTextureFormat(GL_RGBA);
>            // fill in the image data.
>            osg::Vec4* dataPtr = (osg::Vec4*)image->data();
>            osg::Vec4 color(1,1,1,1);
>            *dataPtr = color;
>            // make fake texture
>            osg::Texture2D* fakeTex = new osg::Texture2D;
>
>  fakeTex->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_EDGE);
>
>  fakeTex->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_EDGE);
>
>  fakeTex->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
>
>  fakeTex->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
>            fakeTex->setImage(image);
>            // add fake texture
>
>  
> _stateset->setTextureAttribute(_baseTextureUnit,fakeTex,osg::StateAttribute::ON);
>
>  
> _stateset->setTextureMode(_baseTextureUnit,GL_TEXTURE_1D,osg::StateAttribute::OFF);
>
>  
> _stateset->setTextureMode(_baseTextureUnit,GL_TEXTURE_2D,osg::StateAttribute::ON);
>
>  
> _stateset->setTextureMode(_baseTextureUnit,GL_TEXTURE_3D,osg::StateAttribute::OFF);
>        }
>    }
>
>    _dirty = false;
> }
>
>
> void ShadowMap::update(osg::NodeVisitor& nv)
> {
>    _shadowedScene->osg::Group::traverse(nv);
> }
>
> void ShadowMap::cull(osgUtil::CullVisitor& cv)
> {
>    // record the traversal mask on entry so we can reapply it later.
>    unsigned int traversalMask = cv.getTraversalMask();
>
>    osgUtil::RenderStage* orig_rs = cv.getRenderStage();
>
>    // do traversal of shadow recieving scene which does need to be decorated
> by the shadow map
>    {
>        cv.pushStateSet(_stateset.get());
>
>        _shadowedScene->osg::Group::traverse(cv);
>
>        cv.popStateSet();
>
>    }
>
>    // need to compute view frustum for RTT camera.
>    // 1) get the light position
>    // 2) get the center and extents of the view frustum
>
>    const osg::Light* selectLight = 0;
>    osg::Vec4 lightpos;
>    osg::Vec3 lightDir;
>
>    //MR testing giving a specific light
>    osgUtil::PositionalStateContainer::AttrMatrixList& aml =
> orig_rs->getPositionalStateContainer()->getAttrMatrixList();
>    for(osgUtil::PositionalStateContainer::AttrMatrixList::iterator itr =
> aml.begin();
>        itr != aml.end();
>        ++itr)
>    {
>        const osg::Light* light = dynamic_cast<const
> osg::Light*>(itr->first.get());
>        if (light)
>        {
>            if( _light.valid()) {
>                if( _light.get() == light )
>                    selectLight = light;
>                else
>                    continue;
>            }
>            else
>                selectLight = light;
>
>            osg::RefMatrix* matrix = itr->second.get();
>            if (matrix)
>            {
>                lightpos = light->getPosition() * (*matrix);
>                lightDir = osg::Matrix::transform3x3( light->getDirection(),
> *matrix );
>            }
>            else
>            {
>                lightpos = light->getPosition();
>                lightDir = light->getDirection();
>            }
>
>        }
>    }
>
>    osg::Matrix eyeToWorld;
>    eyeToWorld.invert(*cv.getModelViewMatrix());
>
>    lightpos = lightpos * eyeToWorld;
>    lightDir = osg::Matrix::transform3x3( lightDir, eyeToWorld );
>    lightDir.normalize();
>
>    if (selectLight)
>    {
>
>        // set to ambient on light to black so that the ambient bias uniform
> can take it's affect
>
>  
> const_cast<osg::Light*>(selectLight)->setAmbient(osg::Vec4(0.0f,0.0f,0.0f,1.0f));
>
>        //std::cout<<"----- VxOSG::ShadowMap selectLight spot cutoff
> "<<selectLight->getSpotCutoff()<<std::endl;
>
>        float fov = selectLight->getSpotCutoff() * 2;
>        if(fov < 180.0f)   // spotlight, then we don't need the bounding box
>        {
>            osg::Vec3 position(lightpos.x(), lightpos.y(), lightpos.z());
>            _camera->setProjectionMatrixAsPerspective(fov, 1.0, 0.1, 1000.0);
>
>  
> _camera->setViewMatrixAsLookAt(position,position+lightDir,osg::Vec3(0.0f,1.0f,0.0f));
>        }
>        else
>        {
>            // get the bounds of the model.
>            osg::ComputeBoundsVisitor
> cbbv(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN);
>
>  cbbv.setTraversalMask(getShadowedScene()->getCastsShadowTraversalMask());
>
>            _shadowedScene->osg::Group::traverse(cbbv);
>
>            osg::BoundingBox bb = cbbv.getBoundingBox();
>
>            if (lightpos[3]!=0.0)   // point light
>            {
>                osg::Vec3 position(lightpos.x(), lightpos.y(), lightpos.z());
>
>                float centerDistance = (position-bb.center()).length();
>
>                float znear = centerDistance-bb.radius();
>                float zfar  = centerDistance+bb.radius();
>                float zNearRatio = 0.001f;
>                if (znear<zfar*zNearRatio) znear = zfar*zNearRatio;
>
>                float top   = (bb.radius()/centerDistance)*znear;
>                float right = top;
>
>
>  _camera->setProjectionMatrixAsFrustum(-right,right,-top,top,znear,zfar);
>
>  
> _camera->setViewMatrixAsLookAt(position,bb.center(),osg::Vec3(0.0f,1.0f,0.0f));
>            }
>            else    // directional light
>            {
>                // make an orthographic projection
>                osg::Vec3 lightDir(lightpos.x(), lightpos.y(), lightpos.z());
>                lightDir.normalize();
>
>                // set the position far away along the light direction
>                osg::Vec3 position = bb.center() + lightDir * bb.radius() *
> 2;
>
>                float centerDistance = (position-bb.center()).length();
>
>                float znear = centerDistance-bb.radius();
>                float zfar  = centerDistance+bb.radius();
>                float zNearRatio = 0.001f;
>                if (znear<zfar*zNearRatio) znear = zfar*zNearRatio;
>
>                float top   = bb.radius();
>                float right = top;
>
>                _camera->setProjectionMatrixAsOrtho(-right, right, -top, top,
> znear, zfar);
>
>  
> _camera->setViewMatrixAsLookAt(position,bb.center(),osg::Vec3(0.0f,1.0f,0.0f));
>            }
>
>
>        }
>
>        cv.setTraversalMask( traversalMask &
>            getShadowedScene()->getCastsShadowTraversalMask() );
>
>        // do RTT camera traversal
>        _camera->accept(cv);
>
>        _texgen->setMode(osg::TexGen::EYE_LINEAR);
>
> #if IMPROVE_TEXGEN_PRECISION
>        // compute the matrix which takes a vertex from local coords into tex
> coords
>        // We actually use two matrices one used to define texgen
>        // and second that will be used as modelview when appling to OpenGL
>        _texgen->setPlanesFromMatrix( _camera->getProjectionMatrix() *
>                                      osg::Matrix::translate(1.0,1.0,1.0) *
>                                      osg::Matrix::scale(0.5f,0.5f,0.5f) );
>
>        // Place texgen with modelview which removes big offsets (making it
> float friendly)
>        osg::RefMatrix * refMatrix = new osg::RefMatrix
>            ( _camera->getInverseViewMatrix() * *cv.getModelViewMatrix() );
>
>        cv.getRenderStage()->getPositionalStateContainer()->
>             addPositionedTextureAttribute( _shadowTextureUnit, refMatrix,
> _texgen.get() );
> #else
>        // compute the matrix which takes a vertex from local coords into tex
> coords
>        // will use this later to specify osg::TexGen..
>        osg::Matrix MVPT = _camera->getViewMatrix() *
>               _camera->getProjectionMatrix() *
>               osg::Matrix::translate(1.0,1.0,1.0) *
>               osg::Matrix::scale(0.5f,0.5f,0.5f);
>
>        _texgen->setPlanesFromMatrix(MVPT);
>
>
>  
> orig_rs->getPositionalStateContainer()->addPositionedTextureAttribute(_shadowTextureUnit,
> cv.getModelViewMatrix(), _texgen.get());
> #endif
>    } // if(selectLight)
>
>
>    // reapply the original traversal mask
>    cv.setTraversalMask( traversalMask );
> }
>
> void ShadowMap::cleanSceneGraph()
> {
> }
>
> ///////////////////// Debug Methods
>
> ////////////////////////////////////////////////////////////////////////////////
> osg::ref_ptr<osg::Camera> ShadowMap::makeDebugHUD()
> {
> ////////////////////////////////////////////////////////////////////////////////
> // Callback used by debugging hud to display Shadow Map in color buffer
> // OSG does not allow to use the same GL Texture Id with different
> glTexParams.
> // Callback simply turns shadow compare mode off via GL while rendering hud
> and
> // restores it afterwards.
> ////////////////////////////////////////////////////////////////////////////////
>        class DrawableDrawWithDepthShadowComparisonOffCallback:
>                public osg::Drawable::DrawCallback
>        {
>        public:
>                //
>                DrawableDrawWithDepthShadowComparisonOffCallback
>                        ( osg::Texture2D * texture, unsigned stage = 0 )
>                                : _texture( texture ), _stage( stage )
>                {
>                }
>
>                virtual void drawImplementation
>                        ( osg::RenderInfo & ri,const osg::Drawable* drawable
> ) const
>                {
>                        if( _texture.valid() ) {
>                                // make sure proper texture is currently
> applied
>                                ri.getState()->applyTextureAttribute( _stage,
> _texture.get() );
>
>                                // Turn off depth comparison mode
>                                glTexParameteri( GL_TEXTURE_2D,
> GL_TEXTURE_COMPARE_MODE_ARB,
>                                                                 GL_NONE );
>                        }
>
>                        drawable->drawImplementation(ri);
>
>                        if( _texture.valid() ) {
>                                // Turn it back on
>                                glTexParameteri( GL_TEXTURE_2D,
> GL_TEXTURE_COMPARE_MODE_ARB,
>
> GL_COMPARE_R_TO_TEXTURE_ARB );
>                        }
>                }
>
>                osg::ref_ptr< osg::Texture2D > _texture;
>                unsigned                       _stage;
>        };
>
>    // Make sure we attach initialized texture to HUD
>    if( !_texture.valid() )    init();
>
>    osg::ref_ptr<osg::Camera> camera = new osg::Camera;
>
>    osg::Vec2 size(1280, 1024);
>    // set the projection matrix
>    camera->setProjectionMatrix(osg::Matrix::ortho2D(0,size.x(),0,size.y()));
>
>    // set the view matrix
>    camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
>    camera->setViewMatrix(osg::Matrix::identity());
>
>    // only clear the depth buffer
>    camera->setClearMask(GL_DEPTH_BUFFER_BIT);
>    camera->setClearColor(osg::Vec4(0.2f, 0.3f, 0.5f, 0.2f));
>    //camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
>
>    // draw subgraph after main camera view.
>    camera->setRenderOrder(osg::Camera::POST_RENDER);
>
>    // we don't want the camera to grab event focus from the viewers main
> camera(s).
>    camera->setAllowEventFocus(false);
>
>    osg::Geode* geode = new osg::Geode;
>
>    osg::Vec3 position(10.0f,size.y()-100.0f,0.0f);
>    osg::Vec3 delta(0.0f,-120.0f,0.0f);
>    float length = 300.0f;
>
>    // turn the text off to avoid linking with osgText
> #if 0
>    std::string timesFont("fonts/arial.ttf");
>
>    {
>        osgText::Text* text = new  osgText::Text;
>        geode->addDrawable( text );
>
>        text->setFont(timesFont);
>        text->setPosition(position);
>        text->setText("Shadow Map HUD");
>
>        position += delta;
>    }
> #endif
>
>    osg::Vec3 widthVec(length, 0.0f, 0.0f);
>    osg::Vec3 depthVec(0.0f,length, 0.0f);
>    osg::Vec3 centerBase( 10.0f + length/2, size.y()-length/2, 0.0f);
>    centerBase += delta;
>
>    osg::Geometry *geometry = osg::createTexturedQuadGeometry
>        ( centerBase-widthVec*0.5f-depthVec*0.5f, widthVec, depthVec );
>
>    geode->addDrawable( geometry );
>
>    geometry->setDrawCallback
>        ( new DrawableDrawWithDepthShadowComparisonOffCallback(
> _texture.get() ) );
>
>    osg::StateSet* stateset = geode->getOrCreateStateSet();
>
>    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
>    stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
>    stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
>
>    // test with regular texture
>    //stateset->setTextureAttributeAndModes(0, new
> osg::Texture2D(osgDB::readImageFile("Images/lz.rgb")));
>
>
>  
> stateset->setTextureAttributeAndModes(0,_texture.get(),osg::StateAttribute::ON);
>
>    //test to check the texture coordinates generated during shadow pass
> #if 0
>
>  
> stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON);
>
>  
> stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON);
>
>  
> stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON);
>
>  
> stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON);
>
>    // create TexGen node
>    osg::ref_ptr<osg::TexGenNode> texGenNode = new osg::TexGenNode;
>    texGenNode->setTextureUnit(_shadowTextureUnit);
>    texGenNode->setTexGen(_texgen.get());
>    camera->addChild(texGenNode.get());
> #endif
>    //shader for correct display
>
>    osg::ref_ptr<osg::Program> program = new osg::Program;
>    stateset->setAttribute(program.get());
>
>    osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT,
> fragmentShaderSource_debugHUD);
>    program->addShader(fragment_shader);
>
>    camera->addChild(geode);
>
>    return camera;
> }
>
> //////////////////////// End Debug Section
>
>
> _______________________________________________
> osg-submissions mailing list
> [email protected]
> http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org
>
>
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

Reply via email to