Overview
Show how fire a projectile (a Tank!) using the F key and create an explosion
Expected Result
Projectile over ground Result
Projectile over water Result
Example details
This example shows how to fire a projectile from the observer view point. It will also detect if the impact is on ground or water and display the appropriate explosion (smoke or water splash). Currently the projectile type is amplified by using a tank! The commented code is also present to use a more realistic projectile.
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/exampleProjectile_stealth.bat (on Windows) or ./bin64/exampleProjectile_stealth (on Linux). Press 'f' to fire the projectile. For more information about running examples, please see Running Applications and Examples.
Example Source Files
DtExampleProjectile.cxx
#include <vrvCore/DtSceneObjectAgent.hpp>
#include <vrvCore/DtParticleSystemModelAgent.hpp>
#include <vrvCore/DtWaterImpactModelAgent.hpp>
#include <vrvCore/DtOverlaySegmentedLineModelAgent.hpp>
namespace makVrv
{
: makVrv::DtDriver( am, "DtExampleProjectile" )
, myObserverShooter( 0 )
{
}
DtExampleProjectile::~DtExampleProjectile()
{
DtExampleProjectile::onStop();
}
const std::string& DtExampleProjectile::className() const
{
static std::string name = "DtExampleProjectile";
return name;
}
bool DtExampleProjectile::onStart()
{
DtScene& sceneDriver = myAgentManager.de().scene();
std::string maklandPath = myAgentManager.de().dePathConfiguration().userPath();
maklandPath += "/terrains/Makland.mtf";
if ( sceneDriver.terrainFileName() != maklandPath )
{
}
myObserverShooter = new DtObserverShooter( myAgentManager.de() );
myObserverShooter->setModelDefinitionName( "TrackedM1Abrams" );
myObserverShooter->setProjectileSpeed( 100. );
myObserverShooter->setIntersectionCallback(
boost::bind( &DtExampleProjectile::processIntersection,
this, _1, _2 ) );
return true;
}
bool DtExampleProjectile::onStop()
{
if ( myObserverShooter )
{
delete myObserverShooter;
myObserverShooter = 0;
}
DetonationList::const_iterator detIter = myDetonationObjects.begin();
DetonationList::const_iterator endDetIter = myDetonationObjects.end();
for( ; detIter != endDetIter; ++detIter )
{
if ( ! myAgentManager.de().destructing() )
{
DetonationData detonation = *detIter;
detonation.detonationObject->removeModel( detonation.detonationModel );
delete detonation.detonationModel;
delete detonation.detonationObject;
}
}
myDetonationObjects.clear();
SplashList::const_iterator splashIter = mySplashObjects.begin();
SplashList::const_iterator endSplashIter = mySplashObjects.end();
for( ; splashIter != endSplashIter; ++splashIter )
{
if ( ! myAgentManager.de().destructing() )
{
SplashData splash = *splashIter;
splash.splashObject->removeModel( splash.splashModel );
delete splash.splashModel;
delete splash.splashObject;
}
}
mySplashObjects.clear();
return true;
}
bool DtExampleProjectile::onTick()
{
if ( myObserverShooter )
{
myObserverShooter->tick( myAgentManager.de().simulationTime() );
}
return true;
}
void DtExampleProjectile::slot_displayEngineAdded( const DtDeRecord& igRecord )
{
stop();
start();
}
void DtExampleProjectile::processIntersection( const DtIntersectorResult& isectResult, double speed )
{
std::cout << "Hit: "<< isectResult.x << " " << isectResult.y << " " << isectResult.z;
if ( isectResult.dynamicOcean )
{
createSplash(
DtVector( isectResult.x, isectResult.y, isectResult.z ), speed );
std::cout << " Type: " << "Ocean" << std::endl;
}
else
{
DtElementEntry* entry = myAgentManager.de().dataBank().elementData().findElement( isectResult.id );
if ( entry )
{
switch( entry->type() )
{
createDetonation(
DtVector( isectResult.x, isectResult.y, isectResult.z ) );
std::cout << " Type: " << "Entity" << std::endl;
break;
createDetonation(
DtVector( isectResult.x, isectResult.y, isectResult.z ) );
std::cout << " Type: " << "Prop" << std::endl;
break;
case DtElementEntry::TerrainPatch:
createDetonation(
DtVector( isectResult.x, isectResult.y, isectResult.z ) );
std::cout << " Type: " << "Terrain" << std::endl;
break;
default:
std::cout << " Type: " << entry->type() << std::endl;
break;
}
}
else
{
std::cout << " Type: Unregistered Object" << std::endl;
}
}
}
void DtExampleProjectile::createDetonation(
const DtVector& position )
{
DtSceneObjectAgent* sceneObj = DtSceneObjectAgent::create( myAgentManager );
sceneObj->setModelSet( DtObserverMode::ModelSet3dModels );
sceneObj->setPosition( 0,
DtVector( position ) );
DtParticleSystemModelAgent* detonation = DtParticleSystemModelAgent::create( myAgentManager );
sceneObj->addModel( detonation, 0 );
detonation->setModelDefinition( "DetonationBombBlastLarge" );
DetonationData data;
data.detonationObject = sceneObj;
data.detonationModel = detonation;
data.timeOfOccurence = myAgentManager.de().simulationTime();
myDetonationObjects.push_back( data );
}
void DtExampleProjectile::createSplash(
const DtVector& position,
double speed )
{
DtSceneObjectAgent* sceneObj = DtSceneObjectAgent::create( myAgentManager );
sceneObj->setModelSet( DtObserverMode::ModelSet3dModels );
DtWaterImpactModelAgent* splash = DtWaterImpactModelAgent::create( myAgentManager );
sceneObj->addModel( splash, 0 );
splash->setModelDefinition( "DetonationWaterImpactExtraLarge" );
splash->setImpactLocation( position );
splash->setMunitionSpeed( speed );
SplashData data;
data.splashObject = sceneObj;
data.splashModel = splash;
data.timeOfOccurence = myAgentManager.de().simulationTime();
mySplashObjects.push_back( data );
}
}
DtExampleProjectile.h
#pragma once
#include <matrix/vlVector.h>
#include <string>
#include <list>
namespace makVrv
{
class DtObserverShooter;
class DtIntersectorResult;
class DtSceneObjectAgent;
class DtParticleSystemModelAgent;
class DtWaterImpactModelAgent;
{
public:
virtual ~DtExampleProjectile();
virtual const std::string& className() const;
protected:
virtual bool onStart();
virtual bool onStop();
virtual bool onTick();
virtual void processIntersection( const DtIntersectorResult& isect, double speed );
virtual void createDetonation(
const DtVector& position );
virtual void createSplash(
const DtVector& position,
double speed );
protected:
DtObserverShooter* myObserverShooter;
struct DetonationData
{
DtSceneObjectAgent* detonationObject;
DtParticleSystemModelAgent* detonationModel;
double timeOfOccurence;
};
struct SplashData
{
DtSceneObjectAgent* splashObject;
DtWaterImpactModelAgent* splashModel;
double timeOfOccurence;
};
typedef std::list<DetonationData> DetonationList;
typedef std::list<SplashData> SplashList;
DetonationList myDetonationObjects;
SplashList mySplashObjects;
};
}
DtObserverShooter.cxx
#include <osg/Matrixd>
namespace makVrv
{
: myDe( de )
, myModelDefinitionName( "" )
, myProjectileSpeed( 100. )
, myExpiredProjectiles()
, myIntersectionCallback( (DtProjectile::IntersectionCallback) 0 )
{
DtInputDriver& inputDriver = de.driverManager().inputDriver();
DtKeyMapManager& keyMapManager = DtKeyMapManager::instance(de);
keyMapManager.addKeyFunction(
"Fire Projectile",
boost::bind(
&DtObserverShooter::fireProjectile, this), DtKeyMapManager::Miscellaneous);
DtKeyMap* obsFrame = keyMapManager.findKeyMap( "Observer Frame" );
if ( obsFrame )
{
inputDriver.
addKeyBinding( obsFrame, DtKeyState::KEY_F,
"Fire Projectile" ,
DtKeyState::NO_MODIFIER, true);
}
}
DtObserverShooter::~DtObserverShooter()
{
ProjectileMap::iterator curIter = myProjectiles.begin();
ProjectileMap::iterator endIter = myProjectiles.end();
for( ; curIter != endIter; ++curIter )
{
delete curIter->second;
}
myProjectiles.clear();
DtKeyMapManager& keyMapManager = DtKeyMapManager::instance( myDe );
keyMapManager.removeKeyFunction( "Fire Projectile" );
}
void DtObserverShooter::fireProjectile()
{
DtObserver* obs = myDe.driverManager().inputDriver().findObserverByName( "Observer 1" );
if ( obs )
{
double yaw, pitch, roll;
obs->getOrientation( yaw, pitch, roll );
DtTaitBryan orientation( -yaw, pitch, roll );
DtVector direction = obs->observerCameraFront();
DtProjectile* proj = new DtProjectile( myDe, start, orientation, myProjectileSpeed, direction,
myModelDefinitionName, myIntersectionCallback );
myProjectiles[proj->id()] = proj;
}
}
void DtObserverShooter::setModelDefinitionName( const std::string& modelDefinitionName )
{
myModelDefinitionName = modelDefinitionName;
}
void DtObserverShooter::setProjectileSpeed( double speed )
{
myProjectileSpeed = speed;
}
void DtObserverShooter::setIntersectionCallback( DtProjectile::IntersectionCallback callback )
{
myIntersectionCallback = callback;
}
void DtObserverShooter::removeExpiredProjectiles()
{
std::list<ProjectileMap::iterator> removeList;
ProjectileIDList::iterator curIter = myExpiredProjectiles.begin();
ProjectileIDList::iterator endIter = myExpiredProjectiles.end();
for( ; curIter != endIter; ++curIter )
{
ProjectileMap::iterator findIter = myProjectiles.find( projectile );
if ( findIter != myProjectiles.end() )
{
delete findIter->second;
removeList.push_back( findIter );
}
}
std::list<ProjectileMap::iterator>::iterator delIter = removeList.begin();
std::list<ProjectileMap::iterator>::iterator endDelIter = removeList.end();
for ( ; delIter != endDelIter; ++delIter )
{
myProjectiles.erase( *delIter );
}
}
void DtObserverShooter::tick( double simTime )
{
removeExpiredProjectiles();
ProjectileMap::iterator curIter = myProjectiles.begin();
ProjectileMap::iterator endIter = myProjectiles.end();
for( ; curIter != endIter; ++curIter )
{
if ( ! curIter->second->tick( simTime ) )
{
myExpiredProjectiles.push_back( curIter->first );
}
}
}
}
DtObserverShooter.h
#pragma once
#include <matrix/vlVector.h>
#include <matrix/vlTaitBryan.h>
#include <boost/unordered_map.hpp>
#include <boost/function.hpp>
#include <list>
#include <string>
namespace makVrv
{
class DtDe;
{
public:
DtObserverShooter( DtDe& de );
virtual ~DtObserverShooter();
void fireProjectile();
void setModelDefinitionName( const std::string& modelDefinitionName );
void setProjectileSpeed( double speed );
void tick( double simTime );
void removeExpiredProjectiles();
protected:
typedef boost::unordered_map<DtUniqueID, DtProjectile*> ProjectileMap;
typedef std::list<DtUniqueID> ProjectileIDList;
protected:
DtDe& myDe;
ProjectileMap myProjectiles;
ProjectileIDList myExpiredProjectiles;
std::string myModelDefinitionName;
double myProjectileSpeed;
};
}
DtProjectile.cxx
#include <vrvCore/DtSceneObjectAgent.hpp>
#include <osg/Matrixd>
namespace makVrv
{
const DtVector& direction,
const std::string& modelDefinitionName, IntersectionCallback callback )
: myDe( de )
, myFiringPosition( start )
, myFiringStartTime( -1. )
, myIntersectionCallback( callback )
{
DtUniqueID elementId = myDe.agentManager().createNewUniqueId();
myFacade = new DtEntity3dFacade( myDe.agentManager(),
DtSharedSettingsManager::instance( myDe ), elementId, 0, true );
myFacade->setUpdateTypes( false, false );
myFacade->setArticulatedModelDefinition( modelDefinitionName );
myFacade->setPosition( start );
myFacade->setOrientation( orientation );
myFacade->setVisible( true );
myDe.sharedState().coordinateSystem().converter()->setupTopoFrame( start );
DtVecScale( myDe.sharedState().coordinateSystem().converter()->up( start ), -9.81, myAcceleration );
}
DtProjectile::~DtProjectile()
{
delete myFacade;
myFacade = 0;
}
bool DtProjectile::tick( double simTime )
{
if ( myFiringStartTime < 0. )
{
myFiringStartTime = simTime;
return true;
}
double total_time = simTime - myFiringStartTime;
DtVecScale( myVelocity0, total_time, vComponent );
double oneHalf_tSquared = ( total_time * total_time) / 2. ;
DtVecScale( myAcceleration, oneHalf_tSquared, aComponent );
newPos = myFiringPosition + vComponent + aComponent;
DtIntersector& intersector = DtIntersectorManager::instance(myDe).modelSetIntersector( 0 );
DtIntersectorResult isectResult;
std::vector<DtElementID> ignoreList;
ignoreList.push_back( id() );
bool hit = intersector.findFirstIntersectWithLineSegment( pos.x(), pos.y(), pos.z(),
newPos.x(), newPos.y(), newPos.z(), isectResult, DtIntersector::PickableNodes, &ignoreList );
if ( hit )
{
newPos =
DtVector( isectResult.x, isectResult.y, isectResult.z );
if ( myIntersectionCallback )
{
DtVecScale( myAcceleration, total_time, aComponent );
DtVector velocity = myVelocity0 + aComponent;
myIntersectionCallback( isectResult, sqrt( velocity.magnitudeSquared() ) );
}
myFacade->setOrientation( orientationFromOldAndNewPositions( myFacade->position(), newPos ) );
myFacade->setPosition( newPos );
return false;
}
myFacade->setOrientation( orientationFromOldAndNewPositions( myFacade->position(), newPos ) );
myFacade->setPosition( newPos );
return true;
}
{
if ( myFacade )
{
return myFacade->elementId();
}
}
DtTaitBryan DtProjectile::orientationFromOldAndNewPositions(
const DtVector& oldPos,
const DtVector& newPos )
{
DtCoordinateSystem& coordSys = myDe.sharedState().coordinateSystem();
coordSys.localToNetPos( newPos, geoEnd );
double yaw, pitch, roll;
return DtTaitBryan( yaw, pitch, roll );
}
}
DtProjectile.cxx
#include <vrvCore/DtSceneObjectAgent.hpp>
#include <osg/Matrixd>
namespace makVrv
{
const DtVector& direction,
const std::string& modelDefinitionName, IntersectionCallback callback )
: myDe( de )
, myFiringPosition( start )
, myFiringStartTime( -1. )
, myIntersectionCallback( callback )
{
DtUniqueID elementId = myDe.agentManager().createNewUniqueId();
myFacade = new DtEntity3dFacade( myDe.agentManager(),
DtSharedSettingsManager::instance( myDe ), elementId, 0, true );
myFacade->setUpdateTypes( false, false );
myFacade->setArticulatedModelDefinition( modelDefinitionName );
myFacade->setPosition( start );
myFacade->setOrientation( orientation );
myFacade->setVisible( true );
myDe.sharedState().coordinateSystem().converter()->setupTopoFrame( start );
DtVecScale( myDe.sharedState().coordinateSystem().converter()->up( start ), -9.81, myAcceleration );
}
DtProjectile::~DtProjectile()
{
delete myFacade;
myFacade = 0;
}
bool DtProjectile::tick( double simTime )
{
if ( myFiringStartTime < 0. )
{
myFiringStartTime = simTime;
return true;
}
double total_time = simTime - myFiringStartTime;
DtVecScale( myVelocity0, total_time, vComponent );
double oneHalf_tSquared = ( total_time * total_time) / 2. ;
DtVecScale( myAcceleration, oneHalf_tSquared, aComponent );
newPos = myFiringPosition + vComponent + aComponent;
DtIntersector& intersector = DtIntersectorManager::instance(myDe).modelSetIntersector( 0 );
DtIntersectorResult isectResult;
std::vector<DtElementID> ignoreList;
ignoreList.push_back( id() );
bool hit = intersector.findFirstIntersectWithLineSegment( pos.x(), pos.y(), pos.z(),
newPos.x(), newPos.y(), newPos.z(), isectResult, DtIntersector::PickableNodes, &ignoreList );
if ( hit )
{
newPos =
DtVector( isectResult.x, isectResult.y, isectResult.z );
if ( myIntersectionCallback )
{
DtVecScale( myAcceleration, total_time, aComponent );
DtVector velocity = myVelocity0 + aComponent;
myIntersectionCallback( isectResult, sqrt( velocity.magnitudeSquared() ) );
}
myFacade->setOrientation( orientationFromOldAndNewPositions( myFacade->position(), newPos ) );
myFacade->setPosition( newPos );
return false;
}
myFacade->setOrientation( orientationFromOldAndNewPositions( myFacade->position(), newPos ) );
myFacade->setPosition( newPos );
return true;
}
{
if ( myFacade )
{
return myFacade->elementId();
}
}
DtTaitBryan DtProjectile::orientationFromOldAndNewPositions(
const DtVector& oldPos,
const DtVector& newPos )
{
DtCoordinateSystem& coordSys = myDe.sharedState().coordinateSystem();
coordSys.localToNetPos( oldPos, geoStart );
coordSys.localToNetPos( newPos, geoEnd );
double yaw, pitch, roll;
return DtTaitBryan( yaw, pitch, roll );
}
}
exampleProjectile.cxx
{
}
{
}
{
{
}
}
{
return true;
}
[<< Examples] [Home] [Top of Page]