Skip to content

Commit

Permalink
Refactored osgviewer original app to use osgQOpeGLWidget instead
Browse files Browse the repository at this point in the history
  • Loading branch information
mathieu committed Sep 19, 2018
1 parent d9add78 commit bfb66e0
Showing 1 changed file with 215 additions and 98 deletions.
313 changes: 215 additions & 98 deletions examples/osgviewerQt/osgviewerQt.cpp
Original file line number Diff line number Diff line change
@@ -1,119 +1,236 @@
#include <QTimer>
#include <QApplication>
#include <QGridLayout>
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 Robert Osfield
#include <osgViewer/CompositeViewer>
#include <osgViewer/ViewerEventHandlers>
This application is open source and may be redistributed and/or modified
freely and without restriction, both in commercial and non commercial applications,
as long as this copyright notice is maintained.
#include <osgGA/MultiTouchTrackballManipulator>
This application 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.
*/

#include <osgQOpenGL/osgQOpenGLWidget>

#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osg/CoordinateSystemNode>

#include <osgQt/GraphicsWindowQt>
#include <osg/Switch>
#include <osg/Types>
#include <osgText/Text>

#include <iostream>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>

class ViewerWidget : public QWidget, public osgViewer::CompositeViewer
{
public:
ViewerWidget(QWidget* parent = 0, Qt::WindowFlags f = 0, osgViewer::ViewerBase::ThreadingModel threadingModel=osgViewer::CompositeViewer::SingleThreaded) : QWidget(parent, f)
{
setThreadingModel(threadingModel);

// disable the default setting of viewer.done() by pressing Escape.
setKeyEventSetsDone(0);

QWidget* widget1 = addViewWidget( createGraphicsWindow(0,0,100,100), osgDB::readRefNodeFile("cow.osgt") );
QWidget* widget2 = addViewWidget( createGraphicsWindow(0,0,100,100), osgDB::readRefNodeFile("glider.osgt") );
QWidget* widget3 = addViewWidget( createGraphicsWindow(0,0,100,100), osgDB::readRefNodeFile("axes.osgt") );
QWidget* widget4 = addViewWidget( createGraphicsWindow(0,0,100,100), osgDB::readRefNodeFile("fountain.osgt") );
QWidget* popupWidget = addViewWidget( createGraphicsWindow(900,100,320,240,"Popup window",true), osgDB::readRefNodeFile("dumptruck.osgt") );
popupWidget->show();

QGridLayout* grid = new QGridLayout;
grid->addWidget( widget1, 0, 0 );
grid->addWidget( widget2, 0, 1 );
grid->addWidget( widget3, 1, 0 );
grid->addWidget( widget4, 1, 1 );
setLayout( grid );

connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );
_timer.start( 10 );
}

QWidget* addViewWidget( osgQt::GraphicsWindowQt* gw, osg::ref_ptr<osg::Node> scene )
{
osgViewer::View* view = new osgViewer::View;
addView( view );
#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>
#include <osgGA/SphericalManipulator>

osg::Camera* camera = view->getCamera();
camera->setGraphicsContext( gw );
#include <osgGA/Device>

const osg::GraphicsContext::Traits* traits = gw->getTraits();
#include <QApplication>
#include <QSurfaceFormat>

camera->setClearColor( osg::Vec4(0.2, 0.2, 0.6, 1.0) );
camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );
camera->setProjectionMatrixAsPerspective(30.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 1.0f, 10000.0f );
#include <iostream>

view->setSceneData( scene );
view->addEventHandler( new osgViewer::StatsHandler );
view->setCameraManipulator( new osgGA::MultiTouchTrackballManipulator );
gw->setTouchEventsEnabled( true );
return gw->getGLWidget();
}

osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name="", bool windowDecoration=false )
{
osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
traits->windowName = name;
traits->windowDecoration = windowDecoration;
traits->x = x;
traits->y = y;
traits->width = w;
traits->height = h;
traits->doubleBuffer = true;
traits->alpha = ds->getMinimumNumAlphaBits();
traits->stencil = ds->getMinimumNumStencilBits();
traits->sampleBuffers = ds->getMultiSamples();
traits->samples = ds->getNumMultiSamples();

return new osgQt::GraphicsWindowQt(traits.get());
}

virtual void paintEvent( QPaintEvent* /*event*/ )
{ frame(); }

protected:

QTimer _timer;
};

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

#if QT_VERSION >= 0x050000
// Qt5 is currently crashing and reporting "Cannot make QOpenGLContext current in a different thread" when the viewer is run multi-threaded, this is regression from Qt4
osgViewer::ViewerBase::ThreadingModel threadingModel = osgViewer::ViewerBase::SingleThreaded;
#else
osgViewer::ViewerBase::ThreadingModel threadingModel = osgViewer::ViewerBase::CullDrawThreadPerContext;
#endif

while (arguments.read("--SingleThreaded")) threadingModel = osgViewer::ViewerBase::SingleThreaded;
while (arguments.read("--CullDrawThreadPerContext")) threadingModel = osgViewer::ViewerBase::CullDrawThreadPerContext;
while (arguments.read("--DrawThreadPerContext")) threadingModel = osgViewer::ViewerBase::DrawThreadPerContext;
while (arguments.read("--CullThreadPerCameraDrawThreadPerContext")) threadingModel = osgViewer::ViewerBase::CullThreadPerCameraDrawThreadPerContext;
QSurfaceFormat format = QSurfaceFormat::defaultFormat();

#if QT_VERSION >= 0x040800
// Required for multithreaded QGLWidget on Linux/X11, see http://blog.qt.io/blog/2011/06/03/threaded-opengl-in-4-8/
if (threadingModel != osgViewer::ViewerBase::SingleThreaded)
QApplication::setAttribute(Qt::AA_X11InitThreads);
#ifdef OSG_GL3_AVAILABLE
format.setVersion(3, 2);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setRenderableType(QSurfaceFormat::OpenGL);
format.setOption(QSurfaceFormat::DebugContext);
#else
format.setVersion(2, 0);
format.setProfile(QSurfaceFormat::CompatibilityProfile);
format.setRenderableType(QSurfaceFormat::OpenGL);
format.setOption(QSurfaceFormat::DebugContext);
#endif
format.setDepthBufferSize(24);
//format.setAlphaBufferSize(8);
format.setSamples(8);
format.setStencilBufferSize(8);
format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
QSurfaceFormat::setDefaultFormat(format);

QApplication app(argc, argv);
ViewerWidget* viewWidget = new ViewerWidget(0, Qt::Widget, threadingModel);
viewWidget->setGeometry( 100, 100, 800, 600 );
viewWidget->show();

// use an ArgumentParser object to manage the program arguments.
osg::ArgumentParser arguments(&argc, argv);

arguments.getApplicationUsage()->setApplicationName(
arguments.getApplicationName());
arguments.getApplicationUsage()->setDescription(arguments.getApplicationName() +
" is the standard OpenSceneGraph example which loads and visualises 3d models.");
arguments.getApplicationUsage()->setCommandLineUsage(
arguments.getApplicationName() + " [options] filename ...");
arguments.getApplicationUsage()->addCommandLineOption("--image <filename>",
"Load an image and render it on a quad");
arguments.getApplicationUsage()->addCommandLineOption("--dem <filename>",
"Load an image/DEM and render it on a HeightField");
arguments.getApplicationUsage()->addCommandLineOption("--login <url> <username> <password>",
"Provide authentication information for http file access.");
arguments.getApplicationUsage()->addCommandLineOption("-p <filename>",
"Play specified camera path animation file, previously saved with 'z' key.");
arguments.getApplicationUsage()->addCommandLineOption("--speed <factor>",
"Speed factor for animation playing (1 == normal speed).");
arguments.getApplicationUsage()->addCommandLineOption("--device <device-name>",
"add named device to the viewer");

osgQOpenGLWidget widget(&arguments);

QObject::connect(&widget, &osgQOpenGLWidget::initialized, [ &arguments,
&widget ]
{
unsigned int helpType = 0;

if((helpType = arguments.readHelpType()))
{
arguments.getApplicationUsage()->write(std::cout, helpType);
return 1;
}

// report any errors if they have occurred when parsing the program arguments.
if(arguments.errors())
{
arguments.writeErrorMessages(std::cout);
return 1;
}

if(arguments.argc() <= 1)
{
arguments.getApplicationUsage()->write(std::cout,
osg::ApplicationUsage::COMMAND_LINE_OPTION);
return 1;
}

std::string url, username, password;

while(arguments.read("--login", url, username, password))
{
osgDB::Registry::instance()->getOrCreateAuthenticationMap()->addAuthenticationDetails(
url,
new osgDB::AuthenticationDetails(username, password)
);
}

std::string device;

while(arguments.read("--device", device))
{
osg::ref_ptr<osgGA::Device> dev = osgDB::readRefFile<osgGA::Device>(device);

if(dev.valid())
{
widget.getOsgViewer()->addDevice(dev);
}
}

// 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());
keyswitchManipulator->addMatrixManipulator('5', "Orbit", new osgGA::OrbitManipulator());
keyswitchManipulator->addMatrixManipulator('6', "FirstPerson", new osgGA::FirstPersonManipulator());
keyswitchManipulator->addMatrixManipulator('7', "Spherical", new osgGA::SphericalManipulator());

std::string pathfile;
double animationSpeed = 1.0;

while(arguments.read("--speed", animationSpeed)) {}
char keyForAnimationPath = '8';

while(arguments.read("-p", pathfile))
{
osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(
pathfile);

if(apm || !apm->valid())
{
apm->setTimeScale(animationSpeed);

unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
keyswitchManipulator->addMatrixManipulator(keyForAnimationPath, "Path", apm);
keyswitchManipulator->selectMatrixManipulator(num);
++keyForAnimationPath;
}
}

widget.getOsgViewer()->setCameraManipulator(keyswitchManipulator.get());
}

// add the state manipulator
widget.getOsgViewer()->addEventHandler(new osgGA::StateSetManipulator(widget.getOsgViewer()->getCamera()->getOrCreateStateSet()));

// add the thread model handler
widget.getOsgViewer()->addEventHandler(new osgViewer::ThreadingHandler);

// add the window size toggle handler
widget.getOsgViewer()->addEventHandler(new osgViewer::WindowSizeHandler);

// add the stats handler
widget.getOsgViewer()->addEventHandler(new osgViewer::StatsHandler);

// add the help handler
widget.getOsgViewer()->addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));

// add the record camera path handler
widget.getOsgViewer()->addEventHandler(new osgViewer::RecordCameraPathHandler);

// add the LOD Scale handler
widget.getOsgViewer()->addEventHandler(new osgViewer::LODScaleHandler);

// add the screen capture handler
widget.getOsgViewer()->addEventHandler(new osgViewer::ScreenCaptureHandler);

// load the data
osg::ref_ptr<osg::Node> loadedModel = osgDB::readRefNodeFiles(arguments);

if(!loadedModel)
{
std::cout << arguments.getApplicationName() << ": No data loaded" << std::endl;
return 1;
}

// any option left unread are converted into errors to write out later.
arguments.reportRemainingOptionsAsUnrecognized();

// report any errors if they have occurred when parsing the program arguments.
if(arguments.errors())
{
arguments.writeErrorMessages(std::cout);
return 1;
}


// optimize the scene graph, remove redundant nodes and state etc.
osgUtil::Optimizer optimizer;
optimizer.optimize(loadedModel);

widget.getOsgViewer()->setSceneData(loadedModel);

// widget.getOsgViewer()->realize();

return 0;
});


widget.show();

return app.exec();

}

0 comments on commit bfb66e0

Please sign in to comment.