This example demonstrates how to tactical graphics to the scene in a PVD application.
The example creates a DtExampleTacticalGraphicsDriver for creating line and area symbols that will be displayed on the Ground DB II database.
The driver creates the symbol by waiting for the first application tick, then creating appropriate 2D or 3D line facades according to the model set realized. For the purposes of this example, only 2D (projected) areas are created.
This example is a plug-in. You can run it by running ./bin64/exampleAccessory_stealth.bat (on Windows from cmd.exe) or ./bin64/exampleAccessory_stealth.sh (on Linux). For more information about running examples, please see Running Applications and Examples.
#include <vrvCore/DtSceneObjectAgent.hpp>
#include <matrix/vlVector.h>
namespace makVrv
{
namespace exampleTacticalGraphics
{
enum ModelSets
{
ModelSet_3D = 0,
ModelSet_3DColorized = 1,
ModelSet_2DIcons = 5,
};
static DtVector theSimpleLineVertices[] = {
};
static DtVector theAirAxisVertices[] = {
};
};
};
static DtVector theSimpleAreaVertices[] = {
};
static DtVector theFortifiedAreaVertices[] = {
};
static DtVector thePatternFilledAreaVertices[] = {
};
static bool is2D(int modelSet)
{
return ( modelSet == ModelSet_2DIcons );
}
static std::vector<DtVector> convertToPointVector(
int numVertices,
DtVector* pointVector)
{
int i;
std::vector<DtVector> points;
for (i = 0; i < numVertices; i++)
{
points.push_back(pointVector[i]);
}
return points;
}
: DtDriver( am, className() )
, myCreateElements(true)
, myBaseConnection( nullptr )
{
}
DtExampleTacticalGraphicsDriver::~DtExampleTacticalGraphicsDriver()
{
}
const std::string& DtExampleTacticalGraphicsDriver::className() const
{
static std::string name = "DtExampleTacticalGraphicsDriver";
return name;
}
bool DtExampleTacticalGraphicsDriver::onStart()
{
DtScene& sceneDriver = myAgentManager.de().scene();
std::string groundDbPath = myAgentManager.de().dePathConfiguration().sharedDataPath();
groundDbPath += "/TerrainData/TerrainConfiguration/Ground_DB II.mtf";
sceneDriver.loadTerrain( groundDbPath );
DtTacticalGraphicOverlayManager& tgOverlayMgr =
DtTacticalGraphicOverlayManager::instance( myAgentManager.de() );
tgOverlayMgr.signal_tacticalGraphicVisibilityChanged.connect(
boost::bind(
&DtExampleTacticalGraphicsDriver::slot_tacticalGraphicVisibilityChanged, this, _1, _2 ) );
myBaseConnection = new DtBaseConnection( DtSharedSettingsManager::instance( myAgentManager.de() ),
myAgentManager, myAgentManager.de().sharedState().coordinateSystem() );
DtSymbolDecorationFactory::copyInstance( *myBaseConnection, myAgentManager.de() );
DtStateVisualizerFactory::copyInstance( *myBaseConnection, myAgentManager.de() );
DtOverlayGroupManager::copyInstance( *myBaseConnection, myAgentManager.de() );
DtElementDefinitionTypeManager::copyInstance( *myBaseConnection, myAgentManager.de() );
DtModelSemanticsMapper::copyInstance( *myBaseConnection, myAgentManager.de() );
DtModelDefinitionCollection::buildInstance( *myBaseConnection, myAgentManager.de() );
DtElementFactory::copyInstance( *myBaseConnection, myAgentManager.de() );
DtVisualizerCreationSettingsManager::instance( myAgentManager.de() ).
initializeVisualizerCreationSettings( myBaseConnection->visualizerCreationSettings() );
return true;
}
bool DtExampleTacticalGraphicsDriver::onStop()
{
DtTacticalGraphicOverlayManager& tgOverlayMgr =
DtTacticalGraphicOverlayManager::instance(myAgentManager.de());
tgOverlayMgr.signal_tacticalGraphicVisibilityChanged.disconnect(
boost::bind(
&DtExampleTacticalGraphicsDriver::slot_tacticalGraphicVisibilityChanged, this, _1, _2));
auto iter = myTacticalGraphics.begin();
while( iter != myTacticalGraphics.end() )
{
if( iter->second)
{
delete iter->second;
iter->second = nullptr;
}
if( iter->first )
{
delete iter->first;
iter->second = nullptr;
}
++iter;
}
auto entityIter = myEntities.begin();
while( entityIter != myEntities.end() )
{
if( entityIter->second )
{
delete entityIter->second;
entityIter->second = nullptr;
}
if( entityIter->first )
{
delete entityIter->first;
entityIter->second = nullptr;
}
++entityIter;
}
myCreateElements = true;
if (myChanges.hasChanges())
{
myAgentManager.de().dataBank().elementData().applyChanges(myChanges);
myChanges.clear();
}
if( myBaseConnection )
{
if( myBaseConnection->currentElementChanges().hasChanges() )
{
applyChangesAndDelete( myBaseConnection->takeElementChanges() );
}
delete myBaseConnection;
}
return true;
}
DtTacticalGraphicStateListener* DtExampleTacticalGraphicsDriver::createTacticalGraphicElement( DtElementEntry::ElementType type,
std::string name, std::string elementDefinitionName, std::string overlyName )
{
DtTacticalGraphicStateListener* tgListener = new DtTacticalGraphicStateListener( myAgentManager.createNewUniqueId(), myBaseConnection->settingsManager() );
if( !tgListener )
{
DtWarn << "DtExampleTacticalGraphicsDriver::createLineElements unable to create DtTacticalGraphicStateListener!" << std::endl;
}
tgListener->setName( name );
DtElement* temp = DtElementFactory::instance( myAgentManager.de() ).createElement(
type, *myBaseConnection, *tgListener, "" );
DtTacticalGraphicElement* tacticalGraphicElement = dynamic_cast<DtTacticalGraphicElement*>(temp);
if( !tacticalGraphicElement )
{
DtWarn << "DtExampleTacticalGraphicsDriver::createLineElements unable to create element!" << std::endl;
}
myTacticalGraphics.emplace_back( TacticalGraphicPair( tgListener, tacticalGraphicElement ) );
tacticalGraphicElement->setDriverType( "Tactical Graphics Driver" );
tacticalGraphicElement->setElementDefinition( DtUnicode::fromAscii( elementDefinitionName ) );
DtSharedModelSetSettings::ModelSetVisualizedMap sets;
{
DtReadSettingsLock<DtSharedModelSetSettings> modelSets( myBaseConnection->settingsManager() );
sets = modelSets->modelSetVisualizedMap();
}
tacticalGraphicElement->visualize( sets );
DtTacticalGraphicOverlay* overlay = DtTacticalGraphicOverlayManager::instance( myAgentManager.de() ).findOverlay( overlyName );
if( overlay && tacticalGraphicElement->findSceneObjectForModelSet( (int) ModelSet_2DIcons ) )
{
overlay->addGraphic( tacticalGraphicElement->findSceneObjectForModelSet( (int) ModelSet_2DIcons )->uniqueId() );
}
return tgListener;
}
void DtExampleTacticalGraphicsDriver::createSimpleLine()
{
DtTacticalGraphicStateListener* tgListener = createTacticalGraphicElement( DtElementEntry::GraphicShape, "Simple line", "Route", "Lines" );
tgListener->setPixelLineWidth(4.0);
tgListener->setColor(1.0f, 0.0f, 0.0f, 0.777f);
tgListener->setFillStyle( vrvTacticalGraphicUtilities::FillStyle::SolidFill );
tgListener->setLocalVertexList( convertToPointVector(
sizeof( theSimpleLineVertices ) /
sizeof(
DtVector ), &theSimpleLineVertices[0] ) );
tgListener->setEnvironmentalHatLinesEnabled( false, true );
}
void DtExampleTacticalGraphicsDriver::createAirAxisLine()
{
DtTacticalGraphicStateListener* tgListener = createTacticalGraphicElement( DtElementEntry::GraphicShape, "Air Axis", "ModelSet-4490755-Air Axis", "Lines" );
tgListener->setLocalVertexList( convertToPointVector(
sizeof( theAirAxisVertices ) /
sizeof(
DtVector ), &theAirAxisVertices[0] ) );
tgListener->setLineStyle(vrvTacticalGraphicUtilities::LineStyle::AirAxis);
tgListener->setArrowSize(25.0);
}
void DtExampleTacticalGraphicsDriver::createLineWithArrow()
{
DtTacticalGraphicStateListener* tgListener = createTacticalGraphicElement( DtElementEntry::GraphicShape, "Line with arrow", "ModelSet-340037-Line", "Lines" );
tgListener->setLocalVertexList( convertToPointVector(
sizeof( theLineWithArrow ) /
sizeof(
DtVector ), &theLineWithArrow[0] ) );
tgListener->setArrowHeadPlacement( vrvTacticalGraphicUtilities::ArrowHeadPlacement::LastSegmentOnly );
tgListener->setArrowStyle( vrvTacticalGraphicUtilities::ArrowStyle::Simple );
tgListener->setArrowSize( 25.0 );
}
void DtExampleTacticalGraphicsDriver::createFortifiedLine()
{
DtTacticalGraphicStateListener* tgListener = createTacticalGraphicElement( DtElementEntry::GraphicShape, "Fortified Line", "ModelSet-105957093-Fortified Line", "Lines" );
tgListener->setLocalVertexList( convertToPointVector(
sizeof( theFortifiedLine ) /
sizeof(
DtVector ), &theFortifiedLine[0] ) );
tgListener->setColor(1.0f, 0.0f, 0.0f, 0.777f);
tgListener->setEnvironmentalHatLinesEnabled( false, true );
}
void DtExampleTacticalGraphicsDriver::createSimpleArea()
{
DtTacticalGraphicStateListener* tgListener = createTacticalGraphicElement( DtElementEntry::GraphicShape, "Simple Area", "Other Area", "Areas" );
tgListener->setPixelLineWidth( 4.0 );
tgListener->setColor( 0.0f, 1.0f, 0.0f, 0.777f );
tgListener->setLocalVertexList( convertToPointVector(
sizeof( theSimpleAreaVertices ) /
sizeof(
DtVector ), &theSimpleAreaVertices[0] ) );
tgListener->setEnvironmentalHatLinesEnabled( false, true );
}
void DtExampleTacticalGraphicsDriver::createFortifiedArea()
{
DtTacticalGraphicStateListener* tgListener = createTacticalGraphicElement( DtElementEntry::GraphicShape, "Fortified Area", "ModelSet-105996817-Fortified Area", "Areas" );
tgListener->setColor( 0.0f, 1.0f, 0.0f, 0.777f );
tgListener->setLocalVertexList( convertToPointVector(
sizeof( theFortifiedAreaVertices ) /
sizeof(
DtVector ), &theFortifiedAreaVertices[0] ) );
tgListener->setEnvironmentalHatLinesEnabled( false, true );
}
void DtExampleTacticalGraphicsDriver::createPatternFilledArea()
{
DtTacticalGraphicStateListener* tgListener = createTacticalGraphicElement( DtElementEntry::GraphicShape, "Filled Area", "Other Area", "Areas" );
tgListener->setFillStyle( vrvTacticalGraphicUtilities::FillStyle::HorizontalLines );
tgListener->setLocalVertexList( convertToPointVector(
sizeof( thePatternFilledAreaVertices ) /
sizeof(
DtVector ), &thePatternFilledAreaVertices[0] ) );
tgListener->setEnvironmentalHatLinesEnabled( false, true );
}
void DtExampleTacticalGraphicsDriver::createSimpleEntity()
{
DtEntityStateListener* entityListener = createEntityElement( "FA-18 Hornet", "F/A-18 Hornet", "Symbols" );
entityListener->setForceId( 1 );
entityListener->setForceColor( 0.5f, 224.0f / 255.0f, 1.0f, 0.8f );
entityListener->setLocalLocation(
DtVector( -300.0, -730.0, 1000.0 ) );
}
void DtExampleTacticalGraphicsDriver::createOverlays()
{
DtTacticalGraphicOverlayManager::instance( myAgentManager.de() ).addOverlay( "Lines" );
DtTacticalGraphicOverlayManager::instance( myAgentManager.de() ).addOverlay( "Areas" );
DtTacticalGraphicOverlayManager::instance( myAgentManager.de() ).addOverlay( "Symbols" );
}
void DtExampleTacticalGraphicsDriver::slot_tacticalGraphicVisibilityChanged(
{
auto iter = myTacticalGraphics.begin();
while( iter != myTacticalGraphics.end() )
{
if( iter->second && iter->second->elementID() == id)
{
iter->second->setVisible( flag );
return;
}
++iter;
}
auto entityIter = myEntities.begin();
while( entityIter != myEntities.end() )
{
if( entityIter->second && entityIter->second->elementID() == id )
{
iter->second->setVisible( flag );
return;
}
++entityIter;
}
}
DtEntityStateListener* DtExampleTacticalGraphicsDriver::createEntityElement( std::string name, std::string elementDefinitionName, std::string overlyName )
{
DtEntityStateListener* entityListener = new DtEntityStateListener( myAgentManager.createNewUniqueId(), myBaseConnection->settingsManager() );
if( !entityListener )
{
DtWarn << "DtExampleTacticalGraphicsDriver::createSimpleEntity() unable to create DtEntityStateListener!" << std::endl;
}
entityListener->setDisplayName( name );
DtElement* temp = DtElementFactory::instance( myAgentManager.de() ).createElement(
DtEntityElement* entityElement = dynamic_cast<DtEntityElement*>(temp);
if( !entityElement )
{
DtWarn << "DtExampleTacticalGraphicsDriver::createLineElements unable to create element!" << std::endl;
}
myEntities.emplace_back( EntityPair( entityListener, entityElement ) );
entityElement->setDriverType( "Tactical Graphics Driver" );
entityElement->setElementDefinition( DtUnicode::fromAscii( elementDefinitionName ) );
DtSharedModelSetSettings::ModelSetVisualizedMap sets;
{
DtReadSettingsLock<DtSharedModelSetSettings> modelSets( myBaseConnection->settingsManager() );
sets = modelSets->modelSetVisualizedMap();
}
entityElement->visualize( sets );
DtTacticalGraphicOverlay* overlay = DtTacticalGraphicOverlayManager::instance( myAgentManager.de() ).findOverlay( overlyName );
if( overlay && entityElement->findSceneObjectForModelSet( (int) ModelSet_2DIcons ) )
{
overlay->addGraphic( entityElement->findSceneObjectForModelSet( (int) ModelSet_2DIcons )->uniqueId() );
}
return entityListener;
}
bool DtExampleTacticalGraphicsDriver::onTick()
{
if (myCreateElements)
{
myCreateElements = false;
createOverlays();
createSimpleLine();
createAirAxisLine();
createLineWithArrow();
createFortifiedLine();
createSimpleArea();
createFortifiedArea();
createPatternFilledArea();
createSimpleEntity();
if( myBaseConnection->currentElementChanges().hasChanges() )
{
applyChangesAndDelete( myBaseConnection->takeElementChanges() );
}
}
return true;
}
void DtExampleTacticalGraphicsDriver::slot_displayEngineAdded( const DtDeRecord& igRecord )
{
stop();
start();
}
}
}