4

I'm using OpenSceneGraph and Qt to develop a simulation software. Simulations can involve multiple bots in the same virtual world. My requirements for views are as follows:

  • Ability to show static world cameras
  • Ability to show bot cameras
  • Ability to move these views around and/or stack them

To accomplish these tasks, I have made an 'OSGWidget' that uses an Osg Viewer to render the scene inside a QGLWidget. This OSGWidget is in turn put inside a QDockWidget that can be moved around and/or stacked, fulfilling that requirement.

The problem is that when using multiple singular viewers to render the same scene in different widgets, I get strange render behavior. Namely, textures do not display properly or sometimes even at all.

I have looked around SO and the OSG forums and while people have had similar problems, the only responses I have seen have suggested switching to an Osg CompositeViewer. For my purposes, I would like to avoid using that as it breaks my desired requirement of movable and stackable widgets rendering the same scene.

Is this an intractable situation that just isn't easily handled by Osg? I have seen several posts that say this is not how OSG is 'supposed to work' but they haven't really provided facts to support that claim. Has anyone done something similar or have any ideas/insight? I can provide code snippets if needed, but as this might just be a contradiction to Osg's ideology I will wait to get some responses.

genpfault
  • 51,148
  • 11
  • 85
  • 139
kelano
  • 293
  • 3
  • 14

1 Answers1

3

Thanks to some help from the comments and from a couple other sites, I was able to successfully get the behavior I wanted from CompositeViewer.

Basically, all OSG Views go through my "WidgetDriver" which contains a CompositeViewer.

class OsgWidgetDriver {
public:
    void init() {
        compositeViewer = new osgViewer::CompositeViewer;
        compositeViewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
        compositeViewer->setReleaseContextAtEndOfFrameHint(false);
    }

    void start() {
        initialized = true;
    }

    void stop() {
        compositeViewer->stopThreading();
        compositeViewer->setDone(true);
    }

    void updateFrame() {
        if (initialized)
            compositeViewer->frame();
    }

    void addView(osgViewer::View *view) { compositeViewer->addView(view); }
    bool isInitialized() { return initialized; }
protected:
    bool initialized;
    osgViewer::CompositeViewer *compositeViewer;
};

Then, whenever I make a new Qt OSG Widget, I hand the osg::View off to the driver. I let the driver update the render window, while Qt can still update the QWidget accordingly. It even allows me to place the widget in a QDockWidget so I can move them around and stack them as needed.

Some final notes on the process if anyone else wants to do this:

  • You will very likely run into weird texture display problems when multiple OSG Viewers are looking at one scene. If that happens, use the osgUtil::Optimizer::TextureVisitor to set all textures to "UnrefImageAfterApply = false". This will allow proper texture displays across multiple osg::View instances.
  • The CompositeViewer options I set above, threading model to SingleThreaded and releaseContextAtEndOfFrame to false, are necessary if you want a single thread acting upon multiple views. If you use a widget driver like I did, you will want to do this.
kelano
  • 293
  • 3
  • 14