Overview
When VR-Vantage destroys an entity (typically due to a DIS or HLA/RPR event) it does a number of things. It switches the model from its normal state to it's damaged state. It adds / starts a detonation effect (which is a particle system) that looks like an explosion, with pieces of a generic vehicle flying through the air; it makes a previously placed flame effect on the entity visible(also a particle system); and it makes a previously placed smoke plume visible (particle system).
Expected Result
Effect Plugin Result
Example details
This example loads a terrain (Makland); creates a truck entity using the DtEntityFacade class; shows how to switch between states in a model; and how to create, add and control the three different effects. It also demonstrates how to extend the DtOsgParticleSystemModel to include the ability to modify the model's color through a shader (using code from exampleCustomShaders). Control of the entity's damage state and the smoke color when displayed are bound to keyboard commands.
The method createEntityFacade() creates and add the three particle systems to the entity; one for the detonation, one for the flames, and one for the smoke plume. The smoke plume uses the extended particle system that allows the color to be changed using a shader (see further down). All the effects are made invisible.
The method toggleDamage() checks the current state, and then makes all the effects visible or invisible to create the destroyed or restored effects. The detonation effect is special since it has a specific start and end rather than just a loop; so it is restarted in toggleDamage() when the entity is destroyed. toggleDamage() also toggles the internal model switch to show its damaged state or normal state. This method is called when the 'x' key is pressed. The key binding is set up in the plugin initialization code (found in exampleEffectsPluginInit.cxx). This assumes that the model has been configured with comments on switch node that controls the damage state using the WRM Specification (Fred, you can point to that).
To add the shader from exampleCustomShader that changes the color of the smoke, the DtOsgParticleSystemModel class is extended. This class has a distributed (agent-based) interface and is agent-created; therefore a .ocdx file has to be created for it as well (using the dcgen application). This file is used to generate the related agent classes for the object.
The extended class overrides the setInstance() method in the model to be notified when the model instance is created or destroyed, and uses it to set up the shader manager from the shader example. The changeColorOverride() method is added to its distributed interface (so its defined in the .ocdx file as well) and it calls the shader manager's changeColorOverride() method. By extending the distributed model object in this manner, the color change ability will work on remote displays as well as master displays. A final changeColorOverride() method is added to the DtExampleEffectsDriver, which is bound to several different keys (r, <shift-r>, g, <shift-g>, b, and <shift-b>); it in turn calls the equivalent colorChangeOverride() method in the extended particle system.
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/exampleEffectTexturePlugin_stealth.bat (on Windows) or ./bin64/exampleEffectTexturePlugin_stealth.sh (on Linux). Use the key "x" to toggle the destroyed state and use the keys r, <shift-r>, g, <shift-g>, b, and <shift-b> to change the color of the smoke
For more information about running examples, please see Running Applications and Examples.
Example Source Files
DtExampleEffectsDriver.cxx
#include "MyParticleSystemModelAgent.hpp"
#include <vrvCore/DtParticleSystemModelAgent.hpp>
#include <vrvCore/DtSceneObjectAgent.hpp>
using namespace makVrv;
: makVrv::
DtDriver( am,
"DtExampleEffectsDriver" )
, myEntityFacade( 0 )
, myDamagedFlag( false )
, myFlamesAgent( 0 )
, mySmokePlumeAgent( 0 )
, myDetonationAgent( 0 )
{
}
{
}
{
static std::string name = "DtExampleEffectsDriver";
return name;
}
{
{
{
DtModelSemanticsMapper::States::damage, 0 );
}
else
{
DtModelSemanticsMapper::States::damage, 3 );
}
}
}
{
maklandPath += "/terrains/Makland.mtf";
std::string entityDisplayName = "M-939A Truck";
std::vector<DtUniqueID> objects;
return true;
}
{
{
myEntityFacade = 0;
}
return true;
}
{
return true;
}
{
}
{
DtSharedSettingsManager::instance( am.
de() ), elementId, modelSets,
distribute );
if ( facade3d )
{
}
return facade;
}
{
{
}
}
DtExampleEffectsDriver.h
#pragma once
#include <boost/unordered_map.hpp>
#include <matrix/vlTaitBryan.h>
#include <matrix/vlVector.h>
namespace makVrv
{
class DtDe;
class DtEntityFacade;
class DtParticleSystemModelAgent;
class MyParticleSystemModelAgent;
}
{
public:
virtual const std::string&
className()
const;
virtual void changeColorOverride(int color, float deltaChange);
protected:
protected:
typedef boost::unordered_map<int,makVrv::DtUniqueID> SceneObjectIdsByModelSet;
SceneObjectIdsByModelSet mySceneObjectIds;
bool myDamagedFlag;
makVrv::DtParticleSystemModelAgent* myFlamesAgent;
makVrv::MyParticleSystemModelAgent* mySmokePlumeAgent;
makVrv::DtParticleSystemModelAgent* myDetonationAgent;
};
exampleEffectsPlugin.h
#pragma once
#ifdef _WIN32
#ifdef EXAMPLEEFFECTSPLUGIN_EXPORTS
#define DT_DLL_EXAMPLEEFFECTSPLUGIN __declspec ( dllexport )
#else
#define DT_DLL_EXAMPLEEFFECTSPLUGIN __declspec ( dllimport )
#endif
#else
#define DT_DLL_EXAMPLEEFFECTSPLUGIN
#endif
exampleEffectsPluginInit.cxx
#include <boost/ref.hpp>
{
return true;
}
namespace makVrv
{
namespace vrvExampleEffectsPlugin
{
void installDriverAndKeyBindings(DtDe& de)
{
&installDriverAndKeyBindings, boost::ref(de) ));
de.agentManager() );
de.driverManager().addDriver( driver );
de.driverManager().startDriver( driver );
DtInputDriver& inputDriver = de.driverManager().inputDriver();
keyMapManager.addKeyFunction(
"Toggle Damage",
boost::bind(
keyMapManager.addKeyFunction(
"Inc Green",
boost::bind(
keyMapManager.addKeyFunction(
"Dec Green",
boost::bind(
DtKeyMap* obsFrame = keyMapManager.findKeyMap( "Observer Frame" );
if ( obsFrame )
{
}
DtQtDeMainWindow& mainWindow = dynamic_cast<DtQtDeMainWindow&>(mw);
mainWindow.hideStartupDialog();
}
{
if (de.isInMasterMode())
{
&installDriverAndKeyBindings, boost::ref(de) ));
}
}
}
}
exampleEffectsPluginInit.h
#pragma once
#define DT_DE_PLUGIN_EXPORT_MACRO DT_DLL_EXAMPLEEFFECTSPLUGIN
namespace makVrv
{
class DtDe;
namespace vrvExampleEffectsPlugin
{
}
}
MyParticleSystemModel.cxx
#include <osg/Uniform>
namespace makVrv
{
: myDe(de)
, myModelStateSet(ss)
{
myColorToAdd = ss->getOrCreateUniform("colorToAdd", osg::Uniform::FLOAT_VEC3);
myColorToAdd->set(osg::Vec3(0.0f,0.0f,0.0f));
myVirtualProgram = osgEarth::VirtualProgram::getOrCreate(ss);
myVirtualProgram->setFunction("customLightingFunction",
"uniform vec3 colorToAdd;\
void customLightingFunction(inout vec4 color) \
{\
color.rgb += colorToAdd;\
}\
",
osgEarth::ShaderComp::LOCATION_FRAGMENT_LIGHTING,
NULL,
100.0
);
}
MyShaderManager::~MyShaderManager()
{
}
void MyShaderManager::changeColorOverride(int color, float deltaChange)
{
osg::Vec3 curVal;
myColorToAdd->get(curVal);
switch(color)
{
case 0:
curVal.x() += deltaChange;
curVal.x() = curVal.x() < -1.0 ? -1.0 : curVal.x();
curVal.x() = curVal.x() > 1.0 ? 1.0 : curVal.x();
break;
case 1:
curVal.y() += deltaChange;
curVal.y() = curVal.y() < -1.0 ? -1.0 : curVal.y();
curVal.y() = curVal.y() > 1.0 ? 1.0 : curVal.y();
break;
case 2:
curVal.z() += deltaChange;
curVal.z() = curVal.z() < -1.0 ? -1.0 : curVal.z();
curVal.z() = curVal.z() > 1.0 ? 1.0 : curVal.z();
break;
default:
break;
}
myColorToAdd->set(curVal);
}
MyParticleSystemModel::MyParticleSystemModel(DtDe& de,
DtUniqueID&
id)
: DtOsgParticleSystemModel(de, id)
, myShaderManager( 0 )
{
}
MyParticleSystemModel::~MyParticleSystemModel()
{
delete myShaderManager;
myShaderManager = 0;
}
void MyParticleSystemModel::setModelInstance(DtModelInstance* instance )
{
DtOsgParticleSystemModel::setModelInstance( instance );
if ( instance )
{
DtOsgModelInstance* mi = dynamic_cast<DtOsgModelInstance*>( instance );
if(mi && mi->rootNode())
{
myShaderManager = new MyShaderManager( myDe, mi->rootNode()->getOrCreateStateSet() );
}
}
else
{
delete myShaderManager;
myShaderManager = 0;
}
}
void MyParticleSystemModel::changeColorOverride( int color, float deltaChange )
{
if ( myShaderManager )
{
myShaderManager->changeColorOverride( color, deltaChange );
}
}
}
MyParticleSystemModel.h
#pragma once
#include <osgEarth/VirtualProgram>
#include <osg/ref_ptr>
namespace osg
{
class StateSet;
class Uniform;
}
namespace makVrv
{
class DtDe;
{
public:
MyShaderManager(DtDe& de, osg::StateSet *ss);
virtual ~MyShaderManager();
virtual void changeColorOverride(int color, float deltaChange);
protected:
DtDe& myDe;
osg::ref_ptr<osg::StateSet> myModelStateSet;
osg::ref_ptr<osg::Uniform> myColorToAdd;
osg::ref_ptr<osgEarth::VirtualProgram> myVirtualProgram;
};
: public DtOsgParticleSystemModel
{
public:
virtual ~MyParticleSystemModel();
virtual void setModelInstance(DtModelInstance* modelInstance );
virtual void changeColorOverride( int color, float deltaChange );
protected:
MyShaderManager* myShaderManager;
};
}
[<< Examples] [Home] [Top of Page]