
#include <GL/gl.h>
#include <GL/glut.h>
#include <cmath>

using std::cos;
using std::sin;

#define SCALE_MIN 0.1f
#define SCALE_MAX 10.0f
#define SCALE_MOD 1.1f
#define NUM_STEPS 32
#define PI          3.141592654f

char color = 'r';
char howtodraw = 'l';
float scale = 1.0f;
float colorVal = 0.5f;

int button = 0;
int xprev = 0;
int yprev = 0;

void display()
{
    glClear(GL_COLOR_BUFFER_BIT);

    glLoadIdentity();

    switch(color)
    {
        case 'r':
            glColor3f(colorVal, 0.0f, 0.0f);
            break;

        case 'b':
            glColor3f(0.0f, 0.0f, colorVal);
            break;

        case 'g':
            glColor3f(0.0f, colorVal, 0.0f);
            break;
    }

    switch(howtodraw)
    {
        case 'l':
            glBegin(GL_LINE_STRIP);
            break;

        case 'p':
            glBegin(GL_TRIANGLE_FAN);
            glVertex3f(0.0f, 0.0f, 0.0f);
            break;
    }

    for(int i = 0; i <= NUM_STEPS; ++i)
    {
        float a = 2*i*PI/NUM_STEPS;
        float x = scale*cos(a);
        float y = scale*sin(a);

        glVertex3f(x, y, 0.0f);
    }

    glEnd();

    glutSwapBuffers();
}

void reshape(int x, int y)
{
    glViewport(0, 0, x, y);
}

void keyboard(unsigned char key, int x, int y)
{
    switch(key)
    {
        case 'c':
        case 'C':
            if(color == 'r')        color = 'g';
            else if(color == 'g')    color = 'b';
            else                    color = 'r';

            break;

        case 'r':
        case 'R':
            if(howtodraw == 'l')    howtodraw = 'p';
            else                    howtodraw = 'l';

            break;
    }

    glutPostRedisplay();
}

void mouse(int b, int state, int x, int y)
{
    if(state == GLUT_DOWN)
    {
        button = b;
           xprev = x;
        yprev = y;
    }
    else
    {
        button = 0;
    }
}

void mouseMotion(int x, int y)
{
    int d = x - xprev;

    if(button == GLUT_LEFT_BUTTON)
    {
        if(d > 0)
        {
            scale *= pow(SCALE_MOD, d);
        }
        else
        {
            scale /= pow(SCALE_MOD, -d);
        }

        if(scale < SCALE_MIN)    scale = SCALE_MIN;
        if(scale > SCALE_MAX)    scale = SCALE_MAX;
    }

    if(button == GLUT_RIGHT_BUTTON)
    {
        if(d > 0)
        {
            colorVal += 0.02f;
        }
        else
        {
            colorVal -= 0.02f;
        }

        if(colorVal > 1.0f)    colorVal = 1.0f;
        if(colorVal < 0.0f) colorVal = 0.0f;
    }

    xprev = x;
    yprev = y;

    glutPostRedisplay();
}

void initGL()
{
    glClearColor(0.0, 0.0, 0.0, 0.0);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-10.0, 10.0, -10.0, 10.0, -1.0, 1.0);

    glMatrixMode(GL_MODELVIEW);
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);

    glutInitWindowPosition(200, 200);
    glutInitWindowSize(500, 500);

    int win = glutCreateWindow("OpenGL demo");

    initGL();

    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(keyboard);
    glutMouseFunc(mouse);
    glutMotionFunc(mouseMotion);

    glutMainLoop();

    return 0;
}

