This example demonstrates how to add tactical graphics to the scene.
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 Tacticl Graphics by waiting for the first application tick, then creating appropriate 2D or 3D line elements according to the model set realized.
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 <matrix/vlVector.h>
namespace makVrv
{
namespace exampleTacticalGraphics
{
static DtVector theSimpleLineVertices[] = {
DtVector(-20.0, 30.0, 40.0), DtVector(20.0, 90.0, 40.0),
DtVector(50.0, 50.0, 30.0), DtVector(100.0, 100.0, 30.0)
};
static DtVector theAirAxisVertices[] = {
DtVector(-300.0, -730.0, 700.0), DtVector(500.0, -300.0, 912.05),
DtVector(1400.0, -100.0, 825.62)
};
static DtVector theLineWithArrow[] = {
DtVector(-160.0,-260.0, 190.0), DtVector(0.0, -260.0, 190.0)
};
static DtVector theFortifiedLine[] = {
DtVector(500.0, 100.0, 20.0), DtVector(600.0,-100.0, 20.0),
DtVector(800.0,-100.0, 20.0)
};
static DtVector theSimpleAreaVertices[] = {
DtVector( 595.0, 320.0, 10.0 ), DtVector(560.0, 320.0, 10.0),
DtVector(560.0, 280.0, 10.0), DtVector(595.0, 280.0, 10.0)
};
static DtVector theFortifiedAreaVertices[] = {
DtVector(-160.0, 480.0, 90.0), DtVector(-65.0, 480.0, 90.0 ),
DtVector(-65.0, 550.0, 90.0), DtVector(-160.0, 550.0,90.0 )
};
static DtVector thePatternFilledAreaVertices[] = {
DtVector( -480.0, -820.0, 10.0 ), DtVector(-570.0,-820.0, 10.0),
DtVector(-570.0,-900.0, 10.0), DtVector(-480.0, -900.0, 10.0)
};
{
return ( modelSet == DtModelSetId::Icons2D);
}
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() );
myVisibilityChangedConnection = tgOverlayMgr.signal_tacticalGraphicVisibilityChanged.connect( boost::bind(
&DtExampleTacticalGraphicsDriver::slot_tacticalGraphicVisibilityChanged, this, boost::placeholders::_1, boost::placeholders::_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()
{
myVisibilityChangedConnection.disconnect();
auto iter = myTacticalGraphics.begin();
while( iter != myTacticalGraphics.end() )
{
if( iter->second)
{
delete iter->second;
iter->second = nullptr;
}
if( iter->first )
{
delete iter->first;
iter->first = 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->first = 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 );
tgListener->connectToSharedDisplaySettings();
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( DtModelSetId::Icons2D ) )
{
overlay->addGraphic( tacticalGraphicElement->findSceneObjectForModelSet( DtModelSetId::Icons2D )->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", "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", "Linear Target", "Lines" );
tgListener->setLocalVertexList( convertToPointVector( sizeof( theLineWithArrow ) / sizeof( DtVector ), &theLineWithArrow[0] ) );
tgListener->setArrowHeadPlacement( vrvTacticalGraphicUtilities::ArrowHeadPlacement::LastSegmentOnly );
tgListener->setLineStyle( vrvTacticalGraphicUtilities::LineStyle::Plain );
tgListener->setArrowStyle( vrvTacticalGraphicUtilities::ArrowStyle::Simple );
tgListener->setProjected( false );
tgListener->setArrowSize( 25.0 );
}
void DtExampleTacticalGraphicsDriver::createFortifiedLine()
{
DtTacticalGraphicStateListener* tgListener = createTacticalGraphicElement( DtElementEntry::GraphicShape, "Fortified Line", "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->setClosedFigure(true);
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", "Fortified Area", "Areas" );
tgListener->setClosedFigure(true);
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->setClosedFigure(true);
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->connectToSharedDisplaySettings();
entityListener->setForceId( 1 );
entityListener->setForceColor( 0.5f, 224.0f / 255.0f, 1.0f, 0.8f );
entityListener->setLocalLocation( DtVector( -300.0, -730.0, 750.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(
DtElementEntry::Entity, *myBaseConnection, *entityListener, "" );
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( DtModelSetId::Icons2D ) )
{
overlay->addGraphic( entityElement->findSceneObjectForModelSet( DtModelSetId::Icons2D )->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();
}
}
}