![]() |
VR-Vantage 1.4.1 API Class Documentation
|
Project 4C in the Distributed Simulation tutorial takes a look at how to add an entity to the scene using a custom VR-Vantage agent. For this project we will create a custom class which will contain all the functionality that we want the scene entity to have. In order to add this entity to the scene, we will introduce the VT MAK dcgen tool, which is used to generate the agent and supporting classes that we will use.
For this project, all files from Project 2A will be reused. We will add one more class called ExampleSimulationObject and we will use the dcgen tool (both discussed below) to generate the classes needed for creating an agent. The resulting agent class is what we will use to place an entity into the scene.
Adding an Entity to the Scene
To add an entity to the scene, we will change the driver class so that it has a member pointer to an example simulation object agent, along with a double for use in image rotation.
ExampleSimulationObjectAgent* myAgent;
double myRotationDegree;
In the driver definition file, we will need to add an include for the example simulation object agent class header.
#include "ExampleSimulationObjectClasses.hpp"
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); DtExerciseConn::InitializationStatus status = DtExerciseConn::DtINIT_SUCCESS; try { myConnection = new DtExerciseConn(init, &status); } catch(...) { return false; } myConnectionState = (status == DtExerciseConn::DtINIT_SUCCESS); // Add a cow to the root node by creating a custom agent and loading the cow // model file into it. if (!myAgent) { myAgent = ExampleSimulationObjectAgent::create(myAgentManager); myAgent->loadModel("../data/Lifeforms/Animals/cow.osg"); } return myConnectionState; }
The difference here is that we create an instance of an ExampleSimulationObjectAgent object if it doesn't already exist, and then call that object to load the necessary model from file, as was done with Project 4A. This is different to Project 4B where we had to use a string to reference a VR-Vantage pre-registered model.
// Add a cow to the root node by creating a custom agent and loading the cow // model file into it. if (!myAgent) { myAgent = ExampleSimulationObjectAgent::create(myAgentManager); myAgent->loadModel("../data/Lifeforms/Animals/cow.osg"); }
The new onStop() function removes the added model from the agent object if it exists, and then deletes the object.
bool DistributedSimulationDriver::onStop() { // NOTE: breakdown code goes here. Return false on bad status. std::cout << "DistributedSimulationDriver::onStop(): " << std::endl; delete myConnection; myConnection = 0; // Remove the cow from the scene and delete the agent. if (myAgent) { myAgent->removeModel(); delete myAgent; } myAgent = 0; return true; }
As with Project 4B, the onTick() function is responsible for animating the cow image by rotating it to the left.
bool DistributedSimulationDriver::onTick() { // printout to show whether or not connected at the tick level if (myConnectionState) { int numread = myConnection->drainInput(); std::cout << "." << numread; } else std::cout << "x"; // rotate the model to the left. myAgent->setRotationAngle(myRotationDegree); myRotationDegree += 0.15; if(myRotationDegree > 360.0) { myRotationDegree = 0.0; } return myConnectionState; }
We then need to create the example simulation object class, which will be used to generate the agent class and all other classes needed to support the agent. We will give this class the ability to load a model to the scene root node, remove a model from the scene root node, and set the rotation angle on a loaded node. The files defining this class can be seen at the following links:
Generating an agent class using dcgen
The VR-Vantage Distributed Code Generator can be started as follows:
When the dcgen window opens, choose File > New. Do the following:
The resulting .ocdx file is an XML definition file that will be used to generate the agent class that we will use to add entities to the scene. We can now run dcgen against this .ocdx file to generate the agent files either by GUI or the command line:
Generating from the GUI:
After creating the .ocdx file, before closing the GUI window, do the following:
Generating from the command line:
Type:
dcgend.exe input_file [{-i | -a | -p} -A root_dir -H header_dir -S source_dir -o output_dir -- -v -h]
Where:
The VS project file (.vsproj) for this project already includes the pre-created .ocdx file for the ExampleSimulationObject class. When you open the project in Visual Studio, right-click on the .ocdx file and choose Properties. You should see the following:
$(InputDir)$(InputName)Agent.hpp;$(InputDir)$(InputName)Agent.cpp $(InputDir)$(InputName)Classes.hpp;$(InputDir)$(InputName)Classes.cpp Additional Dependencies: ..\..\bin\sceneObjectCompilerd.exe Command Line: ..\..\bin\sceneObjectCompilerd.exe "$(InputPath)" -a -S "$(InputDir)/" -H "$(InputDir)/" -A "../../include"
Having generated the class files to support the use of an agent, we now need to add these four new files to our project and then build: DtExampleObjectClasses.cpp/.hpp and DtExampleObjectAgent.cpp/.hpp.
Invoke either the tutorialDistributedSimulation4Cd.bat or tutorialDistributedSimulation4C.sh script file to start the VR-Vantage Stealth application. Follow these instructions to test the plugin:
[<< Add an Entity Using an Existing VR-Vantage Agent] [Conclusion >>]
/****************************************************************************** ** Copyright (c) 2011 MAK Technologies, Inc. ** All rights reserved. ******************************************************************************/ #pragma once #include <vrvCore/DtDriver.h> class DtExerciseConn; namespace makVrv { class ExampleSimulationObjectAgent; namespace tutorialDistributedSimulation4C { class DistributedSimulationDriver : public DtDriver { public: 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(); protected: DtExerciseConn* myConnection; bool myConnectionState; ExampleSimulationObjectAgent* myAgent; double myRotationDegree; }; } }
// /****************************************************************************** // ** Copyright (c) 2011 MAK Technologies, Inc. // ** All rights reserved. // ******************************************************************************/ // /****************************************************************************** // ** $RCSfile: DistributedSimulationDriver4C.cxx,v $ $Revision: 1.0 $ $State: Exp $ // ******************************************************************************/ #define DtDIS 1 #include "DistributedSimulationDriver4C.h" #include "ExampleSimulationObjectClasses.hpp" #include <vrvCore/DtDe.h> #include <vl/exConnInit.h> #include <vl/exerciseConn.h> #include <iostream> namespace makVrv { namespace tutorialDistributedSimulation4C { DistributedSimulationDriver::DistributedSimulationDriver(DtAgentManager& agentManager, const std::string& instanceName) : DtDriver(agentManager, instanceName) , myConnection(0) , myAgent(0) , myConnectionState(0) , myRotationDegree(0.0) { } DistributedSimulationDriver::~DistributedSimulationDriver(void) { onStop(); } 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); DtExerciseConn::InitializationStatus status = DtExerciseConn::DtINIT_SUCCESS; try { myConnection = new DtExerciseConn(init, &status); } catch(...) { return false; } myConnectionState = (status == DtExerciseConn::DtINIT_SUCCESS); // Add a cow to the root node by creating a custom agent and loading the cow // model file into it. if (!myAgent) { myAgent = ExampleSimulationObjectAgent::create(myAgentManager); myAgent->loadModel("../data/Lifeforms/Animals/cow.osg"); } return myConnectionState; } bool DistributedSimulationDriver::onStop() { // NOTE: breakdown code goes here. Return false on bad status. std::cout << "DistributedSimulationDriver::onStop(): " << std::endl; delete myConnection; myConnection = 0; // Remove the cow from the scene and delete the agent. if (myAgent) { myAgent->removeModel(); delete myAgent; } myAgent = 0; return true; } bool DistributedSimulationDriver::onTick() { // printout to show whether or not connected at the tick level if (myConnectionState) { int numread = myConnection->drainInput(); std::cout << "." << numread; } else std::cout << "x"; // rotate the model to the left. myAgent->setRotationAngle(myRotationDegree); myRotationDegree += 0.15; if(myRotationDegree > 360.0) { myRotationDegree = 0.0; } return myConnectionState; } } }
/****************************************************************************** ** 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. ******************************************************************************/ /****************************************************************************** ** $RCSfile: DistributedSimulationPlugin4C.cxx,v $ $Revision: 1.0 $ $State: Exp $ ******************************************************************************/ #include "DistributedSimulationPlugin4C.h" #include "DistributedSimulationDriver4C.h" #include <vrvCore/DtDe.h> #include <vrvCore/DtDriverManager.h> #include <boost/bind.hpp> using namespace makVrv; using namespace makVrv::tutorialDistributedSimulation4C; 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(), "DistributedSimulationDriver4C"); // 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/DtDe.h> #include <vrvCore/DtUniqueID.h> #include <osg/PositionAttitudeTransform> #include <string> namespace makVrv { class ExampleSimulationObject { public: ExampleSimulationObject(DtDe& de, DtUniqueID id); virtual ~ExampleSimulationObject(); void loadModel(const std::string& filename); void removeModel(); void setRotationAngle(double rotationAngleInDegrees); protected: DtDe& myDe; osg::ref_ptr<osg::PositionAttitudeTransform> myPat; }; }
// /****************************************************************************** // ** Copyright (c) 2011 MAK Technologies, Inc. // ** All rights reserved. // ******************************************************************************/ // /****************************************************************************** // ** $RCSfile: ExampleSimulationObject.cxx,v $ $Revision: 1.0 $ $State: Exp $ // ******************************************************************************/ #include "ExampleSimulationObject.h" #include <vrvOsg/DtOsgRenderer.h> #include <vrvCore/DtDeSharedState.h> #include <vrvOsg/DtOsgRenderer.h> #include <vrvOsg/DtChannelSpecificGroup.h> #include <osg/Group> #include <osg/Node> #include <osgDB/ReadFile> #include <osg/ShapeDrawable> #include <osg/Geode> namespace makVrv { ExampleSimulationObject::ExampleSimulationObject( DtDe& de, DtUniqueID id ) : myDe(de) , myPat(0) { } ExampleSimulationObject::~ExampleSimulationObject() { } void ExampleSimulationObject::loadModel( const std::string& filename ) { if (!myPat) { // Add a model... osg::ref_ptr<osg::Node> modelNode = osgDB::readNodeFile(filename); // Create a transform for the model. myPat = new osg::PositionAttitudeTransform(); // Add the model to the transform. myPat->addChild(modelNode.get()); // The observer starts at 0,0,0. Move the transform, 100 units away. myPat->setPosition(osg::Vec3(0,100,0)); } // Add the model to the scene graph root for the 3D model set (set number 0), // visualizer type 0 ((DtOsgRenderer&)myDe.renderer()).addNodeToRoot(myPat.get(), DtOsgRenderer::visualizerTypeRoot( 0, 0 ) ); } void ExampleSimulationObject::removeModel() { // Remove the model from the scene graph root for the 3D model set (set number 0), // visualizer type 0 ((DtOsgRenderer&)myDe.renderer()).removeNodeFromRoot(myPat.get(), DtOsgRenderer::visualizerTypeRoot(0, 0)); } void ExampleSimulationObject::setRotationAngle( double rotationAngleInDegrees ) { myPat->setAttitude(osg::Quat( osg::DegreesToRadians(0.0), osg::Vec3d(1.0, 0.0, 0.0), osg::DegreesToRadians(0.0), osg::Vec3d(0.0, 1.0, 0.0), osg::DegreesToRadians(rotationAngleInDegrees), osg::Vec3d(0.0, 0.0, 1.0))); } }