/*
Chloe Fan's OpenGL Piano and Bench
Copyright (c) 2006 Chloe Fan

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

cfan2Piano();
Draws a baby grand piano
Can be placed in auditorium, living room, etc.
Values are scaled based on the width of the piano, or affine transformations can be used to resize piano.
The origin is on the bottom of the base of the piano, right above the legs, where the cover also matches up horizontally, and halfway through the width. This way, the legs are located on the negative y-axis, and the piano will be symmetrical.

cfan2Bench();
Creates a matching bench for the piano.
Symmetrical, origin under seat above legs, same as piano, and centered.
*/

void cfan2Piano() {

  twTriple _wheelColor = {0.84, 0.68, 0.05};

  //=============== PIANO FRONT: KEYS AND BASE ================//

  glPushMatrix(); // keys
  glColor3f(1,1,1); // white
  glTranslatef(0, 1.5, 4.5);
  glScalef(12, 0.25, 1);
  glutSolidCube(1);
  glPopMatrix();

  //  twColor(_pianoColor,0,0); // set color to piano color

  glPushMatrix(); // below keys
  glTranslatef(0,0.5,4.5);
  glScalef(12, 1, 1);
  glutSolidCube(1);
  glPopMatrix();

  glBegin(GL_POLYGON); // right keys "cover"
  {
    twTriple u = {4, 0, 0};
    twVectorNormalize(u);
    glNormal3fv(u);
    glVertex3f(6, 0, 6);
    glVertex3f(6, 0, 4);
    glVertex3f(6, 2, 4);
    glVertex3f(6, 2, 6);
  }
  glEnd();

  glBegin(GL_POLYGON); // left keys "cover"
  {
    twTriple u = {-4, 0, 0};
    twVectorNormalize(u);
    glNormal3fv(u);
    glVertex3f(-6, 0, 4);
    glVertex3f(-6, 0, 6);
    glVertex3f(-6, 2, 6);
    glVertex3f(-6, 2, 4);
  }
  glEnd();

  glBegin(GL_POLYGON); // book stand
  {
    twTriple u = {0, 3, 12};
    twVectorNormalize(u);
    glNormal3fv(u);
    glVertex3f(-3, 3, 2);
    glVertex3f(3, 3, 2);
    glVertex3f(3, 5, 1.5);
    glVertex3f(-3, 5, 1.5);
  }
  glEnd();

  glBegin(GL_POLYGON); // book stand back
  {
    glVertex3f(-0.5, 4, 1.75);
    glVertex3f(0.5, 4, 1.75);
    glVertex3f(0.5, 3, 1);
    glVertex3f(-0.5, 3, 1);
  }
  glEnd();

  glPushMatrix(); // under book stand
  glTranslatef(0, 1.5, 2);
  glScalef(12, 3, 4);
  glutSolidCube(1);
  glPopMatrix();

  glBegin(GL_POLYGON); // piano curved base
  {
    glVertex3f(-6, 1, 0);
    glVertex3f(-6, 1, -5);
    glVertex3f(-5, 1, -7.5);
    glVertex3f(-4, 1, -8.25);
    glVertex3f(-3, 1, -8.8);
    glVertex3f(-2, 1, -9); // top of big curve
    glVertex3f(-1, 1, -8.8);
    glVertex3f(0, 1, -8.25);
    glVertex3f(1, 1, -7.5);
    glVertex3f(2, 1, -5);
    glVertex3f(3, 1, -3.5);
    glVertex3f(4, 1, -3);
    glVertex3f(5, 1, -2.5);
    glVertex3f(6, 1, 0);
  }
  glEnd();

  //  glColor3f(255,255,255); // white: testing

  /*  glBegin(GL_QUAD_STRIP); // piano base wall
  {
    glVertex3f(-6, 1, 0);
    glVertex3f(-6, 3, 0);
    glVertex3f(-6, 1, -5);
    glVertex3f(-6, 3, -5);

    glVertex3f(-5, 1, -7.5);
    glVertex3f(-5, 3, -7.5);

    glVertex3f(-4, 1, -8.25);
    glVertex3f(-4, 3, -8.25);

    glVertex3f(-3, 1, -8.8);
    glVertex3f(-3, 3, -8.8);

    glVertex3f(-2, 1, -9); // top of big curve
    glVertex3f(-2, 3, -9);

    glVertex3f(-1, 1, -8.8);
    glVertex3f(-1, 3, -8.8);

    glVertex3f(0, 1, -8.25);
    glVertex3f(0, 3, -8.25);

    glVertex3f(1, 1, -7.5);
    glVertex3f(1, 3, -7.5);

    glVertex3f(2, 1, -5);
    glVertex3f(2, 3, -5);

    glVertex3f(3, 1, -3.5);
    glVertex3f(3, 3, -3.5);

    glVertex3f(4, 1, -3);
    glVertex3f(4, 3, -3);

    glVertex3f(5, 1, -2.5);
    glVertex3f(5, 3, -2.5);

    glVertex3f(6, 1, 0);
    glVertex3f(6, 3, 0);
  }
  glEnd();*/

  glBegin(GL_QUADS); // piano base wall using quads for normalizing
  {
    twTriple a = {-10, 0, 0};
    twVectorNormalize(a);
    glNormal3fv(a);
    glVertex3f(-6, 1, 0);
    glVertex3f(-6, 3, 0);
    glVertex3f(-6, 3, -5);
    glVertex3f(-6, 1, -5);

    twTriple b = {-5, 0, -2};
    twVectorNormalize(b);
    glNormal3fv(b);
    glVertex3f(-6, 1, -5);
    glVertex3f(-6, 3, -5);
    glVertex3f(-5, 3, -7.5);
    glVertex3f(-5, 1, -7.5);

    twTriple c = {-1.5, 0, -2};
    twVectorNormalize(c);
    glNormal3fv(c);
    glVertex3f(-5, 1, -7.5);
    glVertex3f(-5, 3, -7.5);
    glVertex3f(-4, 3, -8.25);
    glVertex3f(-4, 1, -8.25);

    twTriple d = {-1.1, 0, -2};
    twVectorNormalize(d);
    glNormal3fv(d);
    glVertex3f(-4, 1, -8.25);
    glVertex3f(-4, 3, -8.25);
    glVertex3f(-3, 3, -8.8);
    glVertex3f(-3, 1, -8.8);

    twTriple e = {35.6, 0, -2};
    twVectorNormalize(e);
    glNormal3fv(e);
    glVertex3f(-3, 1, -8.8);
    glVertex3f(-3, 3, -8.8);
    glVertex3f(-2, 3, -9);
    glVertex3f(-2, 1, -9); // top of big curve

    twTriple f = {-0.4, 0, 2};
    twVectorNormalize(f);
    glNormal3fv(f);
    glVertex3f(-2, 1, -9);
    glVertex3f(-2, 3, -9);
    glVertex3f(-1, 3, -8.8);
    glVertex3f(-1, 1, -8.8);
 
    twTriple g = {-1.1, 0, 2};
    twVectorNormalize(g);
    glNormal3fv(g);
    glVertex3f(-1, 1, -8.8);
    glVertex3f(-1, 3, -8.8);
    glVertex3f(0, 3, -8.25);
    glVertex3f(0, 1, -8.25);

    twTriple h = {-1.5, 0, 2};
    twVectorNormalize(h);
    glNormal3fv(h);
    glVertex3f(0, 1, -8.25);
    glVertex3f(0, 3, -8.25);
    glVertex3f(1, 3, -7.5);
    glVertex3f(1, 1, -7.5);

    twTriple i = {-5, 0, 2};
    twVectorNormalize(i);
    glNormal3fv(i);
    glVertex3f(1, 1, -7.5);
    glVertex3f(1, 3, -7.5);
    glVertex3f(2, 3, -5);
    glVertex3f(2, 1, -5);

    twTriple j = {-3, 0, 2};
    twVectorNormalize(j);
    glNormal3fv(j);
    glVertex3f(2, 1, -5);
    glVertex3f(2, 3, -5);
    glVertex3f(3, 3, -3.5);
    glVertex3f(3, 1, -3.5);

    twTriple k = {-5, 0, 2};
    twVectorNormalize(k);
    glNormal3fv(k);
    glVertex3f(3, 1, -3.5);
    glVertex3f(3, 3, -3.5);
    glVertex3f(4, 3, -3);
    glVertex3f(4, 1, -3);

    twTriple l = {-1, 0, 2};
    twVectorNormalize(l);
    glNormal3fv(l);
    glVertex3f(4, 1, -3);
    glVertex3f(4, 3, -3);
    glVertex3f(5, 3, -2.5);
    glVertex3f(5, 1, -2.5);

    twTriple m = {-5, 0, 2};
    twVectorNormalize(m);
    glNormal3fv(m);
    glVertex3f(5, 1, -2.5);
    glVertex3f(5, 3, -2.5);
    glVertex3f(6, 3, 0);
    glVertex3f(6, 1, 0);
  }
  glEnd();

  //======================= PIANO COVER =========================//

  glPushMatrix();
  glTranslatef(0.5,3.5,0);
  glRotatef(30, 0, 0, 1);
  glBegin(GL_POLYGON); // piano curved cover
  {
    twTriple u = {0, -5, 0};
    twVectorNormalize(u);
    glNormal3fv(u);
    glVertex3f(-6, 3, 0);
    glVertex3f(-6, 3, -5);
    glVertex3f(-5, 3, -7.5);
    glVertex3f(-4, 3, -8.25);
    glVertex3f(-3, 3, -8.8);
    glVertex3f(-2, 3, -9); // top of big curve
    glVertex3f(-1, 3, -8.8);
    glVertex3f(0, 3, -8.25);
    glVertex3f(1, 3, -7.5);
    glVertex3f(2, 3, -5);
    glVertex3f(3, 3, -3.5);
    glVertex3f(4, 3, -3);
    glVertex3f(5, 3, -2.5);
    glVertex3f(6, 3, 0);
  }
  glEnd();
  glPopMatrix();

  //  glColor3f(255,255,255); // white: testing

  glBegin(GL_POLYGON); // cover prop
  {
    glVertex3f(5, 3, -0.75);
    glVertex3f(5, 3, -1.25);
    glVertex3f(3, 8.5, -1.25);
    glVertex3f(3, 8.5, -0.75);
  }
  glEnd();

  //==================== PIANO LEGS AND PEDALS ======================//

  glBegin(GL_POLYGON); // right front slanted left
  {
    glVertex3f(5, 0, 0);
    glVertex3f(5, -1, 1.5);
    glVertex3f(5, -1, 2.5);
    glVertex3f(5, 0, 4);
  }
  glEnd();

  glBegin(GL_POLYGON); // right front slanted right
  {
    glVertex3f(6, 0, 0);
    glVertex3f(6, -1, 1.5);
    glVertex3f(6, -1, 2.5);
    glVertex3f(6, 0, 4);
  }
  glEnd();

  glBegin(GL_POLYGON); // left front slanted right
  {
    glVertex3f(-5, 0, 0);
    glVertex3f(-5, -1, 1.5);
    glVertex3f(-5, -1, 2.5);
    glVertex3f(-5, 0, 4);
  }
  glEnd();

  glBegin(GL_POLYGON); // left front slanted left
  {
    glVertex3f(-6, 0, 0);
    glVertex3f(-6, -1, 1.5);
    glVertex3f(-6, -1, 2.5);
    glVertex3f(-6, 0, 4);
  }
  glEnd();

  glBegin(GL_POLYGON); // back slanted front
  {
    glVertex3f(-3, 1, -7.5);
    glVertex3f(-2.5, 0, -7.5);
    glVertex3f(-1.5, 0, -7.5);
    glVertex3f(-1, 1, -7.5);
  }
  glEnd();

  glPushMatrix(); // legs
  glTranslatef(5.5, -2.5, 2);
  glScalef(1, 5, 1);
  glutSolidCube(1); // right leg
  glTranslatef(-11, 0, 0);
  glutSolidCube(1); // left leg
  glPopMatrix();

  glPushMatrix();
  glTranslatef(-2, -2, -8);
  glScalef(1,6,1);
  glutSolidCube(1); // back leg
  glPopMatrix();

  glPushMatrix(); // wheels
  twColor(_wheelColor,0,0); // set color to wheel color
  glTranslatef(-5.5, -5.25, 2);
  glScalef(0.5,0.5,0.5);
  glutSolidSphere(1,20,20); // left wheel
  glTranslatef(22, 0, 0);
  glutSolidSphere(1,20,20); // right wheel
  glTranslatef(-15, 0, -20);
  glutSolidSphere(1,20,20);
  glPopMatrix();

  // pedals: all pedals are supposed to stick out behind past the "box" since they are attached to the bottom of the piano base to control string frames
  glPushMatrix();
  //  twColor(_pianoColor,0,0); // back to piano color
  glTranslatef(-0.75, -2, 2);
  glScalef(0.5, 4, 0.5);
  glutSolidCube(1); // left supporter
  glTranslatef(3, 0, 0);
  glutSolidCube(1); // right supporter
  glPopMatrix();

  glPushMatrix();
  glTranslatef(0, -4, 2);
  glScalef(3, 0.5, 1);
  glutSolidCube(1); // pedal box
  twColor(_wheelColor,0,0); // set color to wheel color
  glTranslatef(0, 0, 0.25);
  glScalef(0.1, 0.5, 1);
  glutSolidSphere(1, 20, 20); // middle pedal
  glPushMatrix();
  glTranslatef(-2.5, 0, 0);
  glutSolidSphere(1,20,20); // left pedal
  glPopMatrix();
  glTranslatef(2.5, 0, 0);
  glutSolidSphere(1,20,20); // right pedal
  glPopMatrix();
}


void cfan2Bench() {

  // bench length
  const GLfloat bLength = 8;
  // bench width
  const GLfloat bWidth = 3;
  // bench depth
  const GLfloat bDepth = 1;
  // leg length
  const GLfloat lLength = 3;

  //twColor(_pianoColor,0,0); // set color to piano color

  glPushMatrix(); // seat
  glTranslatef(0, 0.5, 0);
  glScalef(bLength, bDepth, bWidth);
  glutSolidCube(1);
  glPopMatrix();

  glPushMatrix(); // legs
  glTranslatef(-bLength/2+0.5, -lLength/2, 1);
  glScalef(0.5, lLength, 0.5);
  glutSolidCube(1);

  glTranslatef(0, 0, -((bWidth-1)*2));
  glutSolidCube(1);

  glTranslatef((bLength-1)*2, 0, 0);
  glutSolidCube(1);

  glTranslatef(0, 0, (bWidth-1)*2);
  glutSolidCube(1);
  glPopMatrix();

}
