Removed Particle::Shape support for QUAD_TRIANGLESTRIP, HEXAGON, USER as these are unlikely to be used as their implementation prevents refactoring to use vertex array code paths
This commit is contained in:
parent
c637010c9d
commit
56ed225f17
@ -44,15 +44,15 @@ void createFountainEffect( osgParticle::ModularEmitter* emitter, osgParticle::Mo
|
||||
// Emit specific number of particles every frame
|
||||
osg::ref_ptr<osgParticle::RandomRateCounter> rrc = new osgParticle::RandomRateCounter;
|
||||
rrc->setRateRange( 500, 2000 );
|
||||
|
||||
|
||||
// Accelerate particles in the given gravity direction.
|
||||
osg::ref_ptr<osgParticle::AccelOperator> accel = new osgParticle::AccelOperator;
|
||||
accel->setToGravity();
|
||||
|
||||
|
||||
// Multiply each particle's velocity by a damping constant.
|
||||
osg::ref_ptr<osgParticle::DampingOperator> damping = new osgParticle::DampingOperator;
|
||||
damping->setDamping( 0.9f );
|
||||
|
||||
|
||||
// Bounce particles off objects defined by one or more domains.
|
||||
// Supported domains include triangle, rectangle, plane, disk and sphere.
|
||||
// Since a bounce always happens instantaneously, it will not work correctly with unstable delta-time.
|
||||
@ -63,12 +63,12 @@ void createFountainEffect( osgParticle::ModularEmitter* emitter, osgParticle::Mo
|
||||
bounce->setResilience( 0.35 );
|
||||
bounce->addDiskDomain( osg::Vec3(0.0f, 0.0f, -2.0f), osg::Z_AXIS, 8.0f );
|
||||
bounce->addPlaneDomain( osg::Plane(osg::Z_AXIS, 5.0f) );
|
||||
|
||||
|
||||
// Kill particles going inside/outside of specified domains.
|
||||
osg::ref_ptr<osgParticle::SinkOperator> sink = new osgParticle::SinkOperator;
|
||||
sink->setSinkStrategy( osgParticle::SinkOperator::SINK_OUTSIDE );
|
||||
sink->addSphereDomain( osg::Vec3(), 20.0f );
|
||||
|
||||
|
||||
emitter->setCounter( rrc.get() );
|
||||
program->addOperator( accel.get() );
|
||||
program->addOperator( damping.get() );
|
||||
@ -79,48 +79,33 @@ void createFountainEffect( osgParticle::ModularEmitter* emitter, osgParticle::Mo
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
osg::ArgumentParser arguments( &argc, argv );
|
||||
|
||||
|
||||
std::string textureFile("Images/smoke.rgb");
|
||||
while ( arguments.read("--texture", textureFile) ) {}
|
||||
|
||||
|
||||
float pointSize = 20.0f;
|
||||
while ( arguments.read("--point", pointSize) ) {}
|
||||
|
||||
|
||||
double visibilityDistance = -1.0f;
|
||||
while ( arguments.read("--visibility", visibilityDistance) ) {}
|
||||
|
||||
bool customShape = false;
|
||||
while ( arguments.read("--enable-custom") ) { customShape = true; }
|
||||
|
||||
|
||||
bool useShaders = true;
|
||||
while ( arguments.read("--disable-shaders") ) { useShaders = false; }
|
||||
|
||||
|
||||
/***
|
||||
Customize particle template and system attributes
|
||||
***/
|
||||
osg::ref_ptr<osgParticle::ParticleSystem> ps = new osgParticle::ParticleSystem;
|
||||
|
||||
|
||||
ps->getDefaultParticleTemplate().setLifeTime( 5.0f );
|
||||
|
||||
if ( customShape )
|
||||
{
|
||||
// osgParticle now supports making use of customized drawables. The draw() method will be executed
|
||||
// and display lists will be called for each particle. It is always a huge consumption of memory, and
|
||||
// hardly to use shaders to render them, so please be careful using this feature.
|
||||
ps->getDefaultParticleTemplate().setShape( osgParticle::Particle::USER );
|
||||
ps->getDefaultParticleTemplate().setDrawable( new osg::ShapeDrawable(new osg::Box(osg::Vec3(), 1.0f)) );
|
||||
useShaders = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The shader only supports rendering points at present.
|
||||
ps->getDefaultParticleTemplate().setShape( osgParticle::Particle::POINT );
|
||||
}
|
||||
|
||||
|
||||
// The shader only supports rendering points at present.
|
||||
ps->getDefaultParticleTemplate().setShape( osgParticle::Particle::POINT );
|
||||
|
||||
// Set the visibility distance of particles, due to their Z-value in the eye coordinates.
|
||||
// Particles that are out of the distance (or behind the eye) will not be rendered.
|
||||
ps->setVisibilityDistance( visibilityDistance );
|
||||
|
||||
|
||||
if ( useShaders )
|
||||
{
|
||||
// Set using local GLSL shaders to render particles.
|
||||
@ -133,52 +118,52 @@ int main( int argc, char** argv )
|
||||
// The default methods uses glBegin()/glEnd() pairs. Fortunately the GLBeginEndAdapter does improve the
|
||||
// process, which mimics the immediate mode with glDrawArrays().
|
||||
ps->setDefaultAttributes( textureFile, true, false, 0 );
|
||||
|
||||
|
||||
// Without the help of shaders, we have to sort particles to make the visibility distance work. Sorting is
|
||||
// also useful in rendering transparent particles in back-to-front order.
|
||||
if ( visibilityDistance>0.0 )
|
||||
ps->setSortMode( osgParticle::ParticleSystem::SORT_BACK_TO_FRONT );
|
||||
}
|
||||
|
||||
|
||||
// At last, to make the point sprite work, we have to set the points size and the sprite attribute.
|
||||
osg::StateSet* stateset = ps->getOrCreateStateSet();
|
||||
stateset->setAttribute( new osg::Point(pointSize) );
|
||||
stateset->setTextureAttributeAndModes( 0, new osg::PointSprite, osg::StateAttribute::ON );
|
||||
|
||||
|
||||
/***
|
||||
Construct other particle system elements, including the emitter and program
|
||||
***/
|
||||
osg::ref_ptr<osgParticle::ModularEmitter> emitter = new osgParticle::ModularEmitter;
|
||||
emitter->setParticleSystem( ps.get() );
|
||||
|
||||
|
||||
osg::ref_ptr<osgParticle::ModularProgram> program = new osgParticle::ModularProgram;
|
||||
program->setParticleSystem( ps.get() );
|
||||
|
||||
|
||||
createFountainEffect( emitter.get(), program.get() );
|
||||
|
||||
|
||||
/***
|
||||
Add the entire particle system to the scene graph
|
||||
***/
|
||||
osg::ref_ptr<osg::MatrixTransform> parent = new osg::MatrixTransform;
|
||||
parent->addChild( emitter.get() );
|
||||
parent->addChild( program.get() );
|
||||
|
||||
|
||||
// The updater can receive particle systems as child drawables now. The addParticleSystem() method
|
||||
// is still usable, with which we should define another geode to contain a particle system.
|
||||
osg::ref_ptr<osgParticle::ParticleSystemUpdater> updater = new osgParticle::ParticleSystemUpdater;
|
||||
//updater->addDrawable( ps.get() );
|
||||
|
||||
|
||||
osg::ref_ptr<osg::Group> root = new osg::Group;
|
||||
root->addChild( parent.get() );
|
||||
root->addChild( updater.get() );
|
||||
|
||||
|
||||
// FIXME 2010.9.19: the updater can't be a drawable; otehrwise the ParticleEffect will not work properly. why?
|
||||
updater->addParticleSystem( ps.get() );
|
||||
|
||||
|
||||
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
|
||||
geode->addDrawable( ps.get() );
|
||||
root->addChild( geode.get() );
|
||||
|
||||
|
||||
/***
|
||||
Start the viewer
|
||||
***/
|
||||
@ -188,7 +173,7 @@ int main( int argc, char** argv )
|
||||
viewer.addEventHandler( new osgViewer::WindowSizeHandler );
|
||||
viewer.setSceneData( root.get() );
|
||||
viewer.setCameraManipulator( new osgGA::TrackballManipulator );
|
||||
|
||||
|
||||
// A floating error of delta-time should be explained here:
|
||||
// The particles emitter, program and updater all use a 'dt' to compute the time value in every frame.
|
||||
// Because the 'dt' is a double value, it is not suitable to keep three copies of it separately, which
|
||||
@ -197,7 +182,7 @@ int main( int argc, char** argv )
|
||||
// Now we make use of the getDeltaTime() of ParticleSystem to maintain and dispatch the delta time. But..
|
||||
// it is not the best solution so far, since there are still very few particles acting unexpectedly.
|
||||
return viewer.run();
|
||||
|
||||
|
||||
// FIXME 2010.9.19: At present, getDeltaTime() is not used and the implementations in the updater and processors still
|
||||
// use a (t - _t0) as the delta time, which is of course causing floating errors. ParticleEffect will not work if we
|
||||
// replace the delta time with getDeltaTime()... Need to find a solution.
|
||||
|
@ -61,12 +61,12 @@ namespace osgParticle
|
||||
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_TRI_angleSTRIP as primitive, but each particle needs a glBegin/glEnd pair
|
||||
HEXAGON, // may save some filling time, but uses more triangles
|
||||
POINT, // uses GL_POINTS as primitive
|
||||
QUAD, // uses GL_QUADS as primitive
|
||||
QUAD_TRIANGLESTRIP, // no longer supported, falls back to QUAD
|
||||
HEXAGON, // no longer supported, falls back to QUAD
|
||||
LINE, // uses GL_LINES to draw line segments that point to the direction of motion
|
||||
USER // uses a user-defined drawable as primitive
|
||||
USER // no longer supported, falls back to QUAD
|
||||
};
|
||||
|
||||
Particle();
|
||||
@ -246,9 +246,6 @@ namespace osgParticle
|
||||
/// Render the particle. Called automatically by particle systems.
|
||||
void render(osg::GLBeginEndAdapter* gl, const osg::Vec3& xpos, const osg::Vec3& px, const osg::Vec3& py, float scale = 1.0f) const;
|
||||
|
||||
/// Render the particle with user-defined drawable
|
||||
void render(osg::RenderInfo& renderInfo, const osg::Vec3& xpos, const osg::Vec3& xrot) const;
|
||||
|
||||
/// Perform some post-rendering tasks. Called automatically by particle systems.
|
||||
inline void endRender(osg::GLBeginEndAdapter* gl) const;
|
||||
|
||||
@ -285,13 +282,6 @@ namespace osgParticle
|
||||
/// Get the depth of the particle
|
||||
inline double getDepth() const { return _depth; }
|
||||
|
||||
/// Set the user-defined particle drawable
|
||||
inline void setDrawable(osg::Drawable* d) { _drawable = d; }
|
||||
template<class T> void setDrawable(const osg::ref_ptr<T>& ri) { setDrawable(ri.get()); }
|
||||
|
||||
/// Get the user-defined particle drawable
|
||||
inline osg::Drawable* getDrawable() const { return _drawable.get(); }
|
||||
|
||||
/// Sorting operator
|
||||
bool operator<(const Particle &P) const { return _depth < P._depth; }
|
||||
|
||||
@ -346,9 +336,6 @@ namespace osgParticle
|
||||
|
||||
// the depth of the particle is used only when sorting is enabled
|
||||
double _depth;
|
||||
|
||||
// the particle drawable is used only when USER shape is enabled
|
||||
osg::ref_ptr<osg::Drawable> _drawable;
|
||||
};
|
||||
|
||||
// INLINE FUNCTIONS
|
||||
|
@ -145,7 +145,10 @@ void osgParticle::Particle::render(osg::GLBeginEndAdapter* gl, const osg::Vec3&
|
||||
gl->Vertex3f(xpos.x(), xpos.y(), xpos.z());
|
||||
break;
|
||||
|
||||
case USER:
|
||||
case QUAD:
|
||||
case QUAD_TRIANGLESTRIP:
|
||||
case HEXAGON:
|
||||
gl->TexCoord2f(_s_coord, _t_coord);
|
||||
gl->Vertex3fv((xpos-(p1+p2)).ptr());
|
||||
gl->TexCoord2f(_s_coord+_s_tile, _t_coord);
|
||||
@ -156,48 +159,6 @@ void osgParticle::Particle::render(osg::GLBeginEndAdapter* gl, const osg::Vec3&
|
||||
gl->Vertex3fv((xpos-(p1-p2)).ptr());
|
||||
break;
|
||||
|
||||
case QUAD_TRIANGLESTRIP:
|
||||
gl->PushMatrix();
|
||||
gl->Translatef(xpos.x(), xpos.y(), xpos.z());
|
||||
// we must gl.Begin() and gl.End() here, because each particle is a single strip
|
||||
gl->Begin(GL_TRIANGLE_STRIP);
|
||||
gl->TexCoord2f(_s_coord+_s_tile, _t_coord+_t_tile);
|
||||
gl->Vertex3fv((p1+p2).ptr());
|
||||
gl->TexCoord2f(_s_coord, _t_coord+_t_tile);
|
||||
gl->Vertex3fv((-p1+p2).ptr());
|
||||
gl->TexCoord2f(_s_coord+_s_tile, _t_coord);
|
||||
gl->Vertex3fv((p1-p2).ptr());
|
||||
gl->TexCoord2f(_s_coord, _t_coord);
|
||||
gl->Vertex3fv((-p1-p2).ptr());
|
||||
gl->End();
|
||||
gl->PopMatrix();
|
||||
break;
|
||||
|
||||
case HEXAGON:
|
||||
gl->PushMatrix();
|
||||
gl->Translatef(xpos.x(), xpos.y(), xpos.z());
|
||||
// we must gl.Begin() and gl.End() here, because each particle is a single fan
|
||||
gl->Begin(GL_TRIANGLE_FAN);
|
||||
gl->TexCoord2f(_s_coord + _s_tile * 0.5f, _t_coord + _t_tile * 0.5f);
|
||||
gl->Vertex3f(0,0,0);
|
||||
gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x1, _t_coord + _t_tile * hex_texcoord_y1);
|
||||
gl->Vertex3fv((p1*cosPI3+p2*sinPI3).ptr());
|
||||
gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x2, _t_coord + _t_tile * hex_texcoord_y1);
|
||||
gl->Vertex3fv((-p1*cosPI3+p2*sinPI3).ptr());
|
||||
gl->TexCoord2f(_s_coord, _t_coord + _t_tile * 0.5f);
|
||||
gl->Vertex3fv((-p1).ptr());
|
||||
gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x2, _t_coord + _t_tile * hex_texcoord_y2);
|
||||
gl->Vertex3fv((-p1*cosPI3-p2*sinPI3).ptr());
|
||||
gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x1, _t_coord + _t_tile * hex_texcoord_y2);
|
||||
gl->Vertex3fv((p1*cosPI3-p2*sinPI3).ptr());
|
||||
gl->TexCoord2f(_s_coord + _s_tile, _t_coord + _t_tile * 0.5f);
|
||||
gl->Vertex3fv((p1).ptr());
|
||||
gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x1, _t_coord + _t_tile * hex_texcoord_y1);
|
||||
gl->Vertex3fv((p1*cosPI3+p2*sinPI3).ptr());
|
||||
gl->End();
|
||||
gl->PopMatrix();
|
||||
break;
|
||||
|
||||
case LINE:
|
||||
{
|
||||
// Get the normalized direction of the particle, to be used in the
|
||||
@ -219,35 +180,6 @@ void osgParticle::Particle::render(osg::GLBeginEndAdapter* gl, const osg::Vec3&
|
||||
}
|
||||
}
|
||||
|
||||
void osgParticle::Particle::render(osg::RenderInfo& renderInfo, const osg::Vec3& xpos, const osg::Vec3& xrot) const
|
||||
{
|
||||
#if defined(OSG_GL_MATRICES_AVAILABLE)
|
||||
if (_drawable.valid())
|
||||
{
|
||||
bool requiresRotation = (xrot.x()!=0.0f || xrot.y()!=0.0f || xrot.z()!=0.0f);
|
||||
glColor4f(_current_color.x(),
|
||||
_current_color.y(),
|
||||
_current_color.z(),
|
||||
_current_color.w() * _current_alpha);
|
||||
glPushMatrix();
|
||||
glTranslatef(xpos.x(), xpos.y(), xpos.z());
|
||||
if (requiresRotation)
|
||||
{
|
||||
osg::Quat rotation(xrot.x(), osg::X_AXIS, xrot.y(), osg::Y_AXIS, xrot.z(), osg::Z_AXIS);
|
||||
#if defined(OSG_GLES1_AVAILABLE)
|
||||
glMultMatrixf(osg::Matrixf(rotation).ptr());
|
||||
#else
|
||||
glMultMatrixd(osg::Matrixd(rotation).ptr());
|
||||
#endif
|
||||
}
|
||||
_drawable->draw(renderInfo);
|
||||
glPopMatrix();
|
||||
}
|
||||
#else
|
||||
OSG_NOTICE<<"Warning: Particle::render(..) not supported for user-defined shape."<<std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void osgParticle::Particle::setUpTexCoordsAsPartOfConnectedParticleSystem(ParticleSystem* ps)
|
||||
{
|
||||
if (getPreviousParticle()!=Particle::INVALID_INDEX)
|
||||
|
@ -410,16 +410,9 @@ void osgParticle::ParticleSystem::single_pass_render(osg::RenderInfo& renderInfo
|
||||
|
||||
bool requiresEndRender = false;
|
||||
const Particle* startParticle = &_particles[0];
|
||||
if (startParticle->getShape() != Particle::USER)
|
||||
{
|
||||
startParticle->beginRender(gl);
|
||||
requiresEndRender = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Enable writing depth mask when drawing user-defined particles
|
||||
glDepthMask(GL_TRUE);
|
||||
}
|
||||
|
||||
startParticle->beginRender(gl);
|
||||
requiresEndRender = true;
|
||||
|
||||
for(unsigned int i=0; i<_particles.size(); i+=_detail)
|
||||
{
|
||||
@ -435,28 +428,13 @@ void osgParticle::ParticleSystem::single_pass_render(osg::RenderInfo& renderInfo
|
||||
{
|
||||
startParticle->endRender(gl);
|
||||
startParticle = currentParticle;
|
||||
if (currentParticle->getShape() != Particle::USER)
|
||||
{
|
||||
currentParticle->beginRender(gl);
|
||||
requiresEndRender = true;
|
||||
glDepthMask(GL_FALSE);
|
||||
}
|
||||
else
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
currentParticle->beginRender(gl);
|
||||
requiresEndRender = true;
|
||||
glDepthMask(GL_FALSE);
|
||||
}
|
||||
++_draw_count;
|
||||
|
||||
if (currentParticle->getShape() == Particle::USER)
|
||||
{
|
||||
if (requiresEndRender)
|
||||
{
|
||||
startParticle->endRender(gl);
|
||||
requiresEndRender = false;
|
||||
}
|
||||
currentParticle->render(renderInfo, currentParticle->getPosition(), currentParticle->getAngle());
|
||||
continue;
|
||||
}
|
||||
|
||||
const osg::Vec3& angle = currentParticle->getAngle();
|
||||
bool requiresRotation = (angle.x()!=0.0f || angle.y()!=0.0f || angle.z()!=0.0f);
|
||||
if (requiresRotation)
|
||||
|
@ -165,15 +165,6 @@ bool read_particle(osgDB::Input &fr, osgParticle::Particle &P)
|
||||
}
|
||||
++fr;
|
||||
}
|
||||
if (fr[0].matchWord("drawable") && fr[1].matchString("{")) {
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
osg::Drawable *drawable = dynamic_cast<osg::Drawable *>(fr.readObject());
|
||||
if (drawable) {
|
||||
P.setDrawable(drawable);
|
||||
}
|
||||
++fr;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -250,14 +241,6 @@ void write_particle(const osgParticle::Particle &P, osgDB::Output &fw)
|
||||
fw.moveOut();
|
||||
fw.indent() << "}" << std::endl;
|
||||
|
||||
if ( P.getDrawable() != NULL ) {
|
||||
fw.indent() << "drawable {" << std::endl;
|
||||
fw.moveIn();
|
||||
fw.writeObject(*P.getDrawable());
|
||||
fw.moveOut();
|
||||
fw.indent() << "}" << std::endl;
|
||||
}
|
||||
|
||||
fw.moveOut();
|
||||
fw.indent() << "}" << std::endl;
|
||||
}
|
||||
|
@ -69,15 +69,19 @@ bool readParticle( osgDB::InputStream& is, osgParticle::Particle& p )
|
||||
p.setAngularVelocity( angleV );
|
||||
p.setTextureTile( s, t, num );
|
||||
|
||||
bool hasObject = false; is >> is.PROPERTY("Drawable") >> hasObject;
|
||||
if ( hasObject )
|
||||
if (is.getFileVersion()<145)
|
||||
{
|
||||
is >> is.BEGIN_BRACKET;
|
||||
p.setDrawable( is.readObjectOfType<osg::Drawable>() );
|
||||
bool hasObject = false; is >> is.PROPERTY("Drawable") >> hasObject;
|
||||
if ( hasObject )
|
||||
{
|
||||
is >> is.BEGIN_BRACKET;
|
||||
osg::ref_ptr<osg::Drawable> drawable = is.readObjectOfType<osg::Drawable>();
|
||||
OSG_NOTICE<<"Warning: read osgParticle::Particle with USER defined Drawable which is no longer supported."<<std::endl;
|
||||
is >> is.END_BRACKET;
|
||||
}
|
||||
|
||||
is >> is.END_BRACKET;
|
||||
}
|
||||
|
||||
is >> is.END_BRACKET;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -111,15 +115,6 @@ bool writeParticle( osgDB::OutputStream& os, const osgParticle::Particle& p )
|
||||
os << os.PROPERTY("AngularVelocity") << osg::Vec3d(p.getAngularVelocity()) << std::endl;
|
||||
os << os.PROPERTY("TextureTile") << p.getTileS() << p.getTileT() << p.getNumTiles() << std::endl;
|
||||
|
||||
os << os.PROPERTY("Drawable") << (p.getDrawable()!=NULL);
|
||||
if ( p.getDrawable()!=NULL )
|
||||
{
|
||||
os << os.BEGIN_BRACKET << std::endl;
|
||||
os.writeObject( p.getDrawable() );
|
||||
os << os.END_BRACKET;
|
||||
}
|
||||
os << std::endl;
|
||||
|
||||
os << os.END_BRACKET << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user