Index: /OpenSceneGraph/trunk/include/osgParticle/Particle
===================================================================
--- /OpenSceneGraph/trunk/include/osgParticle/Particle (revision 10660)
+++ /OpenSceneGraph/trunk/include/osgParticle/Particle (revision 10827)
@@ -155,5 +155,5 @@
         
         /// Get number of texture tiles
-        inline int getNumTiles() const { return _num_tile; }
+        inline int getNumTiles() const { return _end_tile - _start_tile + 1; }
         
         /** Kill the particle on next update
@@ -247,6 +247,11 @@
         inline float getCurrentSize() const;
         
-        /// Specify how the particle texture is tiled
-        inline void setTextureTile(int sTile, int tTile, int numTiles = 0);
+        /// Specify how the particle texture is tiled.
+        /// All tiles in the given range are sequentially displayed during the lifetime
+        /// of the particle. When no range is given, all tiles are displayed during the lifetime.
+        inline void setTextureTileRange(int sTile, int tTile, int startTile, int endTile);
+
+        /// Same as above, range starts at 0 and ends at end
+        inline void setTextureTile(int sTile, int tTile, int end = -1);
 
         /// Set the previous particle
@@ -300,5 +305,6 @@
         float _s_tile;
         float _t_tile;
-        int _num_tile;
+        int _start_tile;
+        int _end_tile;
         int _cur_tile;
         float _s_coord;
@@ -567,18 +573,33 @@
     }
 
-    inline void Particle::setTextureTile(int sTile, int tTile, int numTiles)
-    {
-        _s_tile = (sTile>0) ? 1.0f / static_cast<float>(sTile) : 1.0f;
-        _t_tile = (tTile>0) ? 1.0f / static_cast<float>(tTile) : 1.0f;
-        if (numTiles <= 0)
-        {
-            _num_tile = sTile * tTile;
-        }
-        else
-        {
-            _num_tile = numTiles;
-        }
-    }
-
+
+    inline void Particle::setTextureTile(int sTile, int tTile, int end)
+    {
+        setTextureTileRange(sTile, tTile, -1, end);
+    }
+
+    inline void Particle::setTextureTileRange(int sTile, int tTile, int startTile, int endTile)
+    {
+       _s_tile = (sTile>0) ? 1.0f / static_cast<float>(sTile) : 1.0f;
+       _t_tile = (tTile>0) ? 1.0f / static_cast<float>(tTile) : 1.0f;
+       
+       if(startTile == -1)
+       {
+          _start_tile = 0;
+       }
+       else
+       {
+          _start_tile = startTile;
+       }
+
+       if(endTile == -1)
+       {
+          _end_tile = sTile * tTile;
+       }
+       else
+       {
+          _end_tile = endTile;
+       }
+    }
 
 }
Index: /OpenSceneGraph/trunk/src/osgParticle/Particle.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osgParticle/Particle.cpp (revision 10660)
+++ /OpenSceneGraph/trunk/src/osgParticle/Particle.cpp (revision 10827)
@@ -46,5 +46,6 @@
     _s_tile(1.0f),
     _t_tile(1.0f),
-    _num_tile(1),
+    _start_tile(0),
+    _end_tile(0),
     _cur_tile(-1),
     _s_coord(0.0f),
@@ -80,5 +81,5 @@
 
     //Compute the current texture tile based on our normalized age
-    int currentTile = static_cast<int>(x * _num_tile);
+    int currentTile = _start_tile + static_cast<int>(x * getNumTiles());
     
     //If the current texture tile is different from previous, then compute new texture coords
Index: /OpenSceneGraph/trunk/examples/osgparticle/osgparticle.cpp
===================================================================
--- /OpenSceneGraph/trunk/examples/osgparticle/osgparticle.cpp (revision 10657)
+++ /OpenSceneGraph/trunk/examples/osgparticle/osgparticle.cpp (revision 10827)
@@ -324,4 +324,119 @@
 
 
+
+//////////////////////////////////////////////////////////////////////////////
+// ANIMATED PARTICLE SYSTEM CREATION
+//////////////////////////////////////////////////////////////////////////////
+
+
+osgParticle::ParticleSystem *create_animated_particle_system(osg::Group *root)
+{
+
+    // Now we will create a particle system that uses two emitters to 
+    // display two animated particles, one showing an explosion, the other
+    // a smoke cloud. A particle system can only use one texture, so
+    // the animations for both particles are stored in a single bitmap.
+    // The frames of the animation are stored in tiles. For each particle
+    // template, the start and end tile of their animation have to be given.
+    // The example file used here has 64 tiles, stored in eight rows with
+    // eight images each.
+
+    // First create a prototype for the explosion particle.
+    osgParticle::Particle pexplosion;
+
+    // The frames of the explosion particle are played from birth to
+    // death of the particle. So if lifetime is one second, all 16 images 
+    // of the particle are shown in this second.
+    pexplosion.setLifeTime(1);
+
+    // some other particle properties just as in the last example.
+    pexplosion.setSizeRange(osgParticle::rangef(0.75f, 3.0f));
+    pexplosion.setAlphaRange(osgParticle::rangef(0.5f, 1.0f));
+    pexplosion.setColorRange(osgParticle::rangev4(
+        osg::Vec4(1, 1, 1, 1), 
+        osg::Vec4(1, 1, 1, 1)));
+    pexplosion.setRadius(0.05f);
+    pexplosion.setMass(0.05f);
+
+    // This command sets the animation tiles to be shown for the particle.
+    // The first two parameters define the tile layout of the texture image.
+    // 8, 8 means the texture has eight rows of tiles with eight columns each.
+    // 0, 15 defines the start and end tile 
+    pexplosion.setTextureTileRange(8, 8, 0, 15);
+
+    // The smoke particle is just the same, only plays another tile range.
+    osgParticle::Particle psmoke = pexplosion;
+    psmoke.setTextureTileRange(8, 8, 32, 45);
+
+    // Create a single particle system for both particle types
+    osgParticle::ParticleSystem *ps = new osgParticle::ParticleSystem;
+
+    // Assign the tiled texture
+    ps->setDefaultAttributes("Images/fireparticle8x8.png", false, false);
+
+    // Create two emitters, one for the explosions, one for the smoke balls.
+    osgParticle::ModularEmitter *emitter1 = new osgParticle::ModularEmitter;
+    emitter1->setParticleSystem(ps);
+    emitter1->setParticleTemplate(pexplosion);
+
+    osgParticle::ModularEmitter *emitter2 = new osgParticle::ModularEmitter;
+    emitter2->setParticleSystem(ps);
+    emitter2->setParticleTemplate(psmoke);
+
+    // create a counter each. We could reuse the counter for both emitters, but
+    // then we could not control the ratio of smoke balls to explosions
+    osgParticle::RandomRateCounter *counter1 = new osgParticle::RandomRateCounter;
+    counter1->setRateRange(10, 10);
+    emitter1->setCounter(counter1);
+
+    osgParticle::RandomRateCounter *counter2 = new osgParticle::RandomRateCounter;
+    counter2->setRateRange(3, 4);
+    emitter2->setCounter(counter2);
+
+    // setup a single placer for both emitters.
+    osgParticle::SectorPlacer *placer = new osgParticle::SectorPlacer;
+    placer->setCenter(-8, 0, 0);
+    placer->setRadiusRange(2.5, 5);
+    placer->setPhiRange(0, 2 * osg::PI);    // 360° angle to make a circle
+    emitter1->setPlacer(placer);
+    emitter2->setPlacer(placer);
+
+    // the shooter is reused for both emitters
+    osgParticle::RadialShooter *shooter = new osgParticle::RadialShooter;
+    shooter->setInitialSpeedRange(0, 0);
+
+    // give particles a little spin
+    shooter->setInitialRotationalSpeedRange(osgParticle::rangev3(
+       osg::Vec3(0, 0, -1),
+       osg::Vec3(0, 0, 1)));
+    emitter1->setShooter(shooter);
+    emitter2->setShooter(shooter);
+
+    // add both emitters to the scene graph
+    root->addChild(emitter1);
+    root->addChild(emitter2);
+   
+    // create a program, just as before
+    osgParticle::ModularProgram *program = new osgParticle::ModularProgram;
+    program->setParticleSystem(ps);
+
+    // create an operator that moves the particles upwards
+    osgParticle::AccelOperator *op1 = new osgParticle::AccelOperator;
+    op1->setAcceleration(osg::Vec3(0, 0, 2.0f));
+    program->addOperator(op1);  
+
+    // add the program to the scene graph
+    root->addChild(program);
+
+    // create a Geode to contain our particle system.
+    osg::Geode *geode = new osg::Geode;
+    geode->addDrawable(ps);
+
+    // add the geode to the scene graph.
+    root->addChild(geode);
+
+    return ps;
+}
+
 //////////////////////////////////////////////////////////////////////////////
 // MAIN SCENE GRAPH BUILDING FUNCTION
@@ -342,4 +457,5 @@
     osgParticle::ParticleSystem *ps1 = create_simple_particle_system(root);
     osgParticle::ParticleSystem *ps2 = create_complex_particle_system(root);
+    osgParticle::ParticleSystem *ps3 = create_animated_particle_system(root);
 
     // Now that the particle systems and all other related objects have been
@@ -350,4 +466,5 @@
     psu->addParticleSystem(ps1);
     psu->addParticleSystem(ps2);
+    psu->addParticleSystem(ps3);
 
     // add the updater node to the scene graph
