VR-Forces 4.0.4 Class Documentation
exampleDriver

This example creates a new driver.

This driver will load the Makland terrain database and create an F-16 entity on start, attach the main observer to it, and then move the F16 a small amount each time that it's ticked.

The example driver's onStart() method loads the database first.

   DtScene& sceneDriver = myAgentManager.de().scene();

It then creates a new entity facade and tells it to use the F16 Visual Definition.

   // Create the entity
   DtElementID parentElementId = 0;
   myEntityDisplayName = "Entity From Facade";
   DtElementID elementId = myAgentManager.createNewUniqueId();
   myEntityFacade = new DtEntity3dFacade( myAgentManager, elementId, true );
   reportElementCreated( elementId, parentElementId, DtElementEntry::Entity );
   reportElementAttribute( elementId, new DtElementAttributeDisplayName(myEntityDisplayName) );
   reportElementAttribute( elementId, new DtElementAttributeVisibility(true) );

   // Load the model
   myEntityFacade->setArticulatedModelDefinition("FixedWingF-16UnarmedGrey");

Using the coordinate system information provided by the loaded terrain database, the driver provides an initial position and orientation in the coordinate system of the database.

As labels are pinned or unpinned, the togglePinnedLabel slot is called. This slot updates the visibility of both the indicator and the info label, and also tells the driver to listen or stop listening to the mouse hover signals (detailed below).

      std::vector<DtUniqueID> objects;
      objects.push_back( myEntityFacade->elementId() );
      DtObserver* currentObserver =
         myAgentManager.de().driverManager().inputDriver().currentObserver();
      currentObserver->setPrimaryAttachment( objects );

The driver manager updates the example driver by calling its onTick() method. The driver's onTick() method updates the F16's position using updatePosition(), and updates the text displayed on the F16's entity info label.

   updatePosition();

   {  // Attach to entity.
      std::vector<DtUniqueID> objects;
      objects.push_back( myEntityFacade->elementId() );
      DtObserver* currentObserver =
         myAgentManager.de().driverManager().inputDriver().currentObserver();
      currentObserver->setPrimaryAttachment( objects );
   }

   return true;
}

bool DtExampleDriver::onStop()
{
   if ( myEntityFacade )
   {
      if ( myEntityInfoWidget )
      {
         myEntityFacade->sceneObjectAgent().removeModel(
            myEntityInfoWidget->model() );
         delete myEntityInfoWidget;
         myEntityInfoWidget;
      }

      if ( myEntityIndicator )
      {
         setHoverSignalsActive( false );
         myEntityFacade->sceneObjectAgent().removeModel(
            myEntityIndicator->model() );
         delete myEntityIndicator;
         myEntityIndicator = 0;
      }

      reportElementDestroyed( myEntityFacade->elementId() );
      delete myEntityFacade;
      myEntityFacade = 0;
   }
   return true;
}

bool DtExampleDriver::onTick()
{
   updatePosition();
   if ( myEntityInfoWidget )
   {
      myEntityInfoWidget->setText( generateInfoString() );
   }
   return true;
}

void DtExampleDriver::slot_displayEngineAdded( const DtDeRecord& igRecord )
{
   stop();
   start();
}

void DtExampleDriver::slot_togglePinnedLabel(
   const DtSelectionManager::IdSet& sel )
{
   // Iterate over selected entities...
   DtSelectionManager::IdSet::const_iterator i = sel.begin();
   DtSelectionManager::IdSet::const_iterator e = sel.end();
   for ( ; i != e; ++i )
   {
      // If the entity facade is selected...
      if ( (*i) == myEntityFacade->elementId() )
      {
         // Pin/unpin the label and stop/start listening for mouse hovers.
         myEntityInfoWidgetPinnedFlag = ! myEntityInfoWidgetPinnedFlag;
         myEntityIndicator->setIndicatorActive( myEntityInfoWidgetPinnedFlag );
         setEntityInfoWidgetActive( myEntityInfoWidgetPinnedFlag );
         setHoverSignalsActive( ! myEntityInfoWidgetPinnedFlag );
      }
   }
}

void DtExampleDriver::setHoverSignalsActive( bool active )
{
   // Get the event signals for the entity indicator from the widget signaler.
   DtWidgetSignaler& widgetSignaler =
      DtWidgetSignaler::instance( myAgentManager.de().mainEventQueue() );
   DtWidgetEventSignals& signals = myEntityIndicator->eventSignals(
      widgetSignaler );

   // Connect to or disconnect from the signals.
   if ( active )
   {
      signals.signal_mouseEnter.connect( boost::bind(
         &DtExampleDriver::setEntityInfoWidgetActive, this, true ) );
      signals.signal_mouseLeave.connect( boost::bind(
         &DtExampleDriver::setEntityInfoWidgetActive, this, false ) );
   }
   else
   {
      signals.signal_mouseEnter.disconnect( boost::bind(
         &DtExampleDriver::setEntityInfoWidgetActive, this, true ) );
      signals.signal_mouseLeave.disconnect( boost::bind(
         &DtExampleDriver::setEntityInfoWidgetActive, this, false ) );
   }
}

void DtExampleDriver::setEntityInfoWidgetActive( bool active )
{
   // If mouse is hovering and there's no info widget...
   if ( active && ! myEntityInfoWidget )
   {
      // Create the entity info widget and set the color.
      myEntityInfoWidget = new DtEntityInfoWidget( myAgentManager,
         myEntityFacade->modelSet(), "entityInfo" );
      myEntityInfoWidget->setColor( 0, 0, 1, 1 );

      // Set group id in the entityInfoHoverGroup.
      DtOverlayGroupManager& groupManager =
         DtOverlayGroupManager::instance( myAgentManager.de() );
      myEntityInfoWidget->setGroup( groupManager.nextGroupId("hoverGroupSet") );

      // Add it to the entity,
      myEntityFacade->sceneObjectAgent().addModel( myEntityInfoWidget->model(),
         DtStateVisualizer::EntityVisualizerType );

      // And update its display text.
      DtUnicode infoString = generateInfoString();
      myEntityInfoWidget->setText( infoString );
   }
   // If mouse isn't hovering, and there is an info widget...
   else if ( ! active && myEntityInfoWidget )
   {
      // Remove it from the model and destroy it.
      myEntityFacade->sceneObjectAgent().removeModel(
         myEntityInfoWidget->model() );
      delete myEntityInfoWidget;
      myEntityInfoWidget = 0;
   }
}

DtUnicode DtExampleDriver::generateInfoString() const
{
   DtReferenceEllipsoid refEllip( DtWGS84 );
   DtGeodeticCoord geod( &refEllip );
   geod.setGeocentric( myPosition );

   DtVector localp;
   DtTaitBryan hpr;

   const DtCoordinateSystem& coordSys =
      myAgentManager.de().sharedState().coordinateSystem();
   coordSys.netToLocalPos( myPosition, localp );
   coordSys.netToLocalHpr( localp, myOrientation, hpr );

   const char* entityFormatString =
      "Marking :%s\n"            // Marking Text
      "Heading :%.2f Deg\n"      // Heading
      "Lat|Lon :%.2fN %.fE\n"    // Location
      "Alt.    :%.1f m above sea level";

   std::string buffer;
   buffer.resize( 1024, '0' );
   {
      int charsWritten = sprintf(
         const_cast<char*>(buffer.c_str()), entityFormatString,
         myEntityDisplayName.c_str(),  // Marking Text
         DtRad2Deg(myHeading),         // Heading
         DtRad2Deg(geod.lat()),        // Location (Lat)
         DtRad2Deg(geod.lon()),        // Location (Lon)
         myPosition[2]                 // Altitude
      );
      buffer.resize(charsWritten,'0');
   }

   return DtUnicode::fromUtf8(buffer);
}

void DtExampleDriver::updatePosition()
{
   // Get current time and compute time since last update.
   double now = myAgentManager.de().simulationTime();
   double dt = now - myLastUpdateTime;

   // Update clock angle. The clock angle represents the bearing
   // to the aircraft from the center point of its orbit.
   myClockAngle += myAngularVelocity * dt;

   // Compute the offset to the aircraft using the radius and clock angle.
   DtVector offset( myRadius*sin(myClockAngle), myRadius*cos(myClockAngle), 0 );

   // Compute heading and net orientation. Since the aircraft is
   // orbiting in a perfect circle, the heading is always 90 degrees
   // (pi/2) more than the bearing to the aircraft.
   myHeading =  myClockAngle + M_PI_2;
   DtTaitBryan ori( myHeading, 0, myRoll );

   // Update the aircraft's position/orientation with the new parameters.
   repositionAircraft( myOrbitCenter+offset, ori );

   // Store as last update time.
   myLastUpdateTime = now;
}

void DtExampleDriver::repositionAircraft( DtVector position, DtTaitBryan ori )
{
   // Get the coordinate converter and initialize.
   DtCoordinateConverter* coordConverter;
   coordConverter = myAgentManager.de().sharedState().coordinateSystem().converter();
   if ( coordConverter->type() == DtCoordinateConverter::Geocentric )
   {
      // => Use this for MaklandGeocentric - not exact but close enough
      DtGeodeticCoord geod( DtDeg2Rad( 10.0 ), DtDeg2Rad(60.0), 0.0 );
      coordConverter->setupTopoFrame( geod.geocentric() );
   }
   else
   {
      // Or this for Makland (UTM)
      coordConverter->setupTopoFrame( position );
   }

   // Convert the position (from ENU) to local database (CIG) coords.
   coordConverter->enuToCig_coordTrans( position, myPosition );

   // Convert the orientation (from NED) to local database (CIG) ori.
   myOrientation = coordConverter->nedToCig_EulerTrans( ori );

   // Set the Position and Orientation on the aircraft.
   myEntityFacade->setOrientation( myOrientation );

The driver's generateInfoString() method essentially performs some formatting and unit conversion on the information it has about the aircraft's position and orientation in the scene. The value returned from this method is then simply set on the entity info widget (if there is one present - if the mouse isn't hovering, there won't be an info widget).

The driver's updatePosition() method first determines how long it's been since the last update, and updates the aircraft's clock angle based on its angular velocity. The clock angle is the bearing to the aircraft from the point at the center of the aircraft's orbit (0 for north, and increasing in the clockwise direction). It then determines the aircraft's offset from the center of its orbit.

The aircraft's orbit is circular, so computing the heading is as easy as adding 90 degrees (Pi/2) to the clock angle. Once this has been done, the heading and roll can be used to determine the net orientation of the F16.

Now that the F16's position and orientation have been computed, the aircraft can be repositioned in the scene. Finally, the current time is set as the last update time in preparation for the next update.

Positioning the aircraft takes place in the repositionAircraft(..) method. This method first determines the type of coordinate system using the DtCoordinateConverter, then converts the position and orientation to local database (CIG) coordinates. Finally, the CIG coordinates are set on the entity facade, performing the actual reposition.

The driver is stopped by the driver manager callings its onStop() method. This cleans up the entity facade allocated on the heap.

   if ( myEntityFacade )
   {
      if ( myEntityInfoWidget )
      {
         myEntityFacade->sceneObjectAgent().removeModel(
            myEntityInfoWidget->model() );
         delete myEntityInfoWidget;
         myEntityInfoWidget;
      }

      if ( myEntityIndicator )
      {
         setHoverSignalsActive( false );
         myEntityFacade->sceneObjectAgent().removeModel(
            myEntityIndicator->model() );
         delete myEntityIndicator;
         myEntityIndicator = 0;
      }

      reportElementDestroyed( myEntityFacade->elementId() );
      delete myEntityFacade;
      myEntityFacade = 0;
   }
   return true;

The example driver is created, added to the driver manager, and started in the main program.

   DtExampleDriver* driver = new DtExampleDriver( application.de().agentManager() );

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

Example Source Files


exampleDriver.cxx

/*****************************************************************************
 * Copyright (c) 2011 MAK Technologies, Inc.
 * All rights reserved.
 *****************************************************************************/


#include <vrvCore/DtDe.h>
#include <vrvCore/DtDriverManager.h>
#include <vrvCore/DtStealthConfiguration.h>
#include <vrvCore/DtStealthCommandLineProcessor.h>

#include "DtExampleDriver.h"

int main( int argc, char* argv[] )
{
   // Create the Application.
   makVrv::DtStealthConfiguration stealthConfig;
   makVrv::DtStealthCommandLineProcessor stealthParser;
   makVrv::DtVrvApplication application( stealthConfig );
   application.installCommandLineProcessor( &stealthParser );

   // This causes the plug-in manager to load plug-ins, cause a Display Configuration
   // to be realized, creates the default environment, etc.
   application.initialize( argc, argv );

   // Create DtExampleDriver.
   DtExampleDriver* driver = new DtExampleDriver( application.de().agentManager() );

   // The driver is now owned by the display engine. Do not delete it.
   application.de().driverManager().addDriver( driver );

   // Start the driver, creating the agent.
   application.de().driverManager().startDriver( driver );

   // Creates an event loop and begins running it, causing the creation of frames.
   application.run();
}

DtExampleDriver.h

/*****************************************************************************
 * Copyright (c) 2012 MAK Technologies, Inc.
 * All rights reserved.
 *****************************************************************************/


#pragma once

#include <vrvCore/DtDriver.h>

#include <vrvCore/DtEntityIndicatorWidget.h>
#include <vrvCore/DtSelectionManager.h>
#include <vrvCore/DtEntityInfoWidget.h>

#include <vrvUtil/DtUnicode.h>

#include <matrix/vlTaitBryan.h>
#include <matrix/vlVector.h>

#include <string>

namespace makVrv
{
   class DtEntity3dFacade;
}

// This driver creates and owns the example driver.
class DtExampleDriver : public makVrv::DtDriver
{
public:

   DtExampleDriver( makVrv::DtAgentManager& am );

   virtual ~DtExampleDriver();


   virtual const std::string& className() const;

   virtual bool onStart();

   virtual bool onStop();

   virtual bool onTick();

   virtual void slot_displayEngineAdded( const makVrv::DtDeRecord& igRecord );


protected:

   virtual void slot_togglePinnedLabel(
      const makVrv::DtSelectionManager::IdSet& sel );

   virtual void setHoverSignalsActive( bool active );

   virtual void setEntityInfoWidgetActive( bool active );

   virtual makVrv::DtUnicode generateInfoString() const;

   virtual void updatePosition();

   virtual void repositionAircraft( DtVector position, DtTaitBryan ori );

protected:

   makVrv::DtEntity3dFacade* myEntityFacade;
   makVrv::DtEntityIndicatorWidget* myEntityIndicator;
   makVrv::DtEntityInfoWidget* myEntityInfoWidget;

   std::string myEntityDisplayName;
   bool myEntityInfoWidgetPinnedFlag;

   DtTaitBryan myOrientation;
   DtVector myPosition;

   DtVector myOrbitCenter;
   double myAngularVelocity;

   double myLastCommLineTime;
   double myLastUpdateTime;
   double myClockAngle;
   double myHeading;
   double myRadius;
   double myRoll;

};

DtExampleDriver.cxx

/*****************************************************************************
 * Copyright (c) 2012 MAK Technologies, Inc.
 * All rights reserved.
 *****************************************************************************/


#include <DtExampleDriver.h>

#include <vrvCore/DtAgentManager.h>
#include <vrvCore/DtDe.h>
#include <vrvCore/DtDeSharedState.h>
#include <vrvCore/DtDriverManager.h>
#include <vrvCore/DtElementAttributes.h>
#include <vrvCore/DtEntityFacade.h>
#include <vrvCore/DtInputDriver.h>
#include <vrvCore/DtObserver.h>
#include <vrvCore/DtScene.h>
#include <vrvCore/DtOverlayGroupManager.h>
#include <vrvCore/DtStateVisualizer.h>
#include <vrvUtil/DtCoordinateConverter.h>
#include <vrvUtil/DtCoordinateSystem.h>

// Use the VR-Vantage namespace.
// All classes in VR-Vantage are in this namespace.
using namespace makVrv;

DtExampleDriver::DtExampleDriver( DtAgentManager& am )
   : makVrv::DtDriver( am, "DtExampleDriver" )
   , myEntityFacade( 0 )
   , myEntityIndicator( 0 )
   , myEntityInfoWidget( 0 )
   , myEntityDisplayName( "" )
   , myEntityInfoWidgetPinnedFlag( false )
   , myPosition()
   , myOrientation()
   , myOrbitCenter( 2000.0, 1400.0, 350.0 )
   , myAngularVelocity( 0.2 )
   , myLastUpdateTime( 0.0 )
   , myClockAngle( 0.0 )
   , myHeading( 0.0 )
   , myRadius( 1000.0 )
   , myRoll( 0.5 )
{
}

DtExampleDriver::~DtExampleDriver()
{
   DtExampleDriver::onStop();
}

const std::string& DtExampleDriver::className() const
{
   static std::string name = "DtExampleDriver";
   return name;
}

bool DtExampleDriver::onStart()
{
   // Load Makland programatically.
   DtScene& sceneDriver = myAgentManager.de().scene();
   std::string maklandPath = myAgentManager.de().dePathConfiguration().userPath();
   maklandPath += "/terrains/MaklandNoSpeedtrees.mtf";
   sceneDriver.loadTerrain( maklandPath );

   // Create the entity
   DtElementID parentElementId = 0;
   myEntityDisplayName = "Entity From Facade";
   DtElementID elementId = myAgentManager.createNewUniqueId();
   myEntityFacade = new DtEntity3dFacade( myAgentManager, elementId, true );
   reportElementCreated( elementId, parentElementId, DtElementEntry::Entity );
   reportElementAttribute( elementId, new DtElementAttributeDisplayName(myEntityDisplayName) );
   reportElementAttribute( elementId, new DtElementAttributeVisibility(true) );

   // Load the model
   myEntityFacade->setArticulatedModelDefinition("FixedWingF-16UnarmedGrey");

   // Create the entity indicator
   myEntityIndicator =
      new DtEntityIndicatorWidget( myAgentManager, myEntityFacade->modelSet() );
   myEntityIndicator->setEventsEnabled( true );
   myEntityIndicator->setColor( 0, 0, 1, 1 );
   setHoverSignalsActive( true );

   // Attach the entity indicator to the entity
   myEntityFacade->sceneObjectAgent().addModel( myEntityIndicator->model(),
      DtStateVisualizer::EntityVisualizerType );

   // Listen for requests to pin/unpin the info label
   DtSelectionManager& selMgr(
      DtSelectionManager::instance(myAgentManager.de()) );
   selMgr.signal_entityInfoToggled.connect( boost::bind(
      &DtExampleDriver::slot_togglePinnedLabel, this, _1 ) );

   // Initialize the position
   myLastUpdateTime = myAgentManager.de().simulationTime();
   updatePosition();

   {  // Attach to entity.
      std::vector<DtUniqueID> objects;
      objects.push_back( myEntityFacade->elementId() );
      DtObserver* currentObserver =
         myAgentManager.de().driverManager().inputDriver().currentObserver();
      currentObserver->setPrimaryAttachment( objects );
   }

   return true;
}

bool DtExampleDriver::onStop()
{
   if ( myEntityFacade )
   {
      if ( myEntityInfoWidget )
      {
         myEntityFacade->sceneObjectAgent().removeModel(
            myEntityInfoWidget->model() );
         delete myEntityInfoWidget;
         myEntityInfoWidget;
      }

      if ( myEntityIndicator )
      {
         setHoverSignalsActive( false );
         myEntityFacade->sceneObjectAgent().removeModel(
            myEntityIndicator->model() );
         delete myEntityIndicator;
         myEntityIndicator = 0;
      }

      reportElementDestroyed( myEntityFacade->elementId() );
      delete myEntityFacade;
      myEntityFacade = 0;
   }
   return true;
}

bool DtExampleDriver::onTick()
{
   updatePosition();
   if ( myEntityInfoWidget )
   {
      myEntityInfoWidget->setText( generateInfoString() );
   }
   return true;
}

void DtExampleDriver::slot_displayEngineAdded( const DtDeRecord& igRecord )
{
   stop();
   start();
}

void DtExampleDriver::slot_togglePinnedLabel(
   const DtSelectionManager::IdSet& sel )
{
   // Iterate over selected entities...
   DtSelectionManager::IdSet::const_iterator i = sel.begin();
   DtSelectionManager::IdSet::const_iterator e = sel.end();
   for ( ; i != e; ++i )
   {
      // If the entity facade is selected...
      if ( (*i) == myEntityFacade->elementId() )
      {
         // Pin/unpin the label and stop/start listening for mouse hovers.
         myEntityInfoWidgetPinnedFlag = ! myEntityInfoWidgetPinnedFlag;
         myEntityIndicator->setIndicatorActive( myEntityInfoWidgetPinnedFlag );
         setEntityInfoWidgetActive( myEntityInfoWidgetPinnedFlag );
         setHoverSignalsActive( ! myEntityInfoWidgetPinnedFlag );
      }
   }
}

void DtExampleDriver::setHoverSignalsActive( bool active )
{
   // Get the event signals for the entity indicator from the widget signaler.
   DtWidgetSignaler& widgetSignaler =
      DtWidgetSignaler::instance( myAgentManager.de().mainEventQueue() );
   DtWidgetEventSignals& signals = myEntityIndicator->eventSignals(
      widgetSignaler );

   // Connect to or disconnect from the signals.
   if ( active )
   {
      signals.signal_mouseEnter.connect( boost::bind(
         &DtExampleDriver::setEntityInfoWidgetActive, this, true ) );
      signals.signal_mouseLeave.connect( boost::bind(
         &DtExampleDriver::setEntityInfoWidgetActive, this, false ) );
   }
   else
   {
      signals.signal_mouseEnter.disconnect( boost::bind(
         &DtExampleDriver::setEntityInfoWidgetActive, this, true ) );
      signals.signal_mouseLeave.disconnect( boost::bind(
         &DtExampleDriver::setEntityInfoWidgetActive, this, false ) );
   }
}

void DtExampleDriver::setEntityInfoWidgetActive( bool active )
{
   // If mouse is hovering and there's no info widget...
   if ( active && ! myEntityInfoWidget )
   {
      // Create the entity info widget and set the color.
      myEntityInfoWidget = new DtEntityInfoWidget( myAgentManager,
         myEntityFacade->modelSet(), "entityInfo" );
      myEntityInfoWidget->setColor( 0, 0, 1, 1 );

      // Set group id in the entityInfoHoverGroup.
      DtOverlayGroupManager& groupManager =
         DtOverlayGroupManager::instance( myAgentManager.de() );
      myEntityInfoWidget->setGroup( groupManager.nextGroupId("hoverGroupSet") );

      // Add it to the entity,
      myEntityFacade->sceneObjectAgent().addModel( myEntityInfoWidget->model(),
         DtStateVisualizer::EntityVisualizerType );

      // And update its display text.
      DtUnicode infoString = generateInfoString();
      myEntityInfoWidget->setText( infoString );
   }
   // If mouse isn't hovering, and there is an info widget...
   else if ( ! active && myEntityInfoWidget )
   {
      // Remove it from the model and destroy it.
      myEntityFacade->sceneObjectAgent().removeModel(
         myEntityInfoWidget->model() );
      delete myEntityInfoWidget;
      myEntityInfoWidget = 0;
   }
}

DtUnicode DtExampleDriver::generateInfoString() const
{
   DtReferenceEllipsoid refEllip( DtWGS84 );
   DtGeodeticCoord geod( &refEllip );
   geod.setGeocentric( myPosition );

   DtVector localp;
   DtTaitBryan hpr;

   const DtCoordinateSystem& coordSys =
      myAgentManager.de().sharedState().coordinateSystem();
   coordSys.netToLocalPos( myPosition, localp );
   coordSys.netToLocalHpr( localp, myOrientation, hpr );

   const char* entityFormatString =
      "Marking :%s\n"            // Marking Text
      "Heading :%.2f Deg\n"      // Heading
      "Lat|Lon :%.2fN %.fE\n"    // Location
      "Alt.    :%.1f m above sea level";

   std::string buffer;
   buffer.resize( 1024, '0' );
   {
      int charsWritten = sprintf(
         const_cast<char*>(buffer.c_str()), entityFormatString,
         myEntityDisplayName.c_str(),  // Marking Text
         DtRad2Deg(myHeading),         // Heading
         DtRad2Deg(geod.lat()),        // Location (Lat)
         DtRad2Deg(geod.lon()),        // Location (Lon)
         myPosition[2]                 // Altitude
      );
      buffer.resize(charsWritten,'0');
   }

   return DtUnicode::fromUtf8(buffer);
}

void DtExampleDriver::updatePosition()
{
   // Get current time and compute time since last update.
   double now = myAgentManager.de().simulationTime();
   double dt = now - myLastUpdateTime;

   // Update clock angle. The clock angle represents the bearing
   // to the aircraft from the center point of its orbit.
   myClockAngle += myAngularVelocity * dt;

   // Compute the offset to the aircraft using the radius and clock angle.
   DtVector offset( myRadius*sin(myClockAngle), myRadius*cos(myClockAngle), 0 );

   // Compute heading and net orientation. Since the aircraft is
   // orbiting in a perfect circle, the heading is always 90 degrees
   // (pi/2) more than the bearing to the aircraft.
   myHeading =  myClockAngle + M_PI_2;
   DtTaitBryan ori( myHeading, 0, myRoll );

   // Update the aircraft's position/orientation with the new parameters.
   repositionAircraft( myOrbitCenter+offset, ori );

   // Store as last update time.
   myLastUpdateTime = now;
}

void DtExampleDriver::repositionAircraft( DtVector position, DtTaitBryan ori )
{
   // Get the coordinate converter and initialize.
   DtCoordinateConverter* coordConverter;
   coordConverter = myAgentManager.de().sharedState().coordinateSystem().converter();
   if ( coordConverter->type() == DtCoordinateConverter::Geocentric )
   {
      // => Use this for MaklandGeocentric - not exact but close enough
      DtGeodeticCoord geod( DtDeg2Rad( 10.0 ), DtDeg2Rad(60.0), 0.0 );
      coordConverter->setupTopoFrame( geod.geocentric() );
   }
   else
   {
      // Or this for Makland (UTM)
      coordConverter->setupTopoFrame( position );
   }

   // Convert the position (from ENU) to local database (CIG) coords.
   coordConverter->enuToCig_coordTrans( position, myPosition );

   // Convert the orientation (from NED) to local database (CIG) ori.
   myOrientation = coordConverter->nedToCig_EulerTrans( ori );

   // Set the Position and Orientation on the aircraft.
   myEntityFacade->setOrientation( myOrientation );
   myEntityFacade->setPosition( myPosition );
}

Document ID: Generated on Fri Jun 29 16:33:32 EDT 2012 from SVN revision 116588
Copyright © 2005-2012 VT MÄK Inc. All Rights Reserved (www.mak.com)