Sorry, forgot to mention that i've remove the header definitions for mac
and windows. Please add the original header definitions from the
example.
Just to make sure everybody understands what this mod does: We create 9
independent scenes (views) with their own contexts. Each one embedded in
a QGroupBox using QLayout and running independently at 70 fps..
greetings
Lukas
On Wed, Oct 15, 2008 at 05:07:14PM -0400, Lukas Diduch wrote:
>
> This mod to QOSGWidget enables multithreaded rendering using QOSGWidget using
> CompositeViewer. It demonstrates as well the embedding of QOSGWidget into
> other
> QTWidgets. Performance is very good (70 fps) on AMD 3Ghz, FedoraCore8 using
> NVidia 8600GTS.
>
>
> usage:
> ~~~~~~
>
> osgviewerQT --QOSGWidget --MTCompositeViewer cow.osg
>
>
> There are some issues with this mod:
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> 1. Other multithreading modes fail.
>
> 2. Correct Widget inheritance is crucial to functionality.
>
> 3. Written for QT4 only
>
> 4. Using 'ClickToFocus'. Select the widget first before manipulating.
>
> 5. though working fine we get a BadWindow error message see thread
>
> [osg-users] Multiple Contexts in QT Applications
>
> 6. Although the problem (point 5) is related to deranged traits values
> which are set by failing a call to XGetWindowAttributes in
> GraphicsWindowX11::setWindow the following fix (to set traits only if
> XGetWindowAttributes returns with no error) does not solve the problem
> properly:
>
> @ line 750, GraphicsWindowX11.cpp
>
> Status s = XGetWindowAttributes( _display, _window, &watt );
> if (s = True)
> {
> _traits->x = watt.x;
> _traits->y = watt.y;
> _traits->width = watt.width;
> _traits->height = watt.height;
> }
>
> The context can be embedded and displayed but somehow the
> perspective is distored in this case. That's why we set the traits
> in QOSGWidget::createContext after initializing the graphicsContext.
>
>
> Regards,
> Lukas
> /* OpenSceneGraph example, osganimate.
> *
> * Permission is hereby granted, free of charge, to any person obtaining a
> copy
> * of this software and associated documentation files (the "Software"), to
> deal
> * in the Software without restriction, including without limitation the
> rights
> * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> * copies of the Software, and to permit persons to whom the Software is
> * furnished to do so, subject to the following conditions:
> *
> * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> FROM,
> * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> * THE SOFTWARE.
> */
>
> #if USE_QT4
>
> #include <QtCore/QString>
> #include <QtCore/QTimer>
> #include <QtGui/QKeyEvent>
> #include <QtGui/QApplication>
> #include <QtOpenGL/QGLWidget>
> #include <QtGui/QtGui>
> #include <QtGui/QWidget>
> using Qt::WindowFlags;
>
> #else
>
> class QWidget;
> #include <qtimer.h>
> #include <qgl.h>
> #include <qapplication.h>
>
> #define WindowFlags WFlags
>
> #endif
>
>
> #include <osgViewer/Viewer>
> #include <osgViewer/CompositeViewer>
> #include <osgViewer/ViewerEventHandlers>
> #include <osgViewer/GraphicsWindow>
>
> #include <osgViewer/ViewerEventHandlers>
>
> #if defined(WIN32) && !defined(__CYGWIN__)
> #include <osgViewer/api/Win32/GraphicsWindowWin32>
> typedef HWND WindowHandle;
> typedef osgViewer::GraphicsWindowWin32::WindowData WindowData;
> #elif defined(__APPLE__) && defined(APPLE_PRE_10_3)
> #include <osgViewer/api/Carbon/GraphicsWindowCarbon>
> typedef WindowRef WindowHandle;
> typedef osgViewer::GraphicsWindowCarbon::WindowData WindowData;
> #else // all other unix
> #include <osgViewer/api/X11/GraphicsWindowX11>
> typedef Window WindowHandle;
> typedef osgViewer::GraphicsWindowX11::WindowData WindowData;
> #endif
>
>
> #include <osgGA/TrackballManipulator>
> #include <osgGA/FlightManipulator>
> #include <osgGA/DriveManipulator>
> #include <osgGA/KeySwitchMatrixManipulator>
> #include <osgGA/StateSetManipulator>
> #include <osgGA/AnimationPathManipulator>
> #include <osgGA/TerrainManipulator>
>
> #include <osgDB/ReadFile>
>
> #include <iostream>
> #include <sstream>
>
> class QOSGWidget : public QWidget
> {
> public:
>
> QOSGWidget( QWidget * parent = 0, const char * name = 0, WindowFlags
> f = 0, bool overrideTraits = false);
>
> virtual ~QOSGWidget() {}
>
> osgViewer::GraphicsWindow* getGraphicsWindow() { return _gw.get(); }
> const osgViewer::GraphicsWindow* getGraphicsWindow() const { return
> _gw.get(); }
>
> protected:
>
> void init();
> void createContext();
>
> virtual void mouseDoubleClickEvent ( QMouseEvent * event );
> virtual void closeEvent( QCloseEvent * event );
> virtual void destroyEvent( bool destroyWindow = true, bool
> destroySubWindows = true);
> virtual void resizeEvent( QResizeEvent * event );
> virtual void keyPressEvent( QKeyEvent* event );
> virtual void keyReleaseEvent( QKeyEvent* event );
> virtual void mousePressEvent( QMouseEvent* event );
> virtual void mouseReleaseEvent( QMouseEvent* event );
> virtual void mouseMoveEvent( QMouseEvent* event );
>
> osg::ref_ptr<osgViewer::GraphicsWindow> _gw;
> bool _overrideTraits;
> };
>
> QOSGWidget::QOSGWidget( QWidget * parent, const char * name, WindowFlags f,
> bool overrideTraits):
> #if USE_QT4
> QWidget(parent, f), _overrideTraits (overrideTraits)
> #else
> QWidget(parent, name, f), _overrideTraits (overrideTraits)
> #endif
> {
> createContext();
>
>
> #if USE_QT4
> setAttribute(Qt::WA_PaintOnScreen);
> setAttribute(Qt::WA_NoSystemBackground);
> setFocusPolicy(Qt::ClickFocus);
> #else
> setBackgroundMode(Qt::NoBackground);
> #endif
> }
>
> void QOSGWidget::createContext()
> {
> osg::DisplaySettings* ds = osg::DisplaySettings::instance();
>
> osg::ref_ptr<osg::GraphicsContext::Traits> traits = new
> osg::GraphicsContext::Traits;
>
> traits->readDISPLAY();
> if (traits->displayNum<0) traits->displayNum = 0;
>
> traits->windowName = "osgViewerQt";
> traits->screenNum = 0;
> traits->x = x();
> traits->y = y();
> traits->width = width();
> traits->height = height();
> traits->alpha = ds->getMinimumNumAlphaBits();
> traits->stencil = ds->getMinimumNumStencilBits();
> traits->windowDecoration = false;
> traits->doubleBuffer = true;
> traits->sharedContext = 0;
> traits->sampleBuffers = ds->getMultiSamples();
> traits->samples = ds->getNumMultiSamples();
>
> traits->inheritedWindowData = new WindowData(winId());
>
> if (ds->getStereo())
> {
> switch(ds->getStereoMode())
> {
> case(osg::DisplaySettings::QUAD_BUFFER): traits->quadBufferStereo
> = true; break;
> case(osg::DisplaySettings::VERTICAL_INTERLACE):
> case(osg::DisplaySettings::CHECKERBOARD):
> case(osg::DisplaySettings::HORIZONTAL_INTERLACE): traits->stencil
> = 8; break;
> default: break;
> }
> }
>
> osg::ref_ptr<osg::GraphicsContext> gc =
> osg::GraphicsContext::createGraphicsContext(traits.get());
> _gw = dynamic_cast<osgViewer::GraphicsWindow*>(gc.get());
>
> // get around dearanged traits on X11 (MTCompositeViewer only)
> if (_overrideTraits)
> {
> traits->x = x();
> traits->y = y();
> traits->width = width();
> traits->height = height();
> }
>
> }
> void QOSGWidget::destroyEvent(bool destroyWindow, bool destroySubWindows)
> {
> _gw->getEventQueue()->closeWindow();
> }
>
>
> void QOSGWidget::closeEvent( QCloseEvent * event )
> {
> #ifndef USE_QT4
> event->accept();
> #endif
>
> _gw->getEventQueue()->closeWindow();
> }
>
>
> void QOSGWidget::resizeEvent( QResizeEvent * event )
> {
> const QSize & size = event->size();
> _gw->getEventQueue()->windowResize(0, 0, size.width(), size.height() );
> _gw->resized(0, 0, size.width(), size.height());
> }
>
> void QOSGWidget::keyPressEvent( QKeyEvent* event )
> {
> #if USE_QT4
> _gw->getEventQueue()->keyPress( (osgGA::GUIEventAdapter::KeySymbol)
> *(event->text().toAscii().data() ) );
> #else
> _gw->getEventQueue()->keyPress( (osgGA::GUIEventAdapter::KeySymbol)
> event->ascii() );
> #endif
> }
>
> void QOSGWidget::keyReleaseEvent( QKeyEvent* event )
> {
> #if USE_QT4
> int c = *event->text().toAscii().data();
> #else
> int c = event->ascii();
> #endif
>
> _gw->getEventQueue()->keyRelease( (osgGA::GUIEventAdapter::KeySymbol) (c)
> );
> }
>
> void QOSGWidget::mousePressEvent( QMouseEvent* event )
> {
> int button = 0;
> switch(event->button())
> {
> case(Qt::LeftButton): button = 1; break;
> case(Qt::MidButton): button = 2; break;
> case(Qt::RightButton): button = 3; break;
> case(Qt::NoButton): button = 0; break;
> default: button = 0; break;
> }
> _gw->getEventQueue()->mouseButtonPress(event->x(), event->y(), button);
> }
> void QOSGWidget::mouseDoubleClickEvent ( QMouseEvent * event )
> {
> int button = 0;
> switch(event->button())
> {
> case(Qt::LeftButton): button = 1; break;
> case(Qt::MidButton): button = 2; break;
> case(Qt::RightButton): button = 3; break;
> case(Qt::NoButton): button = 0; break;
> default: button = 0; break;
> }
> _gw->getEventQueue()->mouseDoubleButtonPress(event->x(), event->y(),
> button);
> }
> void QOSGWidget::mouseReleaseEvent( QMouseEvent* event )
> {
> int button = 0;
> switch(event->button())
> {
> case(Qt::LeftButton): button = 1; break;
> case(Qt::MidButton): button = 2; break;
> case(Qt::RightButton): button = 3; break;
> case(Qt::NoButton): button = 0; break;
> default: button = 0; break;
> }
> _gw->getEventQueue()->mouseButtonRelease(event->x(), event->y(), button);
> }
>
> void QOSGWidget::mouseMoveEvent( QMouseEvent* event )
> {
> _gw->getEventQueue()->mouseMotion(event->x(), event->y());
> }
>
>
>
>
>
>
>
>
> class ViewerQOSG : public osgViewer::Viewer, public QOSGWidget
> {
> public:
>
> ViewerQOSG(QWidget * parent = 0, const char * name = 0, WindowFlags f
> = 0):
> QOSGWidget( parent, name, f )
> {
> getCamera()->setViewport(new osg::Viewport(0,0,width(),height()));
> getCamera()->setProjectionMatrixAsPerspective(30.0f,
> static_cast<double>(width())/static_cast<double>(height()), 1.0f, 10000.0f);
> getCamera()->setGraphicsContext(getGraphicsWindow());
>
> setThreadingModel(osgViewer::Viewer::SingleThreaded);
>
> connect(&_timer, SIGNAL(timeout()), this, SLOT(update()));
> _timer.start(10);
> }
>
> virtual void paintEvent( QPaintEvent * event ) { frame(); }
>
> protected:
>
> QTimer _timer;
> };
>
>
>
> class CompositeViewerQOSG : public osgViewer::CompositeViewer, public
> QOSGWidget
> {
> public:
>
> CompositeViewerQOSG(QWidget * parent = 0, const char * name = 0,
> WindowFlags f = 0):
> QOSGWidget( parent, name, f )
> {
> setThreadingModel(osgViewer::CompositeViewer::SingleThreaded);
>
> connect(&_timer, SIGNAL(timeout()), this, SLOT(repaint()));
> _timer.start(1);
> }
>
> virtual void paintEvent( QPaintEvent * event ) { frame(); }
>
> protected:
>
> QTimer _timer;
> };
>
>
>
> #if USE_QT4
> // we use this wrapper for CompositeViewer ONLY because of the timer
> //
> class MTCompositeViewer : public osgViewer::CompositeViewer, public QWidget
> {
> public:
>
> MTCompositeViewer (QWidget * parent = 0, WindowFlags f = 0):
> QWidget (parent, f)
> {
>
> setThreadingModel(osgViewer::CompositeViewer::DrawThreadPerContext);
> connect(&_timer, SIGNAL(timeout()), this, SLOT(repaint()));
> _timer.start(1);
> }
>
> virtual void paintEvent( QPaintEvent * event ) { frame(); }
>
> protected:
>
> QTimer _timer;
> };
> #endif
>
> void setupManipulatorAndHandler(osgViewer::View & viewer, osg::ArgumentParser
> & 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() );
> }
>
> // add the state manipulator
> viewer.addEventHandler( new
> osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
>
> // add the thread model handler
> viewer.addEventHandler(new osgViewer::ThreadingHandler);
>
> // add the window size toggle handler
> viewer.addEventHandler(new osgViewer::WindowSizeHandler);
>
> // add the stats handler
> viewer.addEventHandler(new osgViewer::StatsHandler);
>
> // add the help handler
> viewer.addEventHandler(new
> osgViewer::HelpHandler(arguments.getApplicationUsage()));
> }
>
> int mainQOSGWidget(QApplication& a, osg::ArgumentParser& arguments)
> {
> // load the scene.
> osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
> if (!loadedModel)
> {
> std::cout << arguments[0] <<": No data loaded." << std::endl;
> return 1;
> }
>
> std::cout<<"Using QOSGWidget - QWidget + osgViewer creating the graphics
> context."<<std::endl;
>
> #if USE_QT4
> if (arguments.read("--MTCompositeViewer"))
> {
>
> std::cout<<" + using standard CompositeViewer with seperate contexts
> (Multithreaded mode)."<<std::endl;
>
> int nbCowsX = 3;
> int nbCowsY = 3;
> int size = 200;
> unsigned int width = nbCowsX * size;
> unsigned int height = nbCowsY * size;
>
> QGridLayout *uiLayout = new QGridLayout ();
> QWidget *wy = new QWidget ();
>
> // we pass wy as a parent because want wy->show () to work on cViewer
> // too..
> //
> MTCompositeViewer *cViewer = new MTCompositeViewer (wy);
>
> for (int x=0;x<nbCowsX; x++)
> for (int y=0;y<nbCowsY; y++)
> {
>
> // embed the QOSGWidget into QGroupBox to demonstrate that we
> // really use QT's Widgets
> //
> std::stringstream widgetname; widgetname << "View (" << x <<
> "," << y << ")";
> QGroupBox *w= new QGroupBox (QString (widgetname.str ().c_str
> ()), wy);
> QGridLayout *tmpl = new QGridLayout ();
> QOSGWidget *gw = new QOSGWidget (w, 0, 0, true);
> tmpl->addWidget (gw);
> w->setLayout(tmpl);
> uiLayout->addWidget (w, y, x);
>
> // setup views as usual
> osgViewer::View* view = new osgViewer::View;
> view->getCamera()->setGraphicsContext(gw->getGraphicsWindow
> ());
> view->getCamera()->setProjectionMatrixAsPerspective
> (30.0f,
> static_cast<double>(size)/static_cast<double>(size/nbCowsY), 1.0, 1000.0);
> view->getCamera()->setViewport(new
> osg::Viewport(0,0,size,size));
> view->addEventHandler(new osgViewer::StatsHandler);
> view->setCameraManipulator(new osgGA::TrackballManipulator);
> view->setSceneData(loadedModel.get ());
> cViewer->addView(view);
> }
>
> wy->setLayout (uiLayout);
> wy->resize (width, height);
> wy->show ();
>
> a.connect( &a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()) );
>
> return a.exec();
> }
> else
> {
> #endif
> if (arguments.read("--CompositeViewer"))
> {
> osg::ref_ptr<CompositeViewerQOSG> viewerWindow(new
> CompositeViewerQOSG);
> viewerWindow->setGeometry(0,0,640,480);
>
> unsigned int width = viewerWindow->width();
> unsigned int height = viewerWindow->height();
>
> {
> osgViewer::View* view1 = new osgViewer::View;
>
> view1->getCamera()->setGraphicsContext(viewerWindow->getGraphicsWindow());
> view1->getCamera()->setProjectionMatrixAsPerspective(30.0f,
> static_cast<double>(width)/static_cast<double>(height/2), 1.0, 1000.0);
> view1->getCamera()->setViewport(new
> osg::Viewport(0,0,width,height/2));
> view1->setSceneData(loadedModel.get());
>
> setupManipulatorAndHandler(*view1, arguments);
>
> viewerWindow->addView(view1);
> }
>
> {
> osgViewer::View* view2 = new osgViewer::View;
>
> view2->getCamera()->setGraphicsContext(viewerWindow->getGraphicsWindow());
> view2->getCamera()->setProjectionMatrixAsPerspective(30.0f,
> static_cast<double>(width)/static_cast<double>(height/2), 1.0, 1000.0);
> view2->getCamera()->setViewport(new
> osg::Viewport(0,height/2,width,height/2));
> view2->setSceneData(loadedModel.get());
>
> setupManipulatorAndHandler(*view2, arguments);
>
> viewerWindow->addView(view2);
> }
>
> viewerWindow->show();
>
> a.connect( &a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()) );
>
> return a.exec();
> }
> else
> {
> osg::ref_ptr<ViewerQOSG> viewerWindow(new ViewerQOSG);
> viewerWindow->setGeometry(0,0,640,480);
>
> viewerWindow->setCameraManipulator(new
> osgGA::TrackballManipulator);
> viewerWindow->setSceneData(loadedModel.get());
>
> viewerWindow->show();
>
> setupManipulatorAndHandler(*viewerWindow.get(), arguments);
>
> a.connect( &a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()) );
>
> return a.exec();
> }
> #if USE_QT4
> }
> #endif
> }
> _______________________________________________
> osg-submissions mailing list
> [email protected]
> http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org
--
Lukas L. Diduch
Smartspace Laboratory
Information Access Division (IAD)
National Institute of Standards and Technology (NIST)
web : http://www.nist.gov/smartspace
email : [EMAIL PROTECTED]
office : +1 (301) 975 6399
fax : +1 (301) 975 5287
mobile : +1 (240) 899 6536
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org