Overview
This example is a plugin that creates a new driver. This driver reads a CSV file (clouds.csv), then dynamically places clouds in the scene.
Expected Result
TODO
Example details
The CSV file contains information about cloud layers and wind volumes. This example is meant to be used in flat earth projections only. The cloud layer coordinates are in database coordinates.
At each tick, the driver moves each cloud layer based on the wind volumes at its altitude.
Wind volumes are stored as DtWind classes and are declared in DtCloudDriverCommon.h. A wind volume consists of a direction in degrees from north to east, a minimum and maximum altitude, and a speed in meters per second.
#pragma once
#include <vector>
namespace makVrv
{
namespace vrvExampleCloudDriver
{
class DtWind
{
public:
double minAltitude = 0,
double maxAltitude = 100000,
double speedInMps = 100);
};
}
}
The driver's onStart() method does two things: First it connects to the DtEnvironmentSignaler's signal_cloudLayerAdded and signalCloudLayerToBeDestroyed signals. These are used to keep track of the current cloud layers in the scene.
DtEnvironmentSignaler::instance(myAgentManager.de()).signal_cloudLayerAdded.connect(
boost::bind(&DtCloudDriver::on_cloudLayerAdded,
this,_1));
DtEnvironmentSignaler::instance(myAgentManager.de()).signal_cloudLayerToBeDestroyed.connect(
boost::bind(&DtCloudDriver::on_cloudLayerDestroyed,
this,_1));
Then it parses the CSV file first and then creates the cloud layers and wind volumes.
DtCloudParser parser;
if (!parser.parseFile("../examples/exampleCloudDriver/clouds.csv"))
{
DtWarn << "Error parsing cloud file clouds.csv" << std::endl;
}
else
{
makeClouds(parser);
makeWind(parser);
In the driver's onTick() method, the cloud layer list is iterated over, and for each wind volume, if the cloud layer's altitude falls within the wind volume, it is moved the appropriate distance.
for (int index = 0; index < myCloudLayers.size(); ++index)
{
bool changed = false;
double cloudAltitude = cloud.
position()[2];
BOOST_FOREACH(DtWind& wind, myWindList)
{
if (wind.withinAltitude(cloudAltitude))
{
double eastChange = wind.eastVel * dt;
double northChange = wind.northVel * dt;
changed = true;
The plugin initialization is performed in exampleCloudDriverPluginInit.cxx. This consists of the exported function initDeModule(), and a couple of other helper functions. The init() function connects to the display engine's signal_postInitialize signal. After the DtDe has been initialized, installDriver() will be called, which will install the DtCloudDriver into the driver manager, and set it to automatically start.
Building the Example
VR-Vantage includes pre-built versions of the example plug-in. To build it yourself, follow the instructions at Building VR-Vantage Examples, Applications, and Plug-ins.
Running the Example
This example is a plug-in. You can run it by running ./bin64/exampleCloudDriverPlugin_stealth.bat (on Windows) or ./bin64/exampleCloudDriverPlugin_stealth.sh (on Linux). For more information about running examples, please see Running Applications and Examples.
Example Source Files
DtCloudDriver.cxx
#include <matrix/vlMath.h>
#include <math.h>
#include <algorithm>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <vlutil/vlPrint.h>
using namespace makVrv;
namespace makVrv
{
namespace vrvExampleCloudDriver
{
: makVrv::
DtDriver(am,
"Example Cloud Driver")
, myLastUpdate(0)
{
}
DtCloudDriver::~DtCloudDriver()
{
}
const std::string& DtCloudDriver::className() const
{
static std::string name = "Cloud Driver";
return name;
}
bool DtCloudDriver::onStart()
{
DtEnvironmentSignaler::instance(myAgentManager.de()).signal_cloudLayerAdded.connect(
boost::bind(&DtCloudDriver::on_cloudLayerAdded,
this,_1));
DtEnvironmentSignaler::instance(myAgentManager.de()).signal_cloudLayerToBeDestroyed.connect(
boost::bind(&DtCloudDriver::on_cloudLayerDestroyed,
this,_1));
DtCloudParser parser;
if (!parser.parseFile("../examples/exampleCloudDriver/clouds.csv"))
{
DtWarn << "Error parsing cloud file clouds.csv" << std::endl;
}
else
{
makeClouds(parser);
makeWind(parser);
}
myLastUpdate = myAgentManager.de().simulationTime();
return true;
}
bool DtCloudDriver::onStop()
{
DtEnvironmentSignaler::instance(myAgentManager.de()).signal_cloudLayerAdded.disconnect(
boost::bind(&DtCloudDriver::on_cloudLayerAdded,
this,_1));
DtEnvironmentSignaler::instance(myAgentManager.de()).signal_cloudLayerToBeDestroyed.disconnect(
boost::bind(&DtCloudDriver::on_cloudLayerDestroyed,
this,_1));
return true;
}
bool DtCloudDriver::onTick()
{
if(myAgentManager.de().sharedState().coordinateSystem().isGeocentric())
{
return true;
}
double curTime = myAgentManager.de().simulationTime();
double dt = curTime - myLastUpdate;
myLastUpdate = curTime;
for (int index = 0; index < myCloudLayers.size(); ++index)
{
bool changed = false;
double cloudAltitude = cloud.
position()[2];
BOOST_FOREACH(DtWind& wind, myWindList)
{
if (wind.withinAltitude(cloudAltitude))
{
double eastChange = wind.eastVel * dt;
double northChange = wind.northVel * dt;
changed = true;
}
}
if (changed)
{
myAgentManager.de().scene().environment().
setCloudLayerPosition(index,
}
}
return true;
}
void DtCloudDriver::makeClouds(const DtCloudParser& parser)
{
myAgentManager.de().scene().environment().getRecord(envRecord);
envRecord.cloudLayers().clear();
myCloudLayers.clear();
std::copy(parser.cloudLayers().begin(),
parser.cloudLayers().end(),
back_inserter(envRecord.cloudLayers()));
myAgentManager.de().scene().environment().setFromRecord(envRecord);
}
void DtCloudDriver::makeWind(const DtCloudParser& parser)
{
myWindList.clear();
std::copy(parser.windList().begin(),
parser.windList().end(),
back_inserter(myWindList));
}
void DtCloudDriver::on_cloudLayerDestroyed(int index)
{
DtInfo << "[DESTROYED] Cloud layer " << index << std::endl;
if (index < myCloudLayers.size())
{
myCloudLayers.erase(myCloudLayers.begin() + index);
}
}
void DtCloudDriver::on_cloudLayerAdded(int index)
{
DtInfo << "[ADDED] Cloud layer " << index << std::endl;
if (myCloudLayers.size() == index)
{
myAgentManager.de().scene().environment().getRecord(envRecord);
myCloudLayers.push_back(envRecord.cloudLayers()[index]);
}
}
}
}
DtCloudDriver.h
#pragma once
namespace makVrv
{
class DtDe;
namespace vrvExampleCloudDriver
{
class DtCloudParser;
{
public:
DtCloudDriver(DtAgentManager& am);
virtual ~DtCloudDriver();
virtual const std::string& className() const;
protected:
virtual bool onStart();
virtual bool onStop();
virtual bool onTick();
void makeClouds(const DtCloudParser& parser);
void makeWind(const DtCloudParser& parser);
void on_cloudLayerAdded(int index);
void on_cloudLayerDestroyed(int index);
protected:
double myLastUpdate;
};
}
}
DtCloudDriverCommon.cxx
#include <matrix/vlMath.h>
#include <math.h>
namespace makVrv
{
namespace vrvExampleCloudDriver
{
DtWind::DtWind(
double directionN2E,
double minAltitude,
double maxAltitude,
double speedInMps) :
dirNtoE(directionN2E)
, minAlt(minAltitude)
, maxAlt(maxAltitude)
, speed(speedInMps)
{
eastVel = cos(DtDeg2Rad(dirNtoE)) * speed;
northVel = sin(DtDeg2Rad(dirNtoE)) * speed;
}
bool DtWind::withinAltitude(double alt) const
{
return alt >= minAlt && alt <= maxAlt;
}
}
}
DtCloudDriverCommon.h
#pragma once
#include <vector>
namespace makVrv
{
namespace vrvExampleCloudDriver
{
class DtWind
{
public:
double minAltitude = 0,
double maxAltitude = 100000,
double speedInMps = 100);
};
}
}
DtCloudParser.cxx
#include <vlutil/vlPrint.h>
#include <fstream>
using namespace makVrv;
namespace makVrv
{
namespace vrvExampleCloudDriver
{
DtCloudParser::DtCloudParser()
{
}
DtCloudParser::~DtCloudParser()
{
}
bool DtCloudParser::parseFile(std::string fn)
{
std::ifstream f(fn.c_str());
char buf[1024];
if (!f)
{
return false;
}
while (f.good())
{
f.getline(buf, 1024);
parseLine(buf);
}
return true;
}
void DtCloudParser::parseLine(std::string line)
{
if (line.length() == 0 || line[0] == ';')
{
return;
}
const std::string delim(", ");
std::string::size_type idx = line.find_first_of(delim);
if (idx == std::string::npos)
{
return;
}
std::string type = line.substr(0, idx);
line.erase(0, idx);
if (type == "CLOUD")
{
parseCloud(line);
}
else if (type == "WIND")
{
parseWind(line);
}
}
void DtCloudParser::parseCloud(std::string& line)
{
std::vector<std::string> tokens;
tokenize(line, tokens);
if (tokens.size() == 0)
{
return;
}
rec.
setPosition(tokens.size() > 1 ? atof(tokens[1].c_str()) : 0.0,
tokens.size() > 2 ? atof(tokens[2].c_str()) : 0.0,
tokens.size() > 3 ? atof(tokens[3].c_str()) : 0.0);
rec.
setWidth(tokens.size() > 4 ? atof(tokens[4].c_str()) : 0.0);
rec.
setLength(tokens.size() > 5 ? atof(tokens[5].c_str()) : 0.0);
rec.
setThickness(tokens.size() > 6 ? atof(tokens[6].c_str()) : 0.0);
rec.
setDensity(tokens.size() > 7 ? atof(tokens[7].c_str()) : 0.0);
myCloudLayers.push_back(rec);
}
void DtCloudParser::parseWind(std::string& line)
{
std::vector<std::string> tokens;
tokenize(line, tokens);
if (tokens.size() < 4)
{
return;
}
double direction = atof(tokens[0].c_str());
double minAlt = atof(tokens[1].c_str());
double maxAlt = atof(tokens[2].c_str());
double speed = atof(tokens[3].c_str());
myWindList.push_back(DtWind(
direction, minAlt, maxAlt, speed));
}
void DtCloudParser::tokenize(const std::string& line,
std::vector<std::string>& tokens)
{
const std::string delim(", ");
std::string::size_type begIdx, endIdx;
std::string token;
begIdx = line.find_first_not_of(delim);
while (begIdx != std::string::npos)
{
endIdx = line.find_first_of(delim, begIdx);
if (endIdx == std::string::npos)
{
endIdx = line.length();
}
token = line.substr(begIdx, endIdx - begIdx);
tokens.push_back(token);
begIdx = line.find_first_not_of(delim, endIdx);
}
}
DtCloudParser::cloudLayers() const
{
return myCloudLayers;
}
const WindList& DtCloudParser::windList()
const
{
return myWindList;
}
}
}
DtCloudParser.h
#pragma once
namespace makVrv
{
namespace vrvExampleCloudDriver
{
class DtCloudParser
{
public:
protected:
void tokenize(
const std::string& line, std::vector<std::string>& list);
};
}
}
exampleCloudDriverPluginInit.cxx
#include <boost/bind.hpp>
{
{
return true;
}
return false;
}
namespace makVrv
{
namespace vrvExampleCloudDriver
{
{
if (de.isInMasterMode())
{
}
}
{
DtCloudDriver* driver = new DtCloudDriver( de.agentManager());
driver->setIsUserControllable(false);
de.driverManager().addDriver(driver);
}
}
}
exampleCloudDriverPluginInit.h
#ifndef exampleCloudDriverPluginInit_H_
#define exampleCloudDriverPluginInit_H_
#define DT_DE_PLUGIN_EXPORT_MACRO DT_DLL_EXAMPLECLOUDDRIVER
namespace makVrv
{
class DtDe;
namespace vrvExampleCloudDriver
{
}
}
#endif
[<< Examples] [Home] [Top of Page]