An emitter

In this section, we add to the project the emitter, which will create particles at a specified rate.

Note

An example of this is 03-Particles/02-ParticlesEmitter.

The example is based on the 03-Particles/01-SingleParticle project, implemented in the previous section. We implement the emitter right inside the testApp class. In the class declaration, replace the following line with declaration of a single particle Particle p; with an array of particles:

vector<Particle> p;    //Particles

Note

We will delete inactive particles from any parts of the p array. So for computational efficiency, it is preferable to use the deque class instead of vector. But for simplicity, in this example, we use vector. It works fast enough for our purposes in the example.

See usage of deque in the Radial slit-scan example section in Chapter 5, Working with Videos.

Next, add the declaration of the parameter bornRate and the supplementary variable bornCount:

float bornRate;       //Particles born rate per second
float bornCount;      //Integrated number of particles to born

The bornRate parameter sets the number of particles that should be born in one second. If its value is small, the particles should not be born with each testApp::update() calling, so we need a method of detecting when we should emit new particles. Such a method is using the float variable bornCount, which accumulates the number of particles that would be born. When it becomes greater than 1.0, we emit the int( bornCount ) particles.

To initialize the values bornRate and bornCount, add the following lines to the testApp::setup() function:

bornRate = 1000;
bornCount = 0;

The main part of the modification needed for the emitter implementation is in the testApp::update() function. It's the beginning that computes dt that remains untouched from the previous project. Then it deletes the inactive particles from the p array, gives birth to new particles depending on the bornRate value parameter, and finally updates all the particles:

void testApp::update(){
  //Compute dt
  float time = ofGetElapsedTimef();
  float dt = ofClamp( time - time0, 0, 0.1 );
  time0 = time;

  //Delete inactive particles
  int i=0;
  while (i < p.size()) {
      if ( !p[i].live ) {
          p.erase( p.begin() + i );
      }
      else {
          i++;
      }
  }
  
  //Born new particles
  bornCount += dt * bornRate;      //Update bornCount value
  if ( bornCount >= 1 ) {          //It's time to born particle(s)
      int bornN = int( bornCount );//How many born
      bornCount -= bornN;          //Correct bornCount value
      for (int i=0; i<bornN; i++) {
          Particle newP;
          newP.setup();            //Start a new particle
          p.push_back( newP );     //Add this particle to array
      }
  }
  
  //Update the particles
  for (int i=0; i<p.size(); i++) {
      p[i].update( dt );
  }
}

Finally, in testApp::draw(), you will find the ensuing lines:

//Draw the particle
ofFill();
p.draw();

Replace the preceding lines with the following lines:

//Draw the particles
ofFill();
for (int i=0; i<p.size(); i++) {
  p[i].draw();
}

The project is ready.

Tip

We suggest compiling and running the project in the Release mode of your development environment for better performance.

Run it, and you will see a beautiful and vivid picture made by many particles flying in curvilinear trajectories and leaving the trails, as shown in the following screenshot:

An emitter

Now we add a couple of new control parameters for extending the behavior of the particle system.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset