diff --git a/include/osgParticle/FluidProgram b/include/osgParticle/FluidProgram new file mode 100644 index 000000000..6ffc75244 --- /dev/null +++ b/include/osgParticle/FluidProgram @@ -0,0 +1,114 @@ +/* -*-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_FLUIDPROGRAM_ +#define OSGPARTICLE_FLUIDPROGRAM_ 1 + +#include +#include + +#include +#include +#include +#include + +namespace osgParticle +{ + + /** A program class for performing operations on particles using a sequence of operators. + To use a FluidProgram you have to create some Operator objects and + add them to the program. + All operators will be applied to each particle in the same order they've been added to the program. + */ + class OSGPARTICLE_EXPORT FluidProgram: public Program { + public: + FluidProgram(); + FluidProgram(const FluidProgram& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY); + + META_Node(osgParticle,FluidProgram); + + /// Set the viscosity of the fluid. + inline void setFluidViscosity(float v) + { + _viscosity = v; + _A = 6 * osg::PI * _viscosity; + } + + /// Get the viscosity of the fluid. + inline float getFluidViscosity() const { return _viscosity; } + + /// Set the density of the fluid. + inline void setFluidDensity(float d) + { + _density = d; + _B = 0.2f * osg::PI * _density; + } + + /// Get the density of the fluid. + inline float getFluidDensity() const { return _density; } + + + /// 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 acceleration vector. + inline void setAcceleration(const osg::Vec3& v) { _acceleration = v; } + + /// Get the acceleration vector. + inline const osg::Vec3& getAcceleration() const { return _acceleration; } + + /** Set the acceleration vector to the gravity on earth (0, 0, -9.81). + The acceleration will be multiplied by the scale parameter. + */ + inline void setToGravity(float scale = 1.0f) { _acceleration.set(0, 0, -9.81f*scale); } + + /// Set the fluid parameters as for air (20°C temperature). + inline void setFluidToAir() + { + setToGravity(1.0f); + setFluidDensity(1.2929f); + setFluidViscosity(1.8e-5f); + } + + /// Set the fluid parameters as for pure water (20°C temperature). + inline void setFluidToWater() + { + setToGravity(1.0f); + setFluidDensity(1.0f); + setFluidViscosity(1.002e-3f); + } + + + protected: + + virtual ~FluidProgram() {} + FluidProgram& operator=(const FluidProgram&) { return *this; } + + virtual void execute(double dt); + + osg::Vec3 _acceleration; + float _viscosity; + float _density; + osg::Vec3 _wind; + + float _A; + float _B; + }; + + +} + +#endif diff --git a/src/osgParticle/FluidProgram.cpp b/src/osgParticle/FluidProgram.cpp new file mode 100644 index 000000000..54887e9b7 --- /dev/null +++ b/src/osgParticle/FluidProgram.cpp @@ -0,0 +1,47 @@ +#include + +osgParticle::FluidProgram::FluidProgram(): + Program() +{ + setFluidToAir(); +} + +osgParticle::FluidProgram::FluidProgram(const FluidProgram& copy, const osg::CopyOp& copyop): + Program(copy, copyop), + _acceleration(copy._acceleration), + _viscosity(copy._viscosity), + _density(copy._density), + _wind(copy._wind), + _A(copy._A), + _B(copy._B) +{ +} + +void osgParticle::FluidProgram::execute(double dt) +{ + const float four_over_three = 4.0f/3.0f; + ParticleSystem *ps = getParticleSystem(); + int n = ps->numParticles(); + for (int i=0; igetParticle(i); + if (particle->isAlive()) + { + float radius = particle->getRadius(); + float Area = osg::PI*radius*radius; + float Volume = Area*radius*four_over_three; + + // compute force due to gravity + boyancy of displacing the fluid that the particle is emersed in. + osg::Vec3 force = _acceleration * (particle->getMass() - _density*Volume); + + // compute force due to friction + osg::Vec3 relative_wind = particle->getVelocity()-_wind; + force -= relative_wind * Area * (_A + _B*relative_wind.length()); + + // divide force by mass to get acceleration. + force *= particle->getMassInv()*dt; + + particle->addVelocity(force); + } + } +}