 /*
Chloe Fan
Creative Scene
Piano and Bench in room

Final:
Moved piano
Added other furniture
Added plants
Added extras (vase, artwork)
Created left wall
Animations

11.30:
Extended room
Added door

Removed right wall for easy viewing
*/

#include <stdio.h>
#include <tw.h>
#include "cfan2.cpp"
#include <glm.h>
#include <f06/objects.h>
#include <f05/objects.h>

GLuint textureIDs[7];

GLfloat doorRotationLeft = 0;
GLfloat doorRotationRight = 0;
GLfloat benchX = 0;
GLfloat spiralRotation = 0;

twTriple wallColor = {0.85,0.97,0.72};

void init() {
  glGenTextures(7,textureIDs);

  twLoadTexture(textureIDs[0],"wood.ppm");
  twLoadTexture(textureIDs[1],"dawnsmcr.ppm");
  twLoadTexture(textureIDs[2],"sand.ppm");
  twLoadTexture(textureIDs[3],"sheetmusic.ppm");
  twLoadTexture(textureIDs[4],"dpch.ppm");
  twLoadTexture(textureIDs[5],"pianorose.ppm");
  twLoadTexture(textureIDs[6],"bwrose.ppm");
}

void texinit() {
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // light would shine on floor
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}

void drawPalm(bool printBB) {
  static GLMmodel* Palm = NULL;
  const char* obj_filename = "palm.obj";

  if(NULL==Palm) {
    Palm = glmReadOBJ(twPathname(obj_filename,true));
    if (!Palm) {
      fprintf(stderr,"error reading OBJ file %s\n",obj_filename);
      return;
    }
    glmUnitize(Palm);
    if(printBB) {
      GLfloat BoundingBox[6];
      glmBoundingBox(Palm,BoundingBox);
      printf("Bounding Box is (%f,%f,%f,%f,%f,%f)\n",
	     BoundingBox[0], BoundingBox[1],
	     BoundingBox[2], BoundingBox[3],
	     BoundingBox[4], BoundingBox[5]);
    }
    glmFacetNormals(Palm);
    glmVertexNormals(Palm, 90.0);
  }
  glPushMatrix();
  glmDraw(Palm, GLM_SMOOTH | GLM_MATERIAL);
  glPopMatrix();
}

void drawPlant(bool printBB) {
  static GLMmodel* Plant = NULL;
  const char* obj_filename = "palmPotted.obj";

  if(NULL==Plant) {
    Plant = glmReadOBJ(twPathname(obj_filename,true));
    if (!Plant) {
      fprintf(stderr,"error reading OBJ file %s\n",obj_filename);
      return;
    }
    glmUnitize(Plant);
    if(printBB) {
      GLfloat BoundingBox[6];
      glmBoundingBox(Plant,BoundingBox);
      printf("Bounding Box is (%f,%f,%f,%f,%f,%f)\n",
	     BoundingBox[0], BoundingBox[1],
	     BoundingBox[2], BoundingBox[3],
	     BoundingBox[4], BoundingBox[5]);
    }
    glmFacetNormals(Plant);
    glmVertexNormals(Plant, 90.0);
  }
  glPushMatrix();
  glmDraw(Plant, GLM_SMOOTH | GLM_MATERIAL);
  glPopMatrix();
}

void display(void) {
  twDisplayInit();
  twCamera();

  glPushAttrib(GL_ALL_ATTRIB_BITS);

  glEnable(GL_TEXTURE_2D);

  glShadeModel(GL_SMOOTH);
  glEnable(GL_NORMALIZE);
  glEnable(GL_LIGHTING);
  twAmbient(0); // turn down ambient to make lights more obvious

  GLfloat light0pos[] = {0,10,0,0}; // directional light
  twGrayLight(GL_LIGHT0, light0pos, 0.1,0.8,1);
  glEnable(GL_LIGHT0);

  GLfloat light1pos[] = {-16,12,-20,1}; // point light
  twGrayLight(GL_LIGHT1, light1pos, 0,0.5,1);
  glEnable(GL_LIGHT1);

  // 2nd light too bright for dawn
  /*  GLfloat light2pos[] = {15,5,20,1};
  twGrayLight(GL_LIGHT2, light2pos, 0,0.5,1);
  glEnable(GL_LIGHT2);*/

  // floor
    glPushMatrix();
    glBindTexture(GL_TEXTURE_2D, textureIDs[0]);
    glTranslatef(0,-5.5,0);
    glBegin(GL_POLYGON);
    {
      /*twTriple floorColor = {0.85,0.6,0.4};
	twColor(floorColor,0,0);*/
      twTriple u = {0,1,0};
      glNormal3fv(u);
      glTexCoord2f(0,1);
      glVertex3f(-30,0,30); // front left
      glTexCoord2f(1,1);
      glVertex3f(40,0,30); // front right
      glTexCoord2f(1,0);
      glVertex3f(40,0,-30); // back right
      glTexCoord2f(0,0);
      glVertex3f(-30,0,-30); // back left
    }
    glEnd();
    glPopMatrix();
    
    // left wall w/sunset
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);//unaffected by light
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

    glBindTexture(GL_TEXTURE_2D, textureIDs[1]);
    glPushMatrix();
    glEnable(GL_CULL_FACE);
    glBegin(GL_POLYGON);
    {
      glTexCoord2f(0,1); glVertex3f(-40,-5.5,30); // bottom front
      glTexCoord2f(1,1); glVertex3f(-40,-5.5,-30); // bottom back
      glTexCoord2f(1,0); glVertex3f(-40,20,-30); // top back
      glTexCoord2f(0,0); glVertex3f(-40,20,30); // top front
    }
    glEnd();
    glDisable(GL_CULL_FACE);
    glPopMatrix();

    // sand outside
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);//unaffected by light
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

    glBindTexture(GL_TEXTURE_2D, textureIDs[2]);
    glPushMatrix();
    glBegin(GL_POLYGON);
    {
      glTexCoord2f(0,1); glVertex3f(-40,-5.5,30);
      glTexCoord2f(1,1); glVertex3f(-30,-5.5,30);
      glTexCoord2f(1,0); glVertex3f(-30,-5.5,-30);
      glTexCoord2f(0,0); glVertex3f(-40,-5.5,-30);
    }
    glEnd();
    glPopMatrix();

    // sheet music
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);//affected by light
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

    glBindTexture(GL_TEXTURE_2D, textureIDs[3]);
    glPushMatrix();
    glTranslatef(-20,0,-20);
    glRotatef(30,0,1,0);
    glBegin(GL_POLYGON);
    {
      glTexCoord2f(0,1); glVertex3f(-2,3,2);
      glTexCoord2f(1,1); glVertex3f(2,3,2);
      glTexCoord2f(1,0); glVertex3f(2,6,1.5);
      glTexCoord2f(0,0); glVertex3f(-2,6,1.5);
    }
    glEnd();
    glPopMatrix();

    // art 1 coastal harmony
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);//unaffected by light
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

    glBindTexture(GL_TEXTURE_2D, textureIDs[4]);
    glPushMatrix();
    glBegin(GL_POLYGON);
    {
      glTexCoord2f(0,1); glVertex3f(-5,5,-29.9);
      glTexCoord2f(1,1); glVertex3f(10,5,-29.9);
      glTexCoord2f(1,0); glVertex3f(10,13,-29.9);
      glTexCoord2f(0,0); glVertex3f(-5,13,-29.9);
    }
    glEnd();
    glPopMatrix();

    // art 2 piano rose
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);//unaffected by light
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

    glBindTexture(GL_TEXTURE_2D, textureIDs[5]);
    glPushMatrix();
    glBegin(GL_POLYGON);
    {
      glTexCoord2f(0,1); glVertex3f(39.9,5,-5);
      glTexCoord2f(1,1); glVertex3f(39.9,5,5);
      glTexCoord2f(1,0); glVertex3f(39.9,12,5);
      glTexCoord2f(0,0); glVertex3f(39.9,12,-5);
    }
    glEnd();
    glPopMatrix();

    // art 3 bw rose
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);//unaffected by light
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

    glBindTexture(GL_TEXTURE_2D, textureIDs[6]);
    glPushMatrix();
    glEnable(GL_CULL_FACE); // so that it won't block initial scene
    glBegin(GL_POLYGON);
    {
      glTexCoord2f(0,1); glVertex3f(5,5,29.9);
      glTexCoord2f(1,1); glVertex3f(-5,5,29.9);
      glTexCoord2f(1,0); glVertex3f(-5,12,29.9);
      glTexCoord2f(0,0); glVertex3f(5,12,29.9);
    }
    glEnd();
    glDisable(GL_CULL_FACE);
    glPopMatrix();

    glDisable(GL_TEXTURE_2D); // so that the rest of scene shows up

    // left inside wall, will look like window wall
    // horizontal stripes
    glPushMatrix();
    glBegin(GL_POLYGON);
    {
      twColor(wallColor,0,0);
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(-30,19.5,30);
      glVertex3f(-30,19.5,-30);
      glVertex3f(-30,20,-30);
      glVertex3f(-30,20,30);
    }
    glEnd();
    glBegin(GL_POLYGON);
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(-30,14.5,30);
      glVertex3f(-30,14.5,20);
      glVertex3f(-30,15,20);
      glVertex3f(-30,15,30);
    }
    glEnd();
    glBegin(GL_POLYGON);
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(-30,14.5,0);
      glVertex3f(-30,14.5,-30);
      glVertex3f(-30,15,-30);
      glVertex3f(-30,15,0);
    }
    glEnd();
    glBegin(GL_POLYGON);
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(-30,9.5,30);
      glVertex3f(-30,9.5,20);
      glVertex3f(-30,10,20);
      glVertex3f(-30,10,30);
    }
    glEnd();
    glBegin(GL_POLYGON);
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(-30,9.5,0);
      glVertex3f(-30,9.5,-30);
      glVertex3f(-30,10,-30);
      glVertex3f(-30,10,-0);
    }
    glEnd();
    glBegin(GL_POLYGON);
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(-30,4.5,30);
      glVertex3f(-30,4.5,20);
      glVertex3f(-30,5,20);
      glVertex3f(-30,5,30);
    }
    glEnd();
    glBegin(GL_POLYGON);
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(-30,4.5,0);
      glVertex3f(-30,4.5,-30);
      glVertex3f(-30,5,-30);
      glVertex3f(-30,5,0);
    }
    glEnd();
    glBegin(GL_POLYGON);
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(-30,-0.5,30);
      glVertex3f(-30,-0.5,20);
      glVertex3f(-30,0,20);
      glVertex3f(-30,0,30);
    }
    glEnd();
    glBegin(GL_POLYGON);
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(-30,-0.5,0);
      glVertex3f(-30,-0.5,-30);
      glVertex3f(-30,0,-30);
      glVertex3f(-30,0,0);
    }
    glEnd();
    glBegin(GL_POLYGON);
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(-30,-5.5,30);
      glVertex3f(-30,-5.5,20);
      glVertex3f(-30,-5,20);
      glVertex3f(-30,-5,30);
    }
    glEnd();
    glBegin(GL_POLYGON);
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(-30,-5.5,0);
      glVertex3f(-30,-5.5,-30);
      glVertex3f(-30,-5,-30);
      glVertex3f(-30,-5,0);
    }
    glEnd();

    // vertical stripes
    glBegin(GL_POLYGON);
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(-30,-5.5,30);
      glVertex3f(-30,-5.5,29.5);
      glVertex3f(-30,20,29.5);
      glVertex3f(-30,20,30);
    }
    glEnd();
    glBegin(GL_POLYGON);
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(-30,-5.5,20.5);
      glVertex3f(-30,-5.5,20);
      glVertex3f(-30,20,20);
      glVertex3f(-30,20,20.5);
    }
    glEnd();
    glBegin(GL_POLYGON);
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(-30,15,10.25);
      glVertex3f(-30,15,9.75);
      glVertex3f(-30,20,9.75);
      glVertex3f(-30,20,10.25);
    }
    glEnd();
    glBegin(GL_POLYGON);
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(-30,-5.5,0);
      glVertex3f(-30,-5.5,-0.5);
      glVertex3f(-30,20,-0.5);
      glVertex3f(-30,20,0);
    }
    glEnd();
    glBegin(GL_POLYGON);
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(-30,-5.5,-9.75);
      glVertex3f(-30,-5.5,-10.25);
      glVertex3f(-30,20,-10.25);
      glVertex3f(-30,20,-9.75);
    }
    glEnd();
    glBegin(GL_POLYGON);
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(-30,-5.5,-19.75);
      glVertex3f(-30,-5.5,-20.25);
      glVertex3f(-30,20,-20.25);
      glVertex3f(-30,20,-19.75);
    }
    glEnd();
    glBegin(GL_POLYGON);
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(-30,-5.5,-29.5);
      glVertex3f(-30,-5.5,-30);
      glVertex3f(-30,20,-30);
      glVertex3f(-30,20,-29.5);
    }
    glEnd();
    glPopMatrix();

    // left door
    glPushMatrix();
    glTranslatef(-30,-5.5,20);
    glRotatef(doorRotationLeft,0,1,0);
    glBegin(GL_POLYGON); // left panel
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(0,0,0);
      glVertex3f(0,0,-0.5);
      glVertex3f(0,20.5,-0.5);
      glVertex3f(0,20.5,0);
    }
    glEnd();
    glBegin(GL_POLYGON); // right panel
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(0,0,-9.5);
      glVertex3f(0,0,-10);
      glVertex3f(0,20.5,-10);
      glVertex3f(0,20.5,-9.5);
    }
    glEnd();
    glBegin(GL_POLYGON); // bottom panel
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(0,0,0);
      glVertex3f(0,0,-10);
      glVertex3f(0,0.5,-10);
      glVertex3f(0,0.5,0);
    }
    glEnd();
    glBegin(GL_POLYGON); // top panel
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(0,20,0);
      glVertex3f(0,20,-10);
      glVertex3f(0,20.5,-10);
      glVertex3f(0,20.5,0);
    }
    glEnd();
    glPopMatrix();

    // right door
    glPushMatrix();
    glTranslatef(-30,-5.5,0);
    glRotatef(doorRotationRight,0,1,0);
    glBegin(GL_POLYGON); // left panel
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(0,0,10);
      glVertex3f(0,0,9.5);
      glVertex3f(0,20.5,9.5);
      glVertex3f(0,20.5,10);
    }
    glEnd();
    glBegin(GL_POLYGON); // right panel
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(0,0,0.5);
      glVertex3f(0,0,0);
      glVertex3f(0,20.5,0);
      glVertex3f(0,20.5,0.5);
    }
    glEnd();
    glBegin(GL_POLYGON); // bottom panel
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(0,0,10);
      glVertex3f(0,0,0);
      glVertex3f(0,0.5,0);
      glVertex3f(0,0.5,10);
    }
    glEnd();
    glBegin(GL_POLYGON); // top panel
    {
      twTriple u = {1,0,0};
      glNormal3fv(u);
      glVertex3f(0,20,10);
      glVertex3f(0,20,0);
      glVertex3f(0,20.5,0);
      glVertex3f(0,20.5,10);
    }
    glEnd();
    glPopMatrix();

    // back wall
    glPushMatrix();
    glEnable(GL_CULL_FACE);
    glBegin(GL_POLYGON);
    {
      twColor(wallColor,0,0);
      twTriple u = {0,0,1};
      glNormal3fv(u);
      glVertex3f(-30,-5.5,-30); // LL
      glVertex3f(40,-5.5,-30); // LR
      glVertex3f(40,20,-30); // UR
      glVertex3f(-30,20,-30); // UL
    }
    glEnd();
    glPopMatrix();

    // right wall
    glPushMatrix();
    glBegin(GL_POLYGON);
    {
      twTriple u = {-1,0,0};
      glNormal3fv(u);
      glVertex3f(40,-5.5,-30); // LL
      glVertex3f(40,-5.5,30); // LR
      glVertex3f(40,20,30); // UR
      glVertex3f(40,20,-30); // UL
    }
    glEnd();
    glPopMatrix();

     // front wall
    glPushMatrix();
    glBegin(GL_POLYGON);
    {
      twTriple u = {0,0,-1};
      glNormal3fv(u);
      glVertex3f(40,-5.5,30); // LR
      glVertex3f(-30,-5.5,30); // LL
      glVertex3f(-30,20,30); // UL
      glVertex3f(40,20,30); // UR
    }
    glEnd();
    glPopMatrix();

    glDisable(GL_CULL_FACE);
    
    glPushMatrix();
    GLfloat matAmb[] = {0, 0, 0, 1};
    GLfloat matDiff[] = {0.1, 0.1, 0.1, 0.1};
    GLfloat matSpec[] = {1, 1, 1, 1};
    GLfloat matEmis[] = {0, 0, 0, 0};
    GLfloat matShi = 20;
    glMaterialfv(GL_FRONT, GL_AMBIENT, matAmb);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, matDiff);
    glMaterialfv(GL_FRONT, GL_SPECULAR, matSpec);
    glMaterialfv(GL_FRONT, GL_EMISSION, matEmis);
    glMaterialf(GL_FRONT, GL_SHININESS, matShi);
    // move to corner
    glTranslatef(-20,0,-20);
    glRotatef(30,0,1,0);
    // draw piano
    cfan2Piano();
    // move to bench location
    glTranslatef(0,-2.5,8.5);
    glTranslatef(benchX,0,benchX); // to move bench
    glMaterialfv(GL_FRONT, GL_AMBIENT, matAmb);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, matDiff);
    glMaterialfv(GL_FRONT, GL_SPECULAR, matSpec);
    glMaterialfv(GL_FRONT, GL_EMISSION, matEmis);
    glMaterialf(GL_FRONT, GL_SHININESS, matShi);
    // draw bench in color of piano
    cfan2Bench();
    glPopMatrix();
    
    // ===STUDENT CONTRIBUTIONS===
    
    // palm
    glPushMatrix();
    glTranslatef(-35,5,25);
    glScalef(10,10,10);
    drawPalm(false);
    glTranslatef(0,0,-4.5);
    drawPalm(false);
    glPopMatrix();
    
    //plant
    glPushMatrix();
    glTranslatef(36,-1.5,20);
    glScalef(5,5,5);
    drawPlant(false);
    glPopMatrix();
    
    // ceiling lamp
    glPushMatrix();
    glTranslatef(0,15,0);
    glScalef(0.3,0.5,0.3);
    twTriple lightColor = {1,0.71,0}; // gold color
    twTriple bulbColor = {1,1,1};
    msarkarCeilingLight(5,lightColor,bulbColor );
    glPopMatrix();
    
    // couch
    glPushMatrix();
    glTranslatef(39,-2,0);
    glRotatef(-90,0,1,0);
    twTriple colorA = {1,0.97,0.9};
    twTriple colorB = {1,0.93,0.76};
    msarkarCouch(2,colorA,colorB);
    glPopMatrix();
    
    // end tables
    glPushMatrix();
    glTranslatef(36,-6,10);
    glScalef(0.75,0.5,0.75);
    zkabayadTable(false);
    glTranslatef(0,0,-26);
    zkabayadTable(false);
    glPopMatrix();
    
    // vase
    glPushMatrix();
    twTriple vaseColor = {0.31,0.64,0.79};
    twTriple bottomColor = {0.19,0.42,0.52};
    twTriple rimColor = {0.67,0.78,1};
    twTriple flowerColor1 = {1,0.95,0.67};
    twTriple flowerColor2 = {1,0.83,0};
    glTranslatef(36,0.25,-7.5);
    msarkarVase(2,vaseColor,bottomColor,rimColor,flowerColor1,flowerColor2);
    glPopMatrix();
    
    // spiral
    glPushMatrix();
    twTriple color = {0.83,0.83,0.83};
    glTranslatef(-35,5,10);
    glRotatef(spiralRotation,0,1,0);
    zmoriczSpiral(color,3,10);
    glPopMatrix();
    
    glPopAttrib();
    
    glFlush();
    glutSwapBuffers();
}

bool OpeningLeft = false; // if left door is active
bool LeftOpen = false; // if left door is opening
bool OpeningRight = false; // if right door is active
bool RightOpen = false; // if right door is opening
bool IsSliding = false; // if bench is in action
bool Sliding = false; // if bench is sliding out
bool Rotating = false; // if spiral is rotating

// idle callback for door
void openLeft() {
  if(doorRotationLeft == 0 || doorRotationLeft == -90) {
    LeftOpen = !LeftOpen; // switch rotation direction
    if(doorRotationLeft == 0) doorRotationLeft--; // then inc/dec as needed
    if(doorRotationLeft == -90) doorRotationLeft++;
  }
  if(LeftOpen) doorRotationLeft--;
  else
    doorRotationLeft++;
  glutPostRedisplay();
}

void openRight() {
  if(doorRotationRight == 0 || doorRotationRight == 90) {
    RightOpen = !RightOpen; // switch rotation direction
    if(doorRotationRight == 0) doorRotationRight++; // then inc/dec as needed
    if(doorRotationRight == 90) doorRotationRight--;
  }
  if(RightOpen) doorRotationRight++;
  else
    doorRotationRight--;
  glutPostRedisplay();
}

void slideBench() {
  // if in home position or full slide position
  if (benchX == 0 || benchX == 3) {
    Sliding = !Sliding; // switch sliding direction
    if(benchX == 0) // if in home position
      benchX+=0.5;// move out; x value increases, z value increases
    if(benchX == 3)
      benchX-=0.5;
  }
  if(Sliding) benchX++; //increase if in action of sliding out
  else
    benchX--;
  glutPostRedisplay();
}

void rotateSpiral() {
  spiralRotation+=10; // it's already rotating, so keep on rotating
  glutPostRedisplay();
}

void keys(unsigned char k, int, int) {
  switch (k) {
  case '0': // reset animations
    doorRotationLeft = 0;
    OpeningLeft = false;
    LeftOpen = false;
    doorRotationRight = 0;
    OpeningRight = false;
    RightOpen = false;
    Sliding = false;
    Rotating = false;
    spiralRotation = 0;
    break;
  case '1': // open/stop left door
    OpeningLeft = !OpeningLeft;
    if(OpeningLeft)
      glutIdleFunc(openLeft);
    else
      glutIdleFunc(NULL);
    break;
  case '2': //open/stop right door
    OpeningRight = !OpeningRight;
    if(OpeningRight)
      glutIdleFunc(openRight);
    else
      glutIdleFunc(NULL);
    break;
  case '3': // slide in/out piano chair
    IsSliding = !IsSliding;
    if(IsSliding)
      glutIdleFunc(slideBench);
    else
      glutIdleFunc(NULL);
    break;
  case '4': // rotate spiral outside
    Rotating = !Rotating; // turn rotating on or off
    if(Rotating)
      glutIdleFunc(rotateSpiral);
    else
      glutIdleFunc(NULL);
    break;
  }
}

int main(int argc, char** argv) {
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  twInitWindowSize(500,500);
  glutCreateWindow(argv[0]);
  init();
  texinit();
  glutDisplayFunc(display);
  //  twBoundingBox(-12,12,-5.5,9,-9,10); // wrapped
  twBoundingBox(-40, 40, -5.5, 20, -30, 30); // room size
  twMainInit();
  twKeyCallback('0',keys,"Reset animations");
  twKeyCallback('1',keys,"Open left door");
  twKeyCallback('2',keys,"Open right door");
  twKeyCallback('3',keys,"Slide piano chair");
  twKeyCallback('4',keys,"Rotate outside spiral");
  glutMainLoop();
  return 0;
}
