> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.dTr65UflDYB/rev.2334
 * 
 * authors: 
 *   Dimitry K

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   https://creativecommons.org/licenses/by-sa/3.0/ 
 */ 



/**
* Based on original sketch by Thomas C
* http://www.openprocessing.org/user/30409
*
* Original sketch location:
* http://www.openprocessing.org/sketch/106065
* 
*
*
*
* This sketch creates visualization of eyeballs
* appearing somewhere ahead in the distance
* and flying towards the viewer. Whilst flying
* towards the viewer the eyeballs follow spiral 
* trajectory.
*
* The sketch uses 2d rendering mode, and to create
* illusion of 3d (depth) it scales the eyeballs
* via 
*/

/*****************************************
* This is amount of balls simultaneously 
* avaiable on screen.
* Change this value if you want more balls.
******************************************/
int C_TOTAL_EYEBALLS = 50;
int C_MAX_BALL_SIZE  = 200;


/*****************************************
* To simulate distance along z-axis, 
* we introduce the variables. 
*/
float zLimit = 0;
float zHorizon = -100;
float zMaxAwayDistance = zLimit - zHorizon;


/*****************************************
* These arrays are 
* representing parameters of each of the eyeball.
*/

      float[] posX= new float[C_TOTAL_EYEBALLS];
      float[] posY= new float[C_TOTAL_EYEBALLS];

      float[] z = new float[C_TOTAL_EYEBALLS];
      
      float[] ampEye= new float[C_TOTAL_EYEBALLS];

      float[][] pulsEye = new float[C_TOTAL_EYEBALLS][2];

float div = 0;
float gamma = 0;
float gamma_step = PI/1024;

/* @pjs preload="/static/uploaded_resources/p.8420/bieber_transparent_small.png"; */
PImage img;

void setup() {
  size(600, 600);
  background(0);
  
  eyeStartX = width/2;
  eyeStartY = height/2;
  
  for (int i=0;i<C_TOTAL_EYEBALLS; i++) {
        initEyeWithRandomValues(i, div);
  }

 textFont(createFont("Arial", 22));
  
img = loadImage("/static/uploaded_resources/p.8420/bieber_transparent_small.png");  
}


int eyeStartX;
int eyeStartY;
/**
* Inits parameters of the eye, specified 
* by index i with initial random values.
*/
void initEyeWithRandomValues(int i, int div){
    z[i] = random(zHorizon);
    dprintln("ball " + i + " got horizon: "+ z[i]);
    posX[i] = eyeStartX + random(-div,div);
    posY[i] = eyeStartY + random(-div,div);
    ampEye[i] = random(30);
    pulsEye[i][0] = random(6*PI);
    pulsEye[i][1] = random(6*PI);    
    
    }


void mousePressed(){
    setBallSpawnPoint(mouseX, mouseY);    
}



void mouseDragged(){
    setBallSpawnPoint(mouseX, mouseY);     
}

void setBallSpawnPoint(int xx, int yy){
   eyeStartX = xx;
   eyeStartY = yy;
}

void draw() {
  background(0);
  
  div = width/2 * squareSin(gamma);
  gamma += gamma_step;
  
  dprintln("div: " + div);
  for (int i=0; i<C_TOTAL_EYEBALLS; i++) {
    drawEye(posX[i], posY[i], z[i], pulsEye[i][0], pulsEye[i][1],ampEye[i]);
    z[i] += 0.5;
    
    // as we're creating illusion of the eye coming
    // from far distance in front of viewer going towards 
    // the viewer,
    // this code checks whether the eye has
    // arrived to it's closest to viewer (screen surface)
    // and if that's the case
    // it "recycles" the eye
    if (z[i] > zLimit) {
        initEyeWithRandomValues(i, div);
    }
    
  }
  
  drawSpawnPoint();
  drawMessage();
}

void drawSpawnPoint(){
     pushStyle();
       noFill();
       stroke(255, 228);
       strokeWeight(8);
       ellipse(eyeStartX, eyeStartY, 20, 20);
     popStyle();
}

String msg = "Click on the sketch to focus on it. Then hold shift key to change rendering mode. Or click and drag mouse to change eyeball respawn point";
void drawMessage(){
     float txHeight = 110;
     text(msg, 10, height - 50 - txHeight, width * 0.8, txHeight);
    }

void drawEye(float xPos, float yPos, float zPos, float pulsX, float pulsY, float amp) {

  float percentageTravelled =  (zPos-zHorizon)/zMaxAwayDistance;
  float percentageLeftToTarget = 1 - percentageTravelled;  

  float sizeEye = C_MAX_BALL_SIZE * percentageTravelled;

  float xEye, yEye;
  xEye = xPos + amp*cos(pulsX*percentageTravelled);
  yEye = yPos + amp*sin(pulsY*percentageTravelled);

 if ( keyPressed ){
  simpleDrawEyeball(xEye, yEye, sizeEye, percentageLeftToTarget);
  }
  else{
    simpleDrawBieber(xEye, yEye, sizeEye, percentageLeftToTarget);  
    }
}


void simpleDrawEyeball(float xEye, float yEye , float sizeEye, float alphaR)
{
  pushStyle();   
  // this kinda sets the closer the less transparent
  fill(255, 255* alphaR);
  stroke(10, 255* alphaR);   
  ellipse(xEye, yEye, sizeEye, sizeEye);  // eye white

  pushStyle();
  fill(0, 255*alphaR);
  noStroke();
  ellipse(xEye, yEye, sizeEye/2, sizeEye/2); // eye black
  popStyle();
  pushStyle();
  noStroke();
  ellipse(xEye - sizeEye/10, yEye - sizeEye/10, sizeEye/8, sizeEye/8); // glare
  popStyle();
  popStyle();          
}

void simpleDrawBieber(float x, float y, float sz, float alphaR){
      pushStyle();
      imageMode(CENTER);
      pushMatrix();
        translate(x,y);
        scale(sz/200.0, sz/200.0);
       // tint(255, 255 * alphaR);
        image(img, 0, 0);
      popMatrix();
      popStyle();
    }


float squareSin(float beta){
    return sq(sin(beta));    
}


void dprintln(String s){
//     println(s);
    }