import processing.core.*; 
import processing.xml.*; 

import java.applet.*; 
import java.awt.Dimension; 
import java.awt.Frame; 
import java.awt.event.MouseEvent; 
import java.awt.event.KeyEvent; 
import java.awt.event.FocusEvent; 
import java.awt.Image; 
import java.io.*; 
import java.net.*; 
import java.text.*; 
import java.util.*; 
import java.util.zip.*; 
import java.util.regex.*; 

public class sketch_sep08a extends PApplet {

ArrayList<Vertex> splinePoints = new ArrayList<Vertex>();
PGraphics lastFrame;
final int RING_SIZE = 3;
final int MAX_VERTICES = 500;
final float feedbackOffset=1f;
boolean growing=true;

final float ANGLE_CHANGE = 0.001f;
final float MIN_ANGLE = 0.0f;
final float MAX_ANGLE = TWO_PI;
float myAngle=MIN_ANGLE;
boolean spinClockwise=true;

final float SCALE_CHANGE = 0.0f;
final float MIN_SCALE = 1.2f;
final float MAX_SCALE = 3f;
float myScale = MIN_SCALE;
boolean zooming=true;

public void setup()
{
  size(640,480,P3D);
  smooth();
  stroke(255,0,0);
  noFill();
}

public void draw()
{
//  PGraphics frame = RenderFrame();
//  image(frame,0,0,width,height);

  background(0);
 
  RotateAndScale();
  
  if ( lastFrame != null )
    image(lastFrame,0,0,width,height);
    
  //RenderSpline();  
  RenderRings();
  
  if ( splinePoints.size() > MAX_VERTICES )
    growing=false;
  if ( splinePoints.size() < 1 )
    growing=true;
  
  if ( growing )
    AddVertex();
  else
    splinePoints.remove(0);
    
    
  lastFrame = Feedback(this.g);
}

public void RotateAndScale()
{
  translate(width/2, height/2);
  scale(myScale);
  if ( myScale > MAX_SCALE )
    zooming=false;
  if ( myScale < MIN_SCALE )
    zooming=true;

  if ( zooming )
    myScale += SCALE_CHANGE;
//  else
//    myScale -= SCALE_CHANGE;
  
  rotateZ(myAngle);
  if ( myAngle > MAX_ANGLE )
    spinClockwise=false;
  if ( myAngle < MIN_ANGLE )
    spinClockwise=true;
   
  if ( spinClockwise )
    myAngle += ANGLE_CHANGE;
  else
    myAngle -= ANGLE_CHANGE;
  
  translate(-width/2, -height/2);
}

public void RenderSpline()
{
  if ( splinePoints.size() < 1 )
    return;
  
  Vertex start = splinePoints.get(0);
  Vertex end = splinePoints.get(splinePoints.size()-1);
  
  beginShape();
  curveVertex(start.x, start.y, start.z);
  
  for ( int i=0; i < splinePoints.size(); i++ )
  {
    Vertex v = splinePoints.get(i);
    curveVertex(v.x, v.y, v.z);
    v.Move();
  }
  
  curveVertex(end.x, end.y, end.z);
  endShape();
  

}

public void RenderRings()
{
 
  for ( int i=0; i < splinePoints.size(); i++ )
  {
    Vertex v = splinePoints.get(i);
    translate(v.x,v.y,v.z);
    float sz = RING_SIZE + (v.z/10);
    ellipse(0, 0, sz, sz);
    translate(-v.x,-v.y,-v.z);
    v.Move();
  }
      
}

public PGraphics Feedback(PGraphics source)
{
  PGraphics result = createGraphics(source.width, source.height, P3D);
  source.loadPixels();
  result.loadPixels();
  
  int fo = (int)feedbackOffset;
  
  for ( int p = fo; p < source.width*source.height; p++ )
  {
    float r = red(source.pixels[p-fo]);
    if ( r > 0 )
    {
      result.pixels[p] = color(r, 0, 0);
    }
  }
  
  result.updatePixels();
  
  return result;
}

public void AddVertex()
{
  float x=random(0,width);
  float y=random(0,height);
  float z=random(0,100);
  Vertex v = new Vertex(x,y,z);
  
  //Vertex v = new Vertex(width/2, height/2, 50);
  v.RandomizeVector(0.5f);
  splinePoints.add(v);
}

class Coord
{
  public float x,y,z;
  public Coord()
  {
    x=y=z=0;
  }
  public Coord(float _x, float _y, float _z)
  {
    x = _x;
    y = _y;
    z = _z;
  }
}

class Vertex extends Coord
{
  private Vector myVector = new Vector();
  public Vertex()
  {
    super();
  }
  public Vertex(float _x, float _y, float _z)
  {
    super(_x,_y,_z);
  }
  public void Move()
  {
    x += myVector.x;
    y += myVector.y;
    z += myVector.z;
  }
  public void RandomizeVector(float amount)
  {
    myVector.x = random(-amount, amount);
    myVector.y = random(-amount, amount);
    myVector.z = random(-amount, amount);
  }
}

class Vector extends Coord
{
  public Vector()
  {
    super();
  }
  public Vector(float _x, float _y, float _z)
  {
    super(_x,_y,_z);
  }
}
  static public void main(String args[]) {
    PApplet.main(new String[] { "--bgcolor=#F0F0F0", "sketch_sep08a" });
  }
}
