Hi
When cloning effects osg crashes because the copy constructur tries to run av
pure virtual method (setUpEmitterAndProgram). The right thing to do when
cloning an effect is to run the inherited version og buildEffect and
setUpEmitterAndProgram.
Cheers
Morten Hauknes
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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/SmokeTrailEffect>
#include <osgParticle/ConstantRateCounter>
#include <osgParticle/RadialShooter>
#include <osgParticle/SectorPlacer>
#include <osgParticle/ParticleSystemUpdater>
#include <osgParticle/ConnectedParticleSystem>
#include <osg/Geode>
using namespace osgParticle;
SmokeTrailEffect::SmokeTrailEffect(bool automaticSetup):
ParticleEffect(automaticSetup)
{
setDefaults();
_position.set(0.0f,0.0f,0.0f);
_scale = 1.0f;
_intensity = 1.0f;
_emitterDuration = 65.0;
_defaultParticleTemplate.setLifeTime(5.0*_scale);
if (_automaticSetup) buildEffect();
}
SmokeTrailEffect::SmokeTrailEffect(const osg::Vec3& position, float scale,
float intensity)
{
setDefaults();
_position = position;
_scale = scale;
_intensity = intensity;
_emitterDuration = 65.0;
_defaultParticleTemplate.setLifeTime(5.0*_scale);
if (_automaticSetup) buildEffect();
}
SmokeTrailEffect::SmokeTrailEffect(const SmokeTrailEffect& copy, const
osg::CopyOp& copyop):
ParticleEffect(copy,copyop)
{
if (_automaticSetup) buildEffect();
}
void SmokeTrailEffect::setDefaults()
{
ParticleEffect::setDefaults();
_textureFileName = "Images/continous_smoke.rgb";
_emitterDuration = 65.0;
// set up unit particle.
_defaultParticleTemplate.setLifeTime(5.0*_scale);
_defaultParticleTemplate.setSizeRange(osgParticle::rangef(0.75f, 2.0f));
_defaultParticleTemplate.setAlphaRange(osgParticle::rangef(0.7f, 1.0f));
_defaultParticleTemplate.setColorRange(osgParticle::rangev4(
osg::Vec4(1, 1.0f, 1.0f, 1.0f),
osg::Vec4(1, 1.0f, 1.f, 0.0f)));
}
void SmokeTrailEffect::setUpEmitterAndProgram()
{
// set up particle system
if (!_particleSystem)
{
_particleSystem = new osgParticle::ConnectedParticleSystem;
}
if (_particleSystem.valid())
{
_particleSystem->setDefaultAttributes(_textureFileName, false, false);
osgParticle::Particle& ptemplate =
_particleSystem->getDefaultParticleTemplate();
float radius = 0.5f*_scale;
float density = 1.0f; // 1.0kg/m^3
ptemplate.setLifeTime(_defaultParticleTemplate.getLifeTime());
// the following ranges set the envelope of the respective
// graphical properties in time.
ptemplate.setSizeRange(osgParticle::rangef(radius*_defaultParticleTemplate.getSizeRange().minimum,
radius*_defaultParticleTemplate.getSizeRange().maximum));
ptemplate.setAlphaRange(_defaultParticleTemplate.getAlphaRange());
ptemplate.setColorRange(_defaultParticleTemplate.getColorRange());
// these are physical properties of the particle
ptemplate.setRadius(radius);
ptemplate.setMass(density*radius*radius*radius*osg::PI*4.0f/3.0f);
}
// set up emitter
if (!_emitter)
{
_emitter = new osgParticle::ModularEmitter;
_emitter->setCounter(new osgParticle::ConstantRateCounter);
_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::ConstantRateCounter* counter =
dynamic_cast<osgParticle::ConstantRateCounter*>(_emitter->getCounter());
if (counter)
{
counter->setMinimumNumberOfParticlesToCreate(1);
counter->setNumberOfParticlesPerSecondToCreate(0.0);
}
osgParticle::SectorPlacer* placer =
dynamic_cast<osgParticle::SectorPlacer*>(_emitter->getPlacer());
if (placer)
{
placer->setCenter(_position);
placer->setRadiusRange(0.0f*_scale,0.0f*_scale);
}
osgParticle::RadialShooter* shooter =
dynamic_cast<osgParticle::RadialShooter*>(_emitter->getShooter());
if (shooter)
{
shooter->setThetaRange(0.0f, 0.0f);
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);
}
}
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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/ExplosionDebrisEffect>
#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;
ExplosionDebrisEffect::ExplosionDebrisEffect(bool automaticSetup):
ParticleEffect(automaticSetup)
{
setDefaults();
_position.set(0.0f,0.0f,0.0f);
_scale = 1.0f;
_intensity = 1.0f;
_emitterDuration = 0.1;
_defaultParticleTemplate.setLifeTime(1.0+0.6*_scale);
if (_automaticSetup) buildEffect();
}
ExplosionDebrisEffect::ExplosionDebrisEffect(const osg::Vec3& position, float
scale, float intensity)
{
setDefaults();
_position = position;
_scale = scale;
_intensity = intensity;
_emitterDuration = 0.1;
_defaultParticleTemplate.setLifeTime(1.0+0.6*_scale);
if (_automaticSetup) buildEffect();
}
ExplosionDebrisEffect::ExplosionDebrisEffect(const ExplosionDebrisEffect& copy,
const osg::CopyOp& copyop):
ParticleEffect(copy,copyop)
{
if (_automaticSetup) buildEffect();
}
void ExplosionDebrisEffect::setDefaults()
{
ParticleEffect::setDefaults();
_textureFileName = "Images/particle.rgb";
_emitterDuration = 0.1;
// set up unit particle.
_defaultParticleTemplate.setLifeTime(1.0+0.6*_scale);
_defaultParticleTemplate.setSizeRange(osgParticle::rangef(0.75f, 3.0f));
_defaultParticleTemplate.setAlphaRange(osgParticle::rangef(0.0f, 1.0f));
_defaultParticleTemplate.setColorRange(osgParticle::rangev4(
osg::Vec4(0.5f, 0.5f, 0.0f, 1.0f),
osg::Vec4(0.2f, 0.2f, 0.2f, 0.5f)));
}
void ExplosionDebrisEffect::setUpEmitterAndProgram()
{
// set up particle system
if (!_particleSystem)
{
_particleSystem = new osgParticle::ParticleSystem;
}
if (_particleSystem.valid())
{
_particleSystem->setDefaultAttributes(_textureFileName, false, false);
osgParticle::Particle& ptemplate =
_particleSystem->getDefaultParticleTemplate();
float radius = 0.05f*_scale;
float density = 1000.0f; // 1000.0kg/m^3
ptemplate.setLifeTime(_defaultParticleTemplate.getLifeTime());
// the following ranges set the envelope of the respective
// graphical properties in time.
ptemplate.setSizeRange(osgParticle::rangef(radius*_defaultParticleTemplate.getSizeRange().minimum,
radius*_defaultParticleTemplate.getSizeRange().maximum));
ptemplate.setAlphaRange(_defaultParticleTemplate.getAlphaRange());
ptemplate.setColorRange(_defaultParticleTemplate.getColorRange());
// these are physical properties of the particle
ptemplate.setRadius(radius);
ptemplate.setMass(density*radius*radius*radius*osg::PI*4.0f/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);
}
}
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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/ExplosionEffect>
#include <osgParticle/ExplosionEffect>
#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;
ExplosionEffect::ExplosionEffect(bool automaticSetup):
ParticleEffect(automaticSetup)
{
setDefaults();
_position.set(0.0f,0.0f,0.0f);
_scale = 1.0f;
_intensity = 1.0f;
_emitterDuration = 1.0;
if (_automaticSetup) buildEffect();
}
ExplosionEffect::ExplosionEffect(const osg::Vec3& position, float scale, float
intensity)
{
setDefaults();
_position = position;
_scale = scale;
_intensity = intensity;
_emitterDuration = 1.0;
if (_automaticSetup) buildEffect();
}
ExplosionEffect::ExplosionEffect(const ExplosionEffect& copy, const
osg::CopyOp& copyop):
ParticleEffect(copy,copyop)
{
if (_automaticSetup) buildEffect();
}
void ExplosionEffect::setDefaults()
{
ParticleEffect::setDefaults();
_textureFileName = "Images/smoke.rgb";
_emitterDuration = 1.0;
// set up unit particle.
_defaultParticleTemplate.setLifeTime(0.5+0.1*_scale);
_defaultParticleTemplate.setSizeRange(osgParticle::rangef(0.75f, 3.0f));
_defaultParticleTemplate.setAlphaRange(osgParticle::rangef(0.1f, 1.0f));
_defaultParticleTemplate.setColorRange(osgParticle::rangev4(
osg::Vec4(1.0f, 0.8f, 0.2f, 1.0f),
osg::Vec4(1.0f, 0.4f, 0.1f, 0.0f)));
}
void ExplosionEffect::setUpEmitterAndProgram()
{
// set up particle system
if (!_particleSystem)
{
_particleSystem = new osgParticle::ParticleSystem;
}
if (_particleSystem.valid())
{
_particleSystem->setDefaultAttributes(_textureFileName, false, false);
osgParticle::Particle& ptemplate =
_particleSystem->getDefaultParticleTemplate();
float radius = 0.4f*_scale;
float density = 1.2f; // 1.0kg/m^3
ptemplate.setLifeTime(_defaultParticleTemplate.getLifeTime());
// the following ranges set the envelope of the respective
// graphical properties in time.
ptemplate.setSizeRange(osgParticle::rangef(radius*_defaultParticleTemplate.getSizeRange().minimum,
radius*_defaultParticleTemplate.getSizeRange().maximum));
ptemplate.setAlphaRange(_defaultParticleTemplate.getAlphaRange());
ptemplate.setColorRange(_defaultParticleTemplate.getColorRange());
// these are physical properties of the particle
ptemplate.setRadius(radius);
ptemplate.setMass(density*radius*radius*radius*osg::PI*4.0f/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(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
if (!_program)
{
_program = new osgParticle::FluidProgram;
}
if (_program.valid())
{
_program->setParticleSystem(_particleSystem.get());
_program->setWind(_wind);
}
}
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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/FireEffect>
#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;
FireEffect::FireEffect(bool automaticSetup):
ParticleEffect(automaticSetup)
{
setDefaults();
_position.set(0.0f,0.0f,0.0f);
_scale = 1.0f;
_intensity = 1.0f;
_emitterDuration = 60.0;
_defaultParticleTemplate.setLifeTime(0.5+0.1*_scale);
if (_automaticSetup) buildEffect();
}
FireEffect::FireEffect(const osg::Vec3& position, float scale, float intensity)
{
setDefaults();
_position = position;
_scale = scale;
_intensity = intensity;
_emitterDuration = 60.0;
_defaultParticleTemplate.setLifeTime(0.5+0.1*_scale);
if (_automaticSetup) buildEffect();
}
FireEffect::FireEffect(const FireEffect& copy, const osg::CopyOp& copyop):
ParticleEffect(copy,copyop)
{
if (_automaticSetup) buildEffect();
}
void FireEffect::setDefaults()
{
ParticleEffect::setDefaults();
_textureFileName = "Images/smoke.rgb";
_emitterDuration = 60.0;
// set up unit particle.
_defaultParticleTemplate.setLifeTime(0.5+0.1*_scale);
_defaultParticleTemplate.setSizeRange(osgParticle::rangef(0.75f, 3.0f));
_defaultParticleTemplate.setAlphaRange(osgParticle::rangef(0.1f, 1.0f));
_defaultParticleTemplate.setColorRange(osgParticle::rangev4(
osg::Vec4(1, 0.8f, 0.2f, 1.0f),
osg::Vec4(1, 0.3f, 0.2f, 0.0f)));
}
void FireEffect::setUpEmitterAndProgram()
{
// set up particle system
if (!_particleSystem)
{
_particleSystem = new osgParticle::ParticleSystem;
}
if (_particleSystem.valid())
{
_particleSystem->setDefaultAttributes(_textureFileName, false, false);
osgParticle::Particle& ptemplate =
_particleSystem->getDefaultParticleTemplate();
float radius = 0.25f*_scale;
float density = 0.5f; // 0.5kg/m^3
ptemplate.setLifeTime(_defaultParticleTemplate.getLifeTime());
// the following ranges set the envelope of the respective
// graphical properties in time.
ptemplate.setSizeRange(osgParticle::rangef(radius*_defaultParticleTemplate.getSizeRange().minimum,
radius*_defaultParticleTemplate.getSizeRange().maximum));
ptemplate.setAlphaRange(_defaultParticleTemplate.getAlphaRange());
ptemplate.setColorRange(_defaultParticleTemplate.getColorRange());
// these are physical properties of the particle
// these are physical properties of the particle
ptemplate.setRadius(radius);
ptemplate.setMass(density*radius*radius*radius*osg::PI*4.0f/3.0f);
}
// set up emitter
if (!_emitter)
{
_emitter = new osgParticle::ModularEmitter;
_emitter->setNumParticlesToCreateMovementCompensationRatio(1.5f);
_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(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);
}
}
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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/ParticleEffect>
#include <osgParticle/ParticleSystemUpdater>
#include <osg/Geode>
using namespace osgParticle;
ParticleEffect::ParticleEffect(const ParticleEffect& copy, const osg::CopyOp&
copyop):
osg::Group(copy,copyop),
_automaticSetup(copy._automaticSetup),
_useLocalParticleSystem(copy._useLocalParticleSystem),
_textureFileName(copy._textureFileName),
_defaultParticleTemplate(copy._defaultParticleTemplate),
_position(copy._position),
_scale(copy._scale),
_intensity(copy._intensity),
_startTime(copy._startTime),
_emitterDuration(copy._emitterDuration),
_wind(copy._wind)
{
}
void ParticleEffect::setUseLocalParticleSystem(bool local)
{
if (_useLocalParticleSystem==local) return;
_useLocalParticleSystem = local;
if (_automaticSetup) buildEffect();
}
void ParticleEffect::setTextureFileName(const std::string& filename)
{
_textureFileName = filename;
if (_automaticSetup) setUpEmitterAndProgram();
}
void ParticleEffect::setDefaultParticleTemplate(const Particle& p)
{
_defaultParticleTemplate = p;
if (_automaticSetup) setUpEmitterAndProgram();
}
void ParticleEffect::setPosition(const osg::Vec3& position)
{
if (_position==position) return;
_position = position;
if (_automaticSetup) setUpEmitterAndProgram();
}
void ParticleEffect::setScale(float scale)
{
if (_scale==scale) return;
_scale = scale;
if (_automaticSetup) setUpEmitterAndProgram();
}
void ParticleEffect::setIntensity(float intensity)
{
if (_intensity==intensity) return;
_intensity = intensity;
if (_automaticSetup) setUpEmitterAndProgram();
}
void ParticleEffect::setStartTime(double startTime)
{
if (_startTime==startTime) return;
_startTime =startTime;
if (_automaticSetup) setUpEmitterAndProgram();
}
void ParticleEffect::setEmitterDuration(double duration)
{
if (_emitterDuration==duration) return;
_emitterDuration = duration;
if (_automaticSetup) setUpEmitterAndProgram();
}
void ParticleEffect::setParticleDuration(double duration)
{
if (_defaultParticleTemplate.getLifeTime()==duration) return;
_defaultParticleTemplate.setLifeTime(duration);
if (_automaticSetup) setUpEmitterAndProgram();
}
void ParticleEffect::setWind(const osg::Vec3& wind)
{
if (_wind==wind) return;
_wind = wind;
if (_automaticSetup) setUpEmitterAndProgram();
}
void ParticleEffect::setParticleSystem(ParticleSystem* ps)
{
if (_particleSystem==ps) return;
_particleSystem = ps;
if (_automaticSetup) buildEffect();
}
void ParticleEffect::setDefaults()
{
_useLocalParticleSystem = true;
_scale = 1.0f;
_intensity = 1.0f;
_startTime = 0.0;
_emitterDuration = 1.0;
_wind.set(0.0f,0.0f,0.0f);
}
void ParticleEffect::buildEffect()
{
setUpEmitterAndProgram();
osg::ref_ptr<Emitter> emitter = getEmitter();
osg::ref_ptr<Program> program = getProgram();
osg::ref_ptr<ParticleSystem> particleSystem = getParticleSystem();
if (!emitter || !particleSystem || !program) return;
// clear the children.
removeChildren(0,getNumChildren());
// add the emitter
addChild(emitter.get());
// add the program to update the particles
addChild(program.get());
// add the particle system updater.
osg::ref_ptr<osgParticle::ParticleSystemUpdater> psu = new
osgParticle::ParticleSystemUpdater;
psu->addParticleSystem(particleSystem.get());
addChild(psu.get());
if (_useLocalParticleSystem)
{
particleSystem->setParticleScaleReferenceFrame(ParticleSystem::LOCAL_COORDINATES);
// add the geode to the scene graph
osg::Geode* geode = new osg::Geode;
geode->addDrawable(particleSystem.get());
addChild(geode);
}
}
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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/SmokeEffect>
#include <osgParticle/RandomRateCounter>
#include <osgParticle/RadialShooter>
#include <osgParticle/SectorPlacer>
#include <osgParticle/ParticleSystemUpdater>
#include <osg/Geode>
using namespace osgParticle;
SmokeEffect::SmokeEffect(bool automaticSetup):
ParticleEffect(automaticSetup)
{
setDefaults();
_position.set(0.0f,0.0f,0.0f);
_scale = 1.0f;
_intensity = 1.0f;
_emitterDuration = 65.0;
_defaultParticleTemplate.setLifeTime(5.0*_scale);
if (_automaticSetup) buildEffect();
}
SmokeEffect::SmokeEffect(const osg::Vec3& position, float scale, float
intensity)
{
setDefaults();
_position = position;
_scale = scale;
_intensity = intensity;
_emitterDuration = 65.0;
_defaultParticleTemplate.setLifeTime(5.0*_scale);
if (_automaticSetup) buildEffect();
}
SmokeEffect::SmokeEffect(const SmokeEffect& copy, const osg::CopyOp& copyop):
ParticleEffect(copy,copyop)
{
if (_automaticSetup) buildEffect();
}
void SmokeEffect::setDefaults()
{
ParticleEffect::setDefaults();
_textureFileName = "Images/smoke.rgb";
_emitterDuration = 65.0;
// set up unit particle.
_defaultParticleTemplate.setLifeTime(5.0*_scale);
_defaultParticleTemplate.setSizeRange(osgParticle::rangef(0.75f, 2.0f));
_defaultParticleTemplate.setAlphaRange(osgParticle::rangef(0.1f, 1.0f));
_defaultParticleTemplate.setColorRange(osgParticle::rangev4(
osg::Vec4(1, 1.0f, 1.0f, 1.0f),
osg::Vec4(1, 1.0f, 1.f, 0.0f)));
}
void SmokeEffect::setUpEmitterAndProgram()
{
// set up particle system
if (!_particleSystem)
{
_particleSystem = new osgParticle::ParticleSystem;
}
if (_particleSystem.valid())
{
_particleSystem->setDefaultAttributes(_textureFileName, false, false);
osgParticle::Particle& ptemplate =
_particleSystem->getDefaultParticleTemplate();
float radius = 0.5f*_scale;
float density = 1.0f; // 1.0kg/m^3
ptemplate.setLifeTime(_defaultParticleTemplate.getLifeTime());
// the following ranges set the envelope of the respective
// graphical properties in time.
ptemplate.setSizeRange(osgParticle::rangef(radius*_defaultParticleTemplate.getSizeRange().minimum,
radius*_defaultParticleTemplate.getSizeRange().maximum));
ptemplate.setAlphaRange(_defaultParticleTemplate.getAlphaRange());
ptemplate.setColorRange(_defaultParticleTemplate.getColorRange());
// these are physical properties of the particle
ptemplate.setRadius(radius);
ptemplate.setMass(density*radius*radius*radius*osg::PI*4.0f/3.0f);
}
// set up emitter
if (!_emitter)
{
_emitter = new osgParticle::ModularEmitter;
_emitter->setNumParticlesToCreateMovementCompensationRatio(1.5f);
_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(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);
}
}
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org