Merged changed to osgParticle from Marco Jez, the changes are (quoted from
email from Marco) "Most relevant news: 1) particle systems now have the "freezeOnCull" property set to false by default. Since it is an optimization, and using it may cause some unwanted behaviors if not handled properly, it makes more sense to turn it off by default. 2) new "LINE" shape mode which uses GL_LINES to draw line segments that point to the direction of motion. 3) particles can now have a rotation angle and angular velocity. 4) new AngularAccelOperator applies angular acceleration to particles. 5) particle processors such as emitters and programs can have a "start", "end" and "reset" time coordinate. For example, an emitter may be instructed to start emitting particles only after a certain time, stop after another amount of time and then start again. Update (2) is from Gideon May. Updates (3) to (5) are from Douglas A. Pouk."
This commit is contained in:
parent
763ee70f2f
commit
4761442005
@ -145,6 +145,10 @@ SOURCE=..\..\include\osgParticle\AccelOperator
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\include\osgParticle\AngularAccelOperator
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\include\osgParticle\CenteredPlacer
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -98,6 +98,10 @@ SOURCE=..\..\..\src\osgPlugins\osgParticle\IO_AccelOperator.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\osgParticle\IO_AngularAccelOperator.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\osgParticle\IO_CenteredPlacer.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
99
include/osgParticle/AngularAccelOperator
Normal file
99
include/osgParticle/AngularAccelOperator
Normal file
@ -0,0 +1,99 @@
|
||||
/* -*-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.
|
||||
*/
|
||||
//osgParticle - Copyright (C) 2002 Marco Jez
|
||||
|
||||
#ifndef OSGPARTICLE_ANGULARACCELOPERATOR_
|
||||
#define OSGPARTICLE_ANGULARACCELOPERATOR_ 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 angular acceleration to
|
||||
* the particles.
|
||||
*/
|
||||
class AngularAccelOperator: public Operator {
|
||||
public:
|
||||
inline AngularAccelOperator();
|
||||
inline AngularAccelOperator(const AngularAccelOperator ©, const osg::CopyOp ©op = osg::CopyOp::SHALLOW_COPY);
|
||||
|
||||
META_Object(osgParticle, AngularAccelOperator);
|
||||
|
||||
/// Get the angular acceleration vector.
|
||||
inline const osg::Vec3 &getAngularAcceleration() const;
|
||||
|
||||
/// Set the angular acceleration vector.
|
||||
inline void setAngularAcceleration(const osg::Vec3 &v);
|
||||
|
||||
/// Apply the angular 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 ~AngularAccelOperator() {}
|
||||
AngularAccelOperator &operator=(const AngularAccelOperator &) { return *this; }
|
||||
|
||||
private:
|
||||
osg::Vec3 angular_accel_;
|
||||
osg::Vec3 xf_angular_accel_;
|
||||
};
|
||||
|
||||
// INLINE FUNCTIONS
|
||||
|
||||
inline AngularAccelOperator::AngularAccelOperator()
|
||||
: Operator(), angular_accel_(0, 0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
inline AngularAccelOperator::AngularAccelOperator(const AngularAccelOperator ©, const osg::CopyOp ©op)
|
||||
: Operator(copy, copyop), angular_accel_(copy.angular_accel_)
|
||||
{
|
||||
}
|
||||
|
||||
inline const osg::Vec3 &AngularAccelOperator::getAngularAcceleration() const
|
||||
{
|
||||
return angular_accel_;
|
||||
}
|
||||
|
||||
inline void AngularAccelOperator::setAngularAcceleration(const osg::Vec3 &v)
|
||||
{
|
||||
angular_accel_ = v;
|
||||
}
|
||||
|
||||
inline void AngularAccelOperator::operate(Particle *P, double dt)
|
||||
{
|
||||
P->addAngularVelocity(xf_angular_accel_ * dt);
|
||||
}
|
||||
|
||||
inline void AngularAccelOperator::beginOperate(Program *prg)
|
||||
{
|
||||
if (prg->getReferenceFrame() == ModularProgram::RELATIVE_TO_PARENTS) {
|
||||
xf_angular_accel_ = prg->rotateLocalToWorld(angular_accel_);
|
||||
} else {
|
||||
xf_angular_accel_ = angular_accel_;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@ -45,11 +45,16 @@ namespace osgParticle
|
||||
class OSGPARTICLE_EXPORT Particle {
|
||||
public:
|
||||
|
||||
/**
|
||||
Shape of particles.
|
||||
NOTE: the LINE shape should be used in conjunction with FIXED alignment mode (see ParticleSystem).
|
||||
*/
|
||||
enum Shape {
|
||||
POINT, // uses GL_POINTS as primitive
|
||||
QUAD, // uses GL_QUADS as primitive
|
||||
QUAD_TRIANGLESTRIP, // uses GL_TRIANGLE_STRIP as primitive, but each particle needs a glBegin/glEnd pair
|
||||
HEXAGON // may save some filling time, but uses more triangles
|
||||
HEXAGON, // may save some filling time, but uses more triangles
|
||||
LINE // uses GL_LINES to draw line segments that point to the direction of motion
|
||||
};
|
||||
|
||||
Particle();
|
||||
@ -112,6 +117,15 @@ namespace osgParticle
|
||||
/// Get the previous position (the position before last update).
|
||||
inline const osg::Vec3 &getPreviousPosition() const;
|
||||
|
||||
/// Get the angle vector.
|
||||
inline const osg::Vec3 &getAngle() const;
|
||||
|
||||
/// Get the rotational velocity vector.
|
||||
inline const osg::Vec3 &getAngularVelocity() const;
|
||||
|
||||
/// Get the previous angle vector.
|
||||
inline const osg::Vec3 &getPreviousAngle() const;
|
||||
|
||||
/** 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.
|
||||
@ -164,6 +178,21 @@ namespace osgParticle
|
||||
/// Transform position and velocity vectors by a matrix.
|
||||
inline void transformPositionVelocity(const osg::Matrix &xform);
|
||||
|
||||
/// Set the angle vector.
|
||||
inline void setAngle(const osg::Vec3 &a);
|
||||
|
||||
/**
|
||||
Set the angular velocity vector.
|
||||
Components x, y and z are angles of rotation around the respective axis (in radians).
|
||||
*/
|
||||
inline void setAngularVelocity(const osg::Vec3 &v);
|
||||
|
||||
/// Add a vector to the angular velocity vector.
|
||||
inline void addAngularVelocity(const osg::Vec3 &dv);
|
||||
|
||||
/// Transform angle and angularVelocity vectors by a matrix.
|
||||
inline void transformAngleVelocity(const osg::Matrix &xform);
|
||||
|
||||
/** 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,
|
||||
@ -206,6 +235,10 @@ namespace osgParticle
|
||||
osg::Vec3 position_;
|
||||
osg::Vec3 velocity_;
|
||||
|
||||
osg::Vec3 prev_angle_;
|
||||
osg::Vec3 angle_;
|
||||
osg::Vec3 angular_vel_;
|
||||
|
||||
double t0_;
|
||||
|
||||
float current_size_;
|
||||
@ -295,6 +328,21 @@ namespace osgParticle
|
||||
return prev_pos_;
|
||||
}
|
||||
|
||||
inline const osg::Vec3 &Particle::getAngle() const
|
||||
{
|
||||
return angle_;
|
||||
}
|
||||
|
||||
inline const osg::Vec3 &Particle::getAngularVelocity() const
|
||||
{
|
||||
return angular_vel_;
|
||||
}
|
||||
|
||||
inline const osg::Vec3 &Particle::getPreviousAngle() const
|
||||
{
|
||||
return prev_angle_;
|
||||
}
|
||||
|
||||
inline void Particle::kill()
|
||||
{
|
||||
mustdie_ = true;
|
||||
@ -345,9 +393,9 @@ namespace osgParticle
|
||||
velocity_ = v;
|
||||
}
|
||||
|
||||
inline void Particle::addVelocity(const osg::Vec3 &v)
|
||||
inline void Particle::addVelocity(const osg::Vec3 &dv)
|
||||
{
|
||||
velocity_ += v;
|
||||
velocity_ += dv;
|
||||
}
|
||||
|
||||
inline void Particle::transformPositionVelocity(const osg::Matrix &xform)
|
||||
@ -362,6 +410,33 @@ namespace osgParticle
|
||||
velocity_ = p1 - position_;
|
||||
}
|
||||
|
||||
inline void Particle::setAngle(const osg::Vec3 &a)
|
||||
{
|
||||
angle_ = a;
|
||||
}
|
||||
|
||||
inline void Particle::setAngularVelocity(const osg::Vec3 &v)
|
||||
{
|
||||
angular_vel_ = v;
|
||||
}
|
||||
|
||||
inline void Particle::addAngularVelocity(const osg::Vec3 &dv)
|
||||
{
|
||||
angular_vel_ += dv;
|
||||
}
|
||||
|
||||
inline void Particle::transformAngleVelocity(const osg::Matrix &xform)
|
||||
{
|
||||
// this should be optimized!
|
||||
|
||||
osg::Vec3 a1 = angle_ + angular_vel_;
|
||||
|
||||
angle_ = xform.preMult(angle_);
|
||||
a1 = xform.preMult(a1);
|
||||
|
||||
angular_vel_ = a1 - angle_;
|
||||
}
|
||||
|
||||
inline float Particle::getMass() const
|
||||
{
|
||||
return mass_;
|
||||
@ -388,6 +463,9 @@ namespace osgParticle
|
||||
case QUAD:
|
||||
glBegin(GL_QUADS);
|
||||
break;
|
||||
case LINE:
|
||||
glBegin(GL_LINES);
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
@ -398,6 +476,7 @@ namespace osgParticle
|
||||
{
|
||||
case POINT:
|
||||
case QUAD:
|
||||
case LINE:
|
||||
glEnd();
|
||||
break;
|
||||
default: ;
|
||||
|
@ -72,6 +72,36 @@ namespace osgParticle
|
||||
/// Set the destination particle system.
|
||||
inline void setParticleSystem(ParticleSystem *ps);
|
||||
|
||||
/// Set the endless flag of this processor.
|
||||
inline void setEndless(bool type);
|
||||
|
||||
/// Check whether this processor is endless.
|
||||
inline bool isEndless() const;
|
||||
|
||||
/// Set the lifetime of this processor.
|
||||
inline void setLifeTime(double t);
|
||||
|
||||
/// Get the lifetime of this processor.
|
||||
inline double getLifeTime() const;
|
||||
|
||||
/// Set the start time of this processor.
|
||||
inline void setStartTime(double t);
|
||||
|
||||
/// Get the start time of this processor.
|
||||
inline double getStartTime() const;
|
||||
|
||||
/// Set the current time of this processor.
|
||||
inline void setCurrentTime(double t);
|
||||
|
||||
/// Get the current time of this processor.
|
||||
inline double getCurrentTime() const;
|
||||
|
||||
/// Set the reset time of this processor. A value of 0 disables reset.
|
||||
inline void setResetTime(double t);
|
||||
|
||||
/// Get the reset time of this processor.
|
||||
inline double getResetTime() const;
|
||||
|
||||
void traverse(osg::NodeVisitor &nv);
|
||||
|
||||
/// Get the current local-to-world transformation matrix (valid only during cull traversal).
|
||||
@ -110,6 +140,13 @@ namespace osgParticle
|
||||
osg::Matrix ltw_matrix_;
|
||||
osg::Matrix wtl_matrix_;
|
||||
osg::NodeVisitor *current_nodevisitor_;
|
||||
|
||||
bool endless_;
|
||||
|
||||
double lifeTime_;
|
||||
double startTime_;
|
||||
double currentTime_;
|
||||
double resetTime_;
|
||||
};
|
||||
|
||||
// INLINE FUNCTIONS
|
||||
@ -132,7 +169,10 @@ namespace osgParticle
|
||||
inline void ParticleProcessor::setEnabled(bool v)
|
||||
{
|
||||
enabled_ = v;
|
||||
if (enabled_) t0_ = -1;
|
||||
if (enabled_) {
|
||||
t0_ = -1;
|
||||
currentTime_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline ParticleSystem *ParticleProcessor::getParticleSystem()
|
||||
@ -150,6 +190,56 @@ namespace osgParticle
|
||||
ps_ = ps;
|
||||
}
|
||||
|
||||
inline void ParticleProcessor::setEndless(bool type)
|
||||
{
|
||||
endless_ = type;
|
||||
}
|
||||
|
||||
inline bool ParticleProcessor::isEndless() const
|
||||
{
|
||||
return endless_;
|
||||
}
|
||||
|
||||
inline void ParticleProcessor::setLifeTime(double t)
|
||||
{
|
||||
lifeTime_ = t;
|
||||
endless_ = false;
|
||||
}
|
||||
|
||||
inline double ParticleProcessor::getLifeTime() const
|
||||
{
|
||||
return lifeTime_;
|
||||
}
|
||||
|
||||
inline void ParticleProcessor::setStartTime(double t)
|
||||
{
|
||||
startTime_ = t;
|
||||
}
|
||||
|
||||
inline double ParticleProcessor::getStartTime() const
|
||||
{
|
||||
return startTime_;
|
||||
}
|
||||
inline void ParticleProcessor::setCurrentTime(double t)
|
||||
{
|
||||
currentTime_ = t;
|
||||
}
|
||||
|
||||
inline double ParticleProcessor::getCurrentTime() const
|
||||
{
|
||||
return currentTime_;
|
||||
}
|
||||
|
||||
inline void ParticleProcessor::setResetTime(double t)
|
||||
{
|
||||
resetTime_ = t;
|
||||
}
|
||||
|
||||
inline double ParticleProcessor::getResetTime() const
|
||||
{
|
||||
return resetTime_;
|
||||
}
|
||||
|
||||
inline bool ParticleProcessor::computeBound() const
|
||||
{
|
||||
_bsphere.init();
|
||||
|
@ -67,6 +67,15 @@ namespace osgParticle
|
||||
/// Set the range of possible values for initial speed of particles.
|
||||
inline void setInitialSpeedRange(float r1, float r2);
|
||||
|
||||
/// Get the range of possible values for initial rotational speed of particles.
|
||||
inline const rangev3 &getInitialRotationalSpeedRange() const;
|
||||
|
||||
/// Set the range of possible values for initial rotational speed of particles.
|
||||
inline void setInitialRotationalSpeedRange(const rangev3 &r);
|
||||
|
||||
/// Set the range of possible values for initial rotational speed of particles.
|
||||
inline void setInitialRotationalSpeedRange(const osg::Vec3 &r1, const osg::Vec3 &r2);
|
||||
|
||||
/// Shoot a particle. Do not call this method manually.
|
||||
inline void shoot(Particle *P) const;
|
||||
|
||||
@ -78,6 +87,7 @@ namespace osgParticle
|
||||
rangef theta_range_;
|
||||
rangef phi_range_;
|
||||
rangef speed_range_;
|
||||
rangev3 rot_speed_range_;
|
||||
};
|
||||
|
||||
// INLINE FUNCTIONS
|
||||
@ -86,7 +96,8 @@ namespace osgParticle
|
||||
: Shooter(),
|
||||
theta_range_(0, 0.5f*osg::PI_4),
|
||||
phi_range_(0, 2*osg::PI),
|
||||
speed_range_(10, 10)
|
||||
speed_range_(10, 10),
|
||||
rot_speed_range_(osg::Vec3(0,0,0), osg::Vec3(0,0,0))
|
||||
{
|
||||
}
|
||||
|
||||
@ -94,7 +105,8 @@ namespace osgParticle
|
||||
: Shooter(copy, copyop),
|
||||
theta_range_(copy.theta_range_),
|
||||
phi_range_(copy.phi_range_),
|
||||
speed_range_(copy.speed_range_)
|
||||
speed_range_(copy.speed_range_),
|
||||
rot_speed_range_(copy.rot_speed_range_)
|
||||
{
|
||||
}
|
||||
|
||||
@ -113,6 +125,11 @@ namespace osgParticle
|
||||
return speed_range_;
|
||||
}
|
||||
|
||||
inline const rangev3 &RadialShooter::getInitialRotationalSpeedRange() const
|
||||
{
|
||||
return rot_speed_range_;
|
||||
}
|
||||
|
||||
inline void RadialShooter::setThetaRange(const rangef &r)
|
||||
{
|
||||
theta_range_ = r;
|
||||
@ -146,17 +163,31 @@ namespace osgParticle
|
||||
speed_range_.maximum = r2;
|
||||
}
|
||||
|
||||
inline void RadialShooter::setInitialRotationalSpeedRange(const rangev3 &r)
|
||||
{
|
||||
rot_speed_range_ = r;
|
||||
}
|
||||
|
||||
inline void RadialShooter::setInitialRotationalSpeedRange(const osg::Vec3 &r1, const osg::Vec3 &r2)
|
||||
{
|
||||
rot_speed_range_.minimum = r1;
|
||||
rot_speed_range_.maximum = 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();
|
||||
osg::Vec3 rot_speed = rot_speed_range_.get_random();
|
||||
|
||||
P->setVelocity(osg::Vec3(
|
||||
speed * sinf(theta) * cosf(phi),
|
||||
speed * sinf(theta) * sinf(phi),
|
||||
speed * cosf(theta)
|
||||
));
|
||||
|
||||
P->setAngularVelocity(rot_speed);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ osgParticle::FluidFrictionOperator::FluidFrictionOperator(const FluidFrictionOpe
|
||||
{
|
||||
}
|
||||
|
||||
void osgParticle::FluidFrictionOperator::operate(Particle *P, double)
|
||||
void osgParticle::FluidFrictionOperator::operate(Particle *P, double dt)
|
||||
{
|
||||
float r = (ovr_rad_ > 0)? ovr_rad_ : P->getRadius();
|
||||
osg::Vec3 v = P->getVelocity();
|
||||
@ -42,7 +42,7 @@ void osgParticle::FluidFrictionOperator::operate(Particle *P, double)
|
||||
}
|
||||
|
||||
// correct unwanted velocity increments
|
||||
osg::Vec3 dv = Fr * (P->getMassInv() * 0.01);
|
||||
osg::Vec3 dv = Fr * P->getMassInv() * dt;
|
||||
float dvl = dv.length();
|
||||
if (dvl > vm) {
|
||||
dv *= vm / dvl;
|
||||
|
@ -36,6 +36,9 @@ osgParticle::Particle::Particle()
|
||||
prev_pos_(0, 0, 0),
|
||||
position_(0, 0, 0),
|
||||
velocity_(0, 0, 0),
|
||||
prev_angle_(0, 0, 0),
|
||||
angle_(0, 0, 0),
|
||||
angular_vel_(0, 0, 0),
|
||||
t0_(0),
|
||||
current_size_(0),
|
||||
current_alpha_(0)
|
||||
@ -75,6 +78,17 @@ bool osgParticle::Particle::update(double dt)
|
||||
prev_pos_ = position_;
|
||||
position_ += velocity_ * dt;
|
||||
|
||||
// update angle
|
||||
prev_angle_ = angle_;
|
||||
angle_ += angular_vel_ * dt;
|
||||
|
||||
if (angle_.x() > osg::PI*2) angle_.x() -= osg::PI*2;
|
||||
if (angle_.x() < -osg::PI*2) angle_.x() += osg::PI*2;
|
||||
if (angle_.y() > osg::PI*2) angle_.y() -= osg::PI*2;
|
||||
if (angle_.y() < -osg::PI*2) angle_.y() += osg::PI*2;
|
||||
if (angle_.z() > osg::PI*2) angle_.z() -= osg::PI*2;
|
||||
if (angle_.z() < -osg::PI*2) angle_.z() += osg::PI*2;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -85,6 +99,12 @@ void osgParticle::Particle::render(const osg::Vec3 &xpos, const osg::Vec3 &px, c
|
||||
current_color_.z(),
|
||||
current_color_.w() * current_alpha_);
|
||||
|
||||
osg::Matrix R;
|
||||
R.makeRotate(
|
||||
angle_.x(), osg::Vec3(1, 0, 0),
|
||||
angle_.y(), osg::Vec3(0, 1, 0),
|
||||
angle_.z(), osg::Vec3(0, 0, 1));
|
||||
|
||||
osg::Vec3 p1(px * current_size_ * scale);
|
||||
osg::Vec3 p2(py * current_size_ * scale);
|
||||
|
||||
@ -96,56 +116,73 @@ void osgParticle::Particle::render(const osg::Vec3 &xpos, const osg::Vec3 &px, c
|
||||
|
||||
case QUAD:
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex3fv((xpos-p1-p2).ptr());
|
||||
glVertex3fv((xpos-(p1+p2)*R).ptr());
|
||||
glTexCoord2f(1, 0);
|
||||
glVertex3fv((xpos+p1-p2).ptr());
|
||||
glVertex3fv((xpos+(p1-p2)*R).ptr());
|
||||
glTexCoord2f(1, 1);
|
||||
glVertex3fv((xpos+p1+p2).ptr());
|
||||
glVertex3fv((xpos+(p1+p2)*R).ptr());
|
||||
glTexCoord2f(0, 1);
|
||||
glVertex3fv((xpos-p1+p2).ptr());
|
||||
glVertex3fv((xpos-(p1-p2)*R).ptr());
|
||||
break;
|
||||
|
||||
case QUAD_TRIANGLESTRIP:
|
||||
glPushMatrix();
|
||||
glTranslatef(xpos.x(), xpos.y(), xpos.z());
|
||||
glMultMatrixf(R.ptr());
|
||||
// we must glBegin() and glEnd() here, because each particle is a single strip
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
glTexCoord2f(1, 1);
|
||||
glVertex3fv((xpos+p1+p2).ptr());
|
||||
glVertex3fv((p1+p2).ptr());
|
||||
glTexCoord2f(0, 1);
|
||||
glVertex3fv((xpos-p1+p2).ptr());
|
||||
glVertex3fv((-p1+p2).ptr());
|
||||
glTexCoord2f(1, 0);
|
||||
glVertex3fv((xpos+p1-p2).ptr());
|
||||
glVertex3fv((p1-p2).ptr());
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex3fv((xpos-p1-p2).ptr());
|
||||
glVertex3fv((-p1-p2).ptr());
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
break;
|
||||
|
||||
case HEXAGON:
|
||||
glPushMatrix();
|
||||
glTranslatef(xpos.x(), xpos.y(), xpos.z());
|
||||
glMultMatrixf(R.ptr());
|
||||
// we must glBegin() and glEnd() here, because each particle is a single fan
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
glTexCoord2f(0.5f, 0.5f);
|
||||
glVertex3fv(xpos.ptr());
|
||||
glVertex3f(0,0,0);
|
||||
glTexCoord2f(hex_texcoord_x1, hex_texcoord_y1);
|
||||
glVertex3fv((xpos+p1*cosPI3+p2*sinPI3).ptr());
|
||||
//glVertex3f(xpos.x() + cs * cosPI3, xpos.y() + cs * sinPI3, xpos.z());
|
||||
glVertex3fv((p1*cosPI3+p2*sinPI3).ptr());
|
||||
glTexCoord2f(hex_texcoord_x2, hex_texcoord_y1);
|
||||
glVertex3fv((xpos-p1*cosPI3+p2*sinPI3).ptr());
|
||||
//glVertex3f(xpos.x() - cs * cosPI3, xpos.y() + cs * sinPI3, xpos.z());
|
||||
glVertex3fv((-p1*cosPI3+p2*sinPI3).ptr());
|
||||
glTexCoord2f(0, 0.5f);
|
||||
glVertex3fv((xpos-p1).ptr());
|
||||
//glVertex3f(xpos.x() - cs, xpos.y(), xpos.z());
|
||||
glVertex3fv((-p1).ptr());
|
||||
glTexCoord2f(hex_texcoord_x2, hex_texcoord_y2);
|
||||
glVertex3fv((xpos-p1*cosPI3-p2*sinPI3).ptr());
|
||||
//glVertex3f(xpos.x() - cs * cosPI3, xpos.y() - cs * sinPI3, xpos.z());
|
||||
glVertex3fv((-p1*cosPI3-p2*sinPI3).ptr());
|
||||
glTexCoord2f(hex_texcoord_x1, hex_texcoord_y2);
|
||||
glVertex3fv((xpos+p1*cosPI3-p2*sinPI3).ptr());
|
||||
//glVertex3f(xpos.x() + cs * cosPI3, xpos.y() - cs * sinPI3, xpos.z());
|
||||
glVertex3fv((p1*cosPI3-p2*sinPI3).ptr());
|
||||
glTexCoord2f(1, 0.5f);
|
||||
glVertex3fv((xpos+p1).ptr());
|
||||
//glVertex3f(xpos.x() + cs, xpos.y(), xpos.z());
|
||||
glVertex3fv((p1).ptr());
|
||||
glTexCoord2f(hex_texcoord_x1, hex_texcoord_y1);
|
||||
glVertex3fv((xpos+p1*cosPI3+p2*sinPI3).ptr());
|
||||
//glVertex3f(xpos.x() + cs * cosPI3, xpos.y() + cs * sinPI3, xpos.z());
|
||||
glVertex3fv((p1*cosPI3+p2*sinPI3).ptr());
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
break;
|
||||
|
||||
case LINE:
|
||||
{
|
||||
// Get the normalized direction of the particle, to be used in the
|
||||
// calculation of one of the linesegment endpoints.
|
||||
float vl = velocity_.length();
|
||||
if (vl != 0) {
|
||||
osg::Vec3 v = velocity_ * current_size_ * scale / vl;
|
||||
|
||||
glTexCoord1f(0);
|
||||
glVertex3f(xpos.x(), xpos.y(), xpos.z());
|
||||
glTexCoord1f(1);
|
||||
glVertex3f(xpos.x() + v.x(), xpos.y() + v.y(), xpos.z() + v.z());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -19,7 +19,12 @@ osgParticle::ParticleProcessor::ParticleProcessor()
|
||||
ps_(0),
|
||||
need_ltw_matrix_(false),
|
||||
need_wtl_matrix_(false),
|
||||
current_nodevisitor_(0)
|
||||
current_nodevisitor_(0),
|
||||
endless_(true),
|
||||
lifeTime_(0.0),
|
||||
startTime_(0.0),
|
||||
currentTime_(0.0),
|
||||
resetTime_(0.0)
|
||||
{
|
||||
setCullingActive(false);
|
||||
}
|
||||
@ -32,17 +37,17 @@ osgParticle::ParticleProcessor::ParticleProcessor(const ParticleProcessor ©,
|
||||
ps_(static_cast<ParticleSystem *>(copyop(copy.ps_.get()))),
|
||||
need_ltw_matrix_(copy.need_ltw_matrix_),
|
||||
need_wtl_matrix_(copy.need_wtl_matrix_),
|
||||
current_nodevisitor_(0)
|
||||
current_nodevisitor_(0),
|
||||
endless_(copy.endless_),
|
||||
lifeTime_(copy.lifeTime_),
|
||||
startTime_(copy.startTime_),
|
||||
currentTime_(copy.currentTime_),
|
||||
resetTime_(copy.resetTime_)
|
||||
{
|
||||
}
|
||||
|
||||
void osgParticle::ParticleProcessor::traverse(osg::NodeVisitor &nv)
|
||||
{
|
||||
// continue only if enabled
|
||||
if (enabled_ )
|
||||
{
|
||||
|
||||
|
||||
// typecast the NodeVisitor to CullVisitor
|
||||
osgUtil::CullVisitor *cv = dynamic_cast<osgUtil::CullVisitor *>(&nv);
|
||||
|
||||
@ -59,11 +64,30 @@ void osgParticle::ParticleProcessor::traverse(osg::NodeVisitor &nv)
|
||||
// retrieve the current time
|
||||
double t = nv.getFrameStamp()->getReferenceTime();
|
||||
|
||||
// reset this processor if we've reached the reset point
|
||||
if ((currentTime_ >= resetTime_) && (resetTime_ > 0)) {
|
||||
currentTime_ = 0;
|
||||
t0_ = -1;
|
||||
}
|
||||
|
||||
// skip if we haven't initialized t0_ yet
|
||||
if (t0_ != -1) {
|
||||
|
||||
// check whether the particle system is frozen/culled
|
||||
if (!ps_->isFrozen() && (ps_->getLastFrameNumber() >= (nv.getFrameStamp()->getFrameNumber() - 1) || !ps_->getFreezeOnCull())) {
|
||||
// check whether the processor is alive
|
||||
bool alive = false;
|
||||
if (currentTime_ >= startTime_) {
|
||||
if (endless_ || (currentTime_ < (startTime_ + lifeTime_)))
|
||||
alive = true;
|
||||
}
|
||||
|
||||
// update current time
|
||||
currentTime_ += t - t0_;
|
||||
|
||||
// process only if the particle system is not frozen/culled
|
||||
if (alive &&
|
||||
enabled_ &&
|
||||
!ps_->isFrozen() &&
|
||||
(ps_->getLastFrameNumber() >= (nv.getFrameStamp()->getFrameNumber() - 1) || !ps_->getFreezeOnCull())) {
|
||||
|
||||
// initialize matrix flags
|
||||
need_ltw_matrix_ = true;
|
||||
@ -89,7 +113,7 @@ void osgParticle::ParticleProcessor::traverse(osg::NodeVisitor &nv)
|
||||
osg::notify(osg::WARN) << "ParticleProcessor \"" << getName() << "\": invalid particle system\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// call the inherited method
|
||||
Node::traverse(nv);
|
||||
|
@ -30,7 +30,7 @@ osgParticle::ParticleSystem::ParticleSystem()
|
||||
bounds_computed_(false),
|
||||
def_ptemp_(Particle()),
|
||||
last_frame_(0),
|
||||
freeze_on_cull_(true),
|
||||
freeze_on_cull_(false),
|
||||
detail_(1),
|
||||
draw_count_(0)
|
||||
{
|
||||
|
@ -68,11 +68,11 @@ DataInputStream::DataInputStream(std::istream* istream){
|
||||
DataInputStream::~DataInputStream(){}
|
||||
|
||||
bool DataInputStream::readBool(){
|
||||
bool b;
|
||||
_istream->read((char*)&b, BOOLSIZE);
|
||||
char c;
|
||||
_istream->read(&c, CHARSIZE);
|
||||
if (_istream->rdstate() & _istream->failbit)
|
||||
throw Exception("DataInputStream::readBool(): Failed to read boolean value.");
|
||||
return b;
|
||||
return c;
|
||||
}
|
||||
|
||||
char DataInputStream::readChar(){
|
||||
|
@ -58,8 +58,10 @@ DataOutputStream::DataOutputStream(std::ostream * ostream){
|
||||
|
||||
DataOutputStream::~DataOutputStream(){}
|
||||
|
||||
void DataOutputStream::writeBool(bool b){
|
||||
_ostream->write((char*)&b, BOOLSIZE);
|
||||
void DataOutputStream::writeBool(bool b)
|
||||
{
|
||||
char c = b;
|
||||
_ostream->write(&c, CHARSIZE);
|
||||
}
|
||||
|
||||
void DataOutputStream::writeChar(char c){
|
||||
|
@ -3,6 +3,7 @@ include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
IO_AccelOperator.cpp\
|
||||
IO_AngularAccelOperator.cpp\
|
||||
IO_CenteredPlacer.cpp\
|
||||
IO_Emitter.cpp\
|
||||
IO_FluidFrictionOperator.cpp\
|
||||
|
48
src/osgPlugins/osgParticle/IO_AngularAccelOperator.cpp
Normal file
48
src/osgPlugins/osgParticle/IO_AngularAccelOperator.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
|
||||
#include <osgParticle/AngularAccelOperator>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
#include <osg/Vec3>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
bool AngularAccelOperator_readLocalData(osg::Object &obj, osgDB::Input &fr);
|
||||
bool AngularAccelOperator_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
|
||||
|
||||
osgDB::RegisterDotOsgWrapperProxy AngularAccelOperator_Proxy
|
||||
(
|
||||
new osgParticle::AngularAccelOperator,
|
||||
"AngularAccelOperator",
|
||||
"Object Operator AngularAccelOperator",
|
||||
AngularAccelOperator_readLocalData,
|
||||
AngularAccelOperator_writeLocalData
|
||||
);
|
||||
|
||||
bool AngularAccelOperator_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
{
|
||||
osgParticle::AngularAccelOperator &aop = static_cast<osgParticle::AngularAccelOperator &>(obj);
|
||||
bool itAdvanced = false;
|
||||
|
||||
osg::Vec3 a;
|
||||
|
||||
if (fr[0].matchWord("angularAcceleration")) {
|
||||
if (fr[1].getFloat(a.x()) && fr[2].getFloat(a.y()) && fr[3].getFloat(a.z())) {
|
||||
aop.setAngularAcceleration(a);
|
||||
fr += 4;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
return itAdvanced;
|
||||
}
|
||||
|
||||
bool AngularAccelOperator_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
||||
{
|
||||
const osgParticle::AngularAccelOperator &aop = static_cast<const osgParticle::AngularAccelOperator &>(obj);
|
||||
osg::Vec3 a = aop.getAngularAcceleration();
|
||||
fw.indent() << "angularAcceleration " << a.x() << " " << a.y() << " " << a.z() << std::endl;
|
||||
return true;
|
||||
}
|
@ -32,6 +32,8 @@ bool read_particle(osgDB::Input &fr, osgParticle::Particle &P)
|
||||
P.setShape(osgParticle::Particle::POINT);
|
||||
} else if (std::string(ptstr) == "QUAD_TRIANGLESTRIP") {
|
||||
P.setShape(osgParticle::Particle::QUAD_TRIANGLESTRIP);
|
||||
} else if (std::string(ptstr) == "LINE") {
|
||||
P.setShape(osgParticle::Particle::LINE);
|
||||
} else {
|
||||
osg::notify(osg::WARN) << "Particle reader warning: invalid shape: " << ptstr << std::endl;
|
||||
}
|
||||
@ -87,6 +89,22 @@ bool read_particle(osgDB::Input &fr, osgParticle::Particle &P)
|
||||
fr += 4;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
if (fr[0].matchWord("angle")) {
|
||||
osg::Vec3 v;
|
||||
if (fr[1].getFloat(v.x()) && fr[2].getFloat(v.y()) && fr[3].getFloat(v.z())) {
|
||||
P.setAngle(v);
|
||||
fr += 4;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
if (fr[0].matchWord("angularVelocity")) {
|
||||
osg::Vec3 v;
|
||||
if (fr[1].getFloat(v.x()) && fr[2].getFloat(v.y()) && fr[3].getFloat(v.z())) {
|
||||
P.setAngularVelocity(v);
|
||||
fr += 4;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
if (fr[0].matchWord("radius")) {
|
||||
float f;
|
||||
@ -152,8 +170,9 @@ void write_particle(const osgParticle::Particle &P, osgDB::Output &fw)
|
||||
case osgParticle::Particle::POINT: fw << "POINT" << std::endl; break;
|
||||
case osgParticle::Particle::HEXAGON: fw << "HEXAGON" << std::endl; break;
|
||||
case osgParticle::Particle::QUAD_TRIANGLESTRIP: fw << "QUAD_TRIANGLESTRIP" << std::endl; break;
|
||||
case osgParticle::Particle::QUAD:
|
||||
default: fw << "QUAD" << std::endl; break;
|
||||
case osgParticle::Particle::QUAD: fw << "QUAD" << std::endl; break;
|
||||
case osgParticle::Particle::LINE:
|
||||
default: fw << "LINE" << std::endl; break;
|
||||
}
|
||||
|
||||
fw.indent() << "lifeTime " << P.getLifeTime() << std::endl;
|
||||
@ -177,8 +196,16 @@ void write_particle(const osgParticle::Particle &P, osgDB::Output &fw)
|
||||
fw.indent() << "velocity ";
|
||||
fw << v.x() << " " << v.y() << " " << v.z() << std::endl;
|
||||
|
||||
fw.indent() << "mass " << P.getMass() << std::endl;
|
||||
v = P.getAngle();
|
||||
fw.indent() << "angle ";
|
||||
fw << v.x() << " " << v.y() << " " << v.z() << std::endl;
|
||||
|
||||
v = P.getAngularVelocity();
|
||||
fw.indent() << "angularVelocity ";
|
||||
fw << v.x() << " " << v.y() << " " << v.z() << std::endl;
|
||||
|
||||
fw.indent() << "radius " << P.getRadius() << std::endl;
|
||||
fw.indent() << "mass " << P.getMass() << std::endl;
|
||||
|
||||
// interpolators
|
||||
|
||||
|
@ -63,6 +63,54 @@ bool ParticleProcessor_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
}
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("endless")) {
|
||||
if (fr[1].matchWord("TRUE")) {
|
||||
myobj.setEndless(true);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
} else if (fr[1].matchWord("FALSE")) {
|
||||
myobj.setEndless(false);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("lifeTime")) {
|
||||
float lt;
|
||||
if (fr[1].getFloat(lt)) {
|
||||
myobj.setLifeTime(lt);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("startTime")) {
|
||||
float st;
|
||||
if (fr[1].getFloat(st)) {
|
||||
myobj.setStartTime(st);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("currentTime")) {
|
||||
float ct;
|
||||
if (fr[1].getFloat(ct)) {
|
||||
myobj.setCurrentTime(ct);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("resetTime")) {
|
||||
float ct;
|
||||
if (fr[1].getFloat(ct)) {
|
||||
myobj.setResetTime(ct);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
return itAdvanced;
|
||||
}
|
||||
|
||||
@ -89,5 +137,16 @@ bool ParticleProcessor_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
||||
fw << "RELATIVE_TO_PARENTS" << std::endl;
|
||||
}
|
||||
|
||||
fw.indent() << "endless ";
|
||||
if (myobj.isEndless())
|
||||
fw << "TRUE" << std::endl;
|
||||
else
|
||||
fw << "FALSE" << std::endl;
|
||||
|
||||
fw.indent() << "lifeTime " << myobj.getLifeTime() << std::endl;
|
||||
fw.indent() << "startTime " << myobj.getStartTime() << std::endl;
|
||||
fw.indent() << "currentTime " << myobj.getCurrentTime() << std::endl;
|
||||
fw.indent() << "resetTime " << myobj.getResetTime() << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -49,6 +49,17 @@ bool RadialShooter_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
}
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("initialRotationalSpeedRange")) {
|
||||
osg::Vec3 r1;
|
||||
osg::Vec3 r2;
|
||||
if (fr[1].getFloat(r1.x()) && fr[2].getFloat(r1.y()) && fr[3].getFloat(r1.z()) && \
|
||||
fr[4].getFloat(r2.x()) && fr[5].getFloat(r2.y()) && fr[6].getFloat(r2.z())) {
|
||||
myobj.setInitialRotationalSpeedRange(r1,r2);
|
||||
fr += 7;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
return itAdvanced;
|
||||
}
|
||||
|
||||
@ -64,5 +75,12 @@ bool RadialShooter_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
||||
r = myobj.getInitialSpeedRange();
|
||||
fw.indent() << "initialSpeedRange " << r.minimum << " " << r.maximum << std::endl;
|
||||
|
||||
osgParticle::rangev3 rv = myobj.getInitialRotationalSpeedRange();
|
||||
osg::Vec3 v1 = rv.minimum;
|
||||
osg::Vec3 v2 = rv.maximum;
|
||||
fw.indent() << "initialRotationalSpeedRange ";
|
||||
fw << v1.x() << " " << v1.y() << " " << v1.z() << " ";
|
||||
fw << v2.x() << " " << v2.y() << " " << v2.z() << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user