/**
 * Mike playing with CHAOS (trying to learn processing)
 */
 
 int arrColors[] = { 255,0,255, 255,0,0, 255,255,0, 
   0,255,0, 0,255,255, 0,0,255};
   
 int getRed(int nColor) {
   int nStart = (3*nColor) % arrColors.length;
   return arrColors[nStart];
 }
 
 int getGreen(int nColor) {
   int nStart = (3*nColor) % arrColors.length;
   return arrColors[nStart+1];
 }
 
 int getBlue(int nColor) {
   int nStart = (3*nColor) % arrColors.length;
   return arrColors[nStart+2];
 }
 
 
 
 int nStep =4;
 int nWhereAt = nStep;
 
 int nIters=12;
 
 double arrYVals[];
 double arrPrevYVals[];
 
 double func(double c, double x) {
   return c*x*(1.0-x);
 }

 int nMaxIter = 2;
 
 int nFramesPerIter=30;
 int nCurrFrame=0;
 
 
 void setup() {
   size(600,600);
   stroke(255);
   frameRate(2*nFramesPerIter);
   noFill();
   smooth();
   arrYVals = new double[nIters];
   arrPrevYVals = new double[nIters];
 }
 
 
 void draw() {
   background(0);
   for(int i = 0 ; i < nIters; ++i) {
     arrYVals[i] = arrPrevYVals[i] = 0.0;
   }
   for(int xPix = nStep; xPix < width; xPix += nStep) {
     double [] arrTmp = arrYVals;
     arrYVals = arrPrevYVals;
     arrPrevYVals = arrTmp;
     double lfCurrX = xPix/((double)width);
     double lfPrevX = (xPix-nStep)/((double)width);
     arrYVals[0] = 0.234;
     arrPrevYVals[0] = 0.234;
/*     stroke(
         color(getRed(0), getGreen(0), getBlue(0)));
      if(nMaxIter<= 1) {
         stroke(
           color((nCurrFrame*getRed(0))/nFramesPerIter, 
               (nCurrFrame*getGreen(0))/nFramesPerIter, 
               (nCurrFrame*getBlue(0))/nFramesPerIter));
       }
       line(xPix-nStep, (int)(height*arrPrevYVals[0]),
         xPix, (int)(height*arrYVals[0]));
         */
     for(int i = 1; i < nMaxIter; ++i) {
       arrYVals[i] = func(4*lfCurrX, arrYVals[i-1]);
       // arrPrevYVals[i] = func(4*lfPrevX, arrPrevYVals[i-1]);
       stroke(
         color(getRed(i), getGreen(i), getBlue(i)));
       
       if(i == nMaxIter-1) {
         stroke(
           color(
           (nCurrFrame*getRed(i) +
            (nFramesPerIter-nCurrFrame)*getRed(i-1))/nFramesPerIter,
           (nCurrFrame*getGreen(i) +
            (nFramesPerIter-nCurrFrame)*getGreen(i-1))/nFramesPerIter,
           (nCurrFrame*getBlue(i) +
            (nFramesPerIter-nCurrFrame)*getBlue(i-1))/nFramesPerIter));
       }
       
       if(i == nMaxIter-1) {
         double lfAlpha = nCurrFrame/((double)nFramesPerIter);
       line(xPix-nStep, 
       (int)(lfAlpha*height*arrPrevYVals[i] + 
       (1.0-lfAlpha)*height*arrPrevYVals[i-1]),
         xPix, 
       (int)(lfAlpha*height*arrYVals[i] + 
       (1.0-lfAlpha)*height*arrYVals[i-1]));
       } else {
       line(xPix-nStep, (int)(height*arrPrevYVals[i]),
         xPix, (int)(height*arrYVals[i]));
       }
     }
   }
  
  nCurrFrame = (nCurrFrame+1)%nFramesPerIter;
  if(nCurrFrame == 0) {
   nMaxIter = (nMaxIter)%(nIters)+1; 
   nWhereAt += nStep;
   nWhereAt = nWhereAt%width; 
  }
 }