/*
 *  prime number generation based on perspective projection
 *  Shingo W. Kagami <swk(at)kagami.org>
 *  2006/06/27
 */

#include <GL/glut.h>
#include <math.h>
#include <stdlib.h>

#define PI 3.141592

double th, dth;

void
draw_stripes(int k)
{
    int i;

    glPushMatrix();
    glTranslated(0, 500.0 / k + (10 - k) / 2.0 / (double)k, 1000.0 / k);
    for (i = 0; i < 50; i++) {
	glTranslated(0, -10, 0);
	glBegin(GL_QUADS);
	glVertex3d(-20, -9, 0);
	glVertex3d(20, -9, 0);
	glVertex3d(20, -10, 0);
	glVertex3d(-20, -10, 0);
	glEnd();
    }    
    glPopMatrix();
}

void
draw_numbers()
{
    int i;

    glColor3d(0, 1, 0);
    for (i = 2; i <= 100; i++) {
	glPushMatrix();
	glTranslated(14, -10 * i, 0);
	glScaled(-0.08, 0.08, 0.08);
	glutStrokeCharacter(GLUT_STROKE_MONO_ROMAN, " 1"[i / 100]);
	glutStrokeCharacter(GLUT_STROKE_MONO_ROMAN, " 1234567890"[i / 10]);
	glutStrokeCharacter(GLUT_STROKE_MONO_ROMAN, "0123456789"[i % 10]);
	glPopMatrix();
    }

}

void
display()
{
    static double cx, cy, cz;
    int k;
    
    cx = (6 * th) * cos(2 * PI * (th - 90) / 360.0);
    cy = th;
    cz = (6 * th) * sin(2 * PI * (th - 90) / 360.0);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    gluLookAt(cx, cy, cz, 0, 0, 250, 0, 1, 0);

    glColor3d(1, 0, 0);
    for (k = 2; k <= 10; k++) {
	draw_stripes(k);
    }

    glPushMatrix();
    glTranslated(0, 500, 1000);
    draw_numbers();
    glPopMatrix();

    glutSwapBuffers();

    th = (th <= 0.0)? 0.0: (th - dth);
}

void
idle()
{
    glutPostRedisplay();
}

void
resize(int w, int h)
{
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(55, (double)w / h, 1, 5000);

    glMatrixMode(GL_MODELVIEW);
}

void
keyboard(unsigned char key, int x, int y)
{
    static int run = 0;
    
    if (run) {
	exit(0);
    } else {
	glutIdleFunc(idle);
	run = 1;
    }
}

int
main(int argc, char *argv[])
{
    int wsize;
    wsize = (argc >= 2)? atoi(argv[1]): 512;
    dth = (argc >= 3)? atof(argv[2]): 0.3;
    th = (argc >= 4)? atof(argv[3]): 270.0;
    
    glutInitWindowSize(wsize, wsize);
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutCreateWindow(argv[0]);
    glutDisplayFunc(display);
    glutReshapeFunc(resize);
    glutKeyboardFunc(keyboard);
    glutIdleFunc(NULL);
    glClearColor(0, 0, 0.2, 1.0);
    glEnable(GL_DEPTH_TEST);

    glutMainLoop();
    
    return 0;
}
