Baking Particles

Since particle simulation is often an expensive and slow process, many systems allow you to cache the results of a simulation.  This is called "baking." After simulating once, the cached simulation can then be played back without having to recompute the particle positions at each time step. You are required to add this functionality to the ParticleSystem class. Included in the header file are a number of baking-related functions that you are required to implement.  For your convenience, we've also left what we feel are relevant baking variables in the class:

/** Baking properties **/
float bake_fps; // frame rate at which simulation was baked
float bake_start_time; // time at which baking started
float bake_end_time; // time at which baking ended
bool baked; // flag for baked particles

The one significant baking variable that is NOT included in this list is a data structure that stores a collection of particle configurations that can be indexed by time.  When simulation mode is enabled, you should call bakeParticles at each time step from within computeForcesAndParticles to save the positions of all particles into this data structure. Then, when we play back, we can simply look up into this data structure with the current time to see if a configuration has been saved.  If so, you should just draw the particles according to this configuration without re-simulating them. For example, this is a possible structuring of the code:

class ParticleSystem {
  typedef std::list<PointObj *> ptlist;
  typedef std::list<Particle *> partlist;
  ...
protected:
  partlist particles; // list of particles
  std::vector<ptlist> bake_vector; // vector of baked *POINTS* (not particles)
};

virtual void ParticleSystem::computeForcesAndUpdateParticles(float t)
{
  ...
  if (simulate) {
    ... 
    bakeParticles(t);
    ...
  }
  ...
}

virtual void ParticleSystem::bakeParticles(float t)
{
  // create a copy of particles list
  ptlist pt_copy;
  for (partiter p = particles.begin(); p != particles.end(); ++p) {
    PointObj *pt = new PointObj((*p)->getPos());
    pt_copy.push_back(pt);
  }

  // push onto bake vector
  bake_vector.push_back(pt_copy);
}

virtual void ParticleSystem::drawParticles(float t)
{
  // if we need to draw particles, check 
  // if there's an entry in your baked data structure
  // for time t.  if there is, use the saved
  // configuration to draw.
}