VR-Vantage API Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
The Distributed Simulation Tutorial - Add an Entity Using a Custom Agent

Introduction to Project 4C

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.

Examining the files that make up the project

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.

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:

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.

Testing the plugin

Invoke either the tutorialDistributedSimulation4Cd.bat or tutorialDistributedSimulation4C.sh script file to start the VR-Vantage Stealth application. Follow these instructions to test the plugin:

  1. Choose File > View > Drivers Panel.
  2. Select the driver named "DistributedSimulationDriver4C".
  3. Click on the Start button.
  4. In the Stealth window, you will see that a cow image has been added in the center of the scene, and is rotating to the left. You may need to dismiss the "Choose a Terrain" dialog in order to see this, but make sure to do so by clicking on the X at the top right, rather than on the OK, or just choose "Do not load any terrain" and then click OK.
  5. In Stealth, make sure the same driver is selected in the Drivers Panel, and click the Stop button.
  6. You will notice that the image of the cow is no longer present in the center of the Stealth window.
  7. Continually clicking the Start and Stop button will keep starting and stopping the driver, giving these same results in the console window.

[<< Add an Entity Using an Existing VR-Vantage Agent] [Conclusion >>]


Project Files

DistributedSimulationDriver4C.h

/******************************************************************************
** Copyright (c) 2011 MAK Technologies, Inc.
** All rights reserved.
******************************************************************************/
#pragma once
class DtExerciseConn;
namespace makVrv
{
class ExampleSimulationObjectAgent;
namespace tutorialDistributedSimulation4C
{
class DistributedSimulationDriver : public DtDriver
{
public:
virtual const std::string& className() const;
protected:
virtual bool onStart();
virtual bool onStop();
virtual bool onTick();
protected:
DtExerciseConn* myConnection;
ExampleSimulationObjectAgent* myAgent;
};
}
}

DistributedSimulationDriver4C.cxx

// /******************************************************************************
// ** Copyright (c) 2014 MAK Technologies, Inc.
// ** All rights reserved.
// ******************************************************************************/
#define DtDIS 1
#include <vrvCore/DtDe.h>
#include <vl/exerciseConnInitializer.h>
#include <vl/exerciseConn.h>
#include <iostream>
namespace makVrv
{
namespace tutorialDistributedSimulation4C
{
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;
}
}
}

DistributedSimulationPlugin4C.h

/******************************************************************************
** 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))
namespace makVrv { class DtDe; }
// Work function for the plugin initialization
void init(makVrv::DtDe& de);
// Callback to create the stateViewDriver

DistributedSimulationPlugin4C.cxx

/******************************************************************************
** Copyright (c) 2011 MAK Technologies, Inc.
** All rights reserved.
******************************************************************************/
/******************************************************************************
** $RCSfile: DistributedSimulationPlugin4C.cxx,v $ $Revision: 1.0 $ $State: Exp $
******************************************************************************/
#include <vrvCore/DtDe.h>
#include <boost/bind.hpp>
using namespace makVrv;
using namespace makVrv::tutorialDistributedSimulation4C;
{
// We're done with the signal, so disconnect from it
// 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)
// 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.
}
}
{
// Setup the plugin. Normally, the init function and functionality
// should be in its own library.
init(*de);
return true;
}

ExampleSimulationObject.h

/******************************************************************************
** Copyright (c) 2011 MAK Technologies, Inc.
** All rights reserved.
******************************************************************************/
#pragma once
#include <vrvCore/DtDe.h>
#include <osg/PositionAttitudeTransform>
#include <string>
namespace makVrv
{
class ExampleSimulationObject
{
public:
void loadModel(const std::string& filename);
void removeModel();
void setRotationAngle(double rotationAngleInDegrees);
protected:
DtDe& myDe;
osg::ref_ptr<osg::PositionAttitudeTransform> myPat;
};
}

ExampleSimulationObject.cxx

// /******************************************************************************
// ** Copyright (c) 2011 MAK Technologies, Inc.
// ** All rights reserved.
// ******************************************************************************/
// /******************************************************************************
// ** $RCSfile: ExampleSimulationObject.cxx,v $ $Revision: 1.0 $ $State: Exp $
// ******************************************************************************/
#include <osg/Group>
#include <osg/Node>
#include <osgDB/ReadFile>
#include <osg/ShapeDrawable>
#include <osg/Geode>
namespace makVrv
{
: 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)));
}
}


Copyright © 2005-2013 VT MÄK. All Rights Reserved (www.mak.com)