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

 An example of moving an object with a velocity vector.
 A ball moves in the direction pointed by 'velocity', with speed
 equal to the length of the vector.
 The velocity vector can be changed using the mouse - when any
 button is pressed, a new velocity vector is calculated which is
 proportional to the X/Y position of the mouse in the window.
 This program operates in 2 dimensions for simplicity.
 
*****************************************************************/
#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 mousebutton(int button, int state, int x, int y);
void mousemotion(int x, int y);
void idle(void);
void launchBall(void);


/*************** CODE OF INTEREST ******************************/
/* Variables needed to compute the ball's motion - its starting*/
/* position, velocity, and the time that the motion started.   */
/*                                                             */
dms::Vector3 startPosition(0, 0, 0);
dms::Vector3 velocity;
float startTime = 0;

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);
    glutMouseFunc(mousebutton);
    glutMotionFunc(mousemotion);
    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();
    
/*************** CODE OF INTEREST ******************************/
/* Draw the velocity vector, to compare it with the motion.    */
/*                                                             */
    glColor3f(1, 1, 1);
    velocity.drawLine();
    
/*************** CODE OF INTEREST ******************************/
/* Compute the ball's current position, and draw it there.     */
/* The amount of time that the ball has been moving is equal to*/
/* the current time minus the time that it started.            */
/*                                                             */
    float t = dms::currentTime() - startTime;
    dms::Vector3 position = startPosition + velocity * t;
    glColor3f(1.0, 0.9, 0.0);
    glTranslatef(position[0], position[1], position[2]);
    ball.draw();

    glutSwapBuffers();
    }


/*************** CODE OF INTEREST ******************************/
/* launchBall() saves the current time, so that the ball will  */
/* start moving from the origin again, at the time this is     */
/* called.                                                     */
/*                                                             */
void launchBall(void)
    {
    startTime = dms::currentTime();
    }


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



/*************** CODE OF INTEREST ******************************/
/* mousebutton() & mousemotion() set the velocity vector's X & */
/* Y components from the X & Y position of the mouse in the    */
/* window.                                                     */
/*                                                             */
void mousebutton(int button, int state, int x, int y)
    {
    velocity[0] = ((float)x / glutGet(GLUT_WINDOW_WIDTH) - 0.5) * 10.0;
    velocity[1] = -((float)y / glutGet(GLUT_WINDOW_HEIGHT) - 0.5) * 10.0;
    }


void mousemotion(int x, int y)
    {
    velocity[0] = ((float)x / glutGet(GLUT_WINDOW_WIDTH) - 0.5) * 10.0;
    velocity[1] = -((float)y / glutGet(GLUT_WINDOW_HEIGHT) - 0.5) * 10.0;
    }


void idle(void)
    {
    glutPostRedisplay();
    }
