From 22e446dbc9ff882e79deeda1b19775d281d7999c Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 4 Apr 2005 07:54:52 +0000 Subject: [PATCH] Improved ParticleEffects --- VisualStudio/osgParticle/osgParticle.dsp | 8 + include/osgParticle/ExplosionDebriEffect | 52 ++++++ include/osgParticle/ExplosionEffect | 6 +- include/osgParticle/FireEffect | 4 +- include/osgParticle/FluidFrictionOperator | 35 ++-- include/osgParticle/Particle | 166 +++++++++--------- include/osgParticle/ParticleEffect | 34 +++- include/osgParticle/ParticleSystem | 3 + include/osgParticle/SmokeEffect | 6 +- include/osgUtil/IntersectVisitor | 3 + src/osgParticle/ExplosionDebriEffect.cpp | 145 +++++++++++++++ src/osgParticle/ExplosionEffect.cpp | 128 ++++++++------ src/osgParticle/FireEffect.cpp | 120 +++++++------ src/osgParticle/FluidFrictionOperator.cpp | 2 +- src/osgParticle/GNUmakefile | 2 + src/osgParticle/ParticleEffect.cpp | 78 ++++++-- src/osgParticle/SmokeEffect.cpp | 117 ++++++------ src/osgPlugins/osgParticle/GNUmakefile | 5 + .../osgParticle/IO_ExplosionDebriEffect.cpp | 28 +++ .../osgParticle/IO_ExplosionEffect.cpp | 28 +++ src/osgPlugins/osgParticle/IO_FireEffect.cpp | 28 +++ .../osgParticle/IO_ParticleEffect.cpp | 156 ++++++++++++++++ src/osgPlugins/osgParticle/IO_SmokeEffect.cpp | 28 +++ src/osgProducer/Viewer.cpp | 7 + src/osgUtil/Optimizer.cpp | 17 +- 25 files changed, 917 insertions(+), 289 deletions(-) create mode 100644 include/osgParticle/ExplosionDebriEffect create mode 100644 src/osgParticle/ExplosionDebriEffect.cpp create mode 100644 src/osgPlugins/osgParticle/IO_ExplosionDebriEffect.cpp create mode 100644 src/osgPlugins/osgParticle/IO_ExplosionEffect.cpp create mode 100644 src/osgPlugins/osgParticle/IO_FireEffect.cpp create mode 100644 src/osgPlugins/osgParticle/IO_ParticleEffect.cpp create mode 100644 src/osgPlugins/osgParticle/IO_SmokeEffect.cpp diff --git a/VisualStudio/osgParticle/osgParticle.dsp b/VisualStudio/osgParticle/osgParticle.dsp index e20fec180..a1a8ef4e3 100644 --- a/VisualStudio/osgParticle/osgParticle.dsp +++ b/VisualStudio/osgParticle/osgParticle.dsp @@ -111,6 +111,10 @@ SOURCE=..\..\src\osgParticle\FluidFrictionOperator.cpp # End Source File # Begin Source File +SOURCE=..\..\src\osgParticle\FluidProgram.cpp +# End Source File +# Begin Source File + SOURCE=..\..\src\osgParticle\ModularEmitter.cpp # End Source File # Begin Source File @@ -195,6 +199,10 @@ SOURCE=..\..\include\osgParticle\FluidFrictionOperator # End Source File # Begin Source File +SOURCE=..\..\include\osgParticle\FluidProgram +# End Source File +# Begin Source File + SOURCE=..\..\include\osgParticle\ForceOperator # End Source File # Begin Source File diff --git a/include/osgParticle/ExplosionDebriEffect b/include/osgParticle/ExplosionDebriEffect new file mode 100644 index 000000000..8ef2326b2 --- /dev/null +++ b/include/osgParticle/ExplosionDebriEffect @@ -0,0 +1,52 @@ +/* -*-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. +*/ + +#ifndef OSGPARTICLE_EXPLOSIONDEBRIEFFECT +#define OSGPARTICLE_EXPLOSIONDEBRIEFFECT + +#include +#include +#include + +namespace osgParticle +{ + + class OSGPARTICLE_EXPORT ExplosionDebriEffect : public ParticleEffect + { + public: + + ExplosionDebriEffect(const osg::Vec3& position=osg::Vec3(0.0f,0.0f,0.0f), float scale=1.0f, float intensity=1.0f); + + ExplosionDebriEffect(const ExplosionDebriEffect& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY); + + META_Node(osgParticle,ExplosionDebriEffect); + + virtual void setDefaults(); + + virtual void setUpEmitterAndProgram(); + + virtual Emitter* getEmitter() { return _emitter.get(); } + virtual const Emitter* getEmitter() const { return _emitter.get(); } + + virtual Program* getProgram() { return _program.get(); } + virtual const Program* getProgram() const { return _program.get(); } + + protected: + + osg::ref_ptr _emitter; + osg::ref_ptr _program; + + }; +} + +#endif diff --git a/include/osgParticle/ExplosionEffect b/include/osgParticle/ExplosionEffect index 76c03d57e..3a088ab5f 100644 --- a/include/osgParticle/ExplosionEffect +++ b/include/osgParticle/ExplosionEffect @@ -16,7 +16,7 @@ #include #include -#include +#include namespace osgParticle { @@ -34,7 +34,7 @@ namespace osgParticle virtual void setDefaults(); virtual void setUpEmitterAndProgram(); - + virtual Emitter* getEmitter() { return _emitter.get(); } virtual const Emitter* getEmitter() const { return _emitter.get(); } @@ -44,7 +44,7 @@ namespace osgParticle protected: osg::ref_ptr _emitter; - osg::ref_ptr _program; + osg::ref_ptr _program; }; } diff --git a/include/osgParticle/FireEffect b/include/osgParticle/FireEffect index 3188242fd..8e0ec6e3b 100644 --- a/include/osgParticle/FireEffect +++ b/include/osgParticle/FireEffect @@ -16,7 +16,7 @@ #include #include -#include +#include namespace osgParticle { @@ -44,7 +44,7 @@ namespace osgParticle protected: osg::ref_ptr _emitter; - osg::ref_ptr _program; + osg::ref_ptr _program; }; diff --git a/include/osgParticle/FluidFrictionOperator b/include/osgParticle/FluidFrictionOperator index ce8ba0767..c08704965 100644 --- a/include/osgParticle/FluidFrictionOperator +++ b/include/osgParticle/FluidFrictionOperator @@ -40,24 +40,30 @@ namespace osgParticle FluidFrictionOperator(const FluidFrictionOperator ©, const osg::CopyOp ©op = osg::CopyOp::SHALLOW_COPY); META_Object(osgParticle, FluidFrictionOperator); - - /// Get the density of the fluid. - inline float getFluidDensity() const; - + /// Set the density of the fluid. inline void setFluidDensity(float d); - - /// Get the viscosity of the fluid. - inline float getFluidViscosity() const; + + /// Get the density of the fluid. + inline float getFluidDensity() const; /// Set the viscosity of the fluid. inline void setFluidViscosity(float v); - /// Get the overriden radius value. - inline float getOverrideRadius() const; + /// Get the viscosity of the fluid. + inline float getFluidViscosity() const; + /// Set the wind vector. + inline void setWind(const osg::Vec3& wind) { _wind = wind; } + + /// Get the wind vector. + inline const osg::Vec3& getWind() const { return _wind; } + /// Set the overriden radius value (pass 0 if you want to use particle's radius). inline void setOverrideRadius(float r); + + /// Get the overriden radius value. + inline float getOverrideRadius() const; /// Set the fluid parameters as for air (20°C temperature). inline void setFluidToAir(); @@ -76,11 +82,12 @@ namespace osgParticle FluidFrictionOperator &operator=(const FluidFrictionOperator &) { return *this; } private: - float A_; - float B_; - float density_; - float viscosity_; - float ovr_rad_; + float A_; + float B_; + float density_; + float viscosity_; + float ovr_rad_; + osg::Vec3 _wind; Program *current_program_; }; diff --git a/include/osgParticle/Particle b/include/osgParticle/Particle index 2ca8a9003..e0db3ea34 100644 --- a/include/osgParticle/Particle +++ b/include/osgParticle/Particle @@ -46,15 +46,15 @@ namespace osgParticle public: /** - Shape of particles. - NOTE: the LINE shape should be used in conjunction with FIXED alignment mode (see ParticleSystem). - */ - enum Shape { + Shape of particles. + NOTE: the LINE shape should be used in conjunction with FIXED alignment mode (see ParticleSystem). + */ + enum Shape { POINT, // uses GL_POINTS as primitive QUAD, // uses GL_QUADS as primitive QUAD_TRIANGLESTRIP, // uses GL_TRIANGLE_STRIP as primitive, but each particle needs a glBegin/glEnd pair HEXAGON, // may save some filling time, but uses more triangles - LINE // uses GL_LINES to draw line segments that point to the direction of motion + LINE // uses GL_LINES to draw line segments that point to the direction of motion }; Particle(); @@ -117,14 +117,14 @@ namespace osgParticle /// Get the previous position (the position before last update). inline const osg::Vec3 &getPreviousPosition() const; - /// Get the angle vector. - inline const osg::Vec3 &getAngle() const; - - /// Get the rotational velocity vector. - inline const osg::Vec3 &getAngularVelocity() const; - - /// Get the previous angle vector. - inline const osg::Vec3 &getPreviousAngle() const; + /// Get the angle vector. + inline const osg::Vec3 &getAngle() const; + + /// Get the rotational velocity vector. + inline const osg::Vec3 &getAngularVelocity() const; + + /// Get the previous angle vector. + inline const osg::Vec3 &getPreviousAngle() const; /** Kill the particle on next update NOTE: after calling this function, the isAlive() method will still @@ -178,21 +178,21 @@ namespace osgParticle /// Transform position and velocity vectors by a matrix. inline void transformPositionVelocity(const osg::Matrix &xform); - /// Set the angle vector. - inline void setAngle(const osg::Vec3 &a); - - /** - Set the angular velocity vector. - Components x, y and z are angles of rotation around the respective axis (in radians). - */ - inline void setAngularVelocity(const osg::Vec3 &v); - - /// Add a vector to the angular velocity vector. - inline void addAngularVelocity(const osg::Vec3 &dv); - - /// Transform angle and angularVelocity vectors by a matrix. - inline void transformAngleVelocity(const osg::Matrix &xform); - + /// Set the angle vector. + inline void setAngle(const osg::Vec3 &a); + + /** + Set the angular velocity vector. + Components x, y and z are angles of rotation around the respective axis (in radians). + */ + inline void setAngularVelocity(const osg::Vec3 &v); + + /// Add a vector to the angular velocity vector. + inline void addAngularVelocity(const osg::Vec3 &dv); + + /// Transform angle and angularVelocity vectors by a matrix. + inline void transformAngleVelocity(const osg::Matrix &xform); + /** Update the particle (don't call this method manually). This method is called automatically by ParticleSystem::update(); it updates the graphical properties of the particle for the current time, @@ -240,7 +240,7 @@ namespace osgParticle osg::Vec3 prev_angle_; osg::Vec3 angle_; - osg::Vec3 angular_vel_; + osg::Vec3 angular_vel_; double t0_; @@ -338,20 +338,20 @@ namespace osgParticle return prev_pos_; } - inline const osg::Vec3 &Particle::getAngle() const - { - return angle_; - } - - inline const osg::Vec3 &Particle::getAngularVelocity() const - { - return angular_vel_; - } - - inline const osg::Vec3 &Particle::getPreviousAngle() const - { - return prev_angle_; - } + inline const osg::Vec3 &Particle::getAngle() const + { + return angle_; + } + + inline const osg::Vec3 &Particle::getAngularVelocity() const + { + return angular_vel_; + } + + inline const osg::Vec3 &Particle::getPreviousAngle() const + { + return prev_angle_; + } inline void Particle::kill() { @@ -422,30 +422,30 @@ namespace osgParticle inline void Particle::setAngle(const osg::Vec3 &a) { - angle_ = a; - } - - inline void Particle::setAngularVelocity(const osg::Vec3 &v) - { - angular_vel_ = v; - } - - inline void Particle::addAngularVelocity(const osg::Vec3 &dv) - { - angular_vel_ += dv; - } - - inline void Particle::transformAngleVelocity(const osg::Matrix &xform) - { - // this should be optimized! - - osg::Vec3 a1 = angle_ + angular_vel_; - - angle_ = xform.preMult(angle_); - a1 = xform.preMult(a1); - - angular_vel_ = a1 - angle_; - } + angle_ = a; + } + + inline void Particle::setAngularVelocity(const osg::Vec3 &v) + { + angular_vel_ = v; + } + + inline void Particle::addAngularVelocity(const osg::Vec3 &dv) + { + angular_vel_ += dv; + } + + inline void Particle::transformAngleVelocity(const osg::Matrix &xform) + { + // this should be optimized! + + osg::Vec3 a1 = angle_ + angular_vel_; + + angle_ = xform.preMult(angle_); + a1 = xform.preMult(a1); + + angular_vel_ = a1 - angle_; + } inline float Particle::getMass() const { @@ -473,9 +473,9 @@ namespace osgParticle case QUAD: glBegin(GL_QUADS); break; - case LINE: - glBegin(GL_LINES); - break; + case LINE: + glBegin(GL_LINES); + break; default: ; } } @@ -486,7 +486,7 @@ namespace osgParticle { case POINT: case QUAD: - case LINE: + case LINE: glEnd(); break; default: ; @@ -499,18 +499,18 @@ namespace osgParticle } inline void Particle::setTextureTile(int sTile, int tTile, int numTiles) - { - s_tile_ = 1.0f / static_cast(sTile); - t_tile_ = 1.0f / static_cast(tTile); - if (numTiles <= 0) - { - num_tile_ = sTile * tTile; - } - else - { - num_tile_ = numTiles; - } - } + { + s_tile_ = 1.0f / static_cast(sTile); + t_tile_ = 1.0f / static_cast(tTile); + if (numTiles <= 0) + { + num_tile_ = sTile * tTile; + } + else + { + num_tile_ = numTiles; + } + } } diff --git a/include/osgParticle/ParticleEffect b/include/osgParticle/ParticleEffect index dbe66f4ac..e824d3e9a 100644 --- a/include/osgParticle/ParticleEffect +++ b/include/osgParticle/ParticleEffect @@ -25,11 +25,13 @@ namespace osgParticle public: ParticleEffect(): + _useLocalParticleSystem(true), _scale(1.0f), _intensity(1.0f), _startTime(0.0), - _duration(1.0), - _direction(0.0f,0.0f,1.0f) + _emitterDuration(1.0), + _particleDuration(1.0), + _wind(0.0f,0.0f,0.0f) {} ParticleEffect(const ParticleEffect& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY); @@ -40,6 +42,9 @@ namespace osgParticle virtual bool isSameKindAs(const osg::Object *obj) const { return dynamic_cast(obj) != 0; } virtual void accept(osg::NodeVisitor& nv) { if (nv.validNodeMask(*this)) { nv.pushOntoNodePath(this); nv.apply(*this); nv.popFromNodePath(); } } + void setUseLocalParticleSystem(bool local); + bool getUseLocalParticleSystem() const { return _useLocalParticleSystem; } + void setPosition(const osg::Vec3& position); const osg::Vec3& getPosition() const { return _position; } @@ -52,9 +57,17 @@ namespace osgParticle void setStartTime(double startTime); double getStartTime() const { return _startTime; } - void setDuration(double duration); - double getDuration() const { return _duration; } + void setEmitterDuration(double duration); + double getEmitterDuration() const { return _emitterDuration; } + void setParticleDuration(double duration); + double getParticleDuration() const { return _particleDuration; } + + void setWind(const osg::Vec3& wind); + const osg::Vec3& getWind() const { return _wind; } + + /// Get whether all particles are dead + bool areAllParticlesDead() const { return _particleSystem.valid()?_particleSystem->areAllParticlesDead():true; } virtual Emitter* getEmitter() = 0; virtual const Emitter* getEmitter() const = 0; @@ -62,8 +75,9 @@ namespace osgParticle virtual Program* getProgram() = 0; virtual const Program* getProgram() const = 0; - virtual ParticleSystem* getParticleSystem() { return _particleSystem.get(); } - virtual const ParticleSystem* getParticleSystem() const { return _particleSystem.get(); } + void setParticleSystem(ParticleSystem* ps); + inline ParticleSystem* getParticleSystem() { return _particleSystem.get(); } + inline const ParticleSystem* getParticleSystem() const { return _particleSystem.get(); } virtual void setDefaults(); @@ -74,13 +88,15 @@ namespace osgParticle protected: osg::ref_ptr _particleSystem; - + + bool _useLocalParticleSystem; osg::Vec3 _position; float _scale; float _intensity; double _startTime; - double _duration; - osg::Vec3 _direction; + double _emitterDuration; + double _particleDuration; + osg::Vec3 _wind; }; } diff --git a/include/osgParticle/ParticleSystem b/include/osgParticle/ParticleSystem index 00a512768..55da29840 100644 --- a/include/osgParticle/ParticleSystem +++ b/include/osgParticle/ParticleSystem @@ -107,6 +107,9 @@ namespace osgParticle /// Get the number of dead particles. inline int numDeadParticles() const; + + /// Get whether all particles are dead + inline bool areAllParticlesDead() const { return numDeadParticles()==numParticles(); } /// Get a pointer to the i-th particle. inline Particle *getParticle(int i); diff --git a/include/osgParticle/SmokeEffect b/include/osgParticle/SmokeEffect index 4bd51b340..ce9effd67 100644 --- a/include/osgParticle/SmokeEffect +++ b/include/osgParticle/SmokeEffect @@ -16,7 +16,7 @@ #include #include -#include +#include namespace osgParticle { @@ -34,7 +34,7 @@ namespace osgParticle virtual void setDefaults(); virtual void setUpEmitterAndProgram(); - + virtual Emitter* getEmitter() { return _emitter.get(); } virtual const Emitter* getEmitter() const { return _emitter.get(); } @@ -44,7 +44,7 @@ namespace osgParticle protected: osg::ref_ptr _emitter; - osg::ref_ptr _program; + osg::ref_ptr _program; }; } diff --git a/include/osgUtil/IntersectVisitor b/include/osgUtil/IntersectVisitor index 7f9d8a02f..ed2d161a8 100644 --- a/include/osgUtil/IntersectVisitor +++ b/include/osgUtil/IntersectVisitor @@ -63,8 +63,11 @@ class OSGUTIL_EXPORT Hit float getRatio() const { return _ratio; } const osg::LineSegment* getOriginalLineSegment() const { return _originalLineSegment.get(); } const osg::LineSegment* getLocalLineSegment() const { return _localLineSegment.get(); } + osg::NodePath& getNodePath() { return _nodePath; } const osg::NodePath& getNodePath() const { return _nodePath; } + osg::Geode* getGeode() { return _geode.get(); } const osg::Geode* getGeode() const { return _geode.get(); } + osg::Drawable* getDrawable() { return _drawable.get(); } const osg::Drawable* getDrawable() const { return _drawable.get(); } const osg::RefMatrix* getMatrix() const { return _matrix.get(); } const osg::RefMatrix* getInverseMatrix() const { return _inverse.get(); } diff --git a/src/osgParticle/ExplosionDebriEffect.cpp b/src/osgParticle/ExplosionDebriEffect.cpp new file mode 100644 index 000000000..b2b88a8e8 --- /dev/null +++ b/src/osgParticle/ExplosionDebriEffect.cpp @@ -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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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(_emitter->getCounter()); + if (counter) + { + counter->setRateRange(2000*_intensity,2000*_intensity); + } + + osgParticle::SectorPlacer* placer = dynamic_cast(_emitter->getPlacer()); + if (placer) + { + placer->setCenter(_position); + placer->setRadiusRange(0.0f*_scale,0.25f*_scale); + } + + osgParticle::RadialShooter* shooter = dynamic_cast(_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); + } + +} + diff --git a/src/osgParticle/ExplosionEffect.cpp b/src/osgParticle/ExplosionEffect.cpp index e213d20a0..15b310f90 100644 --- a/src/osgParticle/ExplosionEffect.cpp +++ b/src/osgParticle/ExplosionEffect.cpp @@ -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(_emitter->getCounter()); + if (counter) + { + counter->setRateRange(50*_intensity,100*_intensity); + } + + osgParticle::SectorPlacer* placer = dynamic_cast(_emitter->getPlacer()); + if (placer) + { + placer->setCenter(_position); + placer->setRadiusRange(0.0f*_scale,0.25f*_scale); + } + + osgParticle::RadialShooter* shooter = dynamic_cast(_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); + } } diff --git a/src/osgParticle/FireEffect.cpp b/src/osgParticle/FireEffect.cpp index 969208bd5..949454ad1 100644 --- a/src/osgParticle/FireEffect.cpp +++ b/src/osgParticle/FireEffect.cpp @@ -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(_emitter->getCounter()); + if (counter) + { + counter->setRateRange(10*_intensity,15*_intensity); + } + + osgParticle::SectorPlacer* placer = dynamic_cast(_emitter->getPlacer()); + if (placer) + { + placer->setCenter(_position); + placer->setRadiusRange(0.0f*_scale,0.25f*_scale); + } + + osgParticle::RadialShooter* shooter = dynamic_cast(_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); } } diff --git a/src/osgParticle/FluidFrictionOperator.cpp b/src/osgParticle/FluidFrictionOperator.cpp index 81325c520..3e2b9c662 100644 --- a/src/osgParticle/FluidFrictionOperator.cpp +++ b/src/osgParticle/FluidFrictionOperator.cpp @@ -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; diff --git a/src/osgParticle/GNUmakefile b/src/osgParticle/GNUmakefile index 1913c51b5..d03342fe9 100644 --- a/src/osgParticle/GNUmakefile +++ b/src/osgParticle/GNUmakefile @@ -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\ diff --git a/src/osgParticle/ParticleEffect.cpp b/src/osgParticle/ParticleEffect.cpp index b9366842d..112ebb910 100644 --- a/src/osgParticle/ParticleEffect.cpp +++ b/src/osgParticle/ParticleEffect.cpp @@ -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); + } } diff --git a/src/osgParticle/SmokeEffect.cpp b/src/osgParticle/SmokeEffect.cpp index 2b588ed58..9415dbe3d 100644 --- a/src/osgParticle/SmokeEffect.cpp +++ b/src/osgParticle/SmokeEffect.cpp @@ -15,8 +15,6 @@ #include #include -#include -#include #include #include @@ -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(_emitter->getCounter()); + if (counter) + { + counter->setRateRange(3*_intensity,5*_intensity); + } + + osgParticle::SectorPlacer* placer = dynamic_cast(_emitter->getPlacer()); + if (placer) + { + placer->setCenter(_position); + placer->setRadiusRange(0.0f*_scale,0.25f*_scale); + } + + osgParticle::RadialShooter* shooter = dynamic_cast(_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); } } diff --git a/src/osgPlugins/osgParticle/GNUmakefile b/src/osgPlugins/osgParticle/GNUmakefile index a6e95c292..fc9f51ea8 100644 --- a/src/osgPlugins/osgParticle/GNUmakefile +++ b/src/osgPlugins/osgParticle/GNUmakefile @@ -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\ diff --git a/src/osgPlugins/osgParticle/IO_ExplosionDebriEffect.cpp b/src/osgPlugins/osgParticle/IO_ExplosionDebriEffect.cpp new file mode 100644 index 000000000..de222fde2 --- /dev/null +++ b/src/osgPlugins/osgParticle/IO_ExplosionDebriEffect.cpp @@ -0,0 +1,28 @@ + +#include + +#include +#include +#include + +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; +} diff --git a/src/osgPlugins/osgParticle/IO_ExplosionEffect.cpp b/src/osgPlugins/osgParticle/IO_ExplosionEffect.cpp new file mode 100644 index 000000000..f6e2ab564 --- /dev/null +++ b/src/osgPlugins/osgParticle/IO_ExplosionEffect.cpp @@ -0,0 +1,28 @@ + +#include + +#include +#include +#include + +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; +} diff --git a/src/osgPlugins/osgParticle/IO_FireEffect.cpp b/src/osgPlugins/osgParticle/IO_FireEffect.cpp new file mode 100644 index 000000000..b00825af6 --- /dev/null +++ b/src/osgPlugins/osgParticle/IO_FireEffect.cpp @@ -0,0 +1,28 @@ + +#include + +#include +#include +#include + +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; +} diff --git a/src/osgPlugins/osgParticle/IO_ParticleEffect.cpp b/src/osgPlugins/osgParticle/IO_ParticleEffect.cpp new file mode 100644 index 000000000..f1eca92e5 --- /dev/null +++ b/src/osgPlugins/osgParticle/IO_ParticleEffect.cpp @@ -0,0 +1,156 @@ + +#include + +#include +#include +#include + +#include + +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(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 readObject = fr.readObjectOfType(osgDB::type_wrapper()); + if (readObject.valid()) + { + osgParticle::ParticleSystem* ps = static_cast(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(object); + + fw.indent()<<"position "< + +#include +#include +#include + +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; +} diff --git a/src/osgProducer/Viewer.cpp b/src/osgProducer/Viewer.cpp index ca602a229..e7906bbbc 100644 --- a/src/osgProducer/Viewer.cpp +++ b/src/osgProducer/Viewer.cpp @@ -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."<(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"<