a port of the Processing Visualization Language

Reflection1

by Ira Greenberg. Based on the equation (R = 2N(N*L)-L) where R is the reflection vector, N is the normal, and L is the incident vector.

Original Processing.org Example: Reflection1

// All Examples Written by Casey Reas and Ben Fry

// unless otherwise stated.

 float baseX1, baseY1, baseX2, baseY2;

float baseLength;

float[] xCoords, yCoords;

float ellipseX, ellipseY, ellipseRadius = 6;

float directionX, directionY;

float ellipseSpeed = 3.5;

float velocityX, velocityY; 



void setup(){

  size(200, 200);

  frameRate(30);

  fill(128);

  smooth();

  baseX1 = 0;

  baseY1 = height-150;

  baseX2 = width;

  baseY2 = height;



  // start ellipse at middle top of screen

  ellipseX = width/2;

  

  // calculate initial random direction

  directionX = random(0.1, 0.99);

  directionY = random(0.1, 0.99);



  // normalize direction vector

  float directionVectLength = sqrt(directionX*directionX + 

            directionY*directionY);

  directionX /= directionVectLength;

  directionY /= directionVectLength;

}



void draw(){

  // draw background

  fill(0, 12);

  noStroke();

  rect(0, 0, width, height);



  // calculate length of base top

  baseLength = dist(baseX1, baseY1, baseX2, baseY2);

  xCoords = new float[ceil(baseLength)];

  yCoords = new float[ceil(baseLength)];



  // fill base top coordinate array

  for (int i=0; i<xCoords.length; i++){

    xCoords[i] = baseX1 + ((baseX2-baseX1)/baseLength)*i;

    yCoords[i] = baseY1 + ((baseY2-baseY1)/baseLength)*i;

  }



  // draw base

  fill(200);

  quad(baseX1, baseY1, baseX2, baseY2, baseX2, height, 0, height);



  // calculate base top normal

  float baseDeltaX = (baseX2-baseX1)/baseLength;

  float baseDeltaY = (baseY2-baseY1)/baseLength;

  float normalX = -baseDeltaY;

  float normalY = baseDeltaX;



  // draw ellipse

  noFill();

  stroke(200);

  ellipse(ellipseX, ellipseY, ellipseRadius*2, ellipseRadius*2);



  // calculate ellipse velocity

  velocityX = directionX * ellipseSpeed;

  velocityY = directionY * ellipseSpeed;



  // move elipse

  ellipseX += velocityX;

  ellipseY += velocityY;



  // normalized incidence vector

  float incidenceVectorX = -directionX;

  float incidenceVectorY = -directionY;



  // detect and handle collision

  for (int i=0; i<xCoords.length; i++){

    // check distance between ellipse and base top coordinates

    if (dist(ellipseX, ellipseY, xCoords[i], yCoords[i]) < ellipseRadius){



      // calculate dot product of incident vector and base top normal 

      float dot = incidenceVectorX*normalX + incidenceVectorY*normalY;



      // calculate reflection vector

      float reflectionVectorX = 2*normalX*dot - incidenceVectorX;

      float reflectionVectorY = 2*normalY*dot - incidenceVectorY;



      // assign reflection vector to direction vector

      directionX = reflectionVectorX;

      directionY = reflectionVectorY;



      // draw base top normal at collision point

      stroke(255, 128, 0);

      line(ellipseX, ellipseY, ellipseX-normalX*100, 

            ellipseY-normalY*100);

    }

  }



  // detect boundary collision

  // right

  if (ellipseX > width-ellipseRadius){

    ellipseX = width-ellipseRadius;

    directionX *= -1;

  }

  // left 

  if (ellipseX < ellipseRadius){

    ellipseX = ellipseRadius;

    directionX *= -1;

  }

  // top

  if (ellipseY < ellipseRadius){

    ellipseY = ellipseRadius;

    directionY *= -1;

    // randomize base top

    baseY1 = random(height-100, height);

    baseY2 = random(height-100, height);

  }

}
Fork me on GitHub