This example shows how to create a your own QT application with a Main Window that has a VR-Vantage view embedded into it.
It also adds a dockable widget with a second embedded view (and its own independent observer). Finally, it adds some standard VR-Vantage GUI elements, including a File Menu, File Toolbar, and a dockable panel that can display the OSG scene graph.
Create and show the main application:
mainWindow.showMaximized();
Run the application:
The example application has a GUI derived from QMainWindow. This is a very common way of building QT applications.
The main window class owns some key VR-Vantage objects. It owns a DtDe (display engine) which is the core component for adding visualization to any application. It also owns a DtPluginManager which is responsible for loading all the VR-Vantage plug-ins.
The OpenGL graphics context needs to be owned and managed by the QT main window. We connect it the VR-Vantage display engine (and consequently OSG) via the DtOsgAdapterQtWidget. We use a second DtOsgAdapterWidget to embed the display engine into the dock widget.
The main window also owns a DtPage to display the scene graph tree;
as well as some QT widgets for menus and toolbars.
The real work begins in the constructor of the main window.
First, set up the display engine configuration and initializer.
{
DtDeConfiguration deConfig;
std::string displayName = DtDisplayConfiguration::DefaultDisplayString;
displayName += " 1";
init.setDeMode(DtDeInitializer::MasterMode);
init.setDisplayEngineName(displayName);
Create observer configurations for the main window and docked window and include them in the input driver configuration, and add the input driver configuration to the display engine initializer.
init.setInputDriverConfiguration( inputConfig );
Create a window configuration for each window, specifying the observer for each.
wName += " 1";
DtWindowConfiguration wc(wName);
cName += " 1";
DtChannelConfiguration cc(cName);
cc.setObserverName( "Observer 1" );
DtDisplayConfiguration dec(displayName);
wc.setWindowType(DtWindowConfiguration::EmbeddedWindow);
wc.channelConfigurations().add(cc);
wName2 += " 2";
DtWindowConfiguration wc2(wName2);
cName2 += " 2";
DtChannelConfiguration cc2(cName2);
cc2.setObserverName( "Observer 2" );
wc2.setWindowType(DtWindowConfiguration::EmbeddedWindow);
wc2.channelConfigurations().add(cc2);
dec.windowConfigurations().add(wc);
dec.windowConfigurations().add(wc2);
deConfig.displayConfigurations().add(dec);
Create, intialize, and provide the display configuration to the display engine.
Finally, create a plug-in manager, and then initialize and load the plug-ins.
myPluginManager = new DtPluginManager(*myDe);
#ifndef _WIN32
std::list<std::string> excludePlugins;
excludePlugins.push_back("../plugins/release/libvrvDiGuyPlugin.so");
#endif
}
Now we create the GUI. The interesting thing here is the DtQtIgTickerProvider. This provides us with a "ticker" that ticks the display engine as fast as the QT GUI will go. The rest of the function just sets up menus, toolbars, and the other things that would be part of this application.
{
DtQtDeTickerProvider& tickerProvider = DtQtDeTickerProvider::instance(*myDe);
tickerProvider.ticker(this);
DtSceneGraphTreeWidgetCreator* twc = new DtSceneGraphTreeWidgetCreator(*myDe);
mySceneGraphTreeWidget = twc->create(this);
dock->setWidget(mySceneGraphTreeWidget);
addDockWidget(Qt::LeftDockWidgetArea,dock,Qt::Vertical);
setWindowTitle(tr("Embedded Example"));
setWindowIcon(QIcon(":/images/Mak-de.png"));
}
During the call to preDisplayEngineInitialize(), we override the functionality set up by plug-ins. We want to create a DtEmbeddedOsgWindow that uses a DtOsgAdapterQtWidget for its graphic context and we do that by installing a new creator with the DtWindowFactory.
DtWindowFactory::instance(*myDe).setCreator(
DtWindowConfiguration::EmbeddedWindow,
We have to tell our application framework not to try and create a QApplication, which already exists. We also have to tell it not to create a main window, since that already exists too.
DtQApplicationProvider::instance(*myDe).setQAppInstance(qApp);
DtDeMainWindowProvider::registerInstance(*myDe, NULL);
Finally, everything is all set up and we can initialize the display engine:
Building the Example
VR-Vantage includes pre-built versions of the example application. To build it yourself, follow the instructions at Building VR-Vantage Examples, Applications, and Plug-ins.
Running the Example
This example is an application. You can run it by running ./bin/exampleEmbedded.exe (on Windows) or ./bin/exampleEmbedded (on Linux). For more information about running examples, please see Running Applications and Examples.
Example Source Files
exampleEmbeddedMainWindow.h
#ifndef exampleEmbeddedMainWindow_H
#define exampleEmbeddedMainWindow_H
#include <QtGui/QMainWindow>
#include <osg/Group>
#include <osg/Node>
{
Q_OBJECT
public:
public slots:
protected:
protected:
};
{
public:
{
}
protected:
};
#endif
exampleEmbeddedMain.cxx
#include <QtGui/QApplication>
int main(int argc, char *argv[])
{
mainWindow.showMaximized();
return app.exec();
}
exampleEmbeddedMainWindow.cxx
#include <QtGui/QApplication>
#include <QtGui/QtGui>
#include <osg/Group>
#include <osgDB/ReadFile>
#include <osgGA/TrackballManipulator>
using namespace makVrv;
, myPluginManager(0)
, myDe(0)
, myMainOSGWidget(0)
, myMiniOsgWidget(0)
{
createDisplayEngine();
buildGui();
preDisplayEngineInitialize();
initializeDisplayEngine();
postDisplayEngineInitialize();
}
{
if(mySceneGraphTreeWidget)
{
mySceneGraphTreeWidget = 0;
}
if (myMainOSGWidget)
{
myMainOSGWidget = 0;
}
if(myMiniOsgWidget)
{
myMiniOsgWidget = 0;
}
myDe = 0;
myPluginManager = 0;
}
{
}
{
std::string displayName = DtDisplayConfiguration::DefaultDisplayString;
displayName += " 1";
wName += " 1";
cName += " 1";
cc.setObserverName( "Observer 1" );
wc.setWindowType(DtWindowConfiguration::EmbeddedWindow);
wc.channelConfigurations().add(cc);
wName2 += " 2";
cName2 += " 2";
cc2.setObserverName( "Observer 2" );
wc2.setWindowType(DtWindowConfiguration::EmbeddedWindow);
wc2.channelConfigurations().add(cc2);
dec.windowConfigurations().add(wc);
dec.windowConfigurations().add(wc2);
#ifndef _WIN32
std::list<std::string> excludePlugins;
excludePlugins.push_back("../plugins/release/libvrvDiGuyPlugin.so");
#endif
}
{
DtWindowFactory::instance(*myDe).setCreator(
DtWindowConfiguration::EmbeddedWindow,
DtQApplicationProvider::instance(*myDe).setQAppInstance(qApp);
DtDeMainWindowProvider::registerInstance(*myDe, NULL);
}
{
mySceneGraphTreeWidget = twc->
create(
this);
dock->setWidget(mySceneGraphTreeWidget);
addDockWidget(Qt::LeftDockWidgetArea,dock,Qt::Vertical);
setWindowTitle(tr("Embedded Example"));
setWindowIcon(QIcon(":/images/Mak-de.png"));
}
{
}
{
}
{
event->accept();
}
{
osg::GraphicsContext* sharedContext = 0;
{
if(windows.size() > 0)
{
if(osgView)
{
}
}
}
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits();
traits->doubleBuffer = true;
traits->sharedContext = sharedContext;
if(wc.
name() ==
"Window 1")
{
DtOsgAdapterQtWidgetCreator::instance( de ).create( de, traits.get(),
DtOsgAdapterQtWidget::createFormatFromTraits(traits.get()),
myWindow );
}
else if(wc.
name() ==
"Window 2")
{
DtOsgAdapterQtWidgetCreator::instance( de ).create( de, traits.get(),
DtOsgAdapterQtWidget::createFormatFromTraits(traits.get()),
myWindow );
myWindow->addDockWidget(Qt::LeftDockWidgetArea,dockMini,Qt::Vertical);
}
if(pAdapter)
{
if(pWindow)
{
}
}
return pWindow;
}
{
terrainDir += "//Terrain";
QString filename =
DtStaticFileDialog::getOpenFileName(*myDe,this,tr("Open File"),terrainDir,
tr(
"All Readable Data Types (*.mtp *.mtd *.mtl *.gdb *medf *.dt0 *.dt1 *.dt2 *.dted *.flt *.c4b *.c7b *.c7l *.shp *.3ds *.osg *.lwo *.obj *.txp);;" \
"MAK Terrain Project (*.mtp *.mtd);;" \
"MAK Terrain Database (*.gdb);;" \
"MAK Stealth Legacy MTL (*.mtl);;" \
"MAK Encrypted Data Format (*.medf);;" \
"DTED (*.dt0 *.dt1 *.dt2 *.dted);;" \
"OpenFlight (*.flt);;" \
"CTDB Version 4 (*.c4b);;" \
"CTDB Version 7 (*.c7b);;" \
"CTDB Version 7L (*.c7l);;" \
"Shape Terrain Data (*.shp);;" \
"Terrapage (*.txp);;" \
"Other 3D Formats (*.3ds *.osg *.lwo *.obj);;" \
"All (*.*);;"
));
if(!filename.isEmpty())
{
QDir dir;
QString relativePath = dir.relativeFilePath(filename);
std::string modelPath = relativePath.toStdString();
modelDef.setParameter("filename", modelPath);
}
}
{
}
{
myOpenAction =
new QAction(QIcon(
":/images/open.png"), tr(
"&Open..."),
this);
myOpenAction->setShortcut(tr("Ctrl+O"));
myOpenAction->setStatusTip(tr("Open an existing file"));
connect(myOpenAction, SIGNAL(triggered()),
this, SLOT(
open()));
myCloseAction =
new QAction(QIcon(
":/images/close.png"), tr(
"&Close"),
this);
myCloseAction->setShortcut(tr("Ctrl+C"));
myCloseAction->setStatusTip(tr("Close the current file"));
connect(myCloseAction, SIGNAL(triggered()),
this, SLOT(
closeFile()));
myExitAction =
new QAction(QIcon(
":/images/exit.png"),tr(
"E&xit"),
this);
myExitAction->setStatusTip(tr("Exit the application"));
connect(myExitAction, SIGNAL(triggered()), this, SLOT(close()));
}
{
myFileMenu = this->menuBar()->addMenu(tr("&File"));
myFileMenu->addAction(myOpenAction);
myFileMenu->addAction(myCloseAction);
myFileMenu->addSeparator();
myFileMenu->addAction(myExitAction);
}
{
myFileToolBar = this->addToolBar(tr("File"));
myFileToolBar->addAction(myOpenAction);
myFileToolBar->addAction(myCloseAction);
}
{
this->statusBar()->showMessage(tr("Ready"));
}