void PickVisitor::apply(osg::Camera& camera)
{
    if (!camera.isRenderToTextureCamera())
    {
        if (camera.getReferenceFrame()==osg::Camera::RELATIVE_RF)
        {
            if (camera.getTransformOrder()==osg::Camera::POST_MULTIPLY)
            {
                runNestedPickVisitor( camera,
                                      camera.getViewport() ? camera.getViewport() : _lastViewport.get(),
                                      _lastProjectionMatrix * camera.getProjectionMatrix(),
                                      _lastViewMatrix * camera.getViewMatrix(),
                                      _mx, _my );
            }
            else // PRE_MULTIPLY
            {
                runNestedPickVisitor( camera,
                                      camera.getViewport() ? camera.getViewport() : _lastViewport.get(),
                                      camera.getProjectionMatrix() * _lastProjectionMatrix,
                                      camera.getViewMatrix() * _lastViewMatrix,
                                      _mx, _my );
            }
        }
        else
        {
            runNestedPickVisitor( camera,
                                  camera.getViewport() ? camera.getViewport() : _lastViewport.get(),
                                  camera.getProjectionMatrix(),
                                  camera.getViewMatrix(),
                                  _mx, _my );
        }
    }
}
void IntersectionVisitor::apply(osg::Camera& camera)
{
    // osg::notify(osg::NOTICE)<<"apply(Camera&)"<<std::endl;

    // note, commenting out right now because default Camera setup is with the culling active.  Should this be changed?
    // if (!enter(camera)) return;
    
    // osg::notify(osg::NOTICE)<<"inside apply(Camera&)"<<std::endl;

    if (camera.getViewport()) pushWindowMatrix( camera.getViewport() );
    pushProjectionMatrix( new osg::RefMatrix(camera.getProjectionMatrix()) );
    pushViewMatrix( new osg::RefMatrix(camera.getViewMatrix()) );
    pushModelMatrix( new osg::RefMatrix() );

    // now push an new intersector clone transform to the new local coordinates
    push_clone();

    traverse(camera);
    
    // pop the clone.
    pop_clone();
    
    popModelMatrix();
    popViewMatrix();
    popProjectionMatrix();
    if (camera.getViewport()) popWindowMatrix();

    // leave();
}
void MinimalDrawBoundsShadowMap::ViewData::performBoundAnalysis( const osg::Camera& camera )
{
    if( !_projection.valid() )
        return;

    osg::Camera::BufferAttachmentMap & bam 
        = const_cast<osg::Camera&>( camera ).getBufferAttachmentMap();
#if ANALYSIS_DEPTH
    osg::Camera::Attachment & attachment = bam[ osg::Camera::DEPTH_BUFFER ];
#else
    osg::Camera::Attachment & attachment = bam[ osg::Camera::COLOR_BUFFER ];
#endif

    const osg::ref_ptr< osg::Image > image = attachment._image.get();
    if( !image.valid() ) 
        return;

    osg::Matrix m;
    m.invert( *_modellingSpaceToWorldPtr * 
              camera.getViewMatrix() * 
              camera.getProjectionMatrix() );

    m.preMult( osg::Matrix::scale( osg::Vec3( 2.f, 2.f, 2.f ) ) *
               osg::Matrix::translate( osg::Vec3( -1.f, -1.f, -1.f ) ) );

    osg::BoundingBox bb = scanImage( image.get(), m );

    if( getDebugDraw() ) { 
        ConvexPolyhedron p;
        p.setToBoundingBox( bb );
        p.transform( *_modellingSpaceToWorldPtr, 
                 osg::Matrix::inverse( *_modellingSpaceToWorldPtr ) );

        setDebugPolytope( "scan", p,
                      osg::Vec4( 0,0,0,1 ), osg::Vec4( 0,0,0,0.1 ) );
    }

    cutScenePolytope( *_modellingSpaceToWorldPtr, 
                     osg::Matrix::inverse( *_modellingSpaceToWorldPtr ), bb );

    frameShadowCastingCamera( _mainCamera.get(), _camera.get() );

    _projection->set( _camera->getProjectionMatrix( ) );

    BaseClass::ViewData::_texgen->setPlanesFromMatrix(
            _camera->getProjectionMatrix() *
            osg::Matrix::translate(1.0,1.0,1.0) *
            osg::Matrix::scale(0.5,0.5,0.5) );

    updateDebugGeometry( _mainCamera.get(),  _camera.get() );
}
void ScreenMVCullVisitor::apply(osg::Camera& camera)
{
    //std::cerr << "MVCV camera" << std::endl;
    // push the node's state.
    StateSet* node_state = camera.getStateSet();
    if(node_state)
        pushStateSet(node_state);

//#define DEBUG_CULLSETTINGS

#ifdef DEBUG_CULLSETTINGS
    if (osg::isNotifyEnabled(osg::NOTICE))
    {
        notify(osg::NOTICE)<<std::endl<<std::endl<<"CullVisitor, before : ";
        write(osg::notify(osg::NOTICE));
    }
#endif

    // Save current cull settings
    CullSettings saved_cull_settings(*this);

#ifdef DEBUG_CULLSETTINGS
    if (osg::isNotifyEnabled(osg::NOTICE))
    {
        osg::notify(osg::NOTICE)<<"CullVisitor, saved_cull_settings : ";
        saved_cull_settings.write(osg::notify(osg::NOTICE));
    }
#endif

#if 1
    // set cull settings from this Camera
    setCullSettings(camera);

#ifdef DEBUG_CULLSETTINGS
    osg::notify(osg::NOTICE)<<"CullVisitor, after setCullSettings(camera) : ";
    write(osg::notify(osg::NOTICE));
#endif
    // inherit the settings from above
    inheritCullSettings(saved_cull_settings,camera.getInheritanceMask());

#ifdef DEBUG_CULLSETTINGS
    osg::notify(osg::NOTICE)<<"CullVisitor, after inheritCullSettings(saved_cull_settings,"<<camera.getInheritanceMask()<<") : ";
    write(osg::notify(osg::NOTICE));
#endif

#else
    // activate all active cull settings from this Camera
    inheritCullSettings(camera);
#endif

    // set the cull mask.
    unsigned int savedTraversalMask = getTraversalMask();
    bool mustSetCullMask = (camera.getInheritanceMask()
            & osg::CullSettings::CULL_MASK) == 0;
    if(mustSetCullMask)
        setTraversalMask(camera.getCullMask());

    RefMatrix& originalModelView = *getModelViewMatrix();

    osg::RefMatrix* projection = 0;
    osg::RefMatrix* modelview = 0;

    if(camera.getReferenceFrame() == osg::Transform::RELATIVE_RF)
    {
        if(camera.getTransformOrder() == osg::Camera::POST_MULTIPLY)
        {
            projection = createOrReuseMatrix(
                    *getProjectionMatrix() * camera.getProjectionMatrix());
            modelview = createOrReuseMatrix(
                    *getModelViewMatrix() * camera.getViewMatrix());
        }
        else // pre multiply 
        {
            projection = createOrReuseMatrix(
                    camera.getProjectionMatrix() * (*getProjectionMatrix()));
            modelview = createOrReuseMatrix(
                    camera.getViewMatrix() * (*getModelViewMatrix()));
        }
    }
    else
    {
        // an absolute reference frame
        projection = createOrReuseMatrix(camera.getProjectionMatrix());
        modelview = createOrReuseMatrix(camera.getViewMatrix());
    }

    if(camera.getViewport())
        pushViewport(camera.getViewport());

    // record previous near and far values.
    float previous_znear = _computed_znear;
    float previous_zfar = _computed_zfar;

    // take a copy of the current near plane candidates
    DistanceMatrixDrawableMap previousNearPlaneCandidateMap;
    previousNearPlaneCandidateMap.swap(_nearPlaneCandidateMap);

    _computed_znear = FLT_MAX;
    _computed_zfar = -FLT_MAX;

    pushProjectionMatrix(projection);
    pushModelViewMatrix(modelview,camera.getReferenceFrame());

    if(camera.getRenderOrder() == osg::Camera::NESTED_RENDER)
    {
        handle_cull_callbacks_and_traverse(camera);
    }
    else
    {
        // set up lighting.
        // currently ignore lights in the scene graph itself..
        // will do later.
        osgUtil::RenderStage* previous_stage =
                getCurrentRenderBin()->getStage();

//        unsigned int contextID = getState() ? getState()->getContextID() : 0;

        // use render to texture stage.
        // create the render to texture stage.
        osg::ref_ptr<osgUtil::RenderStageCache> rsCache =
                dynamic_cast<osgUtil::RenderStageCache*>(camera.getRenderingCache());
        if(!rsCache)
        {
            rsCache = new osgUtil::RenderStageCache;
            camera.setRenderingCache(rsCache.get());
        }

        osg::ref_ptr < osgUtil::RenderStage > rtts = rsCache->getRenderStage(
                this);
        if(!rtts)
        {
            OpenThreads::ScopedLock < OpenThreads::Mutex
                    > lock(*(camera.getDataChangeMutex()));

            rtts = new osgUtil::RenderStage;
            rsCache->setRenderStage(this,rtts.get());

            rtts->setCamera(&camera);

            if(camera.getInheritanceMask() & DRAW_BUFFER)
            {
                // inherit draw buffer from above.
                rtts->setDrawBuffer(previous_stage->getDrawBuffer(),
                        previous_stage->getDrawBufferApplyMask());
            }
            else
            {
                rtts->setDrawBuffer(camera.getDrawBuffer());
            }

            if(camera.getInheritanceMask() & READ_BUFFER)
            {
                // inherit read buffer from above.
                rtts->setReadBuffer(previous_stage->getReadBuffer(),
                        previous_stage->getReadBufferApplyMask());
            }
            else
            {
                rtts->setReadBuffer(camera.getReadBuffer());
            }
        }
        else
        {
            // reusing render to texture stage, so need to reset it to empty it from previous frames contents.
            rtts->reset();
        }

        // set up clera masks/values        
        rtts->setClearDepth(camera.getClearDepth());
        rtts->setClearAccum(camera.getClearAccum());
        rtts->setClearStencil(camera.getClearStencil());
        rtts->setClearMask(camera.getClearMask());

        // set up the background color and clear mask.
        if(camera.getInheritanceMask() & CLEAR_COLOR)
        {
            rtts->setClearColor(previous_stage->getClearColor());
        }
        else
        {
            rtts->setClearColor(camera.getClearColor());
        }
        if(camera.getInheritanceMask() & CLEAR_MASK)
        {
            rtts->setClearMask(previous_stage->getClearMask());
        }
        else
        {
            rtts->setClearMask(camera.getClearMask());
        }

        // set the color mask.
        osg::ColorMask* colorMask =
                camera.getColorMask() != 0 ?
                        camera.getColorMask() : previous_stage->getColorMask();
        rtts->setColorMask(colorMask);

        // set up the viewport.
        osg::Viewport* viewport =
                camera.getViewport() != 0 ?
                        camera.getViewport() : previous_stage->getViewport();
        rtts->setViewport(viewport);

        // set up to charge the same PositionalStateContainer is the parent previous stage.
        osg::Matrix inheritedMVtolocalMV;
        inheritedMVtolocalMV.invert(originalModelView);
        inheritedMVtolocalMV.postMult(*getModelViewMatrix());
        rtts->setInheritedPositionalStateContainerMatrix(inheritedMVtolocalMV);
        rtts->setInheritedPositionalStateContainer(
                previous_stage->getPositionalStateContainer());

        // record the render bin, to be restored after creation
        // of the render to text
        osgUtil::RenderBin* previousRenderBin = getCurrentRenderBin();

        // set the current renderbin to be the newly created stage.
        setCurrentRenderBin(rtts.get());

        // traverse the subgraph
        {
            handle_cull_callbacks_and_traverse(camera);
        }

        // restore the previous renderbin.
        setCurrentRenderBin(previousRenderBin);

        if(rtts->getStateGraphList().size() == 0
                && rtts->getRenderBinList().size() == 0)
        {
            // getting to this point means that all the subgraph has been
            // culled by small feature culling or is beyond LOD ranges.
        }

        // and the render to texture stage to the current stages
        // dependancy list.
        switch(camera.getRenderOrder())
        {
            case osg::Camera::PRE_RENDER:
                getCurrentRenderBin()->getStage()->addPreRenderStage(rtts.get(),
                        camera.getRenderOrderNum());
                break;
            default:
                getCurrentRenderBin()->getStage()->addPostRenderStage(
                        rtts.get(),camera.getRenderOrderNum());
                break;
        }

    }

    // restore the previous model view matrix.
    popModelViewMatrix();

    // restore the previous model view matrix.
    popProjectionMatrix();

    // restore the original near and far values
    _computed_znear = previous_znear;
    _computed_zfar = previous_zfar;

    // swap back the near plane candidates
    previousNearPlaneCandidateMap.swap(_nearPlaneCandidateMap);

    if(camera.getViewport())
        popViewport();

    // restore the previous traversal mask settings
    if(mustSetCullMask)
        setTraversalMask(savedTraversalMask);

    // restore the previous cull settings
    setCullSettings(saved_cull_settings);

    // pop the node's state off the render graph stack.    
    if(node_state)
        popStateSet();

}