Hi Robert,

My previous submission was likely ignored since I had not yet subscribed to
to the [email protected] mailing list.  So, here goes
again - this version addressing some problems in addition what was updated
in the SVN version.

Here are a couple of fixes for the file examples/osgviewerQT/QOSGWidget.cpp to
address some OS X issues. Most of these fixes were previously submitted by Julian Scheid. However, this patch however should not break the example for non-OS X builds and has been tested on 64-bit Linux as well as Mac OS X 10.5.

o  The value returned by QWidget::winId() is not usable as input for
WindowData under OS X the way it is for both Windows and Unix.  Julian's fix
for this uses the Carbon API.  Since the fix for X11 in unknown, it is now
assumed that OSG has been built with OSG_WINDOWING_SYSTEM='Carbon' for this
example to work at all when running under OS X.

o  The CompositeViewer version would hang on exit with the original timer start
argument.  Changing the argument value to match the non-composite version
seemed to cure the hanging.

o  Julian's patch altered the setGeometry position to 30/30 in order to see any
window decorations.  I did not have this problem, but left his changes intact.

o  The non-composite viewer needed it's camera initialization defered until
after the ViewerQOSG's Qt base class had been initialized.  Otherwise, the view
did not cover the entire window.


There are still issues with resizing and focus handling that need to be
addressed.  I have good resize focus and behavior working in some of my
development code that I'll try to migrate to the osgviewerQT code as soon
as I get a chance.  The --MTCompositeViewer feature still has severe problems.


--Don

=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=

Donald Leich                      Mailto:[email protected]
Senior Software Developer         Voice: 201-460-4700 ext: 215
Intelligent Light                 FAX:   201-460-0221
301 Route 17 North, 7th Floor
Rutherford, NJ  07070-2575

Visit our web site at http://www.ilight.com
=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=

>
> ------------------------------------------------------------------------
>
> Hi Julian,
>
>
>
> For further submissions could you please send whole files rather than
>
> patches.  I've looked through the patch by hand and it's not in a
>
> state that suitable for merging - breaking all build on all platforms
>
> except yours isn't acceptable so another solution will need to be
>
> found.
>
>
>
> As a general note, I'm confused by the mixing of X11 and Carbon.  Is
>
> Qt built against X11 or Carbon?  If Qt is built against X11 then
>
> you'll need to select the X11 build for OSG as well.  My guess is that
>
> the Qt example might need to have some CMake code in it to direct the
>
> example to compile different paths.
>
>
>
> Robert.
>
>

/* 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__)  // Assume using Carbon on Mac.
#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();

#if defined(__APPLE__) 
    // Extract a WindowPtr from the HIViewRef that QWidget::winId() returns.
    // Without this change, the peer tries to call GetWindowPort on the 
HIViewRef
    // which returns 0 and we only render white.
    traits->inheritedWindowData = new 
WindowData(HIViewGetWindow((HIViewRef)winId()));

#else // all others
    traits->inheritedWindowData = new WindowData(winId());
#endif


    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 )
        {
            setThreadingModel(osgViewer::Viewer::SingleThreaded);

            connect(&_timer, SIGNAL(timeout()), this, SLOT(update()));
            _timer.start(10);
        }
        void updateCamera()
        {
            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());
        }

        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()));
            // The app would hang on exit when using start(1).  Behaves better 
with 10
            // like the non-composite viewer.  Was this just a typo?
            _timer.start(10);
        }

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

    protected:

        QTimer _timer;
};



#if USE_QT4
// we use this wrapper for CompositeViewer ONLY because of the timer
// NOTE: this is a workaround because we're not using QT's moc precompiler here.
//
class QViewerTimer : public QWidget
{

    public:

        QViewerTimer (QWidget * parent = 0, WindowFlags f = 0):
            QWidget (parent, f)
    {
        _viewer = new osgViewer::CompositeViewer ();
        
_viewer->setThreadingModel(osgViewer::CompositeViewer::DrawThreadPerContext);
        connect(&_timer, SIGNAL(timeout()), this, SLOT(repaint()));
        _timer.start(10);
    }

    ~QViewerTimer ()
    {
        _timer.stop ();
    }

        virtual void paintEvent (QPaintEvent * event) { _viewer->frame(); }

        osg::ref_ptr <osgViewer::CompositeViewer> _viewer;
        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 (arguments.read("--CompositeViewer"))
    {
        osg::ref_ptr<CompositeViewerQOSG> viewerWindow(new CompositeViewerQOSG);
        viewerWindow->setGeometry(0,0,640,480);
        // Open the ViewerQOSG window at 30/30 instead of 0/0.  In some 
instances,
        // the window may otherwise lack any window decoration.
        // viewerWindow->setGeometry(30,30,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();
    }
#if USE_QT4
    else if (arguments.read("--MTCompositeViewer"))
    {

        std::cout <<" + using standard CompositeViewer with seperate contexts 
(Multithreaded mode / EXPERIMENTAL !)" <<std::endl;

        int nbCowsX = 3;
        int nbCowsY = 2;
        int size = 300;
        unsigned int width = nbCowsX * size;
        unsigned int height = nbCowsY * size;

        QGridLayout *uiLayout = new QGridLayout ();
        QWidget *wy = new QWidget ();

        // the timer holds an instance of osgViewer::CompositeViewer
        // NOTE: this is a workaround since we're not using QT's moc 
precompiler here..
        QViewerTimer *ctimer = new QViewerTimer ();

        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>(width*2)/static_cast<double>(height), 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 ());
                ctimer->_viewer->addView(view);

            }

        //uiLayout->addWidget (ctimer);
        wy->setLayout (uiLayout);
        wy->resize (width, height);
        wy->show ();

        // we need the timer to be visible for repaints
        // NOTE: this is a workaround since we're not using QT's moc 
precompiler here..
        ctimer->resize (1,1);
        ctimer->show ();

        a.connect( &a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()) );

        return a.exec();
    }
#endif
    else
    {
        osg::ref_ptr<ViewerQOSG> viewerWindow(new ViewerQOSG);

        // Open the ViewerQOSG window at 30/30 instead of 0/0.  In some 
instances,
        // the window may otherwise lack any window decoration.
        viewerWindow->setGeometry(0,0,640,480);
        // viewerWindow->setGeometry(30,30,640,480);

        // Setup the camera only after ViewerQOSG's Qt base class has been
        // initialized. Without this change the view doesn't cover the whole
        // window.
        viewerWindow->updateCamera();
        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();
    }
}
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

Reply via email to