Overview
Shows how to use an extended FOM and visualizes the new attribut
Expected Result
N/A
Example details
Using an Extended FOM in VR-Vantage
Simulation developers often extend FOMs to add attributes that are not part of the base FOM. They then want to be able to visualize the new attributes in VR-Vantage. This example shows how to create a VR-Vantage plug-in that listens for the new attributes in an extended FOM. It also shows how to configure VR-Vantage to display the new attribute. Additionally, it shows how to extend a visualizer and listener.
Requirements and Limitations
-
The example uses an extended version of RPR FOM 1.0 that is available as the addAttrHla1516e_64 example in VR-Link.
-
This example only works with HLA 1516e. Adding support for other versions of HLA would not be difficult.
-
The FOM mapper accessory does not check to verify that the correct FED file or RPR FOM version is used.
The exampleHla1516eFomMapper Plug-in:
The FOM Mapper example is a plug-in that lets VR-Vantage listen to an extended FOM and visualize its new attributes. The plug-in extends several of VR-Vantage's systems.
The simulation connection (VR-Link) drivers (for DIS and HLA protocols) have two subsystems - a visualizer system and a listener system. The listener system consists of listener objects that listen to network traffic and report on entities and interactions. The visualizer system connects to listeners. It creates and controls distributed objects that display models and effects in the scene. Each object or interaction is visualized using state visualizers, each of which is responsible for visualizing a particular effect or component. For example, one visualizer creates and updates the main model of a tank, while another visualizer creates and updates fire effects based on the tank's flame state.
The addAttrHla1516e_64 example adds an attribute called Mass to the FOM. For VR-Vantage to visualize this attribute, it must listen for it and have a visualizer to affect the scene. This example replaces the default entity state listener with a modified entity state listener that contains the additional attributes defined by the extended FOM. This example also adds a new state visualizer class that listens for the new mass attribute and displays the value as a 2D text label that is attached to the object. An extended listener signaler ( MyEntitySignaler ) is added that allows additional signals to be sent from protocol-dependent listeners to protocol-independent visualizers. MyEntitySignalerCreator is registered in place of VR-Vantage's DtListenerSignalerCreator; when protocol-dependent listeners are created they will create the new signaler instead of the default one.
This example has a protocol-independent visualizer - MassLabelVisualizer. MassLabelVisualizer is necessary for configuring model definitions in the GUI. The MassLabelVisualizer connects to the new signals added in MyEntitySignaler.
Because VR-Vantage has many drivers and they may execute in separate threads, it uses a class called an accessory to extend or modify particular drivers. The exampleHla1516eFomMapper plug-in has an accessory class which will only work with HLA 1516e drivers and is responsible for registering the new listener and visualizer classes with the driver's HLA 1516e DtVrlinkConnection object. This allows the connection object to create the newly registered listener rather than the original listener class and also the protocol-dependent visualizer class rather than the protocol-independent version.
The example includes a model definition, MassInfoWidget, which is used to configure the new visualizer, and is merged into the existing model definitions using the command line option –mergeModelDefs. This new model definition has the following attributes:
| backgroundImage | $YOUR_SHARED_DATA_DIR/Overlays/infoBackground.png |
| font | $YOUR_SHARED_DATA_DIR/fonts/mak_mono.ttf |
| fontSize | 11 |
| height | 18 |
| originX | 100 |
| originY | 0 |
| paddingX | 6 |
| paddingY | -1 |
| textAlignment | Left |
| textColor | 0, 0, 0, 255 |
| width | 140 |
- Note
- This example is more complex than some of the other VR-Vantage examples, because it does several things: it is an example of a plug-in; it shows how to write a visualizer and a listener; it shows how to create an accessory to extend a driver. Because it does so many things, we do not walk you through the code for each action. Please see the comments in the source files for details as well as the other examples that demonstrate in detail each of these development tasks.
To build the exampleHla1516eFomMapper plug-in, follow the instructions in VR-Vantage Developers Guide.
Using the Plug-in
To use the exampleHla1516eFomMapper plug-in:
- Start a VR-Vantage Application that Uses the Plug-in and Model Definition
- Load a Terrain
- Configure Entities
- Create a Connection using the Extended FOM Mapper
- Connect to the Network and run the VR-Link addAttrHla1516e_64 Example
Start a VR-Vantage Application that Uses the Plug-in and Model Definition
The startup command must specify the plug-in and the new model definition, as follows (using VR-Vantage):
vrvStealth –plugin ../examples/plugins/release/exampleFomMapperPlugin.dll –mergeModelDefs ../examples/exampleHla1516eFomMapper/MassInfoWidget.ommx
Load a Terrain
The entity published by addAttrHla1516e_64 will be located on the Ground_DB II terrain. It is recommended that you load this terrain.
Configure Entities
A Visual Definition needs to be added to an Entity Element Definition so that the new MassLabelVisualizer will be created when the entity it will be attached to is created. Since the VR-Link example addAttrHla1516e_64 publishes a Land entity with the new Mass attribute, the following shows how to add this Visual Definition to all Land entities in the 2D Model Set.
- Select the Entity Definition Editor page (Settings->Visual Model Editors...->Entity Definition Editor).
- Select the Land entity.
- Change the model set to 2D
- Click on the Add Visual Definitions icon. The Add Visualizers dialog box opens.
- Select the 2D Mass Label visualizer. An entry is added to the list of visualizers.
- Scroll to the bottom of the Visual Definitions list and select 2D Mass Label
- Click on the Add Attribute icon, select modeldefinitionschema, and click OK.
- Change the model Definition Schema to WidgetTheme.
- Click on the Add Attribute icon, select modeldefinition, and click OK.
- Change the modelDefinition to MassInfoWidget.
- Click on the Add Attribute icon, select visualtype, and click OK.
- Change the visual Type to main_model.
- Click on the Add Attribute icon, select type, and click OK.
- Type should automatically be set to Mass Label Visualizer; if not, change it.
Close the Visual Model Editors dialog box.
Create a Connection using the Extended FOM Mapper
-
Choose Settings -> Connections.
-
Select the HLA 1516e Connections page.
-
Click the Delete icon (minus sign) until you delete the existing connections. (This will prevent confusion when using this example. The installed connections are still available if you use the default appData directory.)
-
Click the Add Connection icon. A connection called HLA 1516e Connection #1 is added.
-
Click the Rename icon. The Rename Connection dialog box opens.
-
Rename the connection to FOM Mapper Example Connection.
-
Change the Federation Name to example-vrlExtend.
-
Change the RPR FOM Version in advanced settings to 1.0.
-
Change the FED File Name to example-vrlExtend.fed.
-
Copy the example-vrlExtend.fed from the VR-Link bin64 directory to the VR-Vantage bin64 directory.
Connect to the Network and run the VR-Link addAttrHla1516e_64 Example
- If the Simulation Connections dialog box is not still open, choose Settings -> Connections.
- Select the HLA 1516e Connections page.
- Select the FOM Mapper Example Connection.
- Click Connect.
- Close the Simulation Connections dialog box.
- Run the VR-Link addAttrHla1516e_64 example program.
The addAttrHla1516e_64 example should start publishing an entity. VR-Vantage should discover the entity. Double click on the entity in the object list panel to attach to it. A tank should be visible. Change the observer mode to PVD (2D) to the right of the tank there should be a label indicating the entity's mass.
Building the Example
VR-Vantage includes pre-built versions of the example plug-in. To build it yourself, follow the instructions at Building VR-Vantage Examples, Applications, and Plug-ins.
Running the Example
This example is a plug-in. You can run it by running ./bin64/exampleHla1516eFomMapper_stealth.bat (on Windows) or ./bin64/exampleHla1516eFomMapper_stealth.sh (on Linux). For more information about running examples, please see Running Applications and Examples.
Example Source Files
exampleFomMapper.h
#pragma once
#ifdef _WIN32
#ifdef EXAMPLEFOMMAPPER_EXPORTS
#define DT_DLL_EXAMPLEFOMMAPPER __declspec ( dllexport )
#else
#define DT_DLL_EXAMPLEFOMMAPPER __declspec ( dllimport )
#endif
#else
#define DT_DLL_EXAMPLEFOMMAPPER
#endif
#if DtHLA
#define DT_PROTOCOL_NAMESPACE vrvHla13
#define DL_DLL_IGCONVRLINK DT_DLL_VRVHLA13
#endif
configFomMap.h
#pragma once
#if DtHLA
#include <vl/fomMapper.h>
namespace makVrv
{
{
}
}
void encodeMass(
const DtStateRepository& stateRep,
RTI::AttributeHandleValuePairSet* avList,
RTI::AttributeHandle handle);
const RTI::AttributeHandleValuePairSet& avlist,
int pairSetIndex);
const DtStateRepository& stateRep,
const DtStateRepository& asSeenByRemote);
#endif
configFomMap.cxx
#if DtHLA
#if DtHLA
#define DT_PROTOCOL_NAMESPACE vrvHla13
#endif
#include <vl/hlaObject.h>
#include <vl/stateEncoderFactory.h>
#include <vl/stateDecoderFactory.h>
#include <vl/interactionEncoderFactory.h>
#include <vl/interactionDecoderFactory.h>
#include <vl/interactionFactory.h>
{
mapper->stateEncoderFactory()->addAttributeEncoder(
"BaseEntity", "Mass",
(DtHlaStateEncoder::DtAttributeEncoder)
encodeMass,
true);
mapper->stateDecoderFactory()->addAttributeDecoder(
"BaseEntity", "Mass",
(DtHlaStateDecoder::DtAttributeDecoder)
decodeMass,
true);
mapper->stateEncoderFactory()->addAttributeChecker(
"BaseEntity", "Mass",
(DtHlaStateEncoder::DtAttributeChecker)
needMass,
true);
}
void encodeMass(
const DtStateRepository& stateRep,
RTI::AttributeHandleValuePairSet* avList, RTI::AttributeHandle handle)
{
if(actualRep)
{
DtNetFloat64 netVal(mass);
avList->add(handle, (char*) &netVal, sizeof(DtNetFloat64));
}
}
const RTI::AttributeHandleValuePairSet& avlist, int pairSetIndex)
{
if(actualRep)
{
DtNetFloat64 netVal;
avlist.getValue(pairSetIndex, (char* )&netVal, length);
actualRep->
setMass((
double) netVal);
}
}
bool needMass(
const DtStateRepository& stateRep,
const DtStateRepository& asSeenByRemote)
{
if(actualRep && actualSeen)
{
return (
bool) (actualRep->
mass() != actualSeen->
mass());
}
else
{
return false;
}
}
#endif
MyVrlinkEntityStateListener.h
#pragma once
#include <vl/entityStateRepository.h>
{
public:
class makVrv::vrvHla13::DtVrlinkConnection;
};
{
public:
virtual makVrv::vrvHla13::DtVrlinkEntityStateListener*
create(DtHlaObject*
object);
};
MyVrlinkEntityStateListener.cxx
using namespace makVrv;
using namespace makVrv::vrvHla13;
{
}
{
}
{
}
{
}
{
}
{
}
MyVrlinkEntityStateRepInterceptor.h
#pragma once
#include <vl/hlaObject.h>
#include <vl/entityStateRepository.h>
#include <vrfExtObjects/extEntityStateRepository.h>
: public makVrv::vrvHla13::DtEntityStateInterceptor<DtExtEntityStateRepository>
{
public:
virtual void setMass( float mass );
virtual float mass() const;
public:
virtual DtStateRepository* clone(bool copy = false) const;
protected:
protected:
float myMass;
};
: public makVrv::vrvHla13::DtEntityStateInterceptorCreator
{
public:
virtual DtEntityStateRepository* create(makVrv::vrvHla13::DtVrlinkEntityStateListener* listener);
};
MyVrlinkEntityStateRepInterceptor.cxx
using namespace makVrv;
using namespace makVrv::vrvHla13;
, myMass(0.0)
{
}
{
{
if(listener)
{
if( signaler )
{
}
}
}
}
{
}
{
DtTHROW_NEW(DtCorruptedState,"Can't clone MyVrlinkEntityStateRepInterceptor");
}
{
}
{
}
{
}
MyVrlinkEntityStateRep.h
#pragma once
#include <vl/entityStateRepository.h>
#include <vrfExtObjects/extEntityStateRepository.h>
{
public:
virtual void setMass(float mass);
virtual float mass() const;
virtual void printData() const;
virtual DtStateRepository* clone(bool copy = false) const;
protected:
float myMass;
};
: public makVrv::vrvHla13::DtEntityStateRepositoryCreator
{
public:
virtual DtEntityStateRepository* create();
};
MyVrlinkEntityStateRep.cxx
: myMass(1.0f)
{
}
{
}
{
}
{
}
{
DtEntityStateRepository::printData();
printf(
"Mass: %lf\n",
mass());
}
{
if (copy)
{
}
else
{
}
}
{
}
MassLabelVisualizer.h
#pragma once
namespace makVrv
{
class DtWidgetLabelAgent;
class DtProjectedWidgetModelAgent;
class DtSceneObjectAgent;
}
class MyEntityStateListener;
{
public:
protected:
protected:
makVrv::DtWidgetLabelAgent*
myLabel;
};
MassLabelVisualizer.cxx
#include <vrvCore/DtWidgetLabelAgent.hpp>
#include <vrvCore/DtProjectedWidgetModelAgent.hpp>
#include <vrvCore/DtSceneObjectAgent.hpp>
#include <vrvCore/DtSceneObjectAgent.hpp>
#include <stdio.h>
using namespace makVrv;
, myProjectedModel(0)
, myLabel(0)
{
if( signaler )
{
}
}
{
}
{
{
}
{
}
{
}
if( signaler )
{
}
{
}
}
{
{
char buffer[256];
sprintf(buffer,"Mass: %4.4f kg",mass);
DtUnicode txt = DtUnicode::fromAscii(buffer);
}
}
{
{
}
}
{
{
}
}
{
}
{
"MassLabelVisualizerSchema",
DtUnicode::tr("2D Mass Label"));
"MassLabelVisualizer",
DtUnicode::tr("Mass Label Visualizer"),
DtStateVisualizer::EntityVisualizerType,
thisSchema);
return thisTypeInfo;
}
DtFomMapperAccessory.h
#pragma once
namespace makVrv
{
class DtVrlinkBaseConnection;
{
{
public:
DtFomMapperAccessory();
virtual ~DtFomMapperAccessory();
virtual void install(DtDriver* driver);
virtual void uninstall(DtDriver* baseConn);
virtual bool isCompatible(DtDriver* driver);
protected:
virtual void slot_onConnectionCreated(DtVrlinkBaseConnection* connection);
virtual void slot_onConnectionConnected(DtVrlinkBaseConnection* connection);
virtual void slot_onConnectionAboutToBeDisconnected(DtVrlinkBaseConnection* connection);
};
}
}
DtFomMapperAccessory.inl
#include <vl/exerciseConn.h>
#include <boost/bind.hpp>
#include <iostream>
namespace makVrv
{
{
{
}
DtFomMapperAccessory::~DtFomMapperAccessory()
{
}
void DtFomMapperAccessory::install(DtDriver* driver)
{
DtVrlinkDriver* vld = dynamic_cast<DtVrlinkDriver*>(driver);
if(vld)
{
boost::bind(&DtFomMapperAccessory::slot_onConnectionCreated,
this, _1));
}
}
void DtFomMapperAccessory::uninstall(DtDriver* baseConn)
{
DtVrlinkDriver* vld = dynamic_cast<DtVrlinkDriver*>(baseConn);
if(vld)
{
vld->signal_connectionCreated.disconnect(
boost::bind(&DtFomMapperAccessory::slot_onConnectionCreated,
this, _1));
}
}
bool DtFomMapperAccessory::isCompatible(DtDriver* driver)
{
DtVrlinkDriver* dd = dynamic_cast<DtVrlinkDriver*>(driver);
if(dd)
{
return true;
}
return false;
}
void DtFomMapperAccessory::slot_onConnectionCreated(DtVrlinkBaseConnection* conn)
{
conn->signal_connected.connect(
boost::bind(&DtFomMapperAccessory::slot_onConnectionConnected,
this, conn));
conn->signal_toBeDisconnected.connect(
boost::bind(&DtFomMapperAccessory::slot_onConnectionAboutToBeDisconnected,
this, conn));
DtVrlinkConnection* vrlCon = dynamic_cast<DtVrlinkConnection*>(conn);
if(vrlCon)
{
new MyEntitySignalerCreator() );
DtEntityStateRepositoryCreator::registerInstance(*vrlCon,
conn->registerInstance("DtEntityStateInterceptorCreator",
conn->registerInstance("DtVrlinkEntityStateListenerCreator",
}
}
void DtFomMapperAccessory::slot_onConnectionConnected(DtVrlinkBaseConnection* conn)
{
DtVrlinkConnection* vrlCon = dynamic_cast<DtVrlinkConnection*>(conn);
if(vrlCon)
{
}
}
void DtFomMapperAccessory::slot_onConnectionAboutToBeDisconnected(DtVrlinkBaseConnection* conn)
{
DtVrlinkConnection* vrlCon = dynamic_cast<DtVrlinkConnection*>(conn);
if(vrlCon)
{
vrlCon->registerInstance("DtFomMapperVisualizer", 0);
}
}
}
}
exampleFomMapperPlugin.h
#pragma once
#define DT_DE_PLUGIN_EXPORT_MACRO DT_DLL_EXAMPLEFOMMAPPER
namespace makVrv
{
class DtDe;
}
exampleFomMapperPlugin.cxx
#include <functional>
using namespace makVrv;
namespace exampleFomMapperPlugin
{
static vrvSignalsLib::connection postInitializeConnection;
void postInitializeWork(
DtDe* de)
{
postInitializeConnection.disconnect();
new MassLabelVisualizerCreator() );
}
{
{
}
}
}
{
return true;
}
MyEntitySignaler.h
#pragma once
namespace makVrv
{
class DtBaseConnection;
class DtDe;
class MyEntitySignaler : public DtListenerSignaler
{
public:
public:
virtual void setMass(
float mass );
virtual const float mass();
protected:
};
class MyEntitySignalerCreator : public DtListenerSignalerCreator
{
public:
public:
virtual DtListenerSignaler*
create()
const override;
};
}
MyEntitySignaler.cxx
namespace makVrv
{
DtListenerSignaler()
, myMass( 0.0 )
{
}
MyEntitySignaler::~MyEntitySignaler()
{
}
void MyEntitySignaler::setMass( float mass )
{
myMass = mass;
signal_massSet( mass );
}
const float MyEntitySignaler::mass()
{
return myMass;
}
MyEntitySignalerCreator::MyEntitySignalerCreator() :
DtListenerSignalerCreator()
{
}
MyEntitySignalerCreator::~MyEntitySignalerCreator()
{
}
DtListenerSignaler* MyEntitySignalerCreator::create() const
{
return new MyEntitySignaler();
}
}
[<< Examples] [Home] [Top of Page]