VR-Vantage 3.1 API Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
exampleEmbedded

Table of Contents

Overview

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, and File Toolbar.

Expected Result

exampleEmbedded2.png
example Embedded Result

Example details

Create and show the main application:

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 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.

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.

Create a window configuration for each window, specifying the observer for each.

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.

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.

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.

// Set the display window creator function to use the Adapter widget.
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.

// Register the qApp with the DtQApplicationProvider.
DtQApplicationProvider::instance(*myDe).setQAppInstance(qApp);
// Register null with the DtDeMainWindowProvider so that no main window
// is ever created. This DtDe instance is embedded in a QMainWindow already.
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 ./bin64/exampleEmbedded.exe (on Windows) or ./bin64/exampleEmbedded (on Linux). For more information about running examples, please see Running Applications and Examples.

Example Source Files


exampleEmbeddedMainWindow.h

/******************************************************************************
** Copyright (c) 2023 MAK Technologies, Inc.
** All rights reserved.
******************************************************************************/
#pragma once
// Include this header before any Qt header.
#include <vrvCore/DtDe.h>
#include <vrvCore/DtWindow.h>
#include <QtWidgets/QMainWindow>
#include <osg/Group>
#include <osg/Node>
class QAction;
class QMenu;
{
Q_OBJECT
public:
ExampleEmbeddedMainWindow(int argc, char* argv[]);
// The adapter widgets. These will become owned and
// deleted by MainWindow.
void buildGui();
public slots:
void open();
void closeFile();
protected:
void createDisplayEngine(int argc, char* argv[]);
virtual void closeEvent(QCloseEvent *event);
void createActions();
void createMenus();
protected:
makVrv::vrvSignalsLib::connection myCurrentSelectionChangedConnection;
};
{
public:
{
myWindow = window;
}
protected:
};

exampleEmbeddedMain.cxx

/******************************************************************************
** Copyright (c) 2023 MAK Technologies, Inc.
** All rights reserved.
******************************************************************************/
// Include this header before any Qt header.
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
//
// Don't pass in command line arguments to Qt.
// We pass it into the example main window below.
//
int dummy(0);
QApplication app(dummy, argv);
//
// This example illustrates how to embed a DtOsgView into a preexisting
// application.
//
ExampleEmbeddedMainWindow mainWindow(argc, argv);
mainWindow.showMaximized();
//
// Notice how the preexisting applications event loop wasn't changed.
//
return app.exec();
}

exampleEmbeddedMainWindow.cxx

/******************************************************************************
** Copyright (c) 2024 MAK Technologies, Inc.
** All rights reserved.
******************************************************************************/
// Include this header before any Qt header.
#include <vrvOsg/vrvOsg.h>
#include <QtWidgets/QApplication>
#include <QtWidgets/QtWidgets>
#include <osg/Group>
#include <osgDB/ReadFile>
#include <osgGA/TrackballManipulator>
#include <vrvCore/svnRev.h>
#include <vlutil/vlLogFileInfo.h>
using namespace makVrv;
, myPluginManager(0)
, myDe(0)
, myMainOSGWidget(0)
, myMiniOsgWidget(0)
{
myConfiguration.setDeFeatures(DtDeInitializer::Features_Stealth);
createDisplayEngine(argc, argv);
buildGui();
preDisplayEngineInitialize();
initializeDisplayEngine();
postDisplayEngineInitialize();
}
{
if (myMainOSGWidget)
{
myMainOSGWidget = 0;
}
if (myMiniOsgWidget)
{
myMiniOsgWidget = 0;
}
delete myDe;
myDe = 0;
myPluginManager = 0;
}
{
// Pre initialize functions
}
{
DtStealthCommandLineProcessor commandLineProcessor;
commandLineProcessor.processCommandLine(myConfiguration, argc, argv);
DtDePathConfiguration pathConfiguration;
pathConfiguration.setSettingsPath("$(APP_DIR)/settings/stealth");
pathConfiguration.setFactoryPath("$(FACTORY_ROOT_DIR)/settings/stealth");
init.setPathConfiguration(pathConfiguration);
std::string displayName = DtDisplayConfiguration::DefaultDisplayString;
displayName += " 1";
// Configure DtDeInitializer
init.setDeMode(DtDeInitializer::MasterMode);
init.setDisplayEngineName(displayName);
// Configure an observer for channel control
makVrv::DtObserverConfiguration observerConfig("Observer 1");
makVrv::DtObserverConfiguration observerConfig2("Observer 2");
inputConfig.observerConfigurations().add(observerConfig);
inputConfig.observerConfigurations().add(observerConfig2);
inputConfig.setOptionalParameter("windowDependent", "true");
init.setInputDriverConfiguration(inputConfig);
// Configure DtDeConfiguration
wName += " 1";
cName += " 1";
cc.setObserverName("Observer 1");
DtDisplayConfiguration dec(displayName);
wc.setWindowType(DtWindowConfiguration::EmbeddedWindow);
wc.channelConfigurations().add(cc);
wName2 += " 2";
DtWindowConfiguration wc2(wName2);
cName2 += " 2";
cc2.setObserverName("Observer 2");
wc2.setWindowType(DtWindowConfiguration::EmbeddedWindow);
wc2.channelConfigurations().add(cc2);
dec.windowConfigurations().add(wc);
dec.windowConfigurations().add(wc2);
deConfig.displayConfigurations().add(dec);
// Set helper pointer.
myDe = new DtDe();
DtLogFileInfo::instance().setAppName( "ExampleEmbeddedMainWindow" );
DtLogFileInfo::instance().setProtocol( DT_PROTOCOL_SHORT_NAME );
DtLogFileInfo::instance().setSvnRev( SVN_REV );
DtLogFileInfo::instance().setVersion( std::string( VANTAGE_VERSION_STRING ) + VANTAGE_PATCH_STRING );
init.setLogFileName( DtLogFileInfo::instance().getLogFileName() );
init.setDeConfiguration(deConfig);
myDe->setDeInitializer(init);
//create the log once we get the DeInitializer since we need this as early as possible
myDe->createDebugLog(init.logFileName(), init.notifyLevel());
myPluginManager = new DtPluginManager(*myDe);
#ifndef _WIN32
// DI-Guy links in Qt 3, which is incompatible with Qt 4 based applications.
// The following code will exclude the DI-Guy plugin for Linux:
myConfiguration.excludePluginFile("../plugins64/release/libvrvDiGuyPlugin.so");
#endif
myConfiguration.addPluginFile("..\\examples\\plugins\\exampleDisConnection.dll");
myPluginManager->initializePlugins();
}
{
// Set the display window creator function to use the Adapter widget.
DtWindowFactory::instance(*myDe).setCreator(
DtWindowConfiguration::EmbeddedWindow,
vrvOsg::init(*myDe);
// Register the qApp with the DtQApplicationProvider.
DtQApplicationProvider::instance(*myDe).setQAppInstance(qApp);
// Register null with the DtDeMainWindowProvider so that no main window
// is ever created. This DtDe instance is embedded in a QMainWindow already.
DtDeMainWindowProvider::registerInstance(*myDe, NULL);
}
{
// Create an IG ticker to tick during Qt's idle time.
DtQtDeTickerProvider& tickerProvider = DtQtDeTickerProvider::instance(*myDe);
tickerProvider.ticker(this);
// this needs an active Display to be hooked up properly
setWindowTitle(tr("Embedded Example"));
setWindowIcon(QIcon(":/images/Mak-de.png"));
}
{
myDe->initialize();
}
{
DtSelectionManager& selectMgr = DtSelectionManager::instance(*myDe);
}
{
if (!selected.empty())
{
DtSelectionManager::IdSet::const_iterator idIter = selected.begin();
DtElementID selId = *idIter;
std::string nameStr;
if (myDe->dataBank().elementData().attributeManager().elementType(selId) == DtElementEntry::Entity)
{
DtSensorFieldOfViewManager& fovMgr = DtSensorFieldOfViewManager::instance(*myDe);
fovMgr.fieldsOfViewForEntity(selId);
if (fieldsOfView)
{
// an entity can have multiple sensors. This fieldsOfView points to the list of all available ones. If it is
// null, there are no sensors on the entity
std::cout << nameStr << " has " << fieldsOfView->size() << " sensor(s)" << std::endl;
}
else
{
std::cout << nameStr << " has no sensors" << std::endl;
}
}
}
}
{
event->accept();
}
{
DtEmbeddedOsgWindow* pWindow = 0;
DtOsgAdapterQtWidget* pAdapter = 0;
osg::GraphicsContext* sharedContext = 0;
if (de.display())
{
if (windows.size() > 0)
{
DtOsgWindow* osgView = dynamic_cast<DtOsgWindow*>(windows.front());
if (osgView)
{
sharedContext = osgView->graphicsContext();
}
}
}
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits();
traits->sharedContext = sharedContext;
const DtDeInitializer& deInit = de.deInitializer();
traits->doubleBuffer = deInit.doubleBuffer();
traits->vsync = deInit.vsync();
traits->depth = deInit.numDepthBits();
traits->stencil = deInit.numStencilBits();
unsigned short level = deInit.antiAliasingLevel();
if (level == 2 || level == 4 || level == 8 || level == 16 || level == 32)
{
traits->sampleBuffers = 1;
traits->samples = level;
}
else
{
traits->sampleBuffers = 0;
traits->samples = 0;
}
if (wc.name() == "Window 1")
{
// Set the main OSG widget as the central widget.
DtOsgAdapterQtWidgetCreator::instance(de).create(de, traits.get(),
DtOsgAdapterQtWidget::createFormatFromTraits(traits.get()), myWindow, 0);
myWindow->setCentralWidget(myWindow->myMainOSGWidget);
}
else if (wc.name() == "Window 2")
{
DtOsgAdapterQtWidgetCreator::instance(de).create(de, traits.get(),
DtOsgAdapterQtWidget::createFormatFromTraits(traits.get()), myWindow, 0);
QDockWidget* dockMini = new QDockWidget("Mini Widget", myWindow);
dockMini->setWidget(myWindow->myMiniOsgWidget);
myWindow->addDockWidget(Qt::LeftDockWidgetArea, dockMini, Qt::Vertical);
}
if (pAdapter)
{
pWindow = new DtEmbeddedOsgWindow(de, wc, pAdapter);
if (pWindow)
{
pAdapter->setView(pWindow);
}
}
return pWindow;
}
{
QString terrainDir = myDe->dePathConfiguration().dataPath().c_str();
terrainDir += "//Terrain";
QString filename =
DtStaticFileDialog::getOpenFileName(*myDe, this, tr("Open File"), terrainDir,
tr(
"All Readable Data Types (*medf *.dt0 *.dt1 *.dt2 *.dted *.flt *.3ds *.osg *.lwo *.obj *.txp);;" \
"MAK Terrain Database (*.mtf);;" \
"MAK Encrypted Data Format (*.medf);;" \
"DTED (*.dt0 *.dt1 *.dt2 *.dted);;" \
"OpenFlight (*.flt);;" \
"Terrapage (*.txp);;" \
"Other 3D Formats (*.3ds *.osg *.lwo *.obj);;" \
"All (*.*);;"
));
if (!filename.isEmpty())
{
QDir dir;
QString relativePath = dir.relativeFilePath(filename);
// Create a model definition.
std::string modelPath = relativePath.toStdString();
DtModelDefinition modelDef(modelPath);
modelDef.setParameter("filename", modelPath);
myDe->sharedState().addModelDefinition(modelDef);
// Add the model as a terrain patch
myDe->scene().terrain().addTerrainPatch(modelDef.name());
}
}
{
myDe->scene().resetScene();
}
{
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);
//IF you want to quit using a key stroke
//exitAct->setShortcut(tr("Ctrl+Q"));
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"));
}

[<< Examples] [Home] [Top of Page]



Copyright © 2005-2024 MAK Technologies. All Rights Reserved (www.mak.com)