VR-Vantage 2.4 API Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
The Distributed Simulation Tutorial - Adding an Entity Using VR-Link

Introduction to Project 4A

Project 4A in the Distributed Simulation tutorial takes a look at how to add an entity to the scene directly using VR-Link. We will add an image of a cow to the scene when the driver is started, and remove the image when the driver is stopped. The cow will be made to rotate to the left when it is visible on the screen.

Examining the files that make up the project

For this project, all files from Project 2A will be reused. No new files will be needed. All changes, other than filenames, will be made in the DistributedSimulationDriver class files.

Adding an Entity to the Scene

To add an entity to the scene, we will need to add both an OSG reference pointer of type osg::PositionAttitudeTransform and the necessary header for that type to the top of the driver header file.

#include <osg/PositionAttitudeTransform>

osg::ref_ptr<osg::PositionAttitudeTransform> myPat;

The class definition file will also need some headers included to handle the reading of a file into an OSG node as well as the rendering of that node into the scene.

#include <osg/Group>
#include <osg/Node>
#include <osgDB/ReadFile>

The new onStart() function looks as follows:

{
std::cout << "DistributedSimulationDriver::onStart(): " << std::endl;
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 reading the osg file, creating a transform and adding the cow to it,
// moving the transform 100 units away from the observer's starting point (0,0,0), then adding to root.
osg::ref_ptr<osg::Node> cowNode = osgDB::readNodeFile("../data/Lifeforms/Animals/cow.osg");
if (!myPat)
{
myPat = new osg::PositionAttitudeTransform();
myPat->addChild(cowNode.get());
myPat->setPosition(osg::Vec3(0,100,0));
}
// Get the top of the scene graph (the environment root node) from the renderer
// and put the cow node under it
((DtOsgRenderer&)agentManager().de().renderer()).addNodeToRoot( myPat.get(),
((DtOsgRenderer&)agentManager().de().renderer()).environmentRoot());
return myConnectionState;
}

The difference here is that we add code to read in and set the scene position for an image of a cow. We use an osg::PositionAttitudeTransform object to handle the storing of the image data.

// Add a cow to the root node by reading the osg file, creating a transform and adding the cow to it,
// moving the transform 100 units away from the observer's starting point (0,0,0), then adding to root.
osg::ref_ptr<osg::Node> cowNode = osgDB::readNodeFile("../data/Lifeforms/Animals/cow.osg");
if (!myPat)
{
myPat = new osg::PositionAttitudeTransform();
myPat->addChild(cowNode.get());
myPat->setPosition(osg::Vec3(0,100,0));
}

We then use the agent manager object, which was passed in when the simulation driver was constructed, in order to get access to the display engine's renderer and add this new node to the root of the scene.

// Get the top of the scene graph (the environment root node) from the renderer
// and put the cow node under it
((DtOsgRenderer&)agentManager().de().renderer()).addNodeToRoot( myPat.get(),
((DtOsgRenderer&)agentManager().de().renderer()).environmentRoot());

The new onStop() function now needs to remove the node from the scene. Otherwise, if the driver is stopped, the node will continue to be an inactive part of the scene.

{
// NOTE: breakdown code goes here. Return false on bad status.
std::cout << "DistributedSimulationDriver::onStop(): " << std::endl;
// If desired, can remove the cow from the scene root as shown.
((DtOsgRenderer&)agentManager().de().renderer()).removeNodeFromRoot( myPat.get(),
((DtOsgRenderer&)agentManager().de().renderer()).environmentRoot());
delete myConnection;
myConnection = 0;
return true;
}

Testing the plugin

Invoke either the tutorialDistributedSimulation4Ad.bat or tutorialDistributedSimulation4A.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 "DistributedSimulationDriver4A".
  3. Click on the Start button.
  4. For this and all subsequent projects the output to the console window is not important. But if you look you will see in the console window that the text "DistributedSimulationDriver::onStart():" has printed, and on the subsequent line, a series of dots is now continually being printed. More importantly, going back to Stealth, you will see that a cow image has been added in the center of the scene, and it 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. Again, less importantly, you will see in the console window that the dots, byte counts, and detonations are no longer being printed, and that the text "DistributedSimulationDriver::onStop():" has been printed on the subsequent line. More importantly, 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 Existence Listener] [Add an Entity Using an Existing VR-Vantage Agent >>]


Project Files

DistributedSimulationDriver4A.h

/******************************************************************************
** Copyright (c) 2011 MAK Technologies, Inc.
** All rights reserved.
******************************************************************************/
#pragma once
#include <osg/PositionAttitudeTransform>
class DtExerciseConn;
namespace makVrv
{
namespace tutorialDistributedSimulation4A
{
class DistributedSimulationDriver : public DtDriver
{
public:
virtual const std::string& className() const;
protected:
virtual bool onStart();
virtual bool onStop();
virtual bool onTick();
protected:
osg::ref_ptr<osg::PositionAttitudeTransform> myPat;
DtExerciseConn* myConnection;
};
}
}

DistributedSimulationDriver4A.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 <osg/Group>
#include <osg/Node>
#include <osgDB/ReadFile>
#include <iostream>
namespace makVrv
{
namespace tutorialDistributedSimulation4A
{
DtAgentManager& agentManager, const std::string& instanceName)
: DtDriver(agentManager, instanceName)
, myConnection(0)
, myConnectionState(0)
, myPat(0)
, myRotationDegree(0)
{
}
DistributedSimulationDriver::~DistributedSimulationDriver(void)
{
}
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;
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 reading the osg file, creating a transform and adding the cow to it,
// moving the transform 100 units away from the observer's starting point (0,0,0), then adding to root.
osg::ref_ptr<osg::Node> cowNode = osgDB::readNodeFile("../data/Lifeforms/Animals/cow.osg");
if (!myPat)
{
myPat = new osg::PositionAttitudeTransform();
myPat->addChild(cowNode.get());
myPat->setPosition(osg::Vec3(0,100,0));
}
// Get the top of the scene graph (the environment root node) from the renderer
// and put the cow node under it
((DtOsgRenderer&)agentManager().de().renderer()).addNodeToRoot( myPat.get(),
((DtOsgRenderer&)agentManager().de().renderer()).environmentRoot());
return myConnectionState;
}
bool DistributedSimulationDriver::onStop()
{
// NOTE: breakdown code goes here. Return false on bad status.
std::cout << "DistributedSimulationDriver::onStop(): " << std::endl;
// If desired, can remove the cow from the scene root as shown.
((DtOsgRenderer&)agentManager().de().renderer()).removeNodeFromRoot( myPat.get(),
((DtOsgRenderer&)agentManager().de().renderer()).environmentRoot());
delete myConnection;
myConnection = 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";
if (myPat)
{
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(myRotationDegree), osg::Vec3d(0.0, 0.0, 1.0)));
myRotationDegree += 0.15;
if(myRotationDegree > 360.0)
{
myRotationDegree = 0.0;
}
}
return myConnectionState;
}
}
}

DistributedSimulationPlugin4A.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; }
// Callback to create the stateViewDriver

DistributedSimulationPlugin4A.cxx

/******************************************************************************
** Copyright (c) 2011 MAK Technologies, Inc.
** All rights reserved.
******************************************************************************/
#include <vrvCore/DtDe.h>
#include <boost/bind.hpp>
using namespace makVrv;
using namespace makVrv::tutorialDistributedSimulation4A;
{
// 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(), "DistributedSimulationDriver4A");
// 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;
}


Copyright © 2005-2018 VT MAK. All Rights Reserved (www.mak.com)