![]() |
VR-Vantage 1.4.1 API Class Documentation
|
Project 5 in the Distributed Simulation tutorial pulls together what we have learned in earlier projects. Although we won't use threaded connections or VR-Vantage listeners, this project could easily be changed to use them. Instead, we will use a simple VR-Link connection and a detonation callback to receive detonation data interactions. We will also use the pre-existing VR-Vantage agent in order to place a distinct entity into the scene at the coordinates of each detonation interaction received.
For this project, all files from Project 2A will be reused. We will also reuse the custom connection class created for Project 3B. All changes, other than filenames, will be made in the DistributedSimulationDriver class files.
As with Project 3A, in the driver header file we define DtDetonationInteraction as an alias for the VR-Link DtDetonationPdu class type. This helps the code to be self-documenting. To remember which objects were added to the scene to later support animation and eventual removal, we add two more type definitions: one to pair a scene object agent with its associated a model agent, and one as an array of such scene object/model object pairs. We then instantiation a list of such pairs as a member of the driver class.
typedef DtDetonationPdu DtDetonationInteraction;
//! Typedefs describing a SceneObject/Model pair and a list of such pairs. typedef std::pair<DtSceneObjectAgent*, DtModelAgent*> SceneObjectAndModelPair; typedef std::vector<SceneObjectAndModelPair> SceneObjectAndModelList;
SceneObjectAndModelList mySceneObjectAgentsList;
For the driver definition file, we will need to include the following header files:
#include <vrvCore/DtSceneObjectAgent.hpp> #include <vrvCore/DtModelAgent.hpp> #include <vrvCore/DtSharedSettingsManager.h> #include <vrvCore/DtDeSharedState.h> #include <vrvUtil/DtCoordinateSystem.h> #include <vl/detonateInter.h>
The new onStart() function looks as follows:
bool DistributedSimulationDriver::onStart() { std::cout << "DistributedSimulationDriver::onStart(): " << std::endl; DtExerciseConnInitializer init; init.setPort(3152); init.setExerciseId(1); init.setSiteId(2); init.setApplicationNumber(1); // VR-Link default buffer is to small for this application; set it to 1 MB. init.setReceiveBufferSize(0x100000); DtAgentManagerInterface* simSceneInterface = &myAgentManager; mySimulation = new DistributedSimulationConnection(*simSceneInterface, DtSharedSettingsManager::instance(agentManager().de())); mySimulation->connect(init); // Add all models to the scene that may have already been encountered // in the case where a previous onStart() was followed by an onStop(). for (unsigned int i=0; i<mySceneObjectAgentsList.size(); i++) { mySceneObjectAgentsList[i].first->addModel( mySceneObjectAgentsList[i].second, 0); } // Add a detonation interaction callback DtDetonationInteraction::addCallback(mySimulation->exerciseConn(), &processDetonationCb, this); return mySimulation->connected(); }
Here we have used the same code as for Project 3B in order to instantiate a custom connection object.
DtAgentManagerInterface* simSceneInterface = &myAgentManager;
mySimulation = new DistributedSimulationConnection(*simSceneInterface,
DtSharedSettingsManager::instance(agentManager().de()));
mySimulation->connect(init);
We then run through our list of scene object/model object pairs and populate the scene with them. This list is initially empty, but this is necessary in the case where we wanted to place already encountered objects back in the scene each time we restart the driver.
// Add all models to the scene that may have already been encountered // in the case where a previous onStart() was followed by an onStop(). for (unsigned int i=0; i<mySceneObjectAgentsList.size(); i++) { mySceneObjectAgentsList[i].first->addModel( mySceneObjectAgentsList[i].second, 0); }
We then need to add our callback function so that we can receive and respond to detonation interaction data as it comes over our custom connection.
DtDetonationInteraction::addCallback(mySimulation->exerciseConn(), &processDetonationCb, this);
The onStop() function now needs to run through the same list of scene object/model object pairs in order to remove our entities from the scene. We don't delete our objects or clear the list since in our case we will replace these objects in the scene each time we click Start.
bool DistributedSimulationDriver::onStop() { // NOTE: breakdown code goes here. Return false on bad status. std::cout << "DistributedSimulationDriver::onStop(): " << std::endl; if (mySimulation) delete mySimulation; mySimulation = 0; // Remove all models from the scene for (unsigned int i=0; i<mySceneObjectAgentsList.size(); i++) { mySceneObjectAgentsList[i].first->removeModel( mySceneObjectAgentsList[i].second); } return true; }
The onTick() function now runs through our object pair list in order to animate each cow image to rotate to the left.
bool DistributedSimulationDriver::onTick() { // printout to show whether or not connected at the tick level bool connState = mySimulation->connected(); if (connState) { int numread = mySimulation->exerciseConn()->drainInput(); std::cout << "." << numread; } else std::cout << "x"; // rotate all models to the left. for (unsigned int i=0; i<mySceneObjectAgentsList.size(); i++) { const DtTaitBryan orient(myRotationDegree, 0, 0); mySceneObjectAgentsList[i].first->setOrientation(0, orient); myRotationDegree -= 0.005; if(myRotationDegree < 0.0) { myRotationDegree = 360.0; } } return connState; }
The final change is to add a loop to the destructor so that we can run through our object pair list to remove our entities from the scene and reclaim memory.
DistributedSimulationDriver::~DistributedSimulationDriver(void) { // Remove all models from the scene and reclaim memory for (unsigned int i=0; i<mySceneObjectAgentsList.size(); i++) { mySceneObjectAgentsList[i].first->removeModel( mySceneObjectAgentsList[i].second); delete mySceneObjectAgentsList[i].first; delete mySceneObjectAgentsList[i].second; } mySceneObjectAgentsList.clear(); }
Invoke either the tutorialDistributedSimulation5d.bat or tutorialDistributedSimulation5.sh script file to start the VR-Vantage Stealth application. Follow these instructions to test the plugin:
Continually clicking the Start and Stop button will continue to start the driver (placing all currently detected cow images back into the scene) and stop the driver (removing all currently detected cow images from the scene). Note that any detonations that occur in VR-Forces while the driver is stopped in VR-Vantage will never be detected by the driver. These will never be added as cow nodes to the list of agents, and will therefore never be added to the scene.
[<< Add an Entity Using a Custom Agent]
/****************************************************************************** ** Copyright (c) 2011 MAK Technologies, Inc. ** All rights reserved. ******************************************************************************/ #pragma once #include <vrvCore/DtDriver.h> class DtDetonationPdu; typedef DtDetonationPdu DtDetonationInteraction; namespace makVrv { class DtSceneObjectAgent; class DtModelAgent; namespace tutorialDistributedSimulation5 { class DistributedSimulationConnection; class DistributedSimulationDriver : public DtDriver { public: typedef std::pair<DtSceneObjectAgent*, DtModelAgent*> SceneObjectAndModelPair; typedef std::vector<SceneObjectAndModelPair> SceneObjectAndModelList; DistributedSimulationDriver(DtAgentManager& agentManager, const std::string& instanceName); virtual ~DistributedSimulationDriver(); virtual const std::string& className() const; protected: virtual bool onStart(); virtual bool onStop(); virtual bool onTick(); static void processDetonationCb(DtDetonationInteraction* inter, void* usr); virtual void processDetonation(DtDetonationInteraction* inter); protected: DistributedSimulationConnection* mySimulation; SceneObjectAndModelList mySceneObjectAgentsList; double myRotationDegree; }; } }
/****************************************************************************** ** Copyright (c) 2011 MAK Technologies, Inc. ** All rights reserved. ******************************************************************************/ // Compile VR-Link code for DIS protocol #define DtDIS 1 #include "DistributedSimulationDriver5.h" #include "DistributedSimulationConnection5.h" #include <vrvCore/DtDe.h> #include <vrvCore/DtSceneObjectAgent.hpp> #include <vrvCore/DtModelAgent.hpp> #include <vrvCore/DtSharedSettingsManager.h> #include <vrvCore/DtDeSharedState.h> #include <vrvUtil/DtCoordinateSystem.h> #include <vl/detonateInter.h> #include <vl/exConnInit.h> #include <iostream> namespace makVrv { namespace tutorialDistributedSimulation5 { DistributedSimulationDriver::DistributedSimulationDriver( DtAgentManager& agentManager, const std::string& instanceName) : DtDriver(agentManager, instanceName) , mySimulation(0) , myRotationDegree(0) { } DistributedSimulationDriver::~DistributedSimulationDriver(void) { // Remove all models from the scene and reclaim memory for (unsigned int i=0; i<mySceneObjectAgentsList.size(); i++) { mySceneObjectAgentsList[i].first->removeModel( mySceneObjectAgentsList[i].second); delete mySceneObjectAgentsList[i].first; delete mySceneObjectAgentsList[i].second; } mySceneObjectAgentsList.clear(); } const std::string& DistributedSimulationDriver::className() const { // name must be static, since it's returned by reference static std::string name("DistributedSimulationDriver"); return name; } bool DistributedSimulationDriver::onStart() { std::cout << "DistributedSimulationDriver::onStart(): " << std::endl; DtExerciseConnInitializer init; init.setPort(3152); init.setExerciseId(1); init.setSiteId(2); init.setApplicationNumber(1); // VR-Link default buffer is to small for this application; set it to 1 MB. init.setReceiveBufferSize(0x100000); DtAgentManagerInterface* simSceneInterface = &myAgentManager; mySimulation = new DistributedSimulationConnection(*simSceneInterface, DtSharedSettingsManager::instance(agentManager().de())); mySimulation->connect(init); // Add all models to the scene that may have already been encountered // in the case where a previous onStart() was followed by an onStop(). for (unsigned int i=0; i<mySceneObjectAgentsList.size(); i++) { mySceneObjectAgentsList[i].first->addModel( mySceneObjectAgentsList[i].second, 0); } // Add a detonation interaction callback DtDetonationInteraction::addCallback(mySimulation->exerciseConn(), &processDetonationCb, this); return mySimulation->connected(); } bool DistributedSimulationDriver::onStop() { // NOTE: breakdown code goes here. Return false on bad status. std::cout << "DistributedSimulationDriver::onStop(): " << std::endl; if (mySimulation) delete mySimulation; mySimulation = 0; // Remove all models from the scene for (unsigned int i=0; i<mySceneObjectAgentsList.size(); i++) { mySceneObjectAgentsList[i].first->removeModel( mySceneObjectAgentsList[i].second); } return true; } bool DistributedSimulationDriver::onTick() { // printout to show whether or not connected at the tick level bool connState = mySimulation->connected(); if (connState) { int numread = mySimulation->exerciseConn()->drainInput(); std::cout << "." << numread; } else std::cout << "x"; // rotate all models to the left. for (unsigned int i=0; i<mySceneObjectAgentsList.size(); i++) { const DtTaitBryan orient(myRotationDegree, 0, 0); mySceneObjectAgentsList[i].first->setOrientation(0, orient); myRotationDegree -= 0.005; if(myRotationDegree < 0.0) { myRotationDegree = 360.0; } } return connState; } void DistributedSimulationDriver::processDetonationCb(DtDetonationInteraction* inter, void* usr) { ((DistributedSimulationDriver*)usr)->processDetonation(inter); } void DistributedSimulationDriver::processDetonation(DtDetonationInteraction* inter) { std::cout << "((detonation interaction))"; std::cout << "D(" << inter->attackerId().entityNum() << "," << inter->targetId().entityNum() << "," << inter->result() << ")"; DtVector vect2 = inter->worldLocation(); DtVector local; myAgentManager.de().sharedState().coordinateSystem().netToLocalPos( inter->worldLocation(), local); // Add a cow to the root node by creating an existing model and agent // and setting the cow model definition into it. DtModelAgent* simpleModel = DtModelAgent::create(myAgentManager); DtSceneObjectAgent* sceneObjectAgent = DtSceneObjectAgent::create(myAgentManager); sceneObjectAgent->setPosition(0, local); sceneObjectAgent->setModelSet(0); sceneObjectAgent->addModel(simpleModel, 0); simpleModel->setModelDefinition("LifeformsAnimalsCow"); // Remember the agents for later removal of cows. mySceneObjectAgentsList.push_back(std::make_pair(sceneObjectAgent, simpleModel)); } } }
/****************************************************************************** ** Copyright (c) 2011 MAK Technologies, Inc. ** All rights reserved. ******************************************************************************/ #pragma once // Setup proper plugin export symbol #ifdef WIN32 #define DT_DE_PLUGIN_EXPORT_MACRO __declspec ( dllexport ) #else #define DT_DE_PLUGIN_EXPORT_MACRO #endif // Declare & export the plugin initialization function (bool initDeModule(DtDe* de)) #include <vrvCore/exportPlugin.h> namespace makVrv { class DtDe; } // Work function for the plugin initialization void init(makVrv::DtDe& de); // Callback to create the stateViewDriver void createDistributedSimDriver(makVrv::DtDe* de);
/****************************************************************************** ** Copyright (c) 2011 MAK Technologies, Inc. ** All rights reserved. ******************************************************************************/ #include "DistributedSimulationPlugin5.h" #include "DistributedSimulationDriver5.h" #include <vrvCore/DtDe.h> #include <vrvCore/DtDriverManager.h> #include <boost/bind.hpp> using namespace makVrv; using namespace makVrv::tutorialDistributedSimulation5; void createDistributedSimDriver(DtDe* de) { // We're done with the signal, so disconnect from it de->signal_postInitialize.disconnect(boost::bind( &createDistributedSimDriver, de)); // Create the driver that will implement a distributed simulation DistributedSimulationDriver* driver = new DistributedSimulationDriver( de->agentManager(), "DistributedSimulationDriver5"); // After the driver is added to the display engine below, the DE will manage // its memory. This driver will add itself to the connection list. Start // it from the connection panel. de->driverManager().addDriver(driver); } void init(DtDe& de) { // Ensure that init only gets called once // (not strictly necessary here, but this is good practice in general) DT_DE_INIT_ONCE(de); // We only want to create the driver if we're running in master mode: if (de.isInMasterMode()) { // The driver must be created after the DE's initialization is // finished, to make sure all the objects it uses exist. de.signal_postInitialize.connect(boost::bind( &createDistributedSimDriver, &de)); } } bool initDeModule(makVrv::DtDe* de) { // Setup the plugin. Normally, the init function and functionality // should be in its own library. init(*de); return true; }
/****************************************************************************** ** Copyright (c) 2011 MAK Technologies, Inc. ** All rights reserved. ******************************************************************************/ #pragma once #include <vrvCore/DtBaseConnection.h> #include <boost/signal.hpp> class DtExerciseConnInitializer; class DtExerciseConn; namespace makVrv { namespace tutorialDistributedSimulation5 { class DistributedSimulationConnection : public DtBaseConnection { public: DistributedSimulationConnection(DtAgentManagerInterface& aSceneInterface, DtSharedSettingsManager& settingsManager); virtual ~DistributedSimulationConnection(); inline DtExerciseConn* exerciseConn() { return myConnection; } virtual bool connect(const DtExerciseConnInitializer& exConnInitializer); virtual bool disconnect(); virtual bool connected() const; boost::signal<void ()> signal_toBeDisconnected; protected: DtExerciseConn* myConnection; DtExerciseConnInitializer* myExConnInitializer; }; } }
/****************************************************************************** ** Copyright (c) 2011 MAK Technologies, Inc. ** All rights reserved. ******************************************************************************/ #define DtDIS 1 #include "DistributedSimulationConnection5.h" #include <vl/exerciseConn.h> #include <vl/exConnInit.h> namespace makVrv { namespace tutorialDistributedSimulation5 { DistributedSimulationConnection::DistributedSimulationConnection(DtAgentManagerInterface& aSceneInterface, DtSharedSettingsManager& settingsManager) : DtBaseConnection(settingsManager, aSceneInterface) , myConnection(0) , myExConnInitializer(new DtExerciseConnInitializer()) { } DistributedSimulationConnection::~DistributedSimulationConnection(void) { } bool DistributedSimulationConnection::connect(const DtExerciseConnInitializer& exConnInitializer) { *myExConnInitializer = exConnInitializer; if (myConnection) disconnect(); DtExerciseConn::InitializationStatus status = DtExerciseConn::DtINIT_SUCCESS; try { myConnection = new DtExerciseConn(*myExConnInitializer, &status); } catch(...) { return false; } if(status != DtExerciseConn::DtINIT_SUCCESS) { return false; } return true; } bool DistributedSimulationConnection::disconnect() { try { delete myConnection; myConnection = 0; } catch(...) { return false; } return true; } bool DistributedSimulationConnection::connected() const { return myConnection != 0; } } }