float increment = 0.01;

// The noise function's 3rd argument, a global variable that increments once per cycle
float zoff = 0.0;  


// the time in seconds (taken from Moonlander / GNURocket)
float now = 0.0;

// We will increment zoff differently than xoff and yoff
float zincrement = 0.02; 

// These control how big the opened window is.
// Assembly has FullHD (a.k.a. 1080p, a.k.a. 1920x1080) maximum projector resolution
// ref. https://www.assembly.org/summer19/demoscene/rules
float CANVAS_WIDTH = 1920;
float CANVAS_HEIGHT = 1080;

// Moonlander is a library for integrating Processing with GNU Rocket, https://github.com/anttihirvonen/moonlander
// GNURocket is a tool for synchronizing music and visuals in demoscene productions: https://github.com/rocket/rocket
import moonlander.library.*;
import ddf.minim.*;
Moonlander moonlander;

PImage vignette;  // Declare variable "a" of type PImage
PShape radioactiveSphere;
PImage radioactiveTexture;
PImage background;
PImage[] bgImages = new PImage[10];

int framenumber = 0;
float a = 0.0;


void settings() {
  boolean fullscreen = true;
  
  if (fullscreen) {
    //Set the window fullscreen in desktop's native resolution
    fullScreen(P3D);
  } else {
    //open as window
    size((int)CANVAS_WIDTH,(int)CANVAS_HEIGHT, P3D);
    
    //or if you want a smaller window then put some 16:9 aspect ratio resolution
    //like 800x450... do not edit CANVAS_WIDTH/CANVAS_HEIGHT
    //size((int)800,(int)450, P3D);
  }
}

void setup() {

  //hide mouse cursor
  noCursor();

  // Init & start moonlander
  int bpm = 72; // Tune's beats per minute
  int rowsPerBeat = 8; // How many rows one beat consists of in the sync editor (GNURocket or so)
  
  // frameRate() triggers drawing stuff, so do it at the end to avoid getting stuck
  int fps = 60;
  // Assembly has 60Hz maximum projector framerate, ref. https://www.assembly.org/summer19/demoscene/rules
  frameRate(fps);
  
  vignette = loadImage("vignette.png");  // Load the image into the program  
  radioactiveTexture = loadImage("radioactive.jpg");
  fill(255);

  // Load all images
  background = loadImage("noise1.png");

  for (int i=0; i < bgImages.length; i++){
    bgImages[i] = createImage((int)CANVAS_WIDTH, (int)CANVAS_HEIGHT, ARGB);
    
     bgImages[i].loadPixels();

    float xoff = 0.0; // Start xoff at 0
    
    // For every x,y coordinate in a 2D space, calculate a noise value and produce a brightness value
    for (int x = 0; x < CANVAS_WIDTH ; x++) {
      xoff += increment;   // Increment xoff 
      float yoff = 0.0;   // For every xoff, start yoff at 0
      for (int y = 0; y < CANVAS_HEIGHT; y++) {
        yoff += increment; // Increment yoff
        
        // Calculate noise and scale by 255
        //float bright = noise(xoff,yoff,zoff)*255;
  
        // Try using this line instead
        float bright = random(0,100);
        
        // Set each pixel onscreen to a grayscale value
        bgImages[i].pixels[x+y*(int)CANVAS_WIDTH] = color(bright+150,bright+100,bright+50);
      }
    }
      bgImages[i].updatePixels();

  }
  
  moonlander = Moonlander.initWithSoundtrack(this, "Tyrant.mp3", bpm, rowsPerBeat);
  moonlander.start();

}

void draw() {
    moonlander.update();
  
    now = (float)moonlander.getCurrentTime();
    float end = 22.0; //end production after 60 secs which is the maximum time allowed by the One Scene Compo
    if (now > end) {
      exit();
    }

    background(0,0,0,255);
    lights();
    pushMatrix();
    translate(width/2, height/2, 0);
    scale(width/CANVAS_WIDTH,height/CANVAS_HEIGHT,width/CANVAS_WIDTH);
    drawBackground(framenumber++ % bgImages.length);
    hint(ENABLE_DEPTH_TEST);
    
   noStroke();
   translate(0, 0, (float)moonlander.getValue("cube:distance"));

   scale(120);
   
   a += 0.005;
    if(a > TWO_PI) { 
    a = 0.0; 
    }

   rotateX(a * 1.001);
   rotateY(a * 2.002);

   textureMode(NORMAL);
   TexturedCube(radioactiveTexture);
   
   popMatrix();
   noFill();
   noLights();
   hint(DISABLE_DEPTH_TEST);
   image(vignette, 0,0);
}

void drawBackground(int imageNumber) {

   // draw the overlays that are shown only shortly. image to be displayed and its alpha is defined in Rocket
  int backgroundImageNumber = imageNumber;
  if (backgroundImageNumber >= 0) {
    image(bgImages[backgroundImageNumber], -CANVAS_WIDTH/2, -CANVAS_HEIGHT/2);
  }
}

void TexturedCube(PImage tex) {
  beginShape(QUADS);
  texture(tex);

  // Given one texture and six faces, we can easily set up the uv coordinates
  // such that four of the faces tile "perfectly" along either u or v, but the other
  // two faces cannot be so aligned.  This code tiles "along" u, "around" the X/Z faces
  // and fudges the Y faces - the Y faces are arbitrarily aligned such that a
  // rotation along the X axis will put the "top" of either texture at the "top"
  // of the screen, but is not otherwised aligned with the X/Z faces. (This
  // just affects what type of symmetry is required if you need seamless
  // tiling all the way around the cube)
  
  // +Z "front" face
  vertex(-1, -1,  1, 0, 0);
  vertex( 1, -1,  1, 1, 0);
  vertex( 1,  1,  1, 1, 1);
  vertex(-1,  1,  1, 0, 1);

  // -Z "back" face
  vertex( 1, -1, -1, 0, 0);
  vertex(-1, -1, -1, 1, 0);
  vertex(-1,  1, -1, 1, 1);
  vertex( 1,  1, -1, 0, 1);

  // +Y "bottom" face
  vertex(-1,  1,  1, 0, 0);
  vertex( 1,  1,  1, 1, 0);
  vertex( 1,  1, -1, 1, 1);
  vertex(-1,  1, -1, 0, 1);

  // -Y "top" face
  vertex(-1, -1, -1, 0, 0);
  vertex( 1, -1, -1, 1, 0);
  vertex( 1, -1,  1, 1, 1);
  vertex(-1, -1,  1, 0, 1);

  // +X "right" face
  vertex( 1, -1,  1, 0, 0);
  vertex( 1, -1, -1, 1, 0);
  vertex( 1,  1, -1, 1, 1);
  vertex( 1,  1,  1, 0, 1);

  // -X "left" face
  vertex(-1, -1, -1, 0, 0);
  vertex(-1, -1,  1, 1, 0);
  vertex(-1,  1,  1, 1, 1);
  vertex(-1,  1, -1, 0, 1);

  endShape();
}
