// MidiVizControlBank
// Lew Hill II

#include "MidiVizControllerSphere.h"

MidiVizControllerSphere::MidiVizControllerSphere(){
  init();
}

void MidiVizControllerSphere::init(){

  for (int i = 0; i < 8; i++){
    controllerValues[i] = 0;
    rotaryAngles[i] = 0;
  }

  float radians;
  for (int i =0; i < 360; i++){
    radians = i * MV_PI_RAD;
    orbitCoordinates[i][0] = cos(radians);
    orbitCoordinates[i][1] = sin(radians);
  }
  
  position[0] = 0;
  position[1] = 0;  
  position[2] = 0;

  rotation[0] = 0;
  rotation[1] = 0;  
  rotation[2] = 0;

  scale[0] = 0;
  scale[1] = 0;  
  scale[2] = 0;

}

void MidiVizControllerSphere::processMidiEvent(MidiEvent event){
    
  //  int controllerNum = event.getControllerNumber(); 
  int controllerValue = event.getControllerValue();
  
  if (event.isRadiumSlider1()){
    controllerValues[0] = controllerValue;
    
  } else if (event.isRadiumSlider2()){
    controllerValues[1] = controllerValue;
    
  } else if (event.isRadiumSlider3()){
    controllerValues[2] = controllerValue;
    
  } else if (event.isRadiumSlider4()){
    controllerValues[3] = controllerValue;
    
  } else if (event.isRadiumSlider5()){
    controllerValues[4] = controllerValue;
    
  } else if (event.isRadiumSlider6()){
    controllerValues[5] = controllerValue;
    
  } else if (event.isRadiumSlider7()){
    controllerValues[6] = controllerValue;
    
  } else if (event.isRadiumSlider8()){
    controllerValues[7] = controllerValue;
  }

}    

void MidiVizControllerSphere::frame(){
    
  for (int i = 0; i < 8; i++){
    rotaryAngles[i] += controllerValues[i]/20.0;
    if (rotaryAngles[i] > 360){
      rotaryAngles[i] -= 360;
    }
  }
}

void MidiVizControllerSphere::draw(){

  // frame turn rate is the sum of the note spins.

  float ringRadius, ringDepth;
  float *colors;

  glPushMatrix();
  glTranslatef(position[0], position[1], position[2]);
  glScalef(scale[0], scale[1], scale[2]);
  
  for (int i = 0; i < 8; i++){
    
    glRotatef(90,0,1.0,0);
    glRotatef(rotaryAngles[i], 1.0, 0.0, 0.0);
    ringRadius = (controllerValues[i]/127.0) *5;
    ringDepth = (controllerValues[i]/127.0) * .1;
   colors = color_table.getValue(i+1);

    glColor3fv(colors);

    // draw sphere rings... onne per midi channel
    // outside ring
    glBegin(GL_QUAD_STRIP);    
    for (int i =0; i < 360; i++){
      int aheadIndex = i+1;
      if (aheadIndex> 360) { 
	aheadIndex -= 360;
      };

      if (i % 45 == 0){
	glEnd();
	i+=2;
	glBegin(GL_QUAD_STRIP);
      }

      glNormal3f(orbitCoordinates[i][0], 0, orbitCoordinates[i][1]);

      glVertex3f(orbitCoordinates[i][0]*ringRadius, ringDepth, 
		 orbitCoordinates[i][1]*ringRadius);
      glVertex3f(orbitCoordinates[i][0]*ringRadius, -ringDepth, 
		 orbitCoordinates[i][1]*ringRadius);
    }

    glEnd();



    // inside rings
    glBegin(GL_QUAD_STRIP);    
    
    for (int i =0; i < 360; i++){
      int aheadIndex = i+1;
      if (aheadIndex> 360) { 
	aheadIndex -= 360;
      };

      glNormal3f(orbitCoordinates[i][0], 0, orbitCoordinates[i][1]);

      glVertex3f(orbitCoordinates[i][0]*ringRadius*.90, 0, 
		 orbitCoordinates[i][1]*ringRadius*.90);
      glVertex3f(orbitCoordinates[i][0]*ringRadius, -ringDepth, 
		 orbitCoordinates[i][1]*ringRadius);
    }

    glEnd();

    // inside rings
    glBegin(GL_QUAD_STRIP);    
    
    for (int i =0; i < 360; i++){
      int aheadIndex = i+1;
      if (aheadIndex> 360) { 
	aheadIndex -= 360;
      };

      glNormal3f(orbitCoordinates[i][0], .5, orbitCoordinates[i][1]);

      glVertex3f(orbitCoordinates[i][0]*ringRadius, .10, 
		 orbitCoordinates[i][1]*ringRadius);

      glNormal3f(orbitCoordinates[i][0], -.5, orbitCoordinates[i][1]);

      glVertex3f(orbitCoordinates[i][0]*ringRadius*.90, -.10, 
		 orbitCoordinates[i][1]*ringRadius*.90);
    }

    glEnd();




  }

  glPopMatrix();
  
}

void MidiVizControllerSphere::drawbox(GLdouble x0, GLdouble x1, 
				    GLdouble y0, GLdouble y1,
				    GLdouble z0, GLdouble z1, GLenum type)
{
   static GLdouble n[6][3] = {
      {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0},
      {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0}
   };
   static GLint faces[6][4] = {
      { 0, 1, 2, 3}, { 3, 2, 6, 7}, { 7, 6, 5, 4},
      { 4, 5, 1, 0}, { 5, 6, 2, 1}, { 7, 4, 0, 3}
   };
   GLdouble v[8][3], tmp;
   GLint i;

   if (x0 > x1)
   {
      tmp = x0; x0 = x1; x1 = tmp;
   }
   if (y0 > y1)
   {
      tmp = y0; y0 = y1; y1 = tmp;
   }
   if (z0 > z1)
   {
      tmp = z0; z0 = z1; z1 = tmp;
   }
   v[0][0] = v[1][0] = v[2][0] = v[3][0] = x0;
   v[4][0] = v[5][0] = v[6][0] = v[7][0] = x1;
   v[0][1] = v[1][1] = v[4][1] = v[5][1] = y0;
   v[2][1] = v[3][1] = v[6][1] = v[7][1] = y1;
   v[0][2] = v[3][2] = v[4][2] = v[7][2] = z0;
   v[1][2] = v[2][2] = v[5][2] = v[6][2] = z1;

   for (i = 0; i < 6; i++)
   {
      glBegin(type);
         glNormal3dv(&n[i][0]);
         glVertex3dv(&v[faces[i][0]][0]);
         glNormal3dv(&n[i][0]);
         glVertex3dv(&v[faces[i][1]][0]);
         glNormal3dv(&n[i][0]);
         glVertex3dv(&v[faces[i][2]][0]);
         glNormal3dv(&n[i][0]);
         glVertex3dv(&v[faces[i][3]][0]);
      glEnd();
   }
}

