/*****************************************************************
  gravbounce.cpp
  by Dave Pape
  3 March 2003

  This example shows movement with acceleration.
  A ball is dropped from the top of the window, and receives a
  constant acceleration due to gravity.  It also bounces off of
  the edges of the window, the same as in bounce.cpp.
 
*****************************************************************/
#include <unistd.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <dms/dms.h>

void drawEverything(void);
void key(unsigned char k, int x, int y);
void idle(void);
void launchBall(void);
void checkForBounce(void);


/*************** CODE OF INTEREST ******************************/
/* Variables needed to compute the ball's motion - its starting*/
/* position & velocity, acceleration due to gravity, and       */
/* current position & velocity.                                */
dms::Vector3 startPosition(-10, 19, 0);
dms::Vector3 startVelocity(2, 0, 0);
dms::Vector3 acceleration(0, -9.8, 0);
dms::Vector3 position;
dms::Vector3 velocity;

dms::OrthoCamera camera(-20, 20, -20, 20);
dms::QuadricObject ball;


int main(int argc, char *argv[])
    {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(512,512);
    glutCreateWindow("example");
    glutDisplayFunc(drawEverything);
    glutKeyboardFunc(key);
    glutIdleFunc(idle);
    glLineWidth(2);
    launchBall();
    glutMainLoop();
    return 0;
    }


void drawEverything(void)
    {
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    
    camera.apply();
    
    glColor3f(1.0, 0.9, 0.0);
    glTranslatef(position[0], position[1], position[2]);
    ball.draw();
    velocity.drawLine();

    glutSwapBuffers();
    }


/*************** CODE OF INTEREST ******************************/
/* launchBall() sets the current position & velocity to the    */
/* starting position & velocity, to re-start the ball's motion */
/* from that point.                                            */
/*                                                             */
void launchBall(void)
    {
    position = startPosition;
    velocity = startVelocity;
    }


void key(unsigned char k, int x, int y)
    {
    if (k == 27)
        exit(0);
    else if (k == ' ')
        launchBall();
    }



/*************** CODE OF INTEREST ******************************/
/* Compute the ball's new position & velocity.  dms::beginFrame*/
/* is called in order to use dms::deltaTime() for the time-step*/
/* value in the movement.                                      */
/*                                                             */
void idle(void)
    {
    dms::beginFrame();
    velocity += acceleration * dms::deltaTime();
    checkForBounce();
    position += velocity * dms::deltaTime();
    glutPostRedisplay();
    }


void checkForBounce(void)
    {
    if (position[0] > 20.0)
        {
        velocity[0] = -velocity[0];
        position[0] = 20.0 - (position[0] - 20.0);
        }
    if (position[0] < -20.0)
        {
        velocity[0] = -velocity[0];
        position[0] = -20.0 + (-20.0 - position[0]);
        }
    if (position[1] > 20.0)
        {
        velocity[1] = -velocity[1];
        position[1] = 20.0 - (position[1] - 20.0);
        }
    if (position[1] < -20.0)
        {
        velocity[1] = -velocity[1];
        position[1] = -20.0 + (-20.0 - position[1]);
        }
    }
