Added support for rapid movement of the emitter, with particle now seeding between

the position of the emitter in the previous frame and the new position in the new
frame, the number of particles added also scales up to compensate for this movement.
This commit is contained in:
Robert Osfield
2005-08-25 14:12:08 +00:00
parent 320d0f67e4
commit be285c62c0
14 changed files with 183 additions and 28 deletions

View File

@@ -57,6 +57,13 @@ namespace osgParticle
/// Set the Counter object.
inline void setCounter(Counter* c);
/// Get the ratio between number of particle to create in compenstation for movement of the emitter
inline float getNumParticlesToCreateMovementCompenstationRatio() const;
/// Set the ratio between number of particle to create in compenstation for movement of the emitter
inline void setNumParticlesToCreateMovementCompenstationRatio(float r);
/// Get the Placer object.
inline Placer* getPlacer();
@@ -82,6 +89,8 @@ namespace osgParticle
virtual void emit(double dt);
private:
float _numParticleToCreateMovementCompensationRatio;
osg::ref_ptr<Counter> _counter;
osg::ref_ptr<Placer> _placer;
osg::ref_ptr<Shooter> _shooter;
@@ -104,6 +113,16 @@ namespace osgParticle
_counter = c;
}
inline float ModularEmitter::getNumParticlesToCreateMovementCompenstationRatio() const
{
return _numParticleToCreateMovementCompensationRatio;
}
inline void ModularEmitter::setNumParticlesToCreateMovementCompenstationRatio(float r)
{
_numParticleToCreateMovementCompensationRatio = r;
}
inline Placer* ModularEmitter::getPlacer()
{
return _placer.get();

View File

@@ -64,6 +64,9 @@ namespace osgParticle {
/// Place a partice. Called automatically by <CODE>ModularEmitter</CODE>, do not call this method manually.
void place(Particle* P) const;
/// return the control position
inline osg::Vec3 getControlPosition() const;
protected:
virtual ~MultiSegmentPlacer() {}
MultiSegmentPlacer& operator=(const MultiSegmentPlacer&) { return *this; }
@@ -123,6 +126,11 @@ namespace osgParticle {
_vx.erase(_vx.begin()+i);
recompute_length();
}
inline osg::Vec3 MultiSegmentPlacer::getControlPosition() const
{
return _vx.empty() ? osg::Vec3(0.0f,0.0f,0.0f) : _vx[0].first;
}
}
#endif

View File

@@ -178,6 +178,9 @@ namespace osgParticle
/// Transform position and velocity vectors by a matrix.
inline void transformPositionVelocity(const osg::Matrix& xform);
/// Transform position and velocity vectors by a combination of two matrices
void Particle::transformPositionVelocity(const osg::Matrix& xform1, const osg::Matrix& xform2, float r);
/// Set the angle vector.
inline void setAngle(const osg::Vec3& a);
@@ -410,14 +413,19 @@ namespace osgParticle
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;
_velocity = osg::Matrix::transform3x3(_velocity, xform);
}
inline void Particle::transformPositionVelocity(const osg::Matrix& xform1, const osg::Matrix& xform2, float r)
{
osg::Vec3 position1 = xform1.preMult(_position);
osg::Vec3 velocity1 = osg::Matrix::transform3x3(_velocity, xform1);
osg::Vec3 position2 = xform2.preMult(_position);
osg::Vec3 velocity2 = osg::Matrix::transform3x3(_velocity, xform2);
float one_minus_r = 1.0f-r;
_position = position1*r + position2*one_minus_r;
_velocity = velocity1*r + velocity2*one_minus_r;
}
inline void Particle::setAngle(const osg::Vec3& a)

View File

@@ -119,6 +119,13 @@ namespace osgParticle
/// Get the current world-to-local transformation matrix (valid only during cull traversal).
inline const osg::Matrix& getWorldToLocalMatrix();
/// Get the previous local-to-world transformation matrix (valid only during cull traversal).
inline const osg::Matrix& getPreviousLocalToWorldMatrix();
/// Get the previous world-to-local transformation matrix (valid only during cull traversal).
inline const osg::Matrix& getPreviousWorldToLocalMatrix();
/// Transform a point from local to world coordinates (valid only during cull traversal).
inline osg::Vec3 transformLocalToWorld(const osg::Vec3& P);
@@ -144,10 +151,14 @@ namespace osgParticle
bool _enabled;
double _t0;
osg::ref_ptr<ParticleSystem> _ps;
bool _first_ltw_compute;
bool _need_ltw_matrix;
bool _first_wtl_compute;
bool _need_wtl_matrix;
osg::Matrix _ltw_matrix;
osg::Matrix _wtl_matrix;
osg::Matrix _previous_ltw_matrix;
osg::Matrix _previous_wtl_matrix;
osg::NodeVisitor* _current_nodevisitor;
bool _endless;
@@ -252,9 +263,13 @@ namespace osgParticle
inline const osg::Matrix& ParticleProcessor::getLocalToWorldMatrix()
{
if (_need_ltw_matrix) {
_ltw_matrix = osg::Matrix::identity();
//_current_nodevisitor->getLocalToWorldMatrix(_ltw_matrix, this);
_previous_ltw_matrix = _ltw_matrix;
_ltw_matrix = osg::computeLocalToWorld(_current_nodevisitor->getNodePath());
if (_first_ltw_compute)
{
_previous_ltw_matrix = _ltw_matrix;
_first_ltw_compute = false;
}
_need_ltw_matrix = false;
}
return _ltw_matrix;
@@ -263,14 +278,30 @@ namespace osgParticle
inline const osg::Matrix& ParticleProcessor::getWorldToLocalMatrix()
{
if (_need_wtl_matrix) {
_wtl_matrix = osg::Matrix::identity();
//_current_nodevisitor->getWorldToLocalMatrix(_wtl_matrix, this);
_previous_wtl_matrix = _wtl_matrix;
_wtl_matrix = osg::computeWorldToLocal(_current_nodevisitor->getNodePath());
if (_first_wtl_compute)
{
_previous_wtl_matrix = _wtl_matrix;
_first_wtl_compute = false;
}
_need_wtl_matrix = false;
}
return _wtl_matrix;
}
inline const osg::Matrix& ParticleProcessor::getPreviousLocalToWorldMatrix()
{
if (_need_ltw_matrix) getLocalToWorldMatrix();
return _previous_ltw_matrix;
}
inline const osg::Matrix& ParticleProcessor::getPreviousWorldToLocalMatrix()
{
if (_need_wtl_matrix) getWorldToLocalMatrix();
return _previous_wtl_matrix;
}
inline osg::Vec3 ParticleProcessor::transformLocalToWorld(const osg::Vec3& P)
{
return getLocalToWorldMatrix().preMult(P);

View File

@@ -17,6 +17,7 @@
#include <osg/CopyOp>
#include <osg/Object>
#include <osg/Vec3>
namespace osgParticle
{
@@ -39,6 +40,9 @@ namespace osgParticle
/// Place a particle. Must be implemented in descendant classes.
virtual void place(Particle* P) const = 0;
/// Return the control position of particles that placer will generate. Must be implemented in descendant classes.
virtual osg::Vec3 getControlPosition() const = 0;
protected:
~Placer() {}
Placer& operator=(const Placer& ) { return *this; }

View File

@@ -41,6 +41,9 @@ namespace osgParticle
*/
inline void place(Particle* P) const;
/// return the control position
inline osg::Vec3 getControlPosition() const;
protected:
virtual ~PointPlacer() {}
PointPlacer& operator=(const PointPlacer&) { return *this; }
@@ -64,6 +67,11 @@ namespace osgParticle
}
inline osg::Vec3 PointPlacer::getControlPosition() const
{
return getCenter();
}
}

View File

@@ -61,6 +61,9 @@ namespace osgParticle
/// Place a particle. Do not call it manually.
inline void place(Particle* P) const;
/// return the control position
inline osg::Vec3 getControlPosition() const;
protected:
virtual ~SectorPlacer() {}
SectorPlacer& operator=(const SectorPlacer&) { return *this; }
@@ -127,6 +130,10 @@ namespace osgParticle
P->setPosition(pos);
}
inline osg::Vec3 SectorPlacer::getControlPosition() const
{
return getCenter();
}
}

View File

@@ -60,6 +60,9 @@ namespace osgParticle {
/// Place a particle. This method is called by <CODE>ModularEmitter</CODE>, do not call it manually.
inline void place(Particle* P) const;
/// return the control position
inline osg::Vec3 getControlPosition() const;
protected:
virtual ~SegmentPlacer() {}
SegmentPlacer& operator=(const SegmentPlacer&) { return *this; }
@@ -121,6 +124,12 @@ namespace osgParticle {
{
_vertexB.set(x, y, z);
}
inline osg::Vec3 SegmentPlacer::getControlPosition() const
{
return (_vertexA+_vertexB)*0.5f;
}
}

View File

@@ -70,6 +70,11 @@ namespace osgParticle
{
return minimum + (maximum - minimum) * sqrtf( static_cast<float>(rand()) / static_cast<float>(RAND_MAX) );
}
ValueType mid() const
{
return (minimum+maximum)*0.5f;
}
};