I'm working on an application which uses osgEarth to display terrain
databases to users.  I need the application to use as little CPU time as
possible while still providing good user interaction, so I have set my
viewer up so that it only renders when necessary.  I keep a loop running
that does the event and update traversals, but the renderingTraversals are
only done when requestRedraw or requestContinuousUpdate have been called.
This seems to work fine and to the user it generally beahves the same as
when the scene is continuously rendered.  However, when viewing the high
detail levels it database pager often gets stuck in a loop when it keeps
reloading a set of tiles over and over.  You see the tiles alternately go
blurry and then sharp again as the continously reload.

I don't know what is causing this, but if I switch to continuous render, so
that every event and update traversal is followed by a render, the problem
does not occur.  It seems to happen most often loading earth files with
high-res data, like the yahoo or google test files, and then moving the
camera around at the high detail levels.  Unfortunately, I can't seem to
replicate the problem with an animation path.  I have attached a simple
viewer I created that implements the rendering method I described above.
The important code is in the viewer's frame function.  I've pasted it below
in case anyone can tell at a glance what I'm doing wrong.  If someone who
knows the database pager well could take a look at this I would really
appreciate it.

Thanks,
Evan


        advance(simulationTime);

        eventTraversal();

        // If the database pager is going to update the scene the render
flag is
        // set so that the updates show up
        if(getDatabasePager()->requiresUpdateSceneGraph())
            needsRender = true;

        updateTraversal();

        if(needsRender || continuousUpdate)
        {
            renderingTraversals();
            needsRender = false;
        }
// RenderOnDemand.cpp : Defines the entry point for the console application.
//

#include <osgViewer/viewer>
#include <osgDB/ReadFile>
#include <osgViewer/ViewerEventHandlers>

#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/TerrainManipulator>

#include <OpenThreads/Thread>

// The stats handler has to be modified to request continuous updates
// when stats are being displayed
class MyStats : public osgViewer::StatsHandler
{
protected:
    ~MyStats() {}
    int keyPresses;
public:
    MyStats() : osgViewer::StatsHandler(), keyPresses(0) {}
    virtual bool handle(const osgGA::GUIEventAdapter &ea, 
osgGA::GUIActionAdapter &aa)
    {
        if( ea.getEventType() != osgGA::GUIEventAdapter::KEYDOWN )
            return false;

        int key = ea.getKey();

        if(key == -1)
            return false;

        if(key == 's') {
            if(keyPresses < 4)
            {
                aa.requestContinuousUpdate(true);
                keyPresses++;
            }
            else
            {
                keyPresses = 0;
                aa.requestContinuousUpdate(false);
                aa.requestRedraw();
            }

            return osgViewer::StatsHandler::handle(ea, aa);
        }
        return false;
    }
};

class MyViewer : public osgViewer::Viewer
{
public:
    MyViewer() : osgViewer::Viewer(), needsRender(true), 
continuousUpdate(false) {}
    MyViewer(osg::ArgumentParser &arguments) : osgViewer::Viewer(arguments), 
needsRender(true), continuousUpdate(false) {}

    virtual void requestRedraw()
    {
        needsRender = true;
    }

    virtual void requestContinuousUpdate(bool needed=true)
    {
        continuousUpdate = needed;
    }

    virtual int run()
    {
        // From osgViewer::Viewer
        if (!getCameraManipulator() && getCamera()->getAllowEventFocus())
        {
            setCameraManipulator(new osgGA::TrackballManipulator);
        }

        addEventHandler(new MyStats());

        setReleaseContextAtEndOfFrameHint(false);

        // From osgViewer::ViewerBase
        if (!isRealized())
        {
            realize();
        }

        while (!done())
        {
            frame();

            //Sleep for 10 miliseconds
            OpenThreads::Thread::microSleep(10000);
        }

        return 0;
    }

    virtual void frame(double simulationTime=USE_REFERENCE_TIME)
    {
        if (_done) return;

        // 
osg::notify(osg::NOTICE)<<std::endl<<"CompositeViewer::frame()"<<std::endl<<std::endl;

        if (_firstFrame)
        {
            viewerInit();

            if (!isRealized())
            {
                realize();
            }

            _firstFrame = false;
        }

        advance(simulationTime);

        eventTraversal();

        // If the database pager is going to update the scene the render flag is
        // set so that the updates show up
        if(getDatabasePager()->requiresUpdateSceneGraph())
            needsRender = true;

        updateTraversal();

        if(needsRender || continuousUpdate)
        {
            renderingTraversals();
            needsRender = false;
        }
    }

protected:
    ~MyViewer() {}
    bool needsRender;
    bool continuousUpdate;
};


int main(int argc, char* argv[])
{
    osg::ArgumentParser arguments(&argc,argv);

    osg::ref_ptr<MyViewer> viewer = new MyViewer(arguments);

    // set up the camera manipulators.
    {
        osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = 
new osgGA::KeySwitchMatrixManipulator;

        keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new 
osgGA::TrackballManipulator() );
        keyswitchManipulator->addMatrixManipulator( '2', "Flight", new 
osgGA::FlightManipulator() );
        keyswitchManipulator->addMatrixManipulator( '3', "Drive", new 
osgGA::DriveManipulator() );
        keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new 
osgGA::TerrainManipulator() );

        viewer->setCameraManipulator( keyswitchManipulator.get() );
    }

    osg::ref_ptr<osg::Node> node = osgDB::readNodeFiles(arguments);

    if(node.valid())
    {
        viewer->setSceneData(node);
        viewer->run();
    }

    return 0;
}

_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to