Improved ParticleEffects

This commit is contained in:
Robert Osfield
2005-04-04 07:54:52 +00:00
parent e4580f2028
commit 22e446dbc9
25 changed files with 917 additions and 289 deletions

View File

@@ -0,0 +1,145 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <osgParticle/ExplosionDebriEffect>
#include <osgParticle/ExplosionDebriEffect>
#include <osgParticle/ModularEmitter>
#include <osgParticle/ModularProgram>
#include <osgParticle/RandomRateCounter>
#include <osgParticle/SectorPlacer>
#include <osgParticle/RadialShooter>
#include <osgParticle/AccelOperator>
#include <osgParticle/FluidFrictionOperator>
#include <osgParticle/ParticleSystemUpdater>
#include <osg/Geode>
using namespace osgParticle;
ExplosionDebriEffect::ExplosionDebriEffect(const osg::Vec3& position, float scale, float intensity)
{
setDefaults();
_position = position;
_scale = scale;
_intensity = intensity;
_emitterDuration = 0.1;
_particleDuration = 1.0+0.6*_scale;
buildEffect();
}
ExplosionDebriEffect::ExplosionDebriEffect(const ExplosionDebriEffect& copy, const osg::CopyOp& copyop):
ParticleEffect(copy,copyop)
{
}
void ExplosionDebriEffect::setDefaults()
{
ParticleEffect::setDefaults();
_emitterDuration = 0.1;
_particleDuration = 1.0+0.6*_scale;
}
void ExplosionDebriEffect::setUpEmitterAndProgram()
{
// set up particle system
if (!_particleSystem)
{
_particleSystem = new osgParticle::ParticleSystem;
}
if (_particleSystem.valid())
{
_particleSystem->setDefaultAttributes("Images/particle.rgb", false, false);
osgParticle::Particle& ptemplate = _particleSystem->getDefaultParticleTemplate();
ptemplate.setLifeTime(_particleDuration);
float radius = 0.05f*_scale;
float density = 1000.0f; // 1000.0kg/m^3
// the following ranges set the envelope of the respective
// graphical properties in time.
ptemplate.setSizeRange(osgParticle::rangef(radius*0.75f, radius*3.0f));
ptemplate.setAlphaRange(osgParticle::rangef(0.0f, 1.0f));
ptemplate.setColorRange(osgParticle::rangev4(
osg::Vec4(0.5f, 0.5f, 0.0f, 1.0f),
osg::Vec4(0.2f, 0.2f, 0.2f, 0.5f)));
// these are physical properties of the particle
ptemplate.setRadius(radius); // 5 cm wide particles
ptemplate.setMass(density*osg::PI*4.0f*radius*radius*radius/3.0f);
}
// set up emitter
if (!_emitter)
{
_emitter = new osgParticle::ModularEmitter;
_emitter->setCounter(new osgParticle::RandomRateCounter);
_emitter->setPlacer(new osgParticle::SectorPlacer);
_emitter->setShooter(new osgParticle::RadialShooter);
}
if (_emitter.valid())
{
_emitter->setParticleSystem(_particleSystem.get());
_emitter->setReferenceFrame(_useLocalParticleSystem?
osgParticle::ParticleProcessor::ABSOLUTE_RF:
osgParticle::ParticleProcessor::RELATIVE_RF);
_emitter->setStartTime(_startTime);
_emitter->setLifeTime(_emitterDuration);
_emitter->setEndless(false);
osgParticle::RandomRateCounter* counter = dynamic_cast<osgParticle::RandomRateCounter*>(_emitter->getCounter());
if (counter)
{
counter->setRateRange(2000*_intensity,2000*_intensity);
}
osgParticle::SectorPlacer* placer = dynamic_cast<osgParticle::SectorPlacer*>(_emitter->getPlacer());
if (placer)
{
placer->setCenter(_position);
placer->setRadiusRange(0.0f*_scale,0.25f*_scale);
}
osgParticle::RadialShooter* shooter = dynamic_cast<osgParticle::RadialShooter*>(_emitter->getShooter());
if (shooter)
{
shooter->setThetaRange(0.0f, osg::PI_2);
shooter->setInitialSpeedRange(1.0f*_scale,5.0f*_scale);
}
}
// set up program.
if (!_program)
{
_program = new osgParticle::FluidProgram;
}
if (_program.valid())
{
_program->setParticleSystem(_particleSystem.get());
_program->setWind(_wind);
}
}

View File

@@ -35,6 +35,9 @@ ExplosionEffect::ExplosionEffect(const osg::Vec3& position, float scale, float i
_scale = scale;
_intensity = intensity;
_emitterDuration = 1.0;
_particleDuration = 0.5+0.1*_scale;
buildEffect();
}
@@ -46,83 +49,98 @@ ExplosionEffect::ExplosionEffect(const ExplosionEffect& copy, const osg::CopyOp&
void ExplosionEffect::setDefaults()
{
ParticleEffect::setDefaults();
_emitterDuration = 1.0;
_particleDuration = 0.5+0.1*_scale;
}
void ExplosionEffect::setUpEmitterAndProgram()
{
osgParticle::ParticleSystem *ps = new osgParticle::ParticleSystem;
ps->setDefaultAttributes("Images/particle.rgb", false, false);
_particleSystem = ps;
//_particleSystem->setUseIntialViewMatrix(true);
// set up the emitter
// set up particle system
if (!_particleSystem)
{
osgParticle::ModularEmitter *emitter = new osgParticle::ModularEmitter;
emitter->setParticleSystem(ps);
emitter->setReferenceFrame(osgParticle::ParticleProcessor::ABSOLUTE_RF);
_particleSystem = new osgParticle::ParticleSystem;
}
osgParticle::Particle ptemplate;
if (_particleSystem.valid())
{
_particleSystem->setDefaultAttributes("Images/smoke.rgb", false, false);
ptemplate.setLifeTime(3); // 3 seconds of life
osgParticle::Particle& ptemplate = _particleSystem->getDefaultParticleTemplate();
ptemplate.setLifeTime(_particleDuration);
float radius = 0.4f*_scale;
float density = 1.2f; // 1.0kg/m^3
// the following ranges set the envelope of the respective
// graphical properties in time.
ptemplate.setSizeRange(osgParticle::rangef(0.75f, 3.0f));
ptemplate.setAlphaRange(osgParticle::rangef(0.0f, 1.0f));
ptemplate.setSizeRange(osgParticle::rangef(radius*0.75f, radius*3.0f));
ptemplate.setAlphaRange(osgParticle::rangef(0.1f, 1.0f));
ptemplate.setColorRange(osgParticle::rangev4(
osg::Vec4(1, 1.0f, 0.0f, 1.0f),
osg::Vec4(0.5, 0.5f, 0.0f, 0.0f)));
osg::Vec4(1.0f, 0.8f, 0.2f, 1.0f),
osg::Vec4(1.0f, 0.4f, 0.1f, 0.0f)));
// these are physical properties of the particle
ptemplate.setRadius(0.1f*_scale); // 5 cm wide particles
ptemplate.setMass(1.0f*_scale); // 1kg heavy
ptemplate.setRadius(radius); // 5 cm wide particles
ptemplate.setMass(density*osg::PI*4.0f*radius*radius*radius/3.0f);
// assign the particle template to the system.
ps->setDefaultParticleTemplate(ptemplate);
}
//osgParticle::LimitedDurationRandomRateCounter* counter = new osgParticle::LimitedDurationRandomRateCounter;
osgParticle::RandomRateCounter* counter = new osgParticle::RandomRateCounter;
counter->setRateRange(2000*_intensity,2000*_intensity); // generate 1000 particles per second
emitter->setCounter(counter);
osgParticle::SectorPlacer* placer = new osgParticle::SectorPlacer;
placer->setCenter(_position);
placer->setRadiusRange(0.0f,1.0f*_scale);
emitter->setPlacer(placer);
osgParticle::RadialShooter* shooter = new osgParticle::RadialShooter;
shooter->setThetaRange(0.0f, osg::PI_2);
shooter->setInitialSpeedRange(5.0f*_scale,30.0f*_scale);
emitter->setShooter(shooter);
emitter->setStartTime(_startTime);
emitter->setResetTime(5.0f);
emitter->setLifeTime(0.1f);
emitter->setEndless(false);
_emitter = emitter;
// set up emitter
if (!_emitter)
{
_emitter = new osgParticle::ModularEmitter;
_emitter->setCounter(new osgParticle::RandomRateCounter);
_emitter->setPlacer(new osgParticle::SectorPlacer);
_emitter->setShooter(new osgParticle::RadialShooter);
}
if (_emitter.valid())
{
_emitter->setParticleSystem(_particleSystem.get());
_emitter->setReferenceFrame(_useLocalParticleSystem?
osgParticle::ParticleProcessor::ABSOLUTE_RF:
osgParticle::ParticleProcessor::RELATIVE_RF);
_emitter->setStartTime(_startTime);
_emitter->setLifeTime(_emitterDuration);
_emitter->setEndless(false);
osgParticle::RandomRateCounter* counter = dynamic_cast<osgParticle::RandomRateCounter*>(_emitter->getCounter());
if (counter)
{
counter->setRateRange(50*_intensity,100*_intensity);
}
osgParticle::SectorPlacer* placer = dynamic_cast<osgParticle::SectorPlacer*>(_emitter->getPlacer());
if (placer)
{
placer->setCenter(_position);
placer->setRadiusRange(0.0f*_scale,0.25f*_scale);
}
osgParticle::RadialShooter* shooter = dynamic_cast<osgParticle::RadialShooter*>(_emitter->getShooter());
if (shooter)
{
shooter->setThetaRange(0.0f, osg::PI_2);
shooter->setInitialSpeedRange(1.0f*_scale,10.0f*_scale);
}
}
// set up the program
{
osgParticle::ModularProgram *program = new osgParticle::ModularProgram;
program->setParticleSystem(ps);
// create an operator that simulates the gravity acceleration.
osgParticle::AccelOperator *op1 = new osgParticle::AccelOperator;
op1->setToGravity();
program->addOperator(op1);
// let's add a fluid operator to simulate air friction.
osgParticle::FluidFrictionOperator *op3 = new osgParticle::FluidFrictionOperator;
op3->setFluidToAir();
program->addOperator(op3);
_program = program;
if (!_program)
{
_program = new osgParticle::FluidProgram;
}
if (_program.valid())
{
_program->setParticleSystem(_particleSystem.get());
_program->setWind(_wind);
}
}

View File

@@ -33,7 +33,10 @@ FireEffect::FireEffect(const osg::Vec3& position, float scale, float intensity)
_position = position;
_scale = scale;
_intensity = intensity;
_emitterDuration = 60.0;
_particleDuration = 0.5+0.1*_scale;
buildEffect();
}
@@ -45,78 +48,97 @@ FireEffect::FireEffect(const FireEffect& copy, const osg::CopyOp& copyop):
void FireEffect::setDefaults()
{
ParticleEffect::setDefaults();
_emitterDuration = 60.0;
_particleDuration = 0.5+0.1*_scale;
}
void FireEffect::setUpEmitterAndProgram()
{
osgParticle::ParticleSystem *ps = new osgParticle::ParticleSystem;
ps->setDefaultAttributes("Images/smoke.rgb", true, false);
_particleSystem = ps;
// _particleSystem->setUseIntialViewMatrix(true);
// set up the emitter
// set up particle system
if (!_particleSystem)
{
osgParticle::ModularEmitter *emitter = new osgParticle::ModularEmitter;
emitter->setParticleSystem(ps);
emitter->setReferenceFrame(osgParticle::ParticleProcessor::ABSOLUTE_RF);
_particleSystem = new osgParticle::ParticleSystem;
}
if (_particleSystem.valid())
{
_particleSystem->setDefaultAttributes("Images/smoke.rgb", false, false);
osgParticle::Particle ptemplate;
osgParticle::Particle& ptemplate = _particleSystem->getDefaultParticleTemplate();
ptemplate.setLifeTime(2); // 3 seconds of life
ptemplate.setLifeTime(_particleDuration);
float radius = 0.25f*_scale;
float density = 0.5f; // 1.0kg/m^3
// the following ranges set the envelope of the respective
// graphical properties in time.
ptemplate.setSizeRange(osgParticle::rangef(0.75f, 3.0f));
ptemplate.setAlphaRange(osgParticle::rangef(0.0f, 1.0f));
ptemplate.setSizeRange(osgParticle::rangef(radius*0.75f, radius*3.0f));
ptemplate.setAlphaRange(osgParticle::rangef(0.1f, 1.0f));
ptemplate.setColorRange(osgParticle::rangev4(
osg::Vec4(1, 1.0f, 0.2f, 1.0f),
osg::Vec4(1, 0.0f, 0.f, 0.0f)));
// these are physical properties of the particle
ptemplate.setRadius(0.05f*_scale); // 5 cm wide particles
ptemplate.setMass(0.01f*_scale); // 10g heavy
ptemplate.setRadius(radius); // 5 cm wide particles
ptemplate.setMass(density*osg::PI*4.0f*radius*radius*radius/3.0f);
// assign the particle template to the system.
ps->setDefaultParticleTemplate(ptemplate);
osgParticle::RandomRateCounter* counter = new osgParticle::RandomRateCounter;
counter->setRateRange(1*_intensity*_scale,10*_intensity*_scale); // generate 1000 particles per second
emitter->setCounter(counter);
osgParticle::SectorPlacer* placer = new osgParticle::SectorPlacer;
placer->setCenter(_position);
placer->setRadiusRange(0.0f*_scale,0.25f*_scale);
emitter->setPlacer(placer);
osgParticle::RadialShooter* shooter = new osgParticle::RadialShooter;
shooter->setThetaRange(0.0f, osg::PI_4);
shooter->setInitialSpeedRange(0.0f*_scale,0.0f*_scale);
emitter->setShooter(shooter);
emitter->setStartTime(_startTime);
_emitter = emitter;
}
// set up the program
// set up emitter
if (!_emitter)
{
osgParticle::ModularProgram *program = new osgParticle::ModularProgram;
program->setParticleSystem(ps);
_emitter = new osgParticle::ModularEmitter;
_emitter->setCounter(new osgParticle::RandomRateCounter);
_emitter->setPlacer(new osgParticle::SectorPlacer);
_emitter->setShooter(new osgParticle::RadialShooter);
}
// create an operator that simulates the gravity acceleration.
osgParticle::AccelOperator *op1 = new osgParticle::AccelOperator;
op1->setToGravity(-0.2);
program->addOperator(op1);
if (_emitter.valid())
{
_emitter->setParticleSystem(_particleSystem.get());
_emitter->setReferenceFrame(_useLocalParticleSystem?
osgParticle::ParticleProcessor::ABSOLUTE_RF:
osgParticle::ParticleProcessor::RELATIVE_RF);
// let's add a fluid operator to simulate air friction.
osgParticle::FluidFrictionOperator *op3 = new osgParticle::FluidFrictionOperator;
op3->setFluidToAir();
program->addOperator(op3);
_emitter->setStartTime(_startTime);
_emitter->setLifeTime(_emitterDuration);
_emitter->setEndless(false);
// add the program to the scene graph
_program = program;
osgParticle::RandomRateCounter* counter = dynamic_cast<osgParticle::RandomRateCounter*>(_emitter->getCounter());
if (counter)
{
counter->setRateRange(10*_intensity,15*_intensity);
}
osgParticle::SectorPlacer* placer = dynamic_cast<osgParticle::SectorPlacer*>(_emitter->getPlacer());
if (placer)
{
placer->setCenter(_position);
placer->setRadiusRange(0.0f*_scale,0.25f*_scale);
}
osgParticle::RadialShooter* shooter = dynamic_cast<osgParticle::RadialShooter*>(_emitter->getShooter());
if (shooter)
{
shooter->setThetaRange(0.0f, osg::PI_4);
shooter->setInitialSpeedRange(0.0f*_scale,0.0f*_scale);
}
}
// set up program.
if (!_program)
{
_program = new osgParticle::FluidProgram;
}
if (_program.valid())
{
_program->setParticleSystem(_particleSystem.get());
_program->setWind(_wind);
}
}

View File

@@ -30,7 +30,7 @@ osgParticle::FluidFrictionOperator::FluidFrictionOperator(const FluidFrictionOpe
void osgParticle::FluidFrictionOperator::operate(Particle *P, double dt)
{
float r = (ovr_rad_ > 0)? ovr_rad_ : P->getRadius();
osg::Vec3 v = P->getVelocity();
osg::Vec3 v = P->getVelocity()-_wind;
float vm = v.normalize();
float R = A_ * r * vm + B_ * r * r * vm * vm;

View File

@@ -4,9 +4,11 @@ include $(TOPDIR)/Make/makedefs
CXXFILES =\
Emitter.cpp\
ExplosionEffect.cpp\
ExplosionDebriEffect.cpp\
SmokeEffect.cpp\
FireEffect.cpp\
FluidFrictionOperator.cpp\
FluidProgram.cpp\
ModularEmitter.cpp\
ModularProgram.cpp\
MultiSegmentPlacer.cpp\

View File

@@ -18,44 +18,99 @@
using namespace osgParticle;
ParticleEffect::ParticleEffect(const ParticleEffect& copy, const osg::CopyOp& copyop):
osg::Group(copy,copyop)/*,
osg::Group(copy,copyop),/*,
_particleSystem(copy._particleSystem.valid()?copy._particleSystem->clone():0)*/
_useLocalParticleSystem(copy._useLocalParticleSystem),
_scale(copy._scale),
_intensity(copy._intensity),
_startTime(copy._startTime),
_emitterDuration(copy._emitterDuration),
_particleDuration(copy._particleDuration),
_wind(copy._wind)
{
}
void ParticleEffect::setUseLocalParticleSystem(bool local)
{
if (_useLocalParticleSystem==local) return;
_useLocalParticleSystem = local;
buildEffect();
}
void ParticleEffect::setPosition(const osg::Vec3& position)
{
if (_position==position) return;
_position = position;
setUpEmitterAndProgram();
}
void ParticleEffect::setScale(float scale)
{
if (_scale==scale) return;
_scale = scale;
setUpEmitterAndProgram();
}
void ParticleEffect::setIntensity(float intensity)
{
if (_intensity==intensity) return;
_intensity = intensity;
setUpEmitterAndProgram();
}
void ParticleEffect::setStartTime(double startTime)
{
_startTime = startTime;
if (_startTime==startTime) return;
_startTime =startTime;
setUpEmitterAndProgram();
}
void ParticleEffect::setDuration(double duration)
void ParticleEffect::setEmitterDuration(double duration)
{
_duration = duration;
if (_emitterDuration==duration) return;
_emitterDuration = duration;
setUpEmitterAndProgram();
}
void ParticleEffect::setParticleDuration(double duration)
{
if (_particleDuration==duration) return;
_particleDuration = duration;
setUpEmitterAndProgram();
}
void ParticleEffect::setWind(const osg::Vec3& wind)
{
if (_wind==wind) return;
_wind = wind;
setUpEmitterAndProgram();
}
void ParticleEffect::setParticleSystem(ParticleSystem* ps)
{
if (_particleSystem==ps) return;
_particleSystem = ps;
buildEffect();
}
void ParticleEffect::setDefaults()
{
_useLocalParticleSystem = true;
_scale = 1.0f;
_intensity = 1.0f;
_startTime = 0.0;
_duration = 1.0;
_direction.set(0.0f,0.0f,1.0f);
_emitterDuration = 1.0;
_particleDuration = 1.0;
_wind.set(0.0f,0.0f,0.0f);
}
void ParticleEffect::buildEffect()
@@ -83,9 +138,12 @@ void ParticleEffect::buildEffect()
psu->addParticleSystem(particleSystem);
addChild(psu);
// add the geode to the scene graph
osg::Geode *geode = new osg::Geode;
geode->addDrawable(particleSystem);
addChild(geode);
if (_useLocalParticleSystem)
{
// add the geode to the scene graph
osg::Geode *geode = new osg::Geode;
geode->addDrawable(particleSystem);
addChild(geode);
}
}

View File

@@ -15,8 +15,6 @@
#include <osgParticle/RandomRateCounter>
#include <osgParticle/RadialShooter>
#include <osgParticle/AccelOperator>
#include <osgParticle/FluidFrictionOperator>
#include <osgParticle/SectorPlacer>
#include <osgParticle/ParticleSystemUpdater>
@@ -31,6 +29,9 @@ SmokeEffect::SmokeEffect(const osg::Vec3& position, float scale, float intensity
_position = position;
_scale = scale;
_intensity = intensity;
_emitterDuration = 65.0;
_particleDuration = 5.0*_scale;
buildEffect();
}
@@ -43,78 +44,94 @@ SmokeEffect::SmokeEffect(const SmokeEffect& copy, const osg::CopyOp& copyop):
void SmokeEffect::setDefaults()
{
ParticleEffect::setDefaults();
_emitterDuration = 65.0;
_particleDuration = 5.0*_scale;
}
void SmokeEffect::setUpEmitterAndProgram()
{
osgParticle::ParticleSystem *ps = new osgParticle::ParticleSystem;
ps->setDefaultAttributes("Images/smoke.rgb", false, false);
_particleSystem = ps;
// _particleSystem->setUseIntialViewMatrix(true);
// set up the emitter
// set up particle system
if (!_particleSystem)
{
osgParticle::ModularEmitter *emitter = new osgParticle::ModularEmitter;
emitter->setParticleSystem(ps);
emitter->setReferenceFrame(osgParticle::ParticleProcessor::ABSOLUTE_RF);
_particleSystem = new osgParticle::ParticleSystem;
}
if (_particleSystem.valid())
{
_particleSystem->setDefaultAttributes("Images/smoke.rgb", false, false);
osgParticle::Particle ptemplate;
osgParticle::Particle& ptemplate = _particleSystem->getDefaultParticleTemplate();
ptemplate.setLifeTime(5*_scale);
ptemplate.setLifeTime(10*_scale);
float radius = 0.5f*_scale;
float density = 1.0f; // 1.0kg/m^3
// the following ranges set the envelope of the respective
// graphical properties in time.
ptemplate.setSizeRange(osgParticle::rangef(0.75f, 3.0f));
ptemplate.setSizeRange(osgParticle::rangef(radius*0.75f, radius*3.0f));
ptemplate.setAlphaRange(osgParticle::rangef(0.1f, 1.0f));
ptemplate.setColorRange(osgParticle::rangev4(
osg::Vec4(1, 1.0f, 1.0f, 1.0f),
osg::Vec4(1, 1.0f, 1.f, 0.0f)));
// these are physical properties of the particle
ptemplate.setRadius(0.05f*_scale); // 5 cm wide particles
ptemplate.setMass(0.01f*_scale); // 10g heavy
ptemplate.setRadius(radius); // 5 cm wide particles
ptemplate.setMass(density*osg::PI*4.0f*radius*radius*radius/3.0f);
// assign the particle template to the system.
ps->setDefaultParticleTemplate(ptemplate);
osgParticle::RandomRateCounter* counter = new osgParticle::RandomRateCounter;
counter->setRateRange(1*_intensity*_scale,2*_intensity*_scale); // generate 1000 particles per second
emitter->setCounter(counter);
osgParticle::SectorPlacer* placer = new osgParticle::SectorPlacer;
placer->setCenter(_position);
placer->setRadiusRange(0.0f*_scale,0.25f*_scale);
emitter->setPlacer(placer);
osgParticle::RadialShooter* shooter = new osgParticle::RadialShooter;
shooter->setThetaRange(0.0f, osg::PI_4);
shooter->setInitialSpeedRange(0.0f*_scale,0.0f*_scale);
emitter->setShooter(shooter);
emitter->setStartTime(0.0f);
_emitter = emitter;
}
// set up the program
// set up emitter
if (!_emitter)
{
osgParticle::ModularProgram *program = new osgParticle::ModularProgram;
program->setParticleSystem(ps);
_emitter = new osgParticle::ModularEmitter;
_emitter->setCounter(new osgParticle::RandomRateCounter);
_emitter->setPlacer(new osgParticle::SectorPlacer);
_emitter->setShooter(new osgParticle::RadialShooter);
}
// create an operator that simulates the gravity acceleration.
osgParticle::AccelOperator *op1 = new osgParticle::AccelOperator;
op1->setToGravity(-0.1);
program->addOperator(op1);
if (_emitter.valid())
{
_emitter->setParticleSystem(_particleSystem.get());
_emitter->setReferenceFrame(_useLocalParticleSystem?
osgParticle::ParticleProcessor::ABSOLUTE_RF:
osgParticle::ParticleProcessor::RELATIVE_RF);
// let's add a fluid operator to simulate air friction.
osgParticle::FluidFrictionOperator *op3 = new osgParticle::FluidFrictionOperator;
op3->setFluidToAir();
program->addOperator(op3);
_emitter->setStartTime(_startTime);
_emitter->setLifeTime(_emitterDuration);
_emitter->setEndless(false);
_program = program;
osgParticle::RandomRateCounter* counter = dynamic_cast<osgParticle::RandomRateCounter*>(_emitter->getCounter());
if (counter)
{
counter->setRateRange(3*_intensity,5*_intensity);
}
osgParticle::SectorPlacer* placer = dynamic_cast<osgParticle::SectorPlacer*>(_emitter->getPlacer());
if (placer)
{
placer->setCenter(_position);
placer->setRadiusRange(0.0f*_scale,0.25f*_scale);
}
osgParticle::RadialShooter* shooter = dynamic_cast<osgParticle::RadialShooter*>(_emitter->getShooter());
if (shooter)
{
shooter->setThetaRange(0.0f, osg::PI_4);
shooter->setInitialSpeedRange(0.0f*_scale,0.0f*_scale);
}
}
// set up program.
if (!_program)
{
_program = new osgParticle::FluidProgram;
}
if (_program.valid())
{
_program->setParticleSystem(_particleSystem.get());
_program->setWind(_wind);
}
}

View File

@@ -13,6 +13,7 @@ CXXFILES =\
IO_ModularProgram.cpp\
IO_MultiSegmentPlacer.cpp\
IO_Particle.cpp\
IO_ParticleEffect.cpp\
IO_ParticleProcessor.cpp\
IO_ParticleSystem.cpp\
IO_ParticleSystemUpdater.cpp\
@@ -22,6 +23,10 @@ CXXFILES =\
IO_RandomRateCounter.cpp\
IO_SectorPlacer.cpp\
IO_SegmentPlacer.cpp\
IO_SmokeEffect.cpp\
IO_FireEffect.cpp\
IO_ExplosionEffect.cpp\
IO_ExplosionDebriEffect.cpp\
IO_VariableRateCounter.cpp\

View File

@@ -0,0 +1,28 @@
#include <osgParticle/ExplosionDebriEffect>
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
bool ExplosionDebriEffect_readLocalData(osg::Object &obj, osgDB::Input &fr);
bool ExplosionDebriEffect_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
osgDB::RegisterDotOsgWrapperProxy ExplosionDebriEffect_Proxy
(
new osgParticle::ExplosionDebriEffect,
"ExplosionDebriEffect",
"Object Node ParticleEffect ExplosionDebriEffect",
ExplosionDebriEffect_readLocalData,
ExplosionDebriEffect_writeLocalData
);
bool ExplosionDebriEffect_readLocalData(osg::Object &, osgDB::Input &)
{
return false;
}
bool ExplosionDebriEffect_writeLocalData(const osg::Object &, osgDB::Output &)
{
return false;
}

View File

@@ -0,0 +1,28 @@
#include <osgParticle/ExplosionEffect>
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
bool ExplosionEffect_readLocalData(osg::Object &obj, osgDB::Input &fr);
bool ExplosionEffect_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
osgDB::RegisterDotOsgWrapperProxy ExplosionEffect_Proxy
(
new osgParticle::ExplosionEffect,
"ExplosionEffect",
"Object Node ParticleEffect ExplosionEffect",
ExplosionEffect_readLocalData,
ExplosionEffect_writeLocalData
);
bool ExplosionEffect_readLocalData(osg::Object &, osgDB::Input &)
{
return false;
}
bool ExplosionEffect_writeLocalData(const osg::Object &, osgDB::Output &)
{
return false;
}

View File

@@ -0,0 +1,28 @@
#include <osgParticle/FireEffect>
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
bool FireEffect_readLocalData(osg::Object &obj, osgDB::Input &fr);
bool FireEffect_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
osgDB::RegisterDotOsgWrapperProxy FireEffect_Proxy
(
new osgParticle::FireEffect,
"FireEffect",
"Object Node ParticleEffect FireEffect",
FireEffect_readLocalData,
FireEffect_writeLocalData
);
bool FireEffect_readLocalData(osg::Object &, osgDB::Input &)
{
return false;
}
bool FireEffect_writeLocalData(const osg::Object &, osgDB::Output &)
{
return false;
}

View File

@@ -0,0 +1,156 @@
#include <osgParticle/ParticleEffect>
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
#include <osg/Notify>
bool ParticleEffect_readLocalData(osg::Object &obj, osgDB::Input &fr);
bool ParticleEffect_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
osgDB::RegisterDotOsgWrapperProxy ParticleEffect_Proxy
(
0,
"ParticleEffect",
"Object Node ParticleEffect",
ParticleEffect_readLocalData,
ParticleEffect_writeLocalData
);
bool ParticleEffect_readLocalData(osg::Object& object, osgDB::Input& fr)
{
osgParticle::ParticleEffect& effect = static_cast<osgParticle::ParticleEffect&>(object);
bool itrAdvanced = false;
if (fr.matchSequence("position %f %f %f"))
{
osg::Vec3 position;
fr[1].getFloat(position[0]);
fr[2].getFloat(position[1]);
fr[3].getFloat(position[2]);
effect.setPosition(position);
fr += 4;
itrAdvanced = true;
}
if (fr.matchSequence("scale %f"))
{
float scale;
fr[1].getFloat(scale);
effect.setScale(scale);
fr += 2;
itrAdvanced = true;
}
if (fr.matchSequence("intensity %f"))
{
float intensity;
fr[1].getFloat(intensity);
effect.setIntensity(intensity);
fr += 2;
itrAdvanced = true;
}
if (fr.matchSequence("startTime %f"))
{
float startTime;
fr[1].getFloat(startTime);
effect.setStartTime(startTime);
fr += 2;
itrAdvanced = true;
}
if (fr.matchSequence("emitterDuration %f"))
{
float emitterDuration;
fr[1].getFloat(emitterDuration);
effect.setEmitterDuration(emitterDuration);
fr += 2;
itrAdvanced = true;
}
if (fr.matchSequence("particleDuration %f"))
{
float particleDuration;
fr[1].getFloat(particleDuration);
effect.setParticleDuration(particleDuration);
fr += 2;
itrAdvanced = true;
}
if (fr.matchSequence("wind %f %f %f"))
{
osg::Vec3 wind;
fr[1].getFloat(wind[0]);
fr[2].getFloat(wind[1]);
fr[3].getFloat(wind[2]);
effect.setWind(wind);
fr += 4;
itrAdvanced = true;
}
if (fr[0].matchWord("useLocalParticleSystem"))
{
if (fr[1].matchWord("FALSE"))
{
effect.setUseLocalParticleSystem(false);
fr+=2;
itrAdvanced = true;
// now read the particle system that is shared with an node external to this particle effect
osg::ref_ptr<osg::Object> readObject = fr.readObjectOfType(osgDB::type_wrapper<osgParticle::ParticleSystem>());
if (readObject.valid())
{
osgParticle::ParticleSystem* ps = static_cast<osgParticle::ParticleSystem*>(readObject.get());
effect.setParticleSystem(ps);
itrAdvanced = true;
}
}
else if (fr[1].matchWord("TRUE"))
{
effect.setUseLocalParticleSystem(true);
fr+=2;
itrAdvanced = true;
}
}
return itrAdvanced;
}
bool ParticleEffect_writeLocalData(const osg::Object& object, osgDB::Output& fw)
{
const osgParticle::ParticleEffect& effect = static_cast<const osgParticle::ParticleEffect&>(object);
fw.indent()<<"position "<<effect.getPosition()<<std::endl;
fw.indent()<<"scale "<<effect.getScale()<<std::endl;
fw.indent()<<"intensity "<<effect.getIntensity()<<std::endl;
fw.indent()<<"startTime "<<effect.getStartTime()<<std::endl;
fw.indent()<<"emitterDuration "<<effect.getEmitterDuration()<<std::endl;
fw.indent()<<"particleDuration "<<effect.getParticleDuration()<<std::endl;
fw.indent()<<"wind "<<effect.getWind()<<std::endl;
fw.indent()<<"useLocalParticleSystem ";
if (effect.getUseLocalParticleSystem()) fw<<"TRUE"<<std::endl;
else
{
fw<<"FALSE"<<std::endl;
fw.writeObject(*effect.getParticleSystem());
}
return true;
}

View File

@@ -0,0 +1,28 @@
#include <osgParticle/SmokeEffect>
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
bool SmokeEffect_readLocalData(osg::Object &obj, osgDB::Input &fr);
bool SmokeEffect_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
osgDB::RegisterDotOsgWrapperProxy SmokeEffect_Proxy
(
new osgParticle::SmokeEffect,
"SmokeEffect",
"Object Node ParticleEffect SmokeEffect",
SmokeEffect_readLocalData,
SmokeEffect_writeLocalData
);
bool SmokeEffect_readLocalData(osg::Object &, osgDB::Input &)
{
return false;
}
bool SmokeEffect_writeLocalData(const osg::Object &, osgDB::Output &)
{
return false;
}

View File

@@ -123,6 +123,13 @@ public:
inverseMVPW.invert(projm);
osg::Vec3 near_point = osg::Vec3(x,y,-1.0f)*inverseMVPW;
osg::Vec3 far_point = osg::Vec3(x,y,1.0f)*inverseMVPW;
if (!near_point.valid() || !far_point.valid())
{
osg::notify(osg::INFO)<<"Warning: PickVisitor caught invalid nea/far poiints."<<std::endl;
return _PIVsegHitList;
}
setxy(x,y);
getHits(node,near_point,far_point);
return _PIVsegHitList;

View File

@@ -492,7 +492,10 @@ class CollectLowestTransformsVisitor : public Optimizer::BaseOptimizerVisitor
CollectLowestTransformsVisitor(Optimizer* optimizer=0):
Optimizer::BaseOptimizerVisitor(optimizer,Optimizer::FLATTEN_STATIC_TRANSFORMS),
_transformFunctor(osg::Matrix()) {}
_transformFunctor(osg::Matrix())
{
setTraversalMode(osg::NodeVisitor::TRAVERSE_PARENTS);
}
virtual void apply(osg::Node& node)
{
@@ -576,9 +579,9 @@ class CollectLowestTransformsVisitor : public Optimizer::BaseOptimizerVisitor
if (drawable) return isOperationPermissibleForObject(drawable);
const osg::Node* node = dynamic_cast<const osg::Node*>(object);
if (drawable) return isOperationPermissibleForObject(node);
if (node) return isOperationPermissibleForObject(node);
return false;
return true;
}
inline bool isOperationPermissibleForObject(const osg::Drawable* drawable) const
@@ -796,7 +799,6 @@ void CollectLowestTransformsVisitor::disableTransform(osg::Transform* transform)
void CollectLowestTransformsVisitor::setUpMaps()
{
// create the TransformMap from the ObjectMap
ObjectMap::iterator oitr;
for(oitr=_objectMap.begin();
@@ -813,7 +815,6 @@ void CollectLowestTransformsVisitor::setUpMaps()
_transformMap[*titr].add(object);
}
}
// disable all the objects which have more than one matrix associated
// with them, and then disable all transforms which have an object associated
@@ -835,6 +836,7 @@ void CollectLowestTransformsVisitor::setUpMaps()
}
}
}
}
bool CollectLowestTransformsVisitor::removeTransforms(osg::Node* nodeWeCannotRemove)
@@ -862,7 +864,6 @@ bool CollectLowestTransformsVisitor::removeTransforms(osg::Node* nodeWeCannotRem
{
if (titr->second._canBeApplied)
{
if (titr->first!=nodeWeCannotRemove)
{
transformRemoved = true;
@@ -952,8 +953,6 @@ void Optimizer::FlattenStaticTransformsVisitor::apply(osg::Transform& transform)
_transformStack.push_back(&transform);
// simple traverse the children as if this Transform didn't exist.
traverse(transform);
@@ -1026,8 +1025,6 @@ bool Optimizer::CombineStaticTransformsVisitor::removeTransforms(osg::Node* node
if (itr!=_transformSet.end()) _transformSet.erase(itr);
}
osg::notify(osg::INFO)<<"Have found "<<_transformSet.size()<<" static Transform pairs to flatten"<<std::endl;
bool transformRemoved = false;
while (!_transformSet.empty())