Checked in osgParticle, writtten by Marco Jez.

This commit is contained in:
Robert Osfield
2002-06-05 12:44:55 +00:00
parent f8ffc692be
commit 9ba7505d1e
110 changed files with 10467 additions and 0 deletions

View File

@@ -0,0 +1,99 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_ACCELOPERATOR_
#define OSGPARTICLE_ACCELOPERATOR_ 1
#include <osgParticle/ModularProgram>
#include <osgParticle/Operator>
#include <osgParticle/Particle>
#include <osg/CopyOp>
#include <osg/Object>
#include <osg/Vec3>
namespace osgParticle
{
/** An operator class that applies a constant acceleration to the particles.
*/
class AccelOperator: public Operator {
public:
inline AccelOperator();
inline AccelOperator(const AccelOperator &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
META_Object(AccelOperator);
/// Get the acceleration vector.
inline const osg::Vec3 &getAcceleration() const;
/// Set the acceleration vector.
inline void setAcceleration(const osg::Vec3 &v);
/** Quickly set the acceleration vector to the gravity on earth (0, 0, -9.81).
The acceleration will be multiplied by the <CODE>scale</CODE> parameter.
*/
inline void setToGravity(float scale = 1);
/// Apply the acceleration to a particle. Do not call this method manually.
inline void operate(Particle *P, double dt);
/// Perform some initializations. Do not call this method manually.
inline void beginOperate(Program *prg);
protected:
virtual ~AccelOperator() {}
AccelOperator &operator=(const AccelOperator &) { return *this; }
private:
osg::Vec3 accel_;
osg::Vec3 xf_accel_;
};
// INLINE FUNCTIONS
inline AccelOperator::AccelOperator()
: Operator(), accel_(0, 0, 0)
{
}
inline AccelOperator::AccelOperator(const AccelOperator &copy, const osg::CopyOp &copyop)
: Operator(copy, copyop), accel_(copy.accel_)
{
}
inline const osg::Vec3 &AccelOperator::getAcceleration() const
{
return accel_;
}
inline void AccelOperator::setAcceleration(const osg::Vec3 &v)
{
accel_ = v;
}
inline void AccelOperator::setToGravity(float scale)
{
accel_.set(0, 0, -9.80665f * scale);
}
inline void AccelOperator::operate(Particle *P, double dt)
{
P->addVelocity(xf_accel_ * dt);
}
inline void AccelOperator::beginOperate(Program *prg)
{
if (prg->getReferenceFrame() == ModularProgram::RELATIVE_TO_PARENTS) {
xf_accel_ = prg->rotateLocalToWorld(accel_);
} else {
xf_accel_ = accel_;
}
}
}
#endif

View File

@@ -0,0 +1,74 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_CENTEREDPLACER_
#define OSGPARTICLE_CENTEREDPLACER_ 1
#include <osgParticle/Placer>
#include <osg/CopyOp>
#include <osg/Object>
#include <osg/Vec3>
namespace osgParticle
{
/** An abstract placer base class for placers which need a <I>center point</I>.
*/
class CenteredPlacer: public Placer {
public:
inline CenteredPlacer();
inline CenteredPlacer(const CenteredPlacer &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
virtual const char *className() const { return "CenteredPlacer"; }
virtual bool isSameKindAs(const osg::Object *obj) const { return dynamic_cast<const Placer *>(obj) != 0; }
/// Get the center point.
inline const osg::Vec3 &getCenter() const;
/// Set the center point.
inline void setCenter(const osg::Vec3 &v);
/// Set the center point.
inline void setCenter(float x, float y, float z);
protected:
virtual ~CenteredPlacer() {}
private:
osg::Vec3 center_;
};
// INLINE FUNCTIONS
inline CenteredPlacer::CenteredPlacer()
: Placer(), center_(0, 0, 0)
{
}
inline CenteredPlacer::CenteredPlacer(const CenteredPlacer &copy, const osg::CopyOp &copyop)
: Placer(copy, copyop), center_(copy.center_)
{
}
inline const osg::Vec3 &CenteredPlacer::getCenter() const
{
return center_;
}
inline void CenteredPlacer::setCenter(const osg::Vec3 &v)
{
center_ = v;
}
inline void CenteredPlacer::setCenter(float x, float y, float z)
{
center_.set(x, y, z);
}
}
#endif

View File

@@ -0,0 +1,44 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_COUNTER_
#define OSGPARTICLE_COUNTER_ 1
#include <osg/CopyOp>
#include <osg/Object>
namespace osgParticle
{
class Counter: public osg::Object {
public:
inline Counter();
inline Counter(const Counter &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
virtual const char *className() const { return "Counter"; }
virtual bool isSameKindAs(const osg::Object *obj) const { return dynamic_cast<const Counter *>(obj) != 0; }
virtual int numParticlesToCreate(double dt) const = 0;
protected:
~Counter() {}
Counter &operator=(const Counter &) { return *this; }
};
// INLINE FUNCTIONS
inline Counter::Counter()
: osg::Object()
{
}
inline Counter::Counter(const Counter &copy, const osg::CopyOp &copyop)
: osg::Object(copy, copyop)
{
}
}
#endif

View File

@@ -0,0 +1,96 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_EMITTER_
#define OSGPARTICLE_EMITTER_ 1
#include <osgParticle/Export>
#include <osgParticle/ParticleProcessor>
#include <osgParticle/Particle>
#include <osg/Object>
#include <osg/Node>
#include <osg/NodeVisitor>
#include <osg/CopyOp>
namespace osgParticle
{
/** An abstract base class for particle emitters.
Descendant classes must override the <CODE>emit()</CODE> method to generate new particles by
calling the <CODE>ParticleSystem::createParticle()</CODE> method on the particle system associated
to the emitter.
*/
class OSGPARTICLE_EXPORT Emitter: public ParticleProcessor {
public:
Emitter();
Emitter(const Emitter &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
virtual const char *className() const { return "Emitter"; }
virtual bool isSameKindAs(const osg::Object *obj) { return dynamic_cast<const Emitter*>(obj) != 0; }
virtual void accept(osg::NodeVisitor& nv) { if (nv.validNodeMask(*this)) { nv.pushOntoNodePath(this); nv.apply(*this); nv.popFromNodePath(); } }
/// Get the particle template.
inline const Particle &getParticleTemplate() const;
/// Set the particle template (particle is copied).
inline void setParticleTemplate(const Particle &p);
/// Return whether the particle system's default template should be used.
inline bool getUseDefaultTemplate() const;
/** Set whether the default particle template should be used.
When this flag is true, the particle template is ignored, and the
particle system's default template is used instead.
*/
inline void setUseDefaultTemplate(bool v);
protected:
virtual ~Emitter() {}
Emitter &operator=(const Emitter &) { return *this; }
inline void process(double dt);
virtual void emit(double dt) = 0;
private:
bool usedeftemp_;
Particle ptemp_;
};
// INLINE FUNCTIONS
inline const Particle &Emitter::getParticleTemplate() const
{
return ptemp_;
}
inline void Emitter::setParticleTemplate(const Particle &p)
{
ptemp_ = p;
usedeftemp_ = false;
}
inline bool Emitter::getUseDefaultTemplate() const
{
return usedeftemp_;
}
inline void Emitter::setUseDefaultTemplate(bool v)
{
usedeftemp_ = v;
}
inline void Emitter::process(double dt)
{
emit(dt);
}
}
#endif

View File

@@ -0,0 +1,30 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_EXPORT_
#define OSGPARTICLE_EXPORT_ 1
#if defined(WIN32) && !(defined(__CYGWIN__) || defined(__MINGW32__))
#pragma warning( disable : 4244 )
#pragma warning( disable : 4251 )
#pragma warning( disable : 4275 )
#pragma warning( disable : 4786 )
#pragma warning( disable : 4290 )
#endif
#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__) || defined( __MWERKS__)
# ifdef OSGPARTICLE_LIBRARY
# define OSGPARTICLE_EXPORT __declspec(dllexport)
# else
# define OSGPARTICLE_EXPORT __declspec(dllimport)
# endif /* OSGPARTICLE_LIBRARY */
#else
# define OSGPARTICLE_EXPORT
#endif
#endif

View File

@@ -0,0 +1,132 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_FLUIDFRICTIONOPERATOR_
#define OSGPARTICLE_FLUIDFRICTIONOPERATOR_ 1
#include <osgParticle/Export>
#include <osgParticle/Operator>
#include <osg/CopyOp>
#include <osg/Object>
#include <osg/Math>
namespace osgParticle
{
class Particle;
/** An operator that simulates the friction of a fluid.
By using this operator you can let the particles move in a fluid of a given <I>density</I>
and <I>viscosity</I>. There are two functions to quickly setup the parameters for pure water
and air. You can decide whether to compute the forces using the particle's physical
radius or another value, by calling the <CODE>setOverrideRadius()</CODE> method.
*/
class OSGPARTICLE_EXPORT FluidFrictionOperator: public Operator {
public:
FluidFrictionOperator();
FluidFrictionOperator(const FluidFrictionOperator &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
META_Object(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;
/// Set the viscosity of the fluid.
inline void setFluidViscosity(float v);
/// Get the overriden radius value.
inline float getOverrideRadius() const;
/// Set the overriden radius value (pass 0 if you want to use particle's radius).
inline void setOverrideRadius(float r);
/// Set the fluid parameters as for air (20<32>C temperature).
inline void setFluidToAir();
/// Set the fluid parameters as for pure water (20<32>C temperature).
inline void setFluidToWater();
/// Apply the friction forces to a particle. Do not call this method manually.
void operate(Particle *P, double dt);
/// Perform some initializations. Do not call this method manually.
inline void beginOperate(Program *prg);
protected:
virtual ~FluidFrictionOperator() {}
FluidFrictionOperator &operator=(const FluidFrictionOperator &) { return *this; }
private:
float A_;
float B_;
float density_;
float viscosity_;
float ovr_rad_;
Program *current_program_;
};
// INLINE FUNCTIONS
inline float FluidFrictionOperator::getFluidDensity() const
{
return density_;
}
inline float FluidFrictionOperator::getFluidViscosity() const
{
return viscosity_;
}
inline void FluidFrictionOperator::setFluidDensity(float d)
{
density_ = d;
B_ = 0.2f * osg::PI * density_;
}
inline void FluidFrictionOperator::setFluidViscosity(float v)
{
viscosity_ = v;
A_ = 6 * osg::PI * viscosity_;
}
inline void FluidFrictionOperator::setFluidToAir()
{
setFluidViscosity(1.8e-5f);
setFluidDensity(1.2929f);
}
inline void FluidFrictionOperator::setFluidToWater()
{
setFluidViscosity(1.002e-3f);
setFluidDensity(1.0f);
}
inline float FluidFrictionOperator::getOverrideRadius() const
{
return ovr_rad_;
}
inline void FluidFrictionOperator::setOverrideRadius(float r)
{
ovr_rad_ = r;
}
inline void FluidFrictionOperator::beginOperate(Program *prg)
{
current_program_ = prg;
}
}
#endif

View File

@@ -0,0 +1,89 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_FORCEOPERATOR_
#define OSGPARTICLE_FORCEOPERATOR_ 1
#include <osgParticle/ModularProgram>
#include <osgParticle/Operator>
#include <osgParticle/Particle>
#include <osg/CopyOp>
#include <osg/Object>
#include <osg/Vec3>
namespace osgParticle
{
/** An operator that applies a constant force to the particles.
Remember that if the mass of particles is expressed in <U>kg</U> and the lengths are
expressed in <U>meters</U>, then the force should be expressed in <U>Newtons</U>.
*/
class ForceOperator: public Operator {
public:
inline ForceOperator();
inline ForceOperator(const ForceOperator &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
META_Object(ForceOperator);
/// Get the force vector.
inline const osg::Vec3 &getForce() const;
/// Set the force vector.
inline void setForce(const osg::Vec3 &f);
/// Apply the force to a particle. Do not call this method manually.
inline void operate(Particle *P, double dt);
/// Perform some initialization. Do not call this method manually.
inline void beginOperate(Program *prg);
protected:
virtual ~ForceOperator() {};
ForceOperator &operator=(const ForceOperator &) { return *this; }
private:
osg::Vec3 force_;
osg::Vec3 xf_force_;
};
// INLINE FUNCTIONS
inline ForceOperator::ForceOperator()
: Operator(), force_(0, 0, 0)
{
}
inline ForceOperator::ForceOperator(const ForceOperator &copy, const osg::CopyOp &copyop)
: Operator(copy, copyop), force_(copy.force_)
{
}
inline const osg::Vec3 &ForceOperator::getForce() const
{
return force_;
}
inline void ForceOperator::setForce(const osg::Vec3 &v)
{
force_ = v;
}
inline void ForceOperator::operate(Particle *P, double dt)
{
P->addVelocity(xf_force_ * (P->getMassInv() * dt));
}
inline void ForceOperator::beginOperate(Program *prg)
{
if (prg->getReferenceFrame() == ModularProgram::RELATIVE_TO_PARENTS) {
xf_force_ = prg->rotateLocalToWorld(force_);
} else {
xf_force_ = force_;
}
}
}
#endif

View File

@@ -0,0 +1,77 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_INTERPOLATOR_
#define OSGPARTICLE_INTERPOLATOR_
#include <osgParticle/range>
#include <osg/CopyOp>
#include <osg/Object>
#include <osg/Vec2>
#include <osg/Vec3>
#include <osg/Vec4>
namespace osgParticle
{
/// An abstract base class for implementing interpolators.
class Interpolator : public osg::Object {
public:
Interpolator()
: osg::Object() {}
Interpolator(const Interpolator &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY)
: osg::Object(copy, copyop) {}
virtual const char *className() const { return "Interpolator"; }
virtual bool isSameKindAs(const osg::Object *obj) const { return dynamic_cast<const Interpolator *>(obj) != 0; }
/// Interpolate between floats. Must be overriden in descendant classes.
virtual float interpolate(float t, float y1, float y2) const = 0;
/// Interpolate between 2-dimensional vectors. Default behavior is to interpolate each component separately.
virtual osg::Vec2 interpolate(float t, const osg::Vec2 &y1, const osg::Vec2 &y2) const
{
return osg::Vec2(
interpolate(t, y1.x(), y2.x()),
interpolate(t, y1.y(), y2.y())
);
}
/// Interpolate between 3-dimensional vectors. Default behavior is to interpolate each component separately.
virtual osg::Vec3 interpolate(float t, const osg::Vec3 &y1, const osg::Vec3 &y2) const
{
return osg::Vec3(
interpolate(t, y1.x(), y2.x()),
interpolate(t, y1.y(), y2.y()),
interpolate(t, y1.z(), y2.z())
);
}
/// Interpolate between 4-dimensional vectors. Default behavior is to interpolate each component separately.
virtual osg::Vec4 interpolate(float t, const osg::Vec4 &y1, const osg::Vec4 &y2) const
{
return osg::Vec4(
interpolate(t, y1.x(), y2.x()),
interpolate(t, y1.y(), y2.y()),
interpolate(t, y1.z(), y2.z()),
interpolate(t, y1.w(), y2.w())
);
}
template<class T_>
T_ interpolate(float t, const range<T_> &r) const
{
return interpolate(t, r.min, r.max);
}
protected:
virtual ~Interpolator() {}
};
}
#endif

View File

@@ -0,0 +1,41 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_LINEARINTERPOLATOR_
#define OSGPARTICLE_LINEARINTERPOLATOR_
#include <osgParticle/Interpolator>
#include <osg/CopyOp>
#include <osg/Object>
#include <osg/Vec3>
#include <osg/Vec4>
namespace osgParticle
{
/// A linear interpolator.
class LinearInterpolator: public Interpolator {
public:
LinearInterpolator()
: Interpolator() {}
LinearInterpolator(const LinearInterpolator &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY)
: Interpolator(copy, copyop) {}
META_Object(LinearInterpolator);
virtual float interpolate(float t, float y1, float y2) const
{
return y1 + (y2 - y1) * t;
}
protected:
virtual ~LinearInterpolator() {}
};
}
#endif

View File

@@ -0,0 +1,130 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_MODULAREMITTER_
#define OSGPARTICLE_MODULAREMITTER_ 1
#include <osgParticle/Export>
#include <osgParticle/Emitter>
#include <osgParticle/Particle>
#include <osgParticle/RandomRateCounter>
#include <osgParticle/Placer>
#include <osgParticle/PointPlacer>
#include <osgParticle/Shooter>
#include <osgParticle/RadialShooter>
#include <osgParticle/ParticleSystem>
#include <osg/ref_ptr>
#include <osg/CopyOp>
#include <osg/Object>
#include <osg/Node>
#include <osg/NodeVisitor>
namespace osgParticle
{
/** An emitter class that holds three objects to control the creation of particles.
These objects are a <I>counter</I>, a <I>placer</I> and a <I>shooter</I>.
The counter controls the number of particles to be emitted at each frame;
the placer must initialize the particle's position vector, while the shooter initializes
its velocity vector.
You can use the predefined counter/placer/shooter classes, or you can create your own.
*/
class OSGPARTICLE_EXPORT ModularEmitter: public Emitter {
public:
ModularEmitter();
ModularEmitter(const ModularEmitter &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
META_Node(ModularEmitter);
/// Get the counter object.
inline Counter *getCounter();
/// Get the const Counter object.
inline const Counter *getCounter() const;
/// Set the Counter object.
inline void setCounter(Counter *c);
/// Get the Placer object.
inline Placer *getPlacer();
/// Get the const Placer object.
inline const Placer *getPlacer() const;
/// Set the Placer object.
inline void setPlacer(Placer *p);
/// Get the Shooter object.
inline Shooter *getShooter();
/// Get the const Shooter object.
inline const Shooter *getShooter() const;
/// Set the Shooter object.
inline void setShooter(Shooter *s);
protected:
virtual ~ModularEmitter() {}
ModularEmitter &operator=(const ModularEmitter &) { return *this; }
void emit(double dt);
private:
osg::ref_ptr<Counter> counter_;
osg::ref_ptr<Placer> placer_;
osg::ref_ptr<Shooter> shooter_;
};
// INLINE FUNCTIONS
inline Counter *ModularEmitter::getCounter()
{
return counter_.get();
}
inline const Counter *ModularEmitter::getCounter() const
{
return counter_.get();
}
inline void ModularEmitter::setCounter(Counter *c)
{
counter_ = c;
}
inline Placer *ModularEmitter::getPlacer()
{
return placer_.get();
}
inline const Placer *ModularEmitter::getPlacer() const
{
return placer_.get();
}
inline void ModularEmitter::setPlacer(Placer *p)
{
placer_ = p;
}
inline Shooter *ModularEmitter::getShooter()
{
return shooter_.get();
}
inline const Shooter *ModularEmitter::getShooter() const
{
return shooter_.get();
}
inline void ModularEmitter::setShooter(Shooter *s)
{
shooter_ = s;
}
}
#endif

View File

@@ -0,0 +1,90 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_MODULARPROGRAM_
#define OSGPARTICLE_MODULARPROGRAM_ 1
#include <osgParticle/Export>
#include <osgParticle/Program>
#include <osgParticle/Operator>
#include <osg/CopyOp>
#include <osg/Object>
#include <osg/Node>
#include <osg/NodeVisitor>
namespace osgParticle
{
/** A program class for performing operations on particles using a sequence of <I>operators</I>.
To use a <CODE>ModularProgram</CODE> you have to create some <CODE>Operator</CODE> 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 ModularProgram: public Program {
public:
ModularProgram();
ModularProgram(const ModularProgram &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
META_Node(ModularProgram);
/// Get the number of operators.
inline int numOperators() const;
/// Add an operator to the list.
inline void addOperator(Operator *o);
/// Get a pointer to an operator in the list.
inline Operator *getOperator(int i);
/// Get a const pointer to an operator in the list.
inline const Operator *getOperator(int i) const;
/// Remove an operator from the list.
inline void removeOperator(int i);
protected:
virtual ~ModularProgram() {}
ModularProgram &operator=(const ModularProgram &) { return *this; }
void execute(double dt);
private:
typedef std::vector<osg::ref_ptr<Operator> > Operator_vector;
Operator_vector operators_;
};
// INLINE FUNCTIONS
inline int ModularProgram::numOperators() const
{
return static_cast<int>(operators_.size());
}
inline void ModularProgram::addOperator(Operator *o)
{
operators_.push_back(o);
}
inline Operator *ModularProgram::getOperator(int i)
{
return operators_[i].get();
}
inline const Operator *ModularProgram::getOperator(int i) const
{
return operators_[i].get();
}
inline void ModularProgram::removeOperator(int i)
{
operators_.erase(operators_.begin()+i);
}
}
#endif

View File

@@ -0,0 +1,119 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_MULTISEGMENTPLACER_
#define OSGPARTICLE_MULTISEGMENTPLACER_ 1
#include <osgParticle/Export>
#include <osgParticle/Placer>
#include <osgParticle/Particle>
#include <vector>
#include <utility>
#include <osg/Notify>
#include <osg/CopyOp>
#include <osg/Object>
#include <osg/Vec3>
namespace osgParticle {
/** A polyline-shaped particle placer.
This placer class sets the position of incoming particles by choosing a random point on the
specified sequence of connected segments.
*/
class OSGPARTICLE_EXPORT MultiSegmentPlacer: public Placer {
public:
MultiSegmentPlacer();
MultiSegmentPlacer(const MultiSegmentPlacer &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
META_Object(MultiSegmentPlacer);
/// Get the number of vertices which define the segments.
inline int numVertices() const;
/// Get a vertex.
inline const osg::Vec3 &getVertex(int i) const;
/// Set a vertex.
inline void setVertex(int i, const osg::Vec3 &v);
/// Set a vertex.
inline void setVertex(int i, float x, float y, float z);
/// Add a vertex.
inline void addVertex(const osg::Vec3 &v);
/// Add a vertex.
inline void addVertex(float x, float y, float z);
/// Remove a vertex.
inline void removeVertex(int i);
/// Place a partice. Called automatically by <CODE>ModularEmitter</CODE>, do not call this method manually.
void place(Particle *P) const;
protected:
virtual ~MultiSegmentPlacer() {}
MultiSegmentPlacer &operator=(const MultiSegmentPlacer &) { return *this; }
private:
typedef std::pair<osg::Vec3, float> Vertex_data;
typedef std::vector<Vertex_data> Vertex_vector;
Vertex_vector vx_;
float total_length_;
void recompute_length();
};
// INLINE FUNCTIONS
inline int MultiSegmentPlacer::numVertices() const
{
return static_cast<int>(vx_.size());
}
inline const osg::Vec3 &MultiSegmentPlacer::getVertex(int i) const
{
return vx_[i].first;
}
inline void MultiSegmentPlacer::setVertex(int i, const osg::Vec3 &v)
{
vx_[i].first = v;
recompute_length();
}
inline void MultiSegmentPlacer::setVertex(int i, float x, float y, float z)
{
vx_[i].first.set(x, y, z);
recompute_length();
}
inline void MultiSegmentPlacer::addVertex(const osg::Vec3 &v)
{
float l = 0;
if (vx_.size() > 0) {
l = (v - vx_.back().first).length();
}
total_length_ += l;
vx_.push_back(std::make_pair(v, total_length_));
}
inline void MultiSegmentPlacer::addVertex(float x, float y, float z)
{
addVertex(osg::Vec3(x, y, z));
}
inline void MultiSegmentPlacer::removeVertex(int i)
{
vx_.erase(vx_.begin()+i);
recompute_length();
}
}
#endif

View File

@@ -0,0 +1,91 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_OPERATOR_
#define OSGPARTICLE_OPERATOR_ 1
#include <osgParticle/Program>
#include <osg/CopyOp>
#include <osg/Object>
#include <osg/Matrix>
namespace osgParticle
{
// forward declaration to avoid including the whole header file
class Particle;
/** An abstract base class used by <CODE>ModularProgram</CODE> to perform operations on particles before they are updated.
To implement a new operator, derive from this class and override the <CODE>operate()</CODE> method.
You should also override the <CODE>beginOperate()</CODE> method to query the calling program for the reference frame
used, and initialize the right transformations if needed.
*/
class Operator: public osg::Object {
public:
inline Operator();
inline Operator(const Operator &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
virtual const char *className() const { return "Operator"; }
virtual bool isSameKindAs(const osg::Object *obj) const { return dynamic_cast<const Operator *>(obj) != 0; }
/// Get whether this operator is enabled.
inline bool isEnabled() const;
/// Enable or disable this operator.
inline void setEnabled(bool v);
/** Do something on a particle.
This method is called by <CODE>ModularProgram</CODE> objects to perform some operations
on the particles. You must override it in descendant classes. Common operations
consist of modifying the particle's velocity vector. The <CODE>dt</CODE> parameter is
the time elapsed from last operation.
*/
virtual void operate(Particle *P, double dt) = 0;
/** Do something before processing particles via the <CODE>operate()</CODE> method.
Overriding this method could be necessary to query the calling <CODE>Program</CODE> object
for the current reference frame. If the reference frame is RELATIVE_TO_PARENTS, then your
class should prepare itself to do all operations in local coordinates.
*/
virtual void beginOperate(Program *) {}
/// Do something after all particles have been processed.
virtual void endOperate() {}
protected:
virtual ~Operator() {}
Operator &operator=(const Operator &) { return *this; }
private:
bool enabled_;
};
// INLINE FUNCTIONS
inline Operator::Operator()
: osg::Object(), enabled_(true)
{
}
inline Operator::Operator(const Operator &copy, const osg::CopyOp &copyop)
: osg::Object(copy, copyop), enabled_(copy.enabled_)
{
}
inline bool Operator::isEnabled() const
{
return enabled_;
}
inline void Operator::setEnabled(bool v)
{
enabled_ = v;
}
}
#endif

View File

@@ -0,0 +1,399 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_PARTICLE_
#define OSGPARTICLE_PARTICLE_ 1
#include <osgParticle/Export>
#include <osgParticle/Interpolator>
#include <osgParticle/range>
#include <osg/ref_ptr>
#include <osg/Vec3>
#include <osg/Vec4>
#include <osg/Matrix>
#include <osg/GL>
namespace osgParticle
{
/** Implementation of a <B>particle</B>.
Objects of this class are particles, they have some graphical properties
and some physical properties. Particles are created by emitters and then placed
into Particle Systems, where they live and get updated at each frame.
Particles can either live forever (lifeTime < 0), or die after a specified
time (lifeTime >= 0). For each property which is defined as a range of values, a
"current" value will be evaluated at each frame by interpolating the <I>min</I>
and <I>max</I> values so that <I>curr_value = min</I> when <I>t == 0</I>, and
<I>curr_value = max</I> when <I>t == lifeTime</I>.
You may customize the interpolator objects to achieve any kind of transition.
If you want the particle to live forever, set its lifetime to any value <= 0;
in that case, no interpolation is done to compute real-time properties, and only
minimum values are used.
*/
class OSGPARTICLE_EXPORT Particle {
public:
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
};
Particle();
/// Get the shape of the particle.
inline Shape getShape() const;
/// Set the shape of the particle.
inline void setShape(Shape s);
/// Get whether the particle is still alive.
inline bool isAlive() const;
/// Get the life time of the particle (in seconds).
inline double getLifeTime() const;
/// Get the age of the particle (in seconds).
inline double getAge() const;
/// Get the minimum and maximum values for polygon size.
inline const rangef &getSizeRange() const;
/// Get the minimum and maximum values for alpha.
inline const rangef &getAlphaRange() const;
/// Get the minimum and maximum values for color.
inline const rangev4 &getColorRange() const;
/// Get the interpolator for computing the size of polygons.
inline const Interpolator *getSizeInterpolator() const;
/// Get the interpolator for computing alpha values.
inline const Interpolator *getAlphaInterpolator() const;
/// Get the interpolator for computing color values.
inline const Interpolator *getColorInterpolator() const;
/** Get the physical radius of the particle.
For built-in operators to work correctly, lengths must be expressed in meters.
*/
inline float getRadius() const;
/** Get the mass of the particle.
For built-in operators to work correctly, remember that the mass is expressed in kg.
*/
inline float getMass() const;
/// Get <CODE>1 / getMass()</CODE>.
inline float getMassInv() const;
/// Get the position vector.
inline const osg::Vec3 &getPosition() const;
/** Get the velocity vector.
For built-in operators to work correctly, remember that velocity components are expressed
in meters per second.
*/
inline const osg::Vec3 &getVelocity() const;
/// Get the previous position (the position before last update).
inline const osg::Vec3 &getPreviousPosition() const;
/** Kill the particle on next update
NOTE: after calling this function, the <CODE>isAlive()</CODE> method will still
return true until the particle is updated again.
*/
inline void kill();
/// Set the life time of the particle.
inline void setLifeTime(double t);
/// Set the minimum and maximum values for polygon size.
inline void setSizeRange(const rangef &r);
/// Set the minimum and maximum values for alpha.
inline void setAlphaRange(const rangef &r);
/// Set the minimum and maximum values for color.
inline void setColorRange(const rangev4 &r);
/// Set the interpolator for computing size values.
inline void setSizeInterpolator(Interpolator *ri);
/// Set the interpolator for computing alpha values.
inline void setAlphaInterpolator(Interpolator *ai);
/// Set the interpolator for computing color values.
inline void setColorInterpolator(Interpolator *ci);
/** Set the physical radius of the particle.
For built-in operators to work correctly, lengths must be expressed in meters.
*/
inline void setRadius(float r);
/** Set the mass of the particle.
For built-in operators to work correctly, remember that the mass is expressed in kg.
*/
inline void setMass(float m);
/// Set the position vector.
inline void setPosition(const osg::Vec3 &p);
/** Set the velocity vector.
For built-in operators to work correctly, remember that velocity components are expressed
in meters per second.
*/
inline void setVelocity(const osg::Vec3 &v);
/// Add a vector to the velocity vector.
inline void addVelocity(const osg::Vec3 &dv);
/// Transform position and velocity vectors by a matrix.
inline void transformPositionVelocity(const osg::Matrix &xform);
/** Update the particle (don't call this method manually).
This method is called automatically by <CODE>ParticleSystem::update()</CODE>; it
updates the graphical properties of the particle for the current time,
checks whether the particle is still alive, and then updates its position
by computing <I>P = P + V * dt</I> (where <I>P</I> is the position and <I>V</I> is the velocity).
*/
bool update(double dt);
/// Perform some pre-rendering tasks. Called automatically by particle systems.
inline void beginRender();
/// Render the particle. Called automatically by particle systems.
void render(const osg::Matrix &modelview, float scale = 1.0f) const;
/// Perform some post-rendering tasks. Called automatically by particle systems.
inline void endRender();
private:
Shape shape_;
rangef sr_;
rangef ar_;
rangev4 cr_;
osg::ref_ptr<Interpolator> si_;
osg::ref_ptr<Interpolator> ai_;
osg::ref_ptr<Interpolator> ci_;
bool alive_;
bool mustdie_;
double lifetime_;
float radius_;
float mass_;
float massinv_;
osg::Vec3 prev_pos_;
osg::Vec3 position_;
osg::Vec3 velocity_;
double t0_;
float current_size_;
float current_alpha_;
osg::Vec4 current_color_;
};
// INLINE FUNCTIONS
inline Particle::Shape Particle::getShape() const
{
return shape_;
}
inline void Particle::setShape(Shape s)
{
shape_ = s;
}
inline bool Particle::isAlive() const
{
return alive_;
}
inline double Particle::getLifeTime() const
{
return lifetime_;
}
inline double Particle::getAge() const
{
return t0_;
}
inline float Particle::getRadius() const
{
return radius_;
}
inline void Particle::setRadius(float r)
{
radius_ = r;
}
inline const rangef &Particle::getSizeRange() const
{
return sr_;
}
inline const rangef &Particle::getAlphaRange() const
{
return ar_;
}
inline const rangev4 &Particle::getColorRange() const
{
return cr_;
}
inline const Interpolator *Particle::getSizeInterpolator() const
{
return si_.get();
}
inline const Interpolator *Particle::getAlphaInterpolator() const
{
return ai_.get();
}
inline const Interpolator *Particle::getColorInterpolator() const
{
return ci_.get();
}
inline const osg::Vec3 &Particle::getPosition() const
{
return position_;
}
inline const osg::Vec3 &Particle::getVelocity() const
{
return velocity_;
}
inline const osg::Vec3 &Particle::getPreviousPosition() const
{
return prev_pos_;
}
inline void Particle::kill()
{
mustdie_ = true;
}
inline void Particle::setLifeTime(double t)
{
lifetime_ = t;
}
inline void Particle::setSizeRange(const rangef &r)
{
sr_ = r;
}
inline void Particle::setAlphaRange(const rangef &r)
{
ar_ = r;
}
inline void Particle::setColorRange(const rangev4 &r)
{
cr_ = r;
}
inline void Particle::setSizeInterpolator(Interpolator *ri)
{
si_ = ri;
}
inline void Particle::setAlphaInterpolator(Interpolator *ai)
{
ai_ = ai;
}
inline void Particle::setColorInterpolator(Interpolator *ci)
{
ci_ = ci;
}
inline void Particle::setPosition(const osg::Vec3 &p)
{
position_ = p;
}
inline void Particle::setVelocity(const osg::Vec3 &v)
{
velocity_ = v;
}
inline void Particle::addVelocity(const osg::Vec3 &v)
{
velocity_ += v;
}
inline void Particle::transformPositionVelocity(const osg::Matrix &xform)
{
// this should be optimized!
osg::Vec3 p1 = position_ + velocity_;
position_ = xform.preMult(position_);
p1 = xform.preMult(p1);
velocity_ = p1 - position_;
}
inline float Particle::getMass() const
{
return mass_;
}
inline float Particle::getMassInv() const
{
return massinv_;
}
inline void Particle::setMass(float m)
{
mass_ = m;
massinv_ = 1 / m;
}
inline void Particle::beginRender()
{
switch (shape_)
{
case POINT:
glBegin(GL_POINTS);
break;
case QUAD:
glBegin(GL_QUADS);
break;
default: ;
}
}
inline void Particle::endRender()
{
switch (shape_)
{
case POINT:
case QUAD:
glEnd();
break;
default: ;
}
}
}
#endif

View File

@@ -0,0 +1,195 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_PARTICLEPROCESSOR_
#define OSGPARTICLE_PARTICLEPROCESSOR_ 1
#include <osgParticle/Export>
#include <osgParticle/ParticleSystem>
#include <osg/ref_ptr>
#include <osg/Object>
#include <osg/Node>
#include <osg/NodeVisitor>
#include <osg/CopyOp>
#include <osg/Vec3>
#include <osg/Matrix>
namespace osgParticle
{
/** A common base interface for those classes which need to do something on particles. Such classes
are, for example, <CODE>Emitter</CODE> (particle generation) and <CODE>Program</CODE> (particle animation).
This class holds some properties, like a <I>reference frame</I> and a reference to a <CODE>ParticleSystem<CODE>;
descendant classes should process the particles taking into account the reference frame, computing the right
transformations when needed.
*/
class OSGPARTICLE_EXPORT ParticleProcessor: public osg::Node {
public:
enum ReferenceFrame {
RELATIVE_TO_PARENTS,
RELATIVE_TO_ABSOLUTE
};
ParticleProcessor();
ParticleProcessor(const ParticleProcessor &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
virtual const char *className() const { return "ParticleProcessor"; }
virtual bool isSameKindAs(const osg::Object *obj) { return dynamic_cast<const ParticleProcessor*>(obj) != 0; }
virtual void accept(osg::NodeVisitor& nv) { if (nv.validNodeMask(*this)) { nv.pushOntoNodePath(this); nv.apply(*this); nv.popFromNodePath(); } }
/// Get the reference frame.
inline ReferenceFrame getReferenceFrame() const;
/// Set the reference frame.
inline void setReferenceFrame(ReferenceFrame rf);
/// Get whether this processor is enabled or not.
inline bool isEnabled() const;
/// Set whether this processor is enabled or not.
inline void setEnabled(bool v);
/// Get a pointer to the destination particle system.
inline ParticleSystem *getParticleSystem();
/// Get a const pointer to the destination particle system.
inline const ParticleSystem *getParticleSystem() const;
/// Set the destination particle system.
inline void setParticleSystem(ParticleSystem *ps);
void traverse(osg::NodeVisitor &nv);
/// Get the current local-to-world transformation matrix (valid only during cull traversal).
inline const osg::Matrix &getLocalToWorldMatrix();
/// Get the current world-to-local transformation matrix (valid only during cull traversal).
inline const osg::Matrix &getWorldToLocalMatrix();
/// Transform a point from local to world coordinates (valid only during cull traversal).
inline osg::Vec3 transformLocalToWorld(const osg::Vec3 &P);
/// Transform a vector from local to world coordinates, discarding translation (valid only during cull traversal).
inline osg::Vec3 rotateLocalToWorld(const osg::Vec3 &P);
/// Transform a point from world to local coordinates (valid only during cull traversal).
inline osg::Vec3 transformWorldToLocal(const osg::Vec3 &P);
/// Transform a vector from world to local coordinates, discarding translation (valid only during cull traversal).
inline osg::Vec3 rotateWorldToLocal(const osg::Vec3 &P);
protected:
virtual ~ParticleProcessor() {}
ParticleProcessor &operator=(const ParticleProcessor &) { return *this; }
inline const bool computeBound() const;
virtual void process(double dt) = 0;
private:
ReferenceFrame rf_;
bool enabled_;
double t0_;
osg::ref_ptr<ParticleSystem> ps_;
bool need_ltw_matrix_;
bool need_wtl_matrix_;
osg::Matrix ltw_matrix_;
osg::Matrix wtl_matrix_;
osg::NodeVisitor *current_nodevisitor_;
};
// INLINE FUNCTIONS
inline ParticleProcessor::ReferenceFrame ParticleProcessor::getReferenceFrame() const
{
return rf_;
}
inline void ParticleProcessor::setReferenceFrame(ReferenceFrame rf)
{
rf_ = rf;
}
inline bool ParticleProcessor::isEnabled() const
{
return enabled_;
}
inline void ParticleProcessor::setEnabled(bool v)
{
enabled_ = v;
if (enabled_) t0_ = -1;
}
inline ParticleSystem *ParticleProcessor::getParticleSystem()
{
return ps_.get();
}
inline const ParticleSystem *ParticleProcessor::getParticleSystem() const
{
return ps_.get();
}
inline void ParticleProcessor::setParticleSystem(ParticleSystem *ps)
{
ps_ = ps;
}
inline const bool ParticleProcessor::computeBound() const
{
_bsphere.init();
_bsphere_computed = true;
return true;
}
inline const osg::Matrix &ParticleProcessor::getLocalToWorldMatrix()
{
if (need_ltw_matrix_) {
ltw_matrix_ = osg::Matrix::identity();
current_nodevisitor_->getLocalToWorldMatrix(ltw_matrix_, this);
need_ltw_matrix_ = false;
}
return ltw_matrix_;
}
inline const osg::Matrix &ParticleProcessor::getWorldToLocalMatrix()
{
if (need_wtl_matrix_) {
wtl_matrix_ = osg::Matrix::identity();
current_nodevisitor_->getWorldToLocalMatrix(wtl_matrix_, this);
need_wtl_matrix_ = false;
}
return wtl_matrix_;
}
inline osg::Vec3 ParticleProcessor::transformLocalToWorld(const osg::Vec3 &P)
{
return getLocalToWorldMatrix().preMult(P);
}
inline osg::Vec3 ParticleProcessor::transformWorldToLocal(const osg::Vec3 &P)
{
return getWorldToLocalMatrix().preMult(P);
}
inline osg::Vec3 ParticleProcessor::rotateLocalToWorld(const osg::Vec3 &P)
{
return getLocalToWorldMatrix().preMult(P) -
getLocalToWorldMatrix().preMult(osg::Vec3(0, 0, 0));
}
inline osg::Vec3 ParticleProcessor::rotateWorldToLocal(const osg::Vec3 &P)
{
return getWorldToLocalMatrix().preMult(P) -
getWorldToLocalMatrix().preMult(osg::Vec3(0, 0, 0));
}
}
#endif

View File

@@ -0,0 +1,318 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_PARTICLESYSTEM_
#define OSGPARTICLE_PARTICLESYSTEM_ 1
#include <osgParticle/Export>
#include <osgParticle/Particle>
#include <vector>
#include <stack>
#include <algorithm>
#include <string>
#include <osg/Object>
#include <osg/Drawable>
#include <osg/CopyOp>
#include <osg/State>
#include <osg/Vec3>
#include <osg/Statistics>
#include <osg/BoundingBox>
namespace osgParticle
{
/** The heart of this class library; its purpose is to hold a set of particles and manage particle creation, update, rendering and destruction.
You can add this drawable to any <CODE>Geode</CODE> as you usually do with other
<CODE>Drawable</CODE> classes. Each instance of <CODE>ParticleSystem</CODE> is a separate set of
particles; it provides the interface for creating particles and iterating
through them (see the <CODE>Emitter</CODE> and <CODE>Program</CODE> classes).
*/
class OSGPARTICLE_EXPORT ParticleSystem: public osg::Drawable {
public:
ParticleSystem();
ParticleSystem(const ParticleSystem &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
META_Object(ParticleSystem);
/// Get the default bounding box
inline const osg::BoundingBox &getDefaultBoundingBox() const;
/** Set the default bounding box.
The default bounding box is used when a real bounding box cannot be computed, for example
because no particles has been updated yet.
*/
inline void setDefaultBoundingBox(const osg::BoundingBox &bbox);
/// Get the double pass rendering flag.
inline bool getDoublePassRendering() const;
/** Set the double pass rendering flag.
Double pass rendering avoids overdraw problems between particle systems
and other opaque objects. If you can render all the particle systems <U>after</U>
the opaque objects, then double pass is not necessary and can be turned off (best choice).
If you set the default attributes with <CODE>setDefaultAttributes</CODE>, then the particle
system will fall into a transparent bin.
*/
inline void setDoublePassRendering(bool v);
/// Return true if the particle system is frozen.
inline bool isFrozen() const;
/** Set or reset the <I>frozen</I> state.
When the particle system is frozen, emitters and programs won't do anything on it.
*/
inline void setFrozen(bool v);
/// Get the number of allocated particles (alive + dead).
inline int numParticles() const;
/// Get the number of dead particles.
inline int numDeadParticles() const;
/// Get a pointer to the i-th particle.
inline Particle *getParticle(int i);
/// Get a const pointer to the i-th particle.
inline const Particle *getParticle(int i) const;
/// Create a new particle from the specified template (or the default one if <CODE>ptemplate</CODE> is null).
inline virtual Particle *createParticle(const Particle *ptemplate);
/// Destroy the i-th particle.
inline virtual void destroyParticle(int i);
/// Get the last frame number.
inline int getLastFrameNumber() const;
/// Get a reference to the default particle template.
inline const Particle &getDefaultParticleTemplate() const;
/// Set the default particle template (particle is copied).
inline void setDefaultParticleTemplate(const Particle &p);
/// Get whether the particle system can freeze when culled
inline bool getFreezeOnCull() const;
/// Set whether the particle system can freeze when culled (default is true)
inline void setFreezeOnCull(bool v);
/** A useful method to set the most common <CODE>StateAttribute</CODE>'s in one call.
If <CODE>texturefile</CODE> is empty, then texturing is turned off.
*/
void setDefaultAttributes(const std::string &texturefile = "", bool emissive_particles = true, bool lighting = false);
/// (<B>EXPERIMENTAL</B>) Get the level of detail.
inline int getLevelOfDetail() const;
/** (<B>EXPERIMENTAL</B>) Set the level of detail. The total number of particles is divided by the detail value to
get the actual number of particles to be drawn. This value must be greater than zero.
*/
inline void setLevelOfDetail(int v);
/// Update the particles. Don't call this directly, use a <CODE>ParticleSystemUpdater</CODE> instead.
virtual void update(double dt);
inline virtual bool getStats(osg::Statistics &stats);
protected:
virtual ~ParticleSystem();
ParticleSystem &operator=(const ParticleSystem &) { return *this; }
inline virtual const bool computeBound() const;
virtual void drawImmediateMode(osg::State &state);
inline void update_bounds(const osg::Vec3 &p);
void single_pass_render(const osg::Matrix &modelview);
private:
typedef std::vector<Particle> Particle_vector;
typedef std::stack<Particle*> Death_stack;
Particle_vector particles_;
Death_stack deadparts_;
osg::BoundingBox def_bbox_;
bool doublepass_;
bool frozen_;
int display_list_id_;
osg::Vec3 bmin_;
osg::Vec3 bmax_;
bool reset_bounds_flag_;
bool bounds_computed_;
Particle def_ptemp_;
int last_frame_;
bool freeze_on_cull_;
int detail_;
int draw_count_;
};
// INLINE FUNCTIONS
inline bool ParticleSystem::isFrozen() const
{
return frozen_;
}
inline void ParticleSystem::setFrozen(bool v)
{
frozen_ = v;
}
inline const osg::BoundingBox &ParticleSystem::getDefaultBoundingBox() const
{
return def_bbox_;
}
inline void ParticleSystem::setDefaultBoundingBox(const osg::BoundingBox &bbox)
{
def_bbox_ = bbox;
}
inline bool ParticleSystem::getDoublePassRendering() const
{
return doublepass_;
}
inline void ParticleSystem::setDoublePassRendering(bool v)
{
doublepass_ = v;
}
inline int ParticleSystem::numParticles() const
{
return static_cast<int>(particles_.size());
}
inline int ParticleSystem::numDeadParticles() const
{
return static_cast<int>(deadparts_.size());
}
inline Particle *ParticleSystem::getParticle(int i)
{
return &particles_[i];
}
inline const Particle *ParticleSystem::getParticle(int i) const
{
return &particles_[i];
}
inline void ParticleSystem::destroyParticle(int i)
{
particles_[i].kill();
}
inline int ParticleSystem::getLastFrameNumber() const
{
return last_frame_;
}
inline const bool ParticleSystem::computeBound() const
{
if (!bounds_computed_) {
_bbox = def_bbox_;
} else {
_bbox._min = bmin_;
_bbox._max = bmax_;
}
_bbox_computed = true;
return true;
}
inline bool ParticleSystem::getStats(osg::Statistics &stats)
{
stats.addNumPrims(draw_count_);
return true;
}
inline void ParticleSystem::update_bounds(const osg::Vec3 &p)
{
if (reset_bounds_flag_) {
reset_bounds_flag_ = false;
bmin_ = p;
bmax_ = p;
} else {
if (p.x() < bmin_.x()) bmin_.x() = p.x();
if (p.y() < bmin_.y()) bmin_.y() = p.y();
if (p.z() < bmin_.z()) bmin_.z() = p.z();
if (p.x() > bmax_.x()) bmax_.x() = p.x();
if (p.y() > bmax_.y()) bmax_.y() = p.y();
if (p.z() > bmax_.z()) bmax_.z() = p.z();
if (!bounds_computed_)
bounds_computed_ = true;
}
}
inline const Particle &ParticleSystem::getDefaultParticleTemplate() const
{
return def_ptemp_;
}
inline void ParticleSystem::setDefaultParticleTemplate(const Particle &p)
{
def_ptemp_ = p;
}
inline bool ParticleSystem::getFreezeOnCull() const
{
return freeze_on_cull_;
}
inline void ParticleSystem::setFreezeOnCull(bool v)
{
freeze_on_cull_ = v;
}
inline int ParticleSystem::getLevelOfDetail() const
{
return detail_;
}
inline void ParticleSystem::setLevelOfDetail(int v)
{
if (v < 1) v = 1;
detail_ = v;
}
// I'm not sure this function should be inlined...
inline Particle *ParticleSystem::createParticle(const Particle *ptemplate)
{
// is there any dead particle?
if (!deadparts_.empty()) {
// retrieve a pointer to the last dead particle
Particle *P = deadparts_.top();
// create a new (alive) particle in the same place
*P = Particle(ptemplate? *ptemplate: def_ptemp_);
// remove the pointer from the death stack
deadparts_.pop();
return P;
} else {
// add a new particle to the vector
particles_.push_back(Particle(ptemplate? *ptemplate: def_ptemp_));
return &particles_.back();
}
}
}
#endif

View File

@@ -0,0 +1,128 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_PARTICLESYSTEMUPDATER_
#define OSGPARTICLE_PARTICLESYSTEMUPDATER_ 1
#include <osgParticle/Export>
#include <osgParticle/ParticleSystem>
#include <vector>
#include <osg/ref_ptr>
#include <osg/CopyOp>
#include <osg/Object>
#include <osg/Node>
#include <osg/NodeVisitor>
#include <osgUtil/CullVisitor>
namespace osgParticle
{
/** A useful node class for updating particle systems automatically.
When a <CODE>ParticleSystemUpdater</CODE> is traversed by a cull visitor, it calls the
<CODE>update()</CODE> method on the specified particle systems. You should place this updater
<U>AFTER</U> other nodes like emitters and programs.
*/
class OSGPARTICLE_EXPORT ParticleSystemUpdater: public osg::Node {
public:
ParticleSystemUpdater();
ParticleSystemUpdater(const ParticleSystemUpdater &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
META_Node(ParticleSystemUpdater);
/// Return the number of particle systems on the list.
inline int numParticleSystems() const;
/// Add a particle system to the list.
inline void addParticleSystem(ParticleSystem *ps);
/// Get a const particle system from the list.
inline const ParticleSystem *getParticleSystem(int i) const;
/// Get a particle system from the list.
inline ParticleSystem *getParticleSystem(int i);
/// Find a particle system.
inline int findParticleSystem(ParticleSystem *ps) const;
/// Remove a particle system from the list (by index).
inline void removeParticleSystem(int i);
/// Remove a particle system from the list (by pointer).
inline bool removeParticleSystem(ParticleSystem *ps);
virtual void traverse(osg::NodeVisitor &nv);
protected:
virtual ~ParticleSystemUpdater() {}
ParticleSystemUpdater &operator=(const ParticleSystemUpdater &) { return *this; }
inline virtual const bool computeBound() const;
private:
typedef std::vector<osg::ref_ptr<ParticleSystem> > ParticleSystem_Vector;
ParticleSystem_Vector psv_;
double t0_;
};
// INLINE FUNCTIONS
inline const bool ParticleSystemUpdater::computeBound() const
{
_bsphere.init();
_bsphere_computed = true;
return true;
}
inline int ParticleSystemUpdater::numParticleSystems() const
{
return static_cast<int>(psv_.size());
}
inline void ParticleSystemUpdater::addParticleSystem(ParticleSystem *ps)
{
psv_.push_back(ps);
}
inline const ParticleSystem *ParticleSystemUpdater::getParticleSystem(int i) const
{
return psv_[i].get();
}
inline ParticleSystem *ParticleSystemUpdater::getParticleSystem(int i)
{
return psv_[i].get();
}
inline void ParticleSystemUpdater::removeParticleSystem(int i)
{
psv_.erase(psv_.begin()+i);
}
inline int ParticleSystemUpdater::findParticleSystem(ParticleSystem *ps) const
{
ParticleSystem_Vector::const_iterator i;
int j = 0;
for (i=psv_.begin(); i!=psv_.end(); ++i, ++j) {
if (i->get() == ps) return j;
}
return -1;
}
inline bool ParticleSystemUpdater::removeParticleSystem(ParticleSystem *ps)
{
int i = findParticleSystem(ps);
if (i == -1) return false;
removeParticleSystem(i);
return true;
}
}
#endif

View File

@@ -0,0 +1,51 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_PLACER_
#define OSGPARTICLE_PLACER_ 1
#include <osg/CopyOp>
#include <osg/Object>
namespace osgParticle
{
class Particle;
/** An abstract base class for implementing <I>particle placers</I>. A placer is an object which take
a particle as input, and places it somewhere by setting its position vector. Placer objects are
used by the <CODE>ModularEmitter</CODE> class as part of the particle emission process.
*/
class Placer: public osg::Object {
public:
inline Placer();
inline Placer(const Placer &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
virtual const char *className() const { return "Placer"; }
virtual bool isSameKindAs(const osg::Object *obj) const { return dynamic_cast<const Placer *>(obj) != 0; }
/// Place a particle. Must be implemented in descendant classes.
virtual void place(Particle *P) const = 0;
protected:
~Placer() {}
Placer &operator=(const Placer &) { return *this; }
};
// INLINE FUNCTIONS
inline Placer::Placer()
: osg::Object()
{
}
inline Placer::Placer(const Placer &copy, const osg::CopyOp &copyop)
: osg::Object(copy, copyop)
{
}
}
#endif

View File

@@ -0,0 +1,61 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_POINTPLACER_
#define OSGPARTICLE_POINTPLACER_ 1
#include <osgParticle/CenteredPlacer>
#include <osgParticle/Particle>
#include <osg/CopyOp>
#include <osg/Object>
namespace osgParticle
{
/** A point-shaped particle placer.
This placer class uses the center point defined in its base class <CODE>CenteredPlacer</CODE>
to place there all incoming particles.
*/
class PointPlacer: public CenteredPlacer {
public:
inline PointPlacer();
inline PointPlacer(const PointPlacer &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
META_Object(PointPlacer);
/** Place a particle.
This method is called automatically by <CODE>ModularEmitter</CODE> and should not be called
manually.
*/
inline void place(Particle *P) const;
protected:
virtual ~PointPlacer() {}
PointPlacer &operator=(const PointPlacer &) { return *this; }
};
// INLINE FUNCTIONS
inline PointPlacer::PointPlacer()
: CenteredPlacer()
{
}
inline PointPlacer::PointPlacer(const PointPlacer &copy, const osg::CopyOp &copyop)
: CenteredPlacer(copy, copyop)
{
}
inline void PointPlacer::place(Particle *P) const
{
P->setPosition(getCenter());
}
}
#endif

View File

@@ -0,0 +1,57 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_PROGRAM_
#define OSGPARTICLE_PROGRAM_ 1
#include <osgParticle/Export>
#include <osgParticle/ParticleProcessor>
#include <osg/Object>
#include <osg/Node>
#include <osg/NodeVisitor>
#include <osg/CopyOp>
namespace osgParticle
{
/** An abstract <CODE>ParticleProcessor</CODE> descendant for modifying particles "on the fly"
during the cull traversal.
Descendants of this class must implement the <CODE>execute()</CODE> method, which should iterate
through all particles in the linked particle system and modify them somehow
(usually updating their velocity vector).
*/
class OSGPARTICLE_EXPORT Program: public ParticleProcessor {
public:
Program();
Program(const Program &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
virtual const char *className() const { return "Program"; }
virtual bool isSameKindAs(const osg::Object *obj) { return dynamic_cast<const Program*>(obj) != 0; }
virtual void accept(osg::NodeVisitor& nv) { if (nv.validNodeMask(*this)) { nv.pushOntoNodePath(this); nv.apply(*this); nv.popFromNodePath(); } }
protected:
virtual ~Program() {}
Program &operator=(const Program &) { return *this; }
/// Implementation of <CODE>ParticleProcessor::process()</CODE>. Do not call this method by yourself.
inline void process(double dt);
/// Execute the program on the particle system. Must be overriden in descendant classes.
virtual void execute(double dt) = 0;
private:
};
// INLINE FUNCTIONS
inline void Program::process(double dt)
{
execute(dt);
}
}
#endif

View File

@@ -0,0 +1,156 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_RADIALSHOOTER_
#define OSGPARTICLE_RADIALSHOOTER_ 1
#include <osgParticle/Shooter>
#include <osgParticle/Particle>
#include <osgParticle/range>
#include <osg/CopyOp>
#include <osg/Object>
#include <osg/Math>
namespace osgParticle
{
/** A shooter class that shoots particles radially.
This shooter computes the velocity vector of incoming particles by choosing a
random direction and a random speed. Both direction and speed are chosen within
specified ranges. The direction is defined by two angles: <B>theta</B>, which
is the angle between the velocity vector and the Z axis, and <B>phi</B>, which is
the angle between the X axis and the velocity vector projected onto the X-Y plane.
*/
class RadialShooter: public Shooter {
public:
inline RadialShooter();
inline RadialShooter(const RadialShooter &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
META_Object(RadialShooter);
/// Get the range of possible values for <B>theta</B> angle.
inline const rangef &getThetaRange() const;
/// Set the range of possible values for <B>theta</B> angle.
inline void setThetaRange(const rangef &r);
/// Set the range of possible values for <B>theta</B> angle.
inline void setThetaRange(float r1, float r2);
/// Get the range of possible values for <B>phi</B> angle.
inline const rangef &getPhiRange() const;
/// Set the range of possible values for <B>phi</B> angle.
inline void setPhiRange(const rangef &r);
/// Set the range of possible values for <B>phi</B> angle.
inline void setPhiRange(float r1, float r2);
/// Get the range of possible values for initial speed of particles.
inline const rangef &getInitialSpeedRange() const;
/// Set the range of possible values for initial speed of particles.
inline void setInitialSpeedRange(const rangef &r);
/// Set the range of possible values for initial speed of particles.
inline void setInitialSpeedRange(float r1, float r2);
/// Shoot a particle. Do not call this method manually.
inline void shoot(Particle *P) const;
protected:
virtual ~RadialShooter() {}
RadialShooter &operator=(const RadialShooter &) { return *this; }
private:
rangef theta_range_;
rangef phi_range_;
rangef speed_range_;
};
// INLINE FUNCTIONS
inline RadialShooter::RadialShooter()
: Shooter(),
theta_range_(0, 0.5f*osg::PI_4),
phi_range_(0, 2*osg::PI),
speed_range_(10, 10)
{
}
inline RadialShooter::RadialShooter(const RadialShooter &copy, const osg::CopyOp &copyop)
: Shooter(copy, copyop),
theta_range_(copy.theta_range_),
phi_range_(copy.phi_range_),
speed_range_(copy.speed_range_)
{
}
inline const rangef &RadialShooter::getThetaRange() const
{
return theta_range_;
}
inline const rangef &RadialShooter::getPhiRange() const
{
return phi_range_;
}
inline const rangef &RadialShooter::getInitialSpeedRange() const
{
return speed_range_;
}
inline void RadialShooter::setThetaRange(const rangef &r)
{
theta_range_ = r;
}
inline void RadialShooter::setThetaRange(float r1, float r2)
{
theta_range_.min = r1;
theta_range_.max = r2;
}
inline void RadialShooter::setPhiRange(const rangef &r)
{
phi_range_ = r;
}
inline void RadialShooter::setPhiRange(float r1, float r2)
{
phi_range_.min = r1;
phi_range_.max = r2;
}
inline void RadialShooter::setInitialSpeedRange(const rangef &r)
{
speed_range_ = r;
}
inline void RadialShooter::setInitialSpeedRange(float r1, float r2)
{
speed_range_.min = r1;
speed_range_.max = r2;
}
inline void RadialShooter::shoot(Particle *P) const
{
float theta = theta_range_.get_random();
float phi = phi_range_.get_random();
float speed = speed_range_.get_random();
P->setVelocity(osg::Vec3(
speed * sinf(theta) * cosf(phi),
speed * sinf(theta) * sinf(phi),
speed * cosf(theta)
));
}
}
#endif

View File

@@ -0,0 +1,57 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_RANDOMRATECOUNTER_
#define OSGPARTICLE_RANDOMRATECOUNTER_ 1
#include <osgParticle/VariableRateCounter>
#include <osg/CopyOp>
#include <osg/Object>
namespace osgParticle
{
class RandomRateCounter: public VariableRateCounter {
public:
inline RandomRateCounter();
inline RandomRateCounter(const RandomRateCounter &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
META_Object(RandomRateCounter);
/// Return the number of particles to be created in this frame
inline int numParticlesToCreate(double dt) const;
protected:
virtual ~RandomRateCounter() {}
private:
mutable float np_;
};
// INLINE FUNCTIONS
inline RandomRateCounter::RandomRateCounter()
: VariableRateCounter(), np_(0)
{
}
inline RandomRateCounter::RandomRateCounter(const RandomRateCounter &copy, const osg::CopyOp &copyop)
: VariableRateCounter(copy, copyop), np_(copy.np_)
{
}
inline int RandomRateCounter::numParticlesToCreate(double dt) const
{
np_ += dt * getRateRange().get_random();
int n = static_cast<int>(np_);
np_ -= n;
return n;
}
}
#endif

View File

@@ -0,0 +1,124 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_SECTORPLACER_
#define OSGPARTICLE_SECTORPLACER_ 1
#include <osgParticle/CenteredPlacer>
#include <osgParticle/Particle>
#include <osgParticle/range>
#include <osg/CopyOp>
#include <osg/Object>
#include <osg/Vec3>
#include <osg/Math>
namespace osgParticle
{
/** A sector-shaped particle placer.
This placer sets the initial position of incoming particle by choosing a random position
within a circular sector; this sector is defined by three parameters: a <I>center point</I>,
which is inherited directly from <CODE>osgParticle::CenteredPlacer</CODE>, a range of values
for <I>radius</I>, and a range of values for the <I>central angle</I> (sometimes called <B>phi</B>).
*/
class SectorPlacer: public CenteredPlacer {
public:
inline SectorPlacer();
inline SectorPlacer(const SectorPlacer &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
/// Get the range of possible values for radius.
inline const rangef &getRadiusRange() const;
/// Set the range of possible values for radius.
inline void setRadiusRange(const rangef &r);
/// Set the range of possible values for radius.
inline void setRadiusRange(float r1, float r2);
/// Get the range of possible values for the central angle.
inline const rangef &getPhiRange() const;
/// Set the range of possible values for the central angle.
inline void setPhiRange(const rangef &r);
/// Set the range of possible values for the central angle.
inline void setPhiRange(float r1, float r2);
META_Object(SectorPlacer);
/// Place a particle. Do not call it manually.
inline void place(Particle *P) const;
protected:
virtual ~SectorPlacer() {}
SectorPlacer &operator=(const SectorPlacer &) { return *this; }
private:
rangef rad_range_;
rangef phi_range_;
};
// INLINE FUNCTIONS
inline SectorPlacer::SectorPlacer()
: CenteredPlacer(), rad_range_(0, 1), phi_range_(0, osg::PI*2)
{
}
inline SectorPlacer::SectorPlacer(const SectorPlacer &copy, const osg::CopyOp &copyop)
: CenteredPlacer(copy, copyop), rad_range_(copy.rad_range_), phi_range_(copy.phi_range_)
{
}
inline const rangef &SectorPlacer::getRadiusRange() const
{
return rad_range_;
}
inline const rangef &SectorPlacer::getPhiRange() const
{
return phi_range_;
}
inline void SectorPlacer::setRadiusRange(const rangef &r)
{
rad_range_ = r;
}
inline void SectorPlacer::setRadiusRange(float r1, float r2)
{
rad_range_.min = r1;
rad_range_.max = r2;
}
inline void SectorPlacer::setPhiRange(const rangef &r)
{
phi_range_ = r;
}
inline void SectorPlacer::setPhiRange(float r1, float r2)
{
phi_range_.min = r1;
phi_range_.max = r2;
}
inline void SectorPlacer::place(Particle *P) const
{
float rad = rad_range_.get_random();
float phi = phi_range_.get_random();
osg::Vec3 pos(
getCenter().x() + rad * cosf(phi),
getCenter().y() + rad * sinf(phi),
getCenter().z());
P->setPosition(pos);
}
}
#endif

View File

@@ -0,0 +1,118 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_SEGMENTPLACER_
#define OSGPARTICLE_SEGMENTPLACER_ 1
#include <osgParticle/Placer>
#include <osgParticle/Particle>
#include <osg/CopyOp>
#include <osg/Object>
#include <osg/Vec3>
namespace osgParticle {
/** A segment-shaped particle placer.
To use this placer you have to define a segment, by setting its two vertices (<B>A</B> and <B>B</B>);
when an emitter requests a <CODE>SegmentPlacer</CODE> to place a particle, the position is chosen randomly
within that segment.
*/
class SegmentPlacer: public Placer {
public:
inline SegmentPlacer();
inline SegmentPlacer(const SegmentPlacer &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
META_Object(SegmentPlacer);
/// get vertex <B>A</B>.
inline const osg::Vec3 &getVertexA() const;
/// Set vertex <B>A</B> of the segment as a vector.
inline void setVertexA(const osg::Vec3 &v);
/// Set vertex <B>A</B> of the segment as three floats.
inline void setVertexA(float x, float y, float z);
/// get vertex <B>B</B>.
inline const osg::Vec3 &getVertexB() const;
/// Set vertex <B>B</B> of the segment as a vector.
inline void setVertexB(const osg::Vec3 &v);
/// Set vertex <B>B</B> of the segment as three floats.
inline void setVertexB(float x, float y, float z);
/// Set both vertices.
inline void setSegment(const osg::Vec3 &A, const osg::Vec3 &B);
/// Place a particle. This method is called by <CODE>ModularEmitter</CODE>, do not call it manually.
inline void place(Particle *P) const;
protected:
virtual ~SegmentPlacer() {}
SegmentPlacer &operator=(const SegmentPlacer &) { return *this; }
private:
osg::Vec3 A_;
osg::Vec3 B_;
};
// INLINE FUNCTIONS
inline SegmentPlacer::SegmentPlacer()
: Placer(), A_(-1, 0, 0), B_(1, 0, 0)
{
}
inline SegmentPlacer::SegmentPlacer(const SegmentPlacer &copy, const osg::CopyOp &copyop)
: Placer(copy, copyop), A_(copy.A_), B_(copy.B_)
{
}
inline const osg::Vec3 &SegmentPlacer::getVertexA() const
{
return A_;
}
inline const osg::Vec3 &SegmentPlacer::getVertexB() const
{
return B_;
}
inline void SegmentPlacer::setSegment(const osg::Vec3 &A, const osg::Vec3 &B)
{
A_ = A;
B_ = B;
}
inline void SegmentPlacer::place(Particle *P) const
{
P->setPosition(rangev3(A_, B_).get_random());
}
inline void SegmentPlacer::setVertexA(const osg::Vec3 &v)
{
A_ = v;
}
inline void SegmentPlacer::setVertexA(float x, float y, float z)
{
A_.set(x, y, z);
}
inline void SegmentPlacer::setVertexB(const osg::Vec3 &v)
{
B_ = v;
}
inline void SegmentPlacer::setVertexB(float x, float y, float z)
{
B_.set(x, y, z);
}
}
#endif

View File

@@ -0,0 +1,53 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_SHOOTER_
#define OSGPARTICLE_SHOOTER_ 1
#include <osg/CopyOp>
#include <osg/Object>
namespace osgParticle
{
class Particle;
/** An abstract base class used by ModularEmitter to "shoot" the particles after they have been placed.
Descendants of this class must override the <CODE>shoot()</CODE> method.
*/
class Shooter: public osg::Object {
public:
inline Shooter();
inline Shooter(const Shooter &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
virtual const char *className() const { return "Shooter"; }
virtual bool isSameKindAs(const osg::Object *obj) const { return dynamic_cast<const Shooter *>(obj) != 0; }
/** Shoot a particle. Must be overriden by descendants.
This method should only set the velocity vector of particle <CODE>P</CODE>, leaving other
attributes unchanged.
*/
virtual void shoot(Particle *P) const = 0;
protected:
virtual ~Shooter() {}
Shooter &operator=(const Shooter &) { return *this; }
};
// INLINE FUNCTIONS
inline Shooter::Shooter()
: osg::Object()
{
}
inline Shooter::Shooter(const Shooter &copy, const osg::CopyOp &copyop)
: osg::Object(copy, copyop)
{
}
}
#endif

View File

@@ -0,0 +1,67 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_VARIABLERATECOUNTER_
#define OSGPARTICLE_VARIABLERATECOUNTER_ 1
#include <osgParticle/Counter>
#include <osgParticle/range>
#include <osg/CopyOp>
#include <osg/Object>
namespace osgParticle
{
class VariableRateCounter: public Counter {
public:
inline VariableRateCounter();
inline VariableRateCounter(const VariableRateCounter &copy, const osg::CopyOp &copyop = osg::CopyOp::SHALLOW_COPY);
virtual const char *className() const { return "VariableRateCounter"; }
virtual bool isSameKindAs(const osg::Object *obj) const { return dynamic_cast<const VariableRateCounter *>(obj) != 0; }
inline const rangef &getRateRange() const;
inline void setRateRange(const rangef &r);
inline void setRateRange(float minrange, float maxrange);
protected:
virtual ~VariableRateCounter() {}
private:
rangef rate_range_;
};
// INLINE FUNCTIONS
inline VariableRateCounter::VariableRateCounter()
: Counter(), rate_range_(1, 1)
{
}
inline VariableRateCounter::VariableRateCounter(const VariableRateCounter &copy, const osg::CopyOp &copyop)
: Counter(copy, copyop), rate_range_(copy.rate_range_)
{
}
inline const rangef &VariableRateCounter::getRateRange() const
{
return rate_range_;
}
inline void VariableRateCounter::setRateRange(const rangef &r)
{
rate_range_ = r;
}
inline void VariableRateCounter::setRateRange(float minrange, float maxrange)
{
rate_range_.set(minrange, maxrange);
}
}
#endif

View File

@@ -0,0 +1,19 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_VERSION_
#define OSGPARTICLE_VERSION_ 1
#include <osgParticle/Export>
extern "C" {
OSGPARTICLE_EXPORT const char* osgParticleGetVersion();
OSGPARTICLE_EXPORT const char* osgParticleGetLibraryName();
}
#endif

65
include/osgParticle/range Normal file
View File

@@ -0,0 +1,65 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
//osgParticle - Copyright (C) 2002 Marco Jez
#ifndef OSGPARTICLE_RANGE_
#define OSGPARTICLE_RANGE_ 1
#include <cstdlib>
#include <osg/Vec2>
#include <osg/Vec3>
#include <osg/Vec4>
namespace osgParticle
{
/**
A simple struct template useful to store ranges of values as min/max pairs.
This struct template helps storing min/max ranges for values of any kind; class <CODE>T_</CODE> is
the type of values to be stored, and it must support operations <CODE>T_ + T_</CODE>, <CODE>T_ - T_</CODE>,
and <CODE>T_ * float</CODE>, otherwise the <CODE>get_random()</CODE> method will not compile.
This struct could be extended to customize the random number generator (now it uses only
<CODE>std::rand()</CODE>).
*/
template<class T_> struct range {
/// Lower bound.
T_ min;
/// Higher bound.
T_ max;
/// Construct the object by calling default constructors for min and max.
range() : min(T_()), max(T_()) {}
/// Construct and initialize min and max directly.
range(const T_ &mn, const T_ &mx) : min(mn), max(mx) {}
/// Set min and max.
void set(const T_ &mn, const T_ &mx) { min = mn; max = mx; }
/// Get a random value between min and max.
T_ get_random() const
{
return min + (max - min) * std::rand() / RAND_MAX;
}
};
/// Range of floats.
typedef range<float> rangef;
/// Range of osg::Vec2s.
typedef range<osg::Vec2> rangev2;
/// Range of osg::Vec3s.
typedef range<osg::Vec3> rangev3;
/// Range of osg::Vec4s.
typedef range<osg::Vec4> rangev4;
}
#endif