void RayTracedTechnique::traverse(osg::NodeVisitor& nv)
{
    // OSG_NOTICE<<"RayTracedTechnique::traverse(osg::NodeVisitor& nv)"<<std::endl;
    if (!_volumeTile) return;

    // if app traversal update the frame count.
    if (nv.getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR)
    {
        if (_volumeTile->getDirty()) _volumeTile->init();

        osgUtil::UpdateVisitor* uv = nv.asUpdateVisitor();
        if (uv)
        {
            update(uv);
            return;
        }

    }
    else if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR)
    {
        osgUtil::CullVisitor* cv = nv.asCullVisitor();
        if (cv)
        {
            cull(cv);
            return;
        }
    }


    if (_volumeTile->getDirty())
    {
        OSG_INFO<<"******* Doing init ***********"<<std::endl;
        _volumeTile->init();
    }
}
Пример #2
0
void Technique::traverse_implementation(osg::NodeVisitor& nv, Effect* fx)
{
    // define passes if necessary
    if (_passes.empty()) {
        define_passes();
    }

    // special actions must be taken if the node visitor is actually a CullVisitor
    osgUtil::CullVisitor* cv = nv.asCullVisitor();
    if (cv)
    {
        // traverse all passes
        for (int i=0; i<getNumPasses(); ++i)
        {
            // push the i-th pass' StateSet
            cv->pushStateSet(_passes[i].get());

            // traverse the override node if defined, otherwise
            // traverse children as a Group would do
            osg::Node *override = getOverrideChild(i);
            if (override) {
                override->accept(nv);
            } else {
                fx->inherited_traverse(nv);
            }

            // pop the StateSet
            cv->popStateSet();
        }
Пример #3
0
void TXPNode::traverse(osg::NodeVisitor& nv)
{
    switch(nv.getVisitorType())
    {
    case osg::NodeVisitor::CULL_VISITOR:
    {

        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);

        osgUtil::CullVisitor* cv = nv.asCullVisitor();
        if (cv)
        {
//#define PRINT_TILEMAPP_TIMEINFO
#ifdef PRINT_TILEMAPP_TIMEINFO
            const osg::Timer& timer = *osg::Timer::instance();
            osg::Timer_t start = timer.tick();
            std::cout<<"Doing visible tile search"<<std::endl;
#endif // PRINT_TILEMAPP_TIMEINFO

            osg::ref_ptr<TileMapper> tileMapper = new TileMapper;
            tileMapper->setLODScale(cv->getLODScale());
            tileMapper->pushReferenceViewPoint(cv->getReferenceViewPoint());
            tileMapper->pushViewport(cv->getViewport());
            tileMapper->pushProjectionMatrix((cv->getProjectionMatrix()));
            tileMapper->pushModelViewMatrix((cv->getModelViewMatrix()), osg::Transform::RELATIVE_RF);

            // traverse the scene graph to search for valid tiles
            accept(*tileMapper);

            tileMapper->popModelViewMatrix();
            tileMapper->popProjectionMatrix();
            tileMapper->popViewport();
            tileMapper->popReferenceViewPoint();

            //std::cout<<"   found " << tileMapper._tileMap.size() << std::endl;

            cv->setUserData(tileMapper.get());

#ifdef PRINT_TILEMAPP_TIMEINFO
            std::cout<<"Completed visible tile search in "<<timer.delta_m(start,timer.tick())<<std::endl;
#endif // PRINT_TILEMAPP_TIMEINFO

        }

        updateEye(nv);
        break;
    }
    case osg::NodeVisitor::UPDATE_VISITOR:
    {
        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);

        updateSceneGraph();
        break;
    }
    default:
        break;
    }
    Group::traverse(nv);
}
void osgParticle::ParticleSystemUpdater::traverse(osg::NodeVisitor& nv)
{
    osgUtil::CullVisitor* cv = nv.asCullVisitor();
    if (cv)
    {
        if (nv.getFrameStamp())
        {
            if( _frameNumber < nv.getFrameStamp()->getFrameNumber())
            {
                _frameNumber = nv.getFrameStamp()->getFrameNumber();

                double t = nv.getFrameStamp()->getSimulationTime();
                if (_t0 != -1.0)
                {
                    ParticleSystem_Vector::iterator i;
                    for (i=_psv.begin(); i!=_psv.end(); ++i)
                    {
                        ParticleSystem* ps = i->get();

                        ParticleSystem::ScopedWriteLock lock(*(ps->getReadWriteMutex()));

                        // We need to allow at least 2 frames difference, because the particle system's lastFrameNumber
                        // is updated in the draw thread which may not have completed yet.
                        if (!ps->isFrozen() &&
                            (!ps->getFreezeOnCull() || ((nv.getFrameStamp()->getFrameNumber()-ps->getLastFrameNumber()) <= 2)) )
                        {
                            ps->update(t - _t0, nv);
                        }
                    }
                }
                _t0 = t;
            }

        }
        else
        {
            OSG_WARN << "osgParticle::ParticleSystemUpdater::traverse(NodeVisitor&) requires a valid FrameStamp to function, particles not updated.\n";
        }

    }
    Node::traverse(nv);
}
void ShadowTechnique::traverse(osg::NodeVisitor& nv)
{
    if (!_shadowedScene) return;

    if (nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
    {
       if (_dirty) init();

        update(nv);
    }
    else if (nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
    {
        osgUtil::CullVisitor* cv = nv.asCullVisitor();
        if (cv) cull(*cv);
        else _shadowedScene->osg::Group::traverse(nv);
    }
    else
    {
        _shadowedScene->osg::Group::traverse(nv);
    }
}
Пример #6
0
void osgParticle::ParticleSystemUpdater::traverse(osg::NodeVisitor& nv)
{
    osgUtil::CullVisitor* cv = nv.asCullVisitor();
    if (cv)
    {
        if (nv.getFrameStamp())
        {
            if( _frameNumber < nv.getFrameStamp()->getFrameNumber())
            {
                _frameNumber = nv.getFrameStamp()->getFrameNumber();

                double t = nv.getFrameStamp()->getSimulationTime();
                if (_t0 != -1.0)
                {
                    ParticleSystem_Vector::iterator i;
                    for (i=_psv.begin(); i!=_psv.end(); ++i)
                    {
                        ParticleSystem* ps = i->get();

                        ParticleSystem::ScopedWriteLock lock(*(ps->getReadWriteMutex()));

                        if (!ps->isFrozen() && (ps->getLastFrameNumber() >= (nv.getFrameStamp()->getFrameNumber() - 1) || !ps->getFreezeOnCull()))
                        {
                            ps->update(t - _t0, nv);
                        }
                    }
                }
                _t0 = t;
            }

        }
        else
        {
            OSG_WARN << "osgParticle::ParticleSystemUpdater::traverse(NodeVisitor&) requires a valid FrameStamp to function, particles not updated.\n";
        }

    }
    Node::traverse(nv);
}
Пример #7
0
void osgParticle::ParticleProcessor::traverse(osg::NodeVisitor& nv)
{
    // typecast the NodeVisitor to CullVisitor
    osgUtil::CullVisitor* cv = nv.asCullVisitor();

    // continue only if the visitor actually is a cull visitor
    if (cv) {

        // continue only if the particle system is valid
        if (_ps.valid())
        {
            if (nv.getFrameStamp())
            {
                ParticleSystem::ScopedWriteLock lock(*(_ps->getReadWriteMutex()));

                //added- 1/17/06- [email protected]
                //a check to make sure we havent updated yet this frame
                if(_frameNumber < nv.getFrameStamp()->getFrameNumber())
                {


                    // retrieve the current time
                    double t = nv.getFrameStamp()->getSimulationTime();

                    // reset this processor if we've reached the reset point
                    if ((_currentTime >= _resetTime) && (_resetTime > 0))
                    {
                        _currentTime = 0;
                        _t0 = -1;
                    }

                    // skip if we haven't initialized _t0 yet
                    if (_t0 != -1)
                    {

                        // check whether the processor is alive
                        bool alive = false;
                        if (_currentTime >= _startTime)
                        {
                            if (_endless || (_currentTime < (_startTime + _lifeTime)))
                                alive = true;
                        }

                        // update current time
                        _currentTime += t - _t0;

                        // process only if the particle system is not frozen/culled
                        // We need to allow at least 2 frames difference, because the particle system's lastFrameNumber
                        // is updated in the draw thread which may not have completed yet.
                        if (alive &&
                            _enabled &&
                            !_ps->isFrozen() &&
                            (!_ps->getFreezeOnCull() || ((nv.getFrameStamp()->getFrameNumber()-_ps->getLastFrameNumber()) <= 2)) )
                        {
                            // initialize matrix flags
                            _need_ltw_matrix = true;
                            _need_wtl_matrix = true;
                            _current_nodevisitor = &nv;

                            // do some process (unimplemented in this base class)
                            process( t - _t0 );
                        } else {
                            //The values of _previous_wtl_matrix and _previous_ltw_matrix will be invalid
                            //since processing was skipped for this frame
                            _first_ltw_compute = true;
                            _first_wtl_compute = true;
                        }
                    }
                    _t0 = t;
                }

                //added- 1/17/06- [email protected]
                //updates the _frameNumber, keeping it current
                _frameNumber = nv.getFrameStamp()->getFrameNumber();
            }
            else
            {
                OSG_WARN << "osgParticle::ParticleProcessor::traverse(NodeVisitor&) requires a valid FrameStamp to function, particles not updated.\n";
            }

        } else
        {
            OSG_WARN << "ParticleProcessor \"" << getName() << "\": invalid particle system\n";
        }
    }


    // call the inherited method
    Node::traverse(nv);
}
Пример #8
0
void VolumeScene::traverse(osg::NodeVisitor& nv)
{
    osgUtil::CullVisitor* cv = nv.asCullVisitor();
    if (!cv)
    {
        Group::traverse(nv);
        return;
    }

    osg::ref_ptr<ViewData> viewData;
    bool initializeViewData = false;
    {
        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_viewDataMapMutex);
        if (!_viewDataMap[cv])
        {
            _viewDataMap[cv] = new ViewData;
            initializeViewData = true;
        }

        viewData = _viewDataMap[cv];
    }

    if (initializeViewData)
    {
        OSG_NOTICE<<"Creating ViewData"<<std::endl;

        int textureWidth = 512;
        int textureHeight = 512;

        osg::Viewport* viewport = cv->getCurrentRenderStage()->getViewport();
        if (viewport)
        {
            textureWidth = static_cast<int>(viewport->width());
            textureHeight = static_cast<int>(viewport->height());
        }

        // set up depth texture
        viewData->_depthTexture = new osg::Texture2D;

        viewData->_depthTexture->setTextureSize(textureWidth, textureHeight);
        viewData->_depthTexture->setInternalFormat(GL_DEPTH_COMPONENT);
        viewData->_depthTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
        viewData->_depthTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);

        viewData->_depthTexture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER);
        viewData->_depthTexture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER);
        viewData->_depthTexture->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));

        // set up color texture
        viewData->_colorTexture = new osg::Texture2D;

        viewData->_colorTexture->setTextureSize(textureWidth, textureHeight);
        viewData->_colorTexture->setInternalFormat(GL_RGBA);
        viewData->_colorTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
        viewData->_colorTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);

        viewData->_colorTexture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_EDGE);
        viewData->_colorTexture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_EDGE);


        // set up the RTT Camera to capture the main scene to a color and depth texture that can be used in post processing
        viewData->_rttCamera = new osg::Camera;
        viewData->_rttCamera->setName("viewData->_rttCamera");
        viewData->_rttCamera->attach(osg::Camera::DEPTH_BUFFER, viewData->_depthTexture.get());
        viewData->_rttCamera->attach(osg::Camera::COLOR_BUFFER, viewData->_colorTexture.get());
        viewData->_rttCamera->setCullCallback(new RTTCameraCullCallback(this));
        viewData->_rttCamera->setViewport(0,0,textureWidth,textureHeight);

        // clear the depth and colour bufferson each clear.
        viewData->_rttCamera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

        // set the camera to render before the main camera.
        viewData->_rttCamera->setRenderOrder(osg::Camera::PRE_RENDER);

        // tell the camera to use OpenGL frame buffer object where supported.
        viewData->_rttCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);


        viewData->_rttCamera->setReferenceFrame(osg::Transform::RELATIVE_RF);
        viewData->_rttCamera->setProjectionMatrix(osg::Matrixd::identity());
        viewData->_rttCamera->setViewMatrix(osg::Matrixd::identity());

        // create mesh for rendering the RTT textures onto the screen
        osg::ref_ptr<osg::Geode> geode = new osg::Geode;
        geode->setCullingActive(false);

        viewData->_backdropSubgraph = geode;
        //geode->addDrawable(osg::createTexturedQuadGeometry(osg::Vec3(-1.0f,-1.0f,-1.0f),osg::Vec3(2.0f,0.0f,-1.0f),osg::Vec3(0.0f,2.0f,-1.0f)));

        viewData->_geometry = new osg::Geometry;
        geode->addDrawable(viewData->_geometry.get());

        viewData->_geometry->setUseDisplayList(false);
        viewData->_geometry->setUseVertexBufferObjects(false);

        viewData->_vertices = new osg::Vec3Array(4);
        viewData->_geometry->setVertexArray(viewData->_vertices.get());

        osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(1);
        (*colors)[0].set(1.0f,1.0f,1.0f,1.0f);
        viewData->_geometry->setColorArray(colors.get(), osg::Array::BIND_OVERALL);

        osg::ref_ptr<osg::Vec2Array> texcoords = new osg::Vec2Array(4);
        (*texcoords)[0].set(0.0f,1.0f);
        (*texcoords)[1].set(0.0f,0.0f);
        (*texcoords)[2].set(1.0f,1.0f);
        (*texcoords)[3].set(1.0f,0.0f);
        viewData->_geometry->setTexCoordArray(0, texcoords.get(), osg::Array::BIND_PER_VERTEX);

        viewData->_geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLE_STRIP,0,4));


        osg::ref_ptr<osg::StateSet> stateset = viewData->_geometry->getOrCreateStateSet();

        stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
        stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
        stateset->setMode(GL_BLEND, osg::StateAttribute::OFF);
        stateset->setMode(GL_ALPHA_TEST, osg::StateAttribute::OFF);
        stateset->setAttribute(new osg::Depth(osg::Depth::LEQUAL));
        stateset->setRenderBinDetails(10,"DepthSortedBin");

        osg::ref_ptr<osg::Program> program = new osg::Program;
        stateset->setAttribute(program.get());

        // get vertex shaders from source
        osg::ref_ptr<osg::Shader> vertexShader = osgDB::readRefShaderFile(osg::Shader::VERTEX, "shaders/volume_color_depth.vert");
        if (vertexShader.valid())
        {
            program->addShader(vertexShader.get());
        }
#if 0
        else
        {
#include "Shaders/volume_color_depth_vert.cpp"
            program->addShader(new osg::Shader(osg::Shader::VERTEX, volume_color_depth_vert));
        }
#endif
        // get fragment shaders from source
        osg::ref_ptr<osg::Shader> fragmentShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_color_depth.frag");
        if (fragmentShader.valid())
        {
            program->addShader(fragmentShader.get());
        }
#if 0
        else
        {
#include "Shaders/volume_color_depth_frag.cpp"
            program->addShader(new osg::Shader(osg::Shader::FRAGMENT, volume_color_depth_frag));
        }
#endif
        viewData->_stateset = new osg::StateSet;
        viewData->_stateset->addUniform(new osg::Uniform("colorTexture",0));
        viewData->_stateset->addUniform(new osg::Uniform("depthTexture",1));

        viewData->_stateset->setTextureAttributeAndModes(0, viewData->_colorTexture.get(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
        viewData->_stateset->setTextureAttributeAndModes(1, viewData->_depthTexture.get(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);

        viewData->_viewportDimensionsUniform = new osg::Uniform("viewportDimensions",osg::Vec4(0.0,0.0,1280.0,1024.0));
        viewData->_stateset->addUniform(viewData->_viewportDimensionsUniform.get());

        geode->setStateSet(viewData->_stateset.get());

    }
    else
    {
        // OSG_NOTICE<<"Reusing ViewData"<<std::endl;

    }

    osg::Matrix projectionMatrix = *(cv->getProjectionMatrix());
    osg::Matrix modelviewMatrix = *(cv->getModelViewMatrix());


    // new frame so need to clear last frames log of VolumeTiles
    viewData->clearTiles();

    osg::Viewport* viewport = cv->getCurrentRenderStage()->getViewport();
    if (viewport)
    {
        viewData->_viewportDimensionsUniform->set(osg::Vec4(viewport->x(), viewport->y(), viewport->width(),viewport->height()));

        int textureWidth = static_cast<int>(viewport->width());
        int textureHeight = static_cast<int>(viewport->height());

        if (textureWidth != viewData->_colorTexture->getTextureWidth() ||
                textureHeight != viewData->_colorTexture->getTextureHeight())
        {
            OSG_NOTICE<<"Need to change texture size to "<<textureWidth<<", "<< textureHeight<<std::endl;
            viewData->_colorTexture->setTextureSize(textureWidth, textureHeight);
            viewData->_colorTexture->dirtyTextureObject();
            viewData->_depthTexture->setTextureSize(textureWidth, textureHeight);
            viewData->_depthTexture->dirtyTextureObject();
            viewData->_rttCamera->setViewport(0, 0, textureWidth, textureHeight);
            if (viewData->_rttCamera->getRenderingCache())
            {
                viewData->_rttCamera->getRenderingCache()->releaseGLObjects(0);
            }
        }
    }

    cv->setUserValue("VolumeSceneTraversal",std::string("RenderToTexture"));

    //OSG_NOTICE<<"Ready to traverse RTT Camera"<<std::endl;
    //OSG_NOTICE<<"   RTT Camera ProjectionMatrix Before "<<viewData->_rttCamera->getProjectionMatrix()<<std::endl;
    viewData->_rttCamera->accept(nv);

    //OSG_NOTICE<<"   RTT Camera ProjectionMatrix After "<<viewData->_rttCamera->getProjectionMatrix()<<std::endl;
    //OSG_NOTICE<<"   cv ProjectionMatrix After "<<*(cv->getProjectionMatrix())<<std::endl;

    //OSG_NOTICE<<"  after RTT near ="<<cv->getCalculatedNearPlane()<<std::endl;
    //OSG_NOTICE<<"  after RTT far ="<<cv->getCalculatedFarPlane()<<std::endl;

    //OSG_NOTICE<<"tileVisited()"<<viewData->_tiles.size()<<std::endl;


    typedef osgUtil::CullVisitor::value_type NearFarValueType;
    NearFarValueType calculatedNearPlane = std::numeric_limits<NearFarValueType>::max();
    NearFarValueType calculatedFarPlane = -std::numeric_limits<NearFarValueType>::max();
    if (viewData->_rttCamera->getUserValue("CalculatedNearPlane",calculatedNearPlane) &&
            viewData->_rttCamera->getUserValue("CalculatedFarPlane",calculatedFarPlane))
    {
        calculatedNearPlane *= 0.5;
        calculatedFarPlane *= 2.0;

        //OSG_NOTICE<<"Got from RTTCamera CalculatedNearPlane="<<calculatedNearPlane<<std::endl;
        //OSG_NOTICE<<"Got from RTTCamera CalculatedFarPlane="<<calculatedFarPlane<<std::endl;
        if (calculatedNearPlane < cv->getCalculatedNearPlane()) cv->setCalculatedNearPlane(calculatedNearPlane);
        if (calculatedFarPlane > cv->getCalculatedFarPlane()) cv->setCalculatedFarPlane(calculatedFarPlane);
    }

    if (calculatedFarPlane>calculatedNearPlane)
    {
        cv->clampProjectionMatrix(projectionMatrix, calculatedNearPlane, calculatedFarPlane);
    }

    osg::Matrix inv_projectionModelViewMatrix;
    inv_projectionModelViewMatrix.invert(modelviewMatrix*projectionMatrix);

    double depth = 1.0;
    osg::Vec3d v00 = osg::Vec3d(-1.0,-1.0,depth)*inv_projectionModelViewMatrix;
    osg::Vec3d v01 = osg::Vec3d(-1.0,1.0,depth)*inv_projectionModelViewMatrix;
    osg::Vec3d v10 = osg::Vec3d(1.0,-1.0,depth)*inv_projectionModelViewMatrix;
    osg::Vec3d v11 = osg::Vec3d(1.0,1.0,depth)*inv_projectionModelViewMatrix;

    // OSG_NOTICE<<"v00= "<<v00<<std::endl;
    // OSG_NOTICE<<"v01= "<<v01<<std::endl;
    // OSG_NOTICE<<"v10= "<<v10<<std::endl;
    // OSG_NOTICE<<"v11= "<<v11<<std::endl;

    (*(viewData->_vertices))[0] = v01;
    (*(viewData->_vertices))[1] = v00;
    (*(viewData->_vertices))[2] = v11;
    (*(viewData->_vertices))[3] = v10;
    viewData->_geometry->dirtyBound();

    //OSG_NOTICE<<"  new after RTT near ="<<cv->getCalculatedNearPlane()<<std::endl;
    //OSG_NOTICE<<"  new after RTT far ="<<cv->getCalculatedFarPlane()<<std::endl;

    viewData->_backdropSubgraph->accept(*cv);

    osg::NodePath nodePathPriorToTraversingSubgraph = cv->getNodePath();
    cv->setUserValue("VolumeSceneTraversal",std::string("Post"));

    // for each tile that needs post rendering we need to add it into current RenderStage.
    Tiles& tiles = viewData->_tiles;
    for(Tiles::iterator itr = tiles.begin();
            itr != tiles.end();
            ++itr)
    {
        TileData* tileData = itr->second.get();
        if (!tileData || !(tileData->active))
        {
            OSG_INFO<<"Skipping TileData that is inactive : "<<tileData<<std::endl;
            continue;
        }

        unsigned int numStateSetPushed = 0;

        // OSG_NOTICE<<"VolumeTile to add "<<tileData->projectionMatrix.get()<<", "<<tileData->modelviewMatrix.get()<<std::endl;


        osg::NodePath& nodePath = tileData->nodePath;

        cv->getNodePath() = nodePath;
        cv->pushProjectionMatrix(tileData->projectionMatrix.get());
        cv->pushModelViewMatrix(tileData->modelviewMatrix.get(), osg::Transform::ABSOLUTE_RF_INHERIT_VIEWPOINT);


        cv->pushStateSet(viewData->_stateset.get());
        ++numStateSetPushed;

        cv->pushStateSet(tileData->stateset.get());
        ++numStateSetPushed;

        osg::NodePath::iterator np_itr = nodePath.begin();

        // skip over all nodes above VolumeScene as this will have already been traversed by CullVisitor
        while(np_itr!=nodePath.end() && (*np_itr)!=viewData->_rttCamera.get()) {
            ++np_itr;
        }
        if (np_itr!=nodePath.end()) ++np_itr;

        // push the stateset on the nodes between this VolumeScene and the VolumeTile
        for(osg::NodePath::iterator ss_itr = np_itr;
                ss_itr != nodePath.end();
                ++ss_itr)
        {
            if ((*ss_itr)->getStateSet())
            {
                numStateSetPushed++;
                cv->pushStateSet((*ss_itr)->getStateSet());
                // OSG_NOTICE<<"  pushing StateSet"<<std::endl;
            }
        }
        cv->traverse(*(tileData->nodePath.back()));

        // pop the StateSet's
        for(unsigned int i=0; i<numStateSetPushed; ++i)
        {
            cv->popStateSet();
            // OSG_NOTICE<<"  popping StateSet"<<std::endl;
        }

        cv->popModelViewMatrix();
        cv->popProjectionMatrix();
    }

    // need to synchronize projection matrices:
    //    current CV projection matrix
    //    main scene RTT Camera projection matrix
    //    each tile RTT Camera
    //    each tile final render.

    cv->getNodePath() = nodePathPriorToTraversingSubgraph;
}
Пример #9
0
void LightPointNode::traverse(osg::NodeVisitor& nv)
{
    if (_lightPointList.empty())
    {
        // no light points so no op.
        return;
    }

    //#define USE_TIMER
    #ifdef USE_TIMER
    osg::Timer timer;
    osg::Timer_t t1=0,t2=0,t3=0,t4=0,t5=0,t6=0,t7=0,t8=0;
    #endif


#ifdef USE_TIMER
    t1 = timer.tick();
#endif

    osgUtil::CullVisitor* cv = nv.asCullVisitor();

#ifdef USE_TIMER
    t2 = timer.tick();
#endif


    // should we disable small feature culling here?
    if (cv /*&& !cv->isCulled(_bbox)*/)
    {

        osg::Matrix matrix = *(cv->getModelViewMatrix());
        osg::RefMatrix& projection = *(cv->getProjectionMatrix());
        osgUtil::StateGraph* rg = cv->getCurrentStateGraph();

        if (rg->leaves_empty())
        {
            // this is first leaf to be added to StateGraph
            // and therefore should not already know current render bin,
            // so need to add it.
            cv->getCurrentRenderBin()->addStateGraph(rg);
        }

#ifdef USE_TIMER
        t3 = timer.tick();
#endif


        LightPointDrawable* drawable = NULL;
        osg::Referenced* object = rg->getUserData();
        if (object)
        {
            if (typeid(*object)==typeid(LightPointDrawable))
            {
                // resuse the user data attached to the render graph.
                drawable = static_cast<LightPointDrawable*>(object);

            }
            else if (typeid(*object)==typeid(LightPointSpriteDrawable))
            {
                drawable = static_cast<LightPointSpriteDrawable*>(object);
            }
            else
            {
                // will need to replace UserData.
                OSG_WARN << "Warning: Replacing osgUtil::StateGraph::_userData to support osgSim::LightPointNode, may have undefined results."<<std::endl;
            }
        }

        if (!drawable)
        {
            drawable = _pointSprites ? new LightPointSpriteDrawable : new LightPointDrawable;
            rg->setUserData(drawable);

            if (cv->getFrameStamp())
            {
                drawable->setSimulationTime(cv->getFrameStamp()->getSimulationTime());
            }
        }

        // search for a drawable in the RenderLeaf list equal to the attached the one attached to StateGraph user data
        // as this will be our special light point drawable.
        osgUtil::StateGraph::LeafList::iterator litr;
        for(litr = rg->_leaves.begin();
            litr != rg->_leaves.end() && (*litr)->_drawable.get()!=drawable;
            ++litr)
        {}

        if (litr == rg->_leaves.end())
        {
            // haven't found the drawable added in the RenderLeaf list, therefore this may be the
            // first time through LightPointNode in this frame, so need to add drawable into the StateGraph RenderLeaf list
            // and update its time signatures.

            drawable->reset();
            rg->addLeaf(new osgUtil::RenderLeaf(drawable,&projection,NULL,FLT_MAX));

            // need to update the drawable's frame count.
            if (cv->getFrameStamp())
            {
                drawable->updateSimulationTime(cv->getFrameStamp()->getSimulationTime());
            }

        }

#ifdef USE_TIMER
        t4 = timer.tick();
#endif


#ifdef USE_TIMER
        t7 = timer.tick();
#endif


        if (cv->getComputeNearFarMode() != osgUtil::CullVisitor::DO_NOT_COMPUTE_NEAR_FAR)
            cv->updateCalculatedNearFar(matrix,_bbox);


        const float minimumIntensity = 1.0f/256.0f;
        const osg::Vec3 eyePoint = cv->getEyeLocal();

        double time=drawable->getSimulationTime();
        double timeInterval=drawable->getSimulationTimeInterval();

        const osg::Polytope clipvol(cv->getCurrentCullingSet().getFrustum());
        const bool computeClipping = false;//(clipvol.getCurrentMask()!=0);

        //LightPointDrawable::ColorPosition cp;
        for(LightPointList::iterator itr=_lightPointList.begin();
            itr!=_lightPointList.end();
            ++itr)
        {
            const LightPoint& lp = *itr;

            if (!lp._on) continue;

            const osg::Vec3& position = lp._position;

            // skip light point if it is not contianed in the view frustum.
            if (computeClipping && !clipvol.contains(position)) continue;

            // delta vector between eyepoint and light point.
            osg::Vec3 dv(eyePoint-position);

            float intensity = (_lightSystem.valid()) ? _lightSystem->getIntensity() : lp._intensity;

            // slip light point if its intensity is 0.0 or negative.
            if (intensity<=minimumIntensity) continue;

            // (SIB) Clip on distance, if close to limit, add transparancy
            float distanceFactor = 1.0f;
            if (_maxVisibleDistance2!=FLT_MAX)
            {
                if (dv.length2()>_maxVisibleDistance2) continue;
                else if (_maxVisibleDistance2 > 0)
                    distanceFactor = 1.0f - osg::square(dv.length2() / _maxVisibleDistance2);
            }

            osg::Vec4 color = lp._color;

            // check the sector.
            if (lp._sector.valid())
            {
                intensity *= (*lp._sector)(dv);

                // skip light point if it is intensity is 0.0 or negative.
                if (intensity<=minimumIntensity) continue;

            }

            // temporary accounting of intensity.
            //color *= intensity;

            // check the blink sequence.
            bool doBlink = lp._blinkSequence.valid();
            if (doBlink && _lightSystem.valid())
                doBlink = (_lightSystem->getAnimationState() == LightPointSystem::ANIMATION_ON);

            if (doBlink)
            {
                osg::Vec4 bs = lp._blinkSequence->color(time,timeInterval);
                color[0] *= bs[0];
                color[1] *= bs[1];
                color[2] *= bs[2];
                color[3] *= bs[3];
            }

            // if alpha value is less than the min intentsity then skip
            if (color[3]<=minimumIntensity) continue;

            float pixelSize = cv->pixelSize(position,lp._radius);

            //            cout << "pixelsize = "<<pixelSize<<endl;

            // adjust pixel size to account for intensity.
            if (intensity!=1.0) pixelSize *= sqrt(intensity);

            // adjust alpha to account for max range (Fade on distance)
            color[3] *= distanceFactor;

            // round up to the minimum pixel size if required.
            float orgPixelSize = pixelSize;
            if (pixelSize<_minPixelSize) pixelSize = _minPixelSize;

            osg::Vec3 xpos(position*matrix);

            if (lp._blendingMode==LightPoint::BLENDED)
            {
                if (pixelSize<1.0f)
                {
                    // need to use alpha blending...
                    color[3] *= pixelSize;
                    // color[3] *= osg::square(pixelSize);

                    if (color[3]<=minimumIntensity) continue;

                    drawable->addBlendedLightPoint(0, xpos,color);
                }
                else if (pixelSize<_maxPixelSize)
                {

                    unsigned int lowerBoundPixelSize = (unsigned int)pixelSize;
                    float remainder = osg::square(pixelSize-(float)lowerBoundPixelSize);

                    // (SIB) Add transparency if pixel is clamped to minpixelsize
                    if (orgPixelSize<_minPixelSize)
                        color[3] *= (2.0/3.0) + (1.0/3.0) * sqrt(orgPixelSize / pixelSize);

                    drawable->addBlendedLightPoint(lowerBoundPixelSize-1, xpos,color);
                    color[3] *= remainder;
                    drawable->addBlendedLightPoint(lowerBoundPixelSize, xpos,color);
                }
                else // use a billboard geometry.
                {
                    drawable->addBlendedLightPoint((unsigned int)(_maxPixelSize-1.0), xpos,color);
                }
            }
            else // ADDITIVE blending.
            {
                if (pixelSize<1.0f)
                {
                    // need to use alpha blending...
                    color[3] *= pixelSize;
                    // color[3] *= osg::square(pixelSize);

                    if (color[3]<=minimumIntensity) continue;

                    drawable->addAdditiveLightPoint(0, xpos,color);
                }
                else if (pixelSize<_maxPixelSize)
                {

                    unsigned int lowerBoundPixelSize = (unsigned int)pixelSize;
                    float remainder = osg::square(pixelSize-(float)lowerBoundPixelSize);

                    // (SIB) Add transparency if pixel is clamped to minpixelsize
                    if (orgPixelSize<_minPixelSize)
                        color[3] *= (2.0/3.0) + (1.0/3.0) * sqrt(orgPixelSize / pixelSize);

                    float alpha = color[3];
                    color[3] = alpha*(1.0f-remainder);
                    drawable->addAdditiveLightPoint(lowerBoundPixelSize-1, xpos,color);
                    color[3] = alpha*remainder;
                    drawable->addAdditiveLightPoint(lowerBoundPixelSize, xpos,color);
                }
                else // use a billboard geometry.
                {
                    drawable->addAdditiveLightPoint((unsigned int)(_maxPixelSize-1.0), xpos,color);
                }
            }
        }

#ifdef USE_TIMER
        t8 = timer.tick();
#endif

    }
#ifdef USE_TIMER
    cout << "compute"<<endl;
    cout << "  t2-t1="<<t2-t1<<endl;
    cout << "  t4-t3="<<t4-t3<<endl;
    cout << "  t6-t5="<<t6-t5<<endl;
    cout << "  t8-t7="<<t8-t7<<endl;
    cout << "_lightPointList.size()="<<_lightPointList.size()<<endl;
    cout << "  t8-t7/size = "<<(float)(t8-t7)/(float)_lightPointList.size()<<endl;
#endif
}
Пример #10
0
void osgParticle::ParticleSystem::update(double dt, osg::NodeVisitor& nv)
{
    // reset bounds
    _reset_bounds_flag = true;

    if (_useShaders)
    {
        // Update shader uniforms
        // This slightly reduces the consumption of traversing the particle vector, because we
        // don't compute tile and angle attributes that are useleff for shaders.
        // At present, our lcoal shader implementation will ignore these particle props:
        //     _cur_tile, _s_coord, _t_coord, _prev_pos, _prev_angle and _angle
        osg::StateSet* stateset = getOrCreateStateSet();

        if (_dirty_uniforms)
        {
            osg::Uniform* u_vd = stateset->getUniform("visibilityDistance");
            if (u_vd) u_vd->set((float)_visibilityDistance);
            _dirty_uniforms = false;
        }
    }

    for(unsigned int i=0; i<_particles.size(); ++i)
    {
        Particle& particle = _particles[i];
        if (particle.isAlive())
        {
            if (particle.update(dt, _useShaders))
            {
                update_bounds(particle.getPosition(), particle.getCurrentSize());
            }
            else
            {
                reuseParticle(i);
            }
        }
    }

    if (_sortMode != NO_SORT)
    {
        // sort particles
        osgUtil::CullVisitor* cv = nv.asCullVisitor();
        if (cv)
        {
            osg::Matrixd modelview = *(cv->getModelViewMatrix());
            double scale = (_sortMode==SORT_FRONT_TO_BACK ? -1.0 : 1.0);
            double deadDistance = DBL_MAX;
            for (unsigned int i=0; i<_particles.size(); ++i)
            {
                Particle& particle = _particles[i];
                if (particle.isAlive())
                    particle.setDepth(distance(particle.getPosition(), modelview) * scale);
                else
                    particle.setDepth(deadDistance);
            }
            std::sort<Particle_vector::iterator>(_particles.begin(), _particles.end());

            // Repopulate the death stack as it will have been invalidated by the sort.
            unsigned int numDead = _deadparts.size();
            if (numDead>0)
            {
                 // clear the death stack
                _deadparts = Death_stack();

                // copy the tail of the _particles vector as this will contain all the dead Particle thanks to the depth sort against DBL_MAX
                Particle* first_dead_ptr  = &_particles[_particles.size()-numDead];
                Particle* last_dead_ptr  = &_particles[_particles.size()-1];
                for(Particle* dead_ptr  = first_dead_ptr; dead_ptr<=last_dead_ptr; ++dead_ptr)
                {
                    _deadparts.push(dead_ptr);
                }
            }
        }
    }

    // force recomputing of bounding box on next frame
    dirtyBound();
}
Пример #11
0
void Widget::traverseImplementation(osg::NodeVisitor& nv)
{
    if (!_graphicsInitialized && nv.getVisitorType()!=osg::NodeVisitor::CULL_VISITOR) createGraphics();

    osgGA::EventVisitor* ev = nv.asEventVisitor();
    if (ev)
    {
        if (_visible && _enabled)
        {

            updateFocus(nv);

            // OSG_NOTICE<<"EventTraversal getHasEventFocus()="<<getHasEventFocus()<<std::endl;

            // signify that event has been taken by widget with focus

            bool widgetsWithFocusSetHandled = getHasEventFocus();

            osgGA::EventQueue::Events& events = ev->getEvents();
            for(osgGA::EventQueue::Events::iterator itr = events.begin();
                itr != events.end();
                ++itr)
            {
                if (handle(ev, itr->get()) || widgetsWithFocusSetHandled)
                {
                    (*itr)->setHandled(true);
                    ev->setEventHandled(true);
                }
            }

            GraphicsSubgraphMap::iterator itr = _graphicsSubgraphMap.begin();
            while(itr!= _graphicsSubgraphMap.end() && itr->first<=0)
            {
                itr->second->accept(nv);
                ++itr;
            }

            osg::Group::traverse(nv);

            while(itr!= _graphicsSubgraphMap.end())
            {
                itr->second->accept(nv);
                ++itr;
            }

        }
    }
    else if (_visible ||
            (nv.getVisitorType()!=osg::NodeVisitor::UPDATE_VISITOR && nv.getVisitorType()!=osg::NodeVisitor::CULL_VISITOR && nv.getVisitorType()!=osg::NodeVisitor::INTERSECTION_VISITOR) )
    {
        osgUtil::CullVisitor* cv = (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR) ? nv.asCullVisitor() : 0;
        if (cv && _widgetStateSet.valid()) cv->pushStateSet(_widgetStateSet.get());

        GraphicsSubgraphMap::iterator itr = _graphicsSubgraphMap.begin();
        while(itr!= _graphicsSubgraphMap.end() && itr->first<=0)
        {
            itr->second->accept(nv);
            ++itr;
        }

        Group::traverse(nv);

        while(itr!= _graphicsSubgraphMap.end())
        {
            itr->second->accept(nv);
            ++itr;
        }

        if (cv && _widgetStateSet.valid()) cv->popStateSet();
    }
}
Пример #12
0
void Impostor::traverse(osg::NodeVisitor& nv)
{
    if (nv.getVisitorType() != osg::NodeVisitor::CULL_VISITOR)
    {
        LOD::traverse(nv);
        return;
    }

    osgUtil::CullVisitor* cv = nv.asCullVisitor();
    if (!cv)
    {
        LOD::traverse(nv);
        return;
    }


    osg::Vec3 eyeLocal = nv.getEyePoint();
    const BoundingSphere& bs = getBound();

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

    float distance2 = (eyeLocal-bs.center()).length2();
    float LODScale = cv->getLODScale();
    if (!cv->getImpostorsActive() ||
        distance2*LODScale*LODScale<osg::square(getImpostorThreshold()) ||
        distance2<bs.radius2()*2.0f)
    {
        // outwith the impostor distance threshold therefore simple
        // traverse the appropriate child of the LOD.
        LOD::traverse(nv);
    }
    else
    {

        // within the impostor distance threshold therefore attempt
        // to use impostor instead.

        RefMatrix& matrix = *cv->getModelViewMatrix();

        // search for the best fit ImpostorSprite;
        ImpostorSprite* impostorSprite = findBestImpostorSprite(contextID,eyeLocal);

        if (impostorSprite)
        {
            // impostor found, now check to see if it is good enough to use
            float error = impostorSprite->calcPixelError(*(cv->getMVPW()));

            if (error>cv->getImpostorPixelErrorThreshold())
            {
                // chosen impostor sprite pixel error is too great to use
                // from this eye point, therefore invalidate it.
                impostorSprite=NULL;
            }
        }


// need to think about sprite reuse and support for multiple context's.

        if (impostorSprite==NULL)
        {
            // no appropriate sprite has been found therefore need to create
            // one for use

            // create the impostor sprite.
            impostorSprite = createImpostorSprite(cv);

            //if (impostorSprite) impostorSprite->_color.set(0.0f,0.0f,1.0f,1.0f);

        }
        //else impostorSprite->_color.set(1.0f,1.0f,1.0f,1.0f);

        if (impostorSprite)
        {

            // update frame number to show that impostor is in action.
            impostorSprite->setLastFrameUsed(cv->getTraversalNumber());

            if (cv->getComputeNearFarMode()) cv->updateCalculatedNearFar(matrix,*impostorSprite, false);

            StateSet* stateset = impostorSprite->getStateSet();

            if (stateset) cv->pushStateSet(stateset);

            cv->addDrawableAndDepth(impostorSprite, &matrix, distance(getCenter(),matrix));

            if (stateset) cv->popStateSet();


        }
        else
        {
           // no impostor has been selected or created so default to
           // traversing the usual LOD selected child.
            LOD::traverse(nv);
        }

    }
}