/*****************************************************************
  bubble.cpp
  by Dave Pape
  4 March 2003

 This program demonstrates a random walk.
 Bubbles (several spheres) drift upward across the window, with
 randomly perturbed motion.

*****************************************************************/
#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);

#define RANDOM_MOTION_SCALE 1

/*************** CODE OF INTEREST ******************************/
/* Positions & velocities of each of the bubbles.              */
/*                                                             */
#define NUM_BALLS 10
dms::Vector3 position[NUM_BALLS];
dms::Vector3 velocity[NUM_BALLS];

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(argv[0]);
    glutDisplayFunc(drawEverything);
    glutKeyboardFunc(key);
    glutIdleFunc(idle);
    glLineWidth(2);
    for (int i=0; i < NUM_BALLS; i++)
        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);
    for (int i=0; i < NUM_BALLS; i++)
        {
        glPushMatrix();
        glTranslatef(position[i][0], position[i][1], position[i][2]);
        ball.draw();
        glPopMatrix();
        }

    glutSwapBuffers();
    }


void launchBall(void)
    {
    static int nextBall = 0;
    position[nextBall].set(drand48()*40.0 - 20.0,-20,0);
    velocity[nextBall].set(0, 5, 0);
    nextBall = (nextBall+1) % NUM_BALLS;
    }


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


/*************** CODE OF INTEREST ******************************/
/* This function returns a random Vector3, with the X & Y      */
/* values ranging from -1 to 1.                                */
/*                                                             */
dms::Vector3 randomVector(void)
    {
    return dms::Vector3(drand48()*2.0 - 1.0, drand48()*2.0 - 1.0, 0.0);
    }


void idle(void)
    {
    static float lastLaunch = 0;
    dms::beginFrame();
    if (dms::currentTime() - lastLaunch > 1.0)
        {
        launchBall();
        lastLaunch = dms::currentTime();
        }
/*************** CODE OF INTEREST ******************************/
/* Randomly perturb the velocity of the bubbles, by adding a   */
/* random vector to each one.  The amount of variation can be  */
/* adjusted by changing the RANDOM_MOTION_SCALE constant.      */
/*                                                             */
    for (int i=0; i < NUM_BALLS; i++)
        velocity[i] += randomVector() * RANDOM_MOTION_SCALE;
    for (int i=0; i < NUM_BALLS; i++)
        position[i] += velocity[i] * dms::deltaTime();
    glutPostRedisplay();
    }
