Files
simgear/simgear/scene/model/particles.hxx
T
James Turner 5a1ed52d7c Particles: rewrite global manager for thread-safety
Avoid re-registering the global node callback each time a new particle
animation is loaded, and use mutexes to protected all shared data.
2020-08-26 10:37:54 +01:00

197 lines
5.7 KiB
C++

// particles.hxx - classes to manage particles
// Copyright (C) 2008 Tiago Gusm�o
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program 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 GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef _SG_PARTICLES_HXX
#define _SG_PARTICLES_HXX 1
#include <osg/ref_ptr>
#include <osgParticle/SmokeTrailEffect>
#include <osgParticle/Particle>
#include <osgParticle/ModularEmitter>
#include <osgDB/ReaderWriter>
#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <osgDB/ReadFile>
#include <osg/Notify>
#include <osg/Vec3>
namespace osg
{
class Group;
class MatrixTransform;
class Node;
class NodeVisitor;
}
namespace osgParticle
{
class ParticleSystem;
class ParticleSystemUpdater;
}
#include <simgear/scene/util/SGNodeMasks.hxx>
#include <simgear/props/props.hxx>
#include <simgear/props/condition.hxx>
#include <simgear/structure/SGExpression.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
#include <simgear/math/SGQuat.hxx>
#include <simgear/math/SGMatrix.hxx>
namespace simgear
{
class ParticlesGlobalManager;
class Particles : public osg::NodeCallback
{
public:
Particles() = default;
void operator()(osg::Node* node, osg::NodeVisitor* nv) override;
void setupShooterSpeedData(const SGPropertyNode* configNode,
SGPropertyNode* modelRoot);
void setupCounterData(const SGPropertyNode* configNode,
SGPropertyNode* modelRoot);
void setupCounterCondition(const SGPropertyNode* configNode,
SGPropertyNode* modelRoot);
void setupCounterCondition(float counterStaticValue,
float counterStaticExtraRange);
void setupStartSizeData(const SGPropertyNode* configNode,
SGPropertyNode* modelRoot);
void setupEndSizeData(const SGPropertyNode* configNode,
SGPropertyNode* modelRoot);
void setupLifeData(const SGPropertyNode* configNode,
SGPropertyNode* modelRoot);
void setupStaticSizeData(float startSize, float endSize)
{
this->startSize=startSize;
this->endSize=endSize;
}
void setGeneralData(osgParticle::RadialShooter* shooter,
osgParticle::RandomRateCounter* counter,
osgParticle::ParticleSystem* particleSys,
osgParticle::FluidProgram* program)
{
this->shooter = shooter;
this->counter = counter;
this->particleSys = particleSys;
this->program = program;
}
void setupProgramGravity(bool useGravity)
{
this->useGravity = useGravity;
}
void setupProgramWind(bool useWind)
{
this->useWind = useWind;
}
//component: r=0, g=1, ... ; color: 0=start color, 1=end color
void setupColorComponent(const SGPropertyNode* configNode,
SGPropertyNode* modelRoot, int color,
int component);
void setupStaticColorComponent(float r1, float g1, float b1, float a1,
float r2, float g2, float b2, float a2);
protected:
friend class ParticlesGlobalManager;
float shooterExtraRange;
float counterExtraRange;
SGSharedPtr<SGExpressiond> shooterValue;
SGSharedPtr<SGExpressiond> counterValue;
SGSharedPtr<SGExpressiond> colorComponents[8];
SGSharedPtr<SGExpressiond> startSizeValue;
SGSharedPtr<SGExpressiond> endSizeValue;
SGSharedPtr<SGExpressiond> lifeValue;
SGSharedPtr<SGCondition> counterCond;
float staticColorComponents[8];
float startSize;
float endSize;
float counterStaticValue;
float counterStaticExtraRange;
osg::ref_ptr<osgParticle::RadialShooter> shooter;
osg::ref_ptr<osgParticle::RandomRateCounter> counter;
osg::ref_ptr<osgParticle::ParticleSystem> particleSys;
osg::ref_ptr<osgParticle::FluidProgram> program;
osg::ref_ptr<osg::MatrixTransform> particleFrame;
bool useGravity = false;
bool useWind = false;
};
class ParticlesGlobalManager
{
public:
~ParticlesGlobalManager();
static ParticlesGlobalManager* instance();
static void clear();
bool isEnabled() const;
osg::ref_ptr<osg::Group> appendParticles(const SGPropertyNode* configNode, SGPropertyNode* modelRoot, const osgDB::Options* options);
osg::Group* getCommonRoot();
osg::Geode* getCommonGeode();
osgParticle::ParticleSystemUpdater* getPSU();
void setFrozen(bool e);
bool isFrozen() const;
void setSwitchNode(const SGPropertyNode* n);
/**
* Set and get the wind vector for particles in the
* atmosphere. This vector is in the Z-up Y-north frame, and the
* magnitude is the velocity in meters per second.
*/
void setWindVector(const osg::Vec3& wind);
void setWindFrom(const double from_deg, const double speed_kt);
osg::Vec3 getWindVector() const;
private:
ParticlesGlobalManager();
class ParticlesGlobalManagerPrivate;
// because Private inherits NodeCallback, we need to own it
// via an osg::ref_ptr
osg::ref_ptr<ParticlesGlobalManagerPrivate> d;
};
} // namespace simgear
#endif