import igeo.*;
import processing.opengl.*;
import controlP5.*;


//DECLARE CONTROLS
ControlP5 controlP5;
ControlWindow myControlWindow;
Controller mySliderA;
Controller mySliderB;
Controller mySliderC;
Controller mySliderD;
Controller mySliderE;
Controller mySliderF;


void setup() {
  //INITIALIZE piGeon
  size(480, 360, IG.GL);

  //INITIALIZE CONTROLP5 AND CONTROL WINDOW
  ctrlSetup();  //function for initializing sliders
}

void draw() {
  //REFRESH PIGEON GEOMETRY
  refpiGeon(); //function to refresh variable piGeon geometry

  //SLIDER PARAMETERS
  //supershape parameters
  float m = mySliderA.value();
  float a = mySliderB.value();
  float b = mySliderC.value();
  float n1 = mySliderD.value();
  float n2 = mySliderE.value();
  float n3 = mySliderF.value();

  //MAIN CODE
  int unum = 40;
  int vnum = 40;
  float uinc = PI/(unum/2);
  float vinc = (PI/2)/(vnum/2);

  //points array
  IVec[][] mypts = new IVec[unum+1][vnum+1];

  //math stuff
  float theta = -PI;
  for (int i = 0; i<=unum; i++) {
    float phi = -PI/2;
    float r1 = 1/pow(pow(abs(cos(m*theta/4)/a), n2) + pow(abs(sin(m*theta/4)/b), n3), 1/n1);
    for (int j = 0; j<=vnum; j++) {
      float r2 = 1/pow(pow(abs(cos(m*phi/4)/a), n2) + pow(abs(sin(m*phi/4)/b), n3), 1/n1);
      float x = r1*cos(theta) * r2*cos(phi);
      float y = r1*sin(theta) * r2*cos(phi);
      float z = r2*sin(phi);

      mypts[i][j] = new IVec(x*20, y*20, z*20);
      new IPoint(mypts[i][j]).clr(abs(1./theta), 0, abs(1./phi));

      phi = phi + vinc;
    }
    theta = theta + uinc;
  }
  new ISurface(mypts).clr(.9);
}


//INITIALIZE CONTROLS
//initializes controlp5 sliders.
void ctrlSetup() {

  controlP5 = new ControlP5(this);
  myControlWindow = controlP5.addControlWindow("piGeon Controls", 100, 100, 480, 360);
  myControlWindow.hideCoordinates(); //hides window dimensions
  
  //INITIALIZE CONTROLS
  //SLIDER A 
  mySliderA = controlP5.addSlider("m", 0, 30, 14.25, 80, 60, 300, 14);
  mySliderA.setWindow(myControlWindow); //assign slider to myControlWindow

    //SLIDER B
  mySliderB = controlP5.addSlider("a", -5, 5, -0.06, 80, 100, 300, 14);
  mySliderB.setWindow(myControlWindow); //assign slider to myControlWindow

    //SLIDER C
  mySliderC = controlP5.addSlider("b", -5, 5, 2, 80, 140, 300, 14);
  mySliderC.setWindow(myControlWindow); //assign slider to myControlWindow

    //SLIDER D
  mySliderD = controlP5.addSlider("n1", 0, 5, 3.7, 80, 180, 300, 14);
  mySliderD.setWindow(myControlWindow); //assign slider to myControlWindow

    //SLIDER E
  mySliderE = controlP5.addSlider("n2", -1, 1, -.48, 80, 220, 300, 14);
  mySliderE.setWindow(myControlWindow); //assign slider to myControlWindow

    //SLIDER F
  mySliderF = controlP5.addSlider("n3", 0, 5, 1.48, 80, 260, 300, 14);
  mySliderF.setWindow(myControlWindow); //assign slider to myControlWindow
}

//REFRESH FUNCTION.
//Clears piGeon geometry in the scene.
void refpiGeon() {
  //Refreshes (deletes) iGeo geometry.
  IPoint[] ptarr = IG.points();
  ICurve[] crvarr = IG.curves();
  ISurface[] srfarr = IG.surfaces();
  IMesh[] mesharr = IG.meshes();
  //clear points
  for (IPoint pt: ptarr) {
    pt.del();
  }
  //clear curves
  for (ICurve crv: crvarr) {
    crv.del();
  }
  //clear surfaces
  for (ISurface srf:  srfarr) {
    srf.del();
  }
  //clear meshes
  for (IMesh mesh: mesharr) {
    mesh.del();
  }
}

