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:
Robert Osfield 2016-08-25 15:13:36 +01:00
parent c637010c9d
commit 56ed225f17
6 changed files with 54 additions and 194 deletions

View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
}