VR-Forces 4.3 Class Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
exampleMultipleChannels

Table of Contents

Overview

This example shows how to create a multiple windows and channels. This application demonstrates the use of multiple windows with multiple channels each rendering the same scene, however each channel renders the scene differently.

Example details

A VR-Vantage application displays one or more windows; floating, embedded or full-screen. Each window can be divided into one or more channels. Each channel displays a view into the scene being rendered. To get the view, each channel has one observer in the scene rendering to the viewport the channel defines in the parent window.

Channels can share observers to display the same view within the scene. However to render different views into the same scene, different observer instances per channel are required. For this example to demonstrate how to render different models in each channel, multiple channels are created, each with its own observer-mode configuration. When creating an observer for a channel, the observer mode describes how the observer is to render the scene to the channel; such as 3D or 2D. Among other attributes defined by the observer-mode is the model-set to be rendered. A model-set is an identifier given to branches of the scene-graph that define which channel to render in. Each channel is configured with an observer-mode and the observer-mode defines which model-set renders in the channel.

When models are added into the scene, they are generally added to a scene-object which manages the model for the scene. The scene-object inserts the geometry to the scene-graph and positions the model in the scene. It is the scene-object that defines the model-set for the model. When a channel is rendering the scene-objects in the scene, the channel's observer will cull-out scene-objects that do not have a matching model-set for the channel. For example, if a channel is configured with the '3D' observer-mode, the channel will only render scene-objects with model-set zero. Scene-objects with other model-sets will not be rendered within that channel.

The observer-mode to model-set mapping is defined automatically when the VR-Vantage application is configured during initialization. At start-up and initialization, the application reads configuration files, one of which associate the observer-modes with the model-set identifiers to be used. To create custom observer-mode to model-set mappings, a custom configuration file can be used. This application uses a default configuration for the VR-Vantage XR application. The default observer configuration is located in a file named 'default_ObserverModes.omcx' located in the '.../appData/settings/vantageXR' directory.

The two important steps to rendering different scene-objects in different channels are:

  1. Configure the channel with an observer-mode.
  2. Specify the model-set in the scene-object.

This example uses three helper functions to configure the display into multiple windows with multiple channels, each with a different observer-mode.

makVrv::DtDe& de, double left=0, double right=100, double bottom=0,
double top=100);
makVrv::DtDe& de, int x, int y, unsigned int numChannels=1);
makVrv::DtDe& de, const std::string& name = "My Display Configuration");

The helper function to create the channels first creates an observer configuration with a unique observer name.

std::string oName = DtObserverConfiguration::ObserverConfigurationString;
DtObserverConfiguration observerConfig(oName);

The observer-mode is defined in the observer-configuration, then the configuration is registered with the input driver found in the display engine's drive-manager.

observerConfig.setObserverMode(mode);

The mode is a string matching one of the default observer-modes read in at application configuration time. The channel configuration is then created with its own unique channel name

std::string cName = DtChannelConfiguration::DefaultChannelString;
DtChannelConfiguration channelConfig(cName);

The channel's viewport is defined and it is given the name of the observer configuration.

channelConfig.setViewport(left, right, bottom, top);
channelConfig.setObserverName(oName);
return channelConfig;

The helper function to create the windows first creates a window configuration with a unique window name.

std::string wName = DtWindowConfiguration::DefaultWindowString;
DtWindowConfiguration windowConfig(wName);

Then the type of window, size and position are set in the window's configuration.

windowConfig.setWindowType(DtWindowConfiguration::Window);
windowConfig.setPosition(x, y);
windowConfig.setSize(400, 300);

For each channel that the window displays, the window configuration is given a channel configuration by calling the helper function for channels.

windowConfig.channelConfigurations().add(makeChannelConfiguration(de, 1, 99, 51, 99));
return windowConfig;

The helper function to create the display configuration just creates a configuration and for each window displayed, is given a window configuration by calling the helper function for windows.

DtDisplayConfiguration dc;
dc.setName(name);
dc.windowConfigurations().add(makeWindowConfiguration(de, 100, 100, 2));
dc.windowConfigurations().add(makeWindowConfiguration(de, 600, 100, 3));
dc.windowConfigurations().add(makeWindowConfiguration(de, 100, 500, 1));
dc.windowConfigurations().add(makeWindowConfiguration(de, 600, 500, 4));
return dc;

This example uses three helper functions to load the geometry files into scene-objects, each for a different model-set.

std::string registerModelDefinition(DtDe& de, const std::string& dataFile)
void addModelToTheScene(DtDe& de, const std::string& modelName)
void loadTheScene(DtDe& de)

The helper function to register the model definitions takes the name of a model geometry file, creates a definition with a unique name and registers the definition with the display engine.

DtModelDefinition md(modelName.str());
md.setParameter("filename", dataFile);
de.sharedState().addModelDefinition(md);
return modelName.str();

The helper function to load a model into the scene creates a scene-object with a unique id, assigns a model-set to the scene-object, and adds a model to the scene-object. The model is created with a previously registered model-definition.

DtSceneObject* sceneObj = new DtSceneObject(de, id);
sceneObj->setModelSet(modelSet);
DtOsgSimpleModel* model = new DtOsgSimpleModel(de, id);
model->setModelDefinition(modelName);
sceneObj->addModel(model, 0);

When the model is added to the scene-object, the model is loaded from disk using the model-configuration.

The helper function to load the scene just iterates over a list of filenames for models, registering their definitions and generating scene-objects for each.

std::vector<std::string>::const_iterator iter(modelFiles.begin());
std::vector<std::string>::const_iterator endr(modelFiles.end());
for (; iter != endr; ++iter)
{
std::string modelName = registerModelDefinition(de, *iter);
addModelToTheScene(de, modelName);
}

The main application for this example is created with the default configuration for a VR-Vantage XR application.

When the application is initialized, it creates a default display layout.

This application creates a custom display layout with multiple windows and overwrites the initialized default

It is important to note that the custom display must be created and realized after the default application initialization. If the custom display were created first, the act of initializing would overwrite the custom display with the default. After the custom display is created the scene is loaded and the application is run.

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/exampleMultipleChannels.exe (on Windows) or ./bin/exampleMultipleChannels (on Linux). For more information about running examples, please see Running Applications and Examples.

Learn More

Example Source Files


exampleMultipleChannels.cxx

/*****************************************************************************
* Copyright (c) 2012 MAK Technologies, Inc.
* All rights reserved.
*****************************************************************************/
#include <string>
#include <sstream>
#include <iostream>
#include <vrvCore/DtDe.h>
// Use the VR-Vantage namespace. All classes in VR-Vantage are in this namespace.
using namespace makVrv;
// The main function configures the display-engine with multiple windows
// (containing multiple channels) displaying the same scene. The scene has
// different models, each loaded into a different model-set, and the window-
// channels are each configured to display a different model-set.
int main(int argc, char** argv)
{
// A DtVrvApplication wraps up all the components required to build a
// complete VR-Vantage application. This application configures the
// DtVrvApplication to be an Stealth application. Doing so will automatically
// read the default observer modes we wish to use.
DtVrvApplication app(config);
// Initializing the application sets up the default environment, loads
// the plug-ins and sets up the default configuration.
app.initialize(argc, argv);
// Always create the display configuration after initializing the
// application. Custom configurations added before the application is
// initialized will be overwritten with default configuration during
// initialization.
// Try to add this configuration to the Display Engine.
{
// Realize the display configuration on this display engine
// causing the windows and channels to be created.
std::string displayName = app.de().igCommunicator().name();
app.de().realizeDisplayConfiguration(displayName, dc.name());
// For this example print out the window/channel structure of the display.
// Load all the models into the scene.
loadTheScene(app.de());
}
else
{
std::cerr << "Could not add display configuration: " << dc.name() << std::endl;
}
// Create an event loop and begin running the display engine.
app.run();
}

multipleChannelUtilities.h

/*****************************************************************************
* Copyright (c) 2012 MAK Technologies, Inc.
* All rights reserved.
*****************************************************************************/
#pragma once
#include <string>
namespace makVrv { class DtDe; }
makVrv::DtDe& de, double left=0, double right=100, double bottom=0,
double top=100);
makVrv::DtDe& de, int x, int y, unsigned int numChannels=1);
makVrv::DtDe& de, const std::string& name = "My Display Configuration");
extern std::string registerModelDefinition(
makVrv::DtDe& de, const std::string& dataFile);
extern void addModelToTheScene(makVrv::DtDe& de, const std::string& modelName);

multipleChannelUtilities.cxx

/*****************************************************************************
* Copyright (c) 2012 MAK Technologies, Inc.
* All rights reserved.
*****************************************************************************/
#include <sstream>
#include <iostream>
#include <matrix/vlTaitBryan.h>
#include <matrix/vlVector.h>
#include <vrvCore/DtDe.h>
// Use the VR-Vantage namespace. All classes in VR-Vantage are in this namespace.
using namespace makVrv;
// This is a list of mode-names and model-set values. Mode-names define the
// rendering modes (2D/3D), model-sets, and other attributes. These mode-names
// are standard modes used in VR-Vantage. They are defined (and can be found)
// in the configuration files that are loaded when an application is
// initialized. These mode-names and model-sets were taken from the file:
// ...\appData\settings\stealth\default_ObserverModes.omcx.
//
// This example gives each channel a different mode (and model-set) in order to
// demonstrate a scene with multiple scene-objects can render the same scene-
// graph differently in each channel. For this example, each channel should
// render only one of the multiple scene-objects in the scene.
typedef std::pair<std::string, int> ModeToModelSet;
const std::vector<ModeToModelSet> modesAndSets =
StdVectorCreator< ModeToModelSet >
(ModeToModelSet("3D", 0))
(ModeToModelSet("XR", 1))
(ModeToModelSet("Plan View", 5))
(ModeToModelSet("OTW", 0))
// (ModeToModelSet("Inset", 0))
;
// This is a list of file names. All files are loaded into the scene-graph,
// however each channel will render only one of the models.
const std::string vehicles("$(DATA_DIR)/Vehicles/Wheeled/");
const std::string trees("$(DATA_DIR)/Vegetation/Trees/");
const std::vector<std::string> modelFiles = StdVectorCreator< std::string >
(vehicles + "MiniCooperBlue/MiniCooperBlue.medf")
(vehicles + "ChevroletTahoeSilver/ChevroletTahoeSilver.medf")
(vehicles + "BMWM5SilverPolice/BMWM5SilverPolice.medf")
(vehicles + "HondaAccordPurple/HondaAccordPurple.medf")
// (trees + "BigLeafMaple/BigLeafMaple.medf")
// (trees + "DatePalm/DatePalm.medf")
// (trees + "Ficus/Ficus.medf")
// (trees + "WeepingWillow/WeepingWillow.medf")
;
DtDe& de, double left, double right, double bottom, double top)
{
// Id value to make the channel and observer names unique
static DtUniqueID id(1);
std::stringstream idName;
idName << " " << id;
// Create a new observer for this channel.
oName += idName.str();
DtObserverConfiguration observerConfig(oName);
// Give each observer a different mode.
const std::string&
mode(modesAndSets.at((id-1) % modesAndSets.size()).first);
observerConfig.setObserverMode(mode);
// Register the observer-configuration for the channel to use later.
// Create a channel, giving it a unique name.
cName += idName.str();
DtChannelConfiguration channelConfig(cName);
// Set the viewport for this channel (where it will render within a window).
// The default is to fill the entire window.
channelConfig.setViewport(left, right, bottom, top);
// Set the observer that the channel will use.
channelConfig.setObserverName(oName);
// return the configuration for this channel.
++id;
return channelConfig;
}
DtDe& de, int x, int y, unsigned int numChannels)
{
// Id value to make the window name unique
static DtUniqueID id(1);
std::stringstream idName;
idName << " " << id;
// Create a window, giving it a unique name.
wName += idName.str();
DtWindowConfiguration windowConfig(wName);
// Set the type and position for this window.
windowConfig.setPosition(x, y);
windowConfig.setSize(400, 300);
// Create the channel-configurations for this window.
// Note: channels are configured slightly less then window sizes
// to display a visible (black) boarder around each channel.
switch (numChannels)
{
case 2:
windowConfig.channelConfigurations().add(makeChannelConfiguration(de, 1, 99, 51, 99));
windowConfig.channelConfigurations().add(makeChannelConfiguration(de, 1, 99, 1, 49));
break;
case 3:
windowConfig.channelConfigurations().add(makeChannelConfiguration(de, 1, 49, 51, 99));
windowConfig.channelConfigurations().add(makeChannelConfiguration(de, 51, 99, 51, 99));
windowConfig.channelConfigurations().add(makeChannelConfiguration(de, 1, 99, 1, 49));
break;
case 4:
windowConfig.channelConfigurations().add(makeChannelConfiguration(de, 1, 49, 51, 99));
windowConfig.channelConfigurations().add(makeChannelConfiguration(de, 51, 99, 51, 99));
windowConfig.channelConfigurations().add(makeChannelConfiguration(de, 1, 49, 1, 49));
windowConfig.channelConfigurations().add(makeChannelConfiguration(de, 51, 99, 1, 49));
break;
default:
windowConfig.channelConfigurations().add(makeChannelConfiguration(de, 1, 99, 1, 99));
break;
}
// return the configuration for this window.
++id;
return windowConfig;
}
DtDe& de, const std::string& name)
{
// Configure a display with two windows containing two or three channels.
dc.setName(name);
return dc;
}
{
// For each window in the display...
std::cerr << std::endl;
const DtWindowManager::WindowList& windows =
for (DtWindowManager::WindowList::const_iterator witer(windows.begin());
witer != windows.end(); ++witer)
{
// Print the window's name.
const DtWindow* win(*witer);
std::cerr << "***** WINDOW : ["
<< win->configuration().name() << "]" << std::endl;
// For each channel in the window...
const DtChannelManager::ChannelMap& cm(win->channelManager().channels());
for (DtChannelManager::ChannelMap::const_iterator citer(cm.begin());
citer != cm.end(); ++citer)
{
// Print the channel's name and the name of its observer.
const DtChannel* chan(citer->second);
const DtObserverObject* obs(chan->findObserver());
std::cerr << "----- CHANNEL : ["
<< chan->configuration().name() << "]\t";
if (obs)
{
std::cerr << "Model-Set : " << obs->modelSet();
}
else
{
std::cerr << "No observer at this time.";
}
std::cerr << std::endl;
}
std::cerr << std::endl;
}
}
std::string registerModelDefinition(DtDe& de, const std::string& dataFile)
{
// Id value to make the model name unique
static DtUniqueID id(1);
std::stringstream modelName;
modelName << "model " << id;
// Create a model definition describing the model to load.
// The DtModelDefinition class is used to describe several attributes about
// the model. This example just specifies the name of the geometry file to
// load.
DtModelDefinition md(modelName.str());
md.setParameter("filename", dataFile);
// Retrieve the DtDeSharedState from the display engine and register the
// definition. The DtDeSharedState contains a model definition manager.
// When registering with the DtDeSharedState, all distributed applications
// are notified to register the same model definition.
// return the unique name for the model definition.
++id;
return modelName.str();
}
void addModelToTheScene(DtDe& de, const std::string& modelName)
{
// Id value to make the scene-object name unique
static DtUniqueID id(1);
// Create a DtSceneObject to hold the model. DtSceneObjects provide an
// an API to 'group' multiple models together into a single association.
// The scene-object can then be used to manipulate all the associated
// models as a single entity. Among other features like positioning and
// orientating the associated models, the DtSceneObject also provides the
// ability to add models to the scene-graph and channels for rendering.
// This example creates a single DtSceneObject for each channel and
// positions its models away from the eye-point in the scene.
DtSceneObject* sceneObj = new DtSceneObject(de, id);
sceneObj->setPosition(0, DtVector(0.0f, 5.0f, 0.0f));
sceneObj->setOrientation(0, DtTaitBryan(
osg::DegreesToRadians(-150.0f),
osg::DegreesToRadians(-30.0f),
osg::DegreesToRadians(-10.0f)));
// Tell each DtSceneObject to use a different model-set. For this example
// we are using the mode-sets defined for each mode that is loaded during
// application configuration time.
int modelSet(modesAndSets.at((id - 1) % modesAndSets.size()).second);
sceneObj->setModelSet(modelSet);
// Create a model and set its definition to a preregistered definition.
// A DtModel (in this case a DtOsgSimpleModel) is a managing container for
// a single model-instance. It provides rendering attributes about the
// model-instance, such as the visualizer-type for choosing which channel
// the model will render in. Each model requires a unique id. Since this
// is just an example, arbitrarily pick the same id as the scene-object.
DtOsgSimpleModel* model = new DtOsgSimpleModel(de, id);
model->setModelDefinition(modelName);
// Associate the model with the scene-object. When a model is associated
// with a scene-object, the scene-object automatically inserts the model-
// instance (within the model) into the scene-graph of the renderer in the
// appropriate channel.
sceneObj->addModel(model, 0);
++id;
}
void loadTheScene(DtDe& de)
{
std::vector<std::string>::const_iterator iter(modelFiles.begin());
std::vector<std::string>::const_iterator endr(modelFiles.end());
for (; iter != endr; ++iter)
{
std::string modelName = registerModelDefinition(de, *iter);
std::cerr << "Adding Model: [" << modelName << "] " << *iter << std::endl;
addModelToTheScene(de, modelName);
}
}

InitVector.h


Document ID: Generated on Wed Mar 11 21:20:57 EDT 2015 from SVN revision 150940
Copyright © 2005-2014 VT MÄK. All Rights Reserved (www.mak.com)