diff --git a/examples/osgparticleshader/osgparticleshader.cpp b/examples/osgparticleshader/osgparticleshader.cpp index a36c1fa87..cda57878b 100644 --- a/examples/osgparticleshader/osgparticleshader.cpp +++ b/examples/osgparticleshader/osgparticleshader.cpp @@ -44,15 +44,15 @@ void createFountainEffect( osgParticle::ModularEmitter* emitter, osgParticle::Mo // Emit specific number of particles every frame osg::ref_ptr rrc = new osgParticle::RandomRateCounter; rrc->setRateRange( 500, 2000 ); - + // Accelerate particles in the given gravity direction. osg::ref_ptr accel = new osgParticle::AccelOperator; accel->setToGravity(); - + // Multiply each particle's velocity by a damping constant. osg::ref_ptr 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 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 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 emitter = new osgParticle::ModularEmitter; emitter->setParticleSystem( ps.get() ); - + osg::ref_ptr 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 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 updater = new osgParticle::ParticleSystemUpdater; //updater->addDrawable( ps.get() ); - + osg::ref_ptr 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 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. diff --git a/include/osgParticle/Particle b/include/osgParticle/Particle index d08faf973..0d401651c 100644 --- a/include/osgParticle/Particle +++ b/include/osgParticle/Particle @@ -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 void setDrawable(const osg::ref_ptr& 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 _drawable; }; // INLINE FUNCTIONS diff --git a/src/osgParticle/Particle.cpp b/src/osgParticle/Particle.cpp index c978ed7b0..b63674f84 100644 --- a/src/osgParticle/Particle.cpp +++ b/src/osgParticle/Particle.cpp @@ -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."<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) diff --git a/src/osgWrappers/deprecated-dotosg/osgParticle/IO_Particle.cpp b/src/osgWrappers/deprecated-dotosg/osgParticle/IO_Particle.cpp index 824ad36b2..47f9d9bf4 100644 --- a/src/osgWrappers/deprecated-dotosg/osgParticle/IO_Particle.cpp +++ b/src/osgWrappers/deprecated-dotosg/osgParticle/IO_Particle.cpp @@ -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(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; } diff --git a/src/osgWrappers/serializers/osgParticle/Particle.cpp b/src/osgWrappers/serializers/osgParticle/Particle.cpp index c92716e41..ccbd795ad 100644 --- a/src/osgWrappers/serializers/osgParticle/Particle.cpp +++ b/src/osgWrappers/serializers/osgParticle/Particle.cpp @@ -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() ); + bool hasObject = false; is >> is.PROPERTY("Drawable") >> hasObject; + if ( hasObject ) + { + is >> is.BEGIN_BRACKET; + osg::ref_ptr drawable = is.readObjectOfType(); + OSG_NOTICE<<"Warning: read osgParticle::Particle with USER defined Drawable which is no longer supported."<> 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; }