#include <GL/glut.h>
#include <stdio.h> // for debugging
#include <stdlib.h>
int detail = 3; // How many levels of recursion?
float theta = .1; // Angle of rotation, which is constant for all shapes
int strangerotation = 0; // Washing machine rotation?
char red[] = {123, 150, 200, 90, 150, 70, 34, 200};
char green[] = {34, 25, 90, 172, 20, 10, 90, 125};
char blue[] = {123, 85, 200, 112, 90, 70, 134, 200};
float lightswitch[] = {1,1,1};
GLfloat light0_pos[] = {0, 0, 10, 1};
GLfloat light1_pos[] = {-10, -5, 5, 1};
GLfloat light2_pos[] = {-10, 0, 5, 0};
GLfloat light2_dir[] = {0,1,0};
GLfloat conesize[] = {85};
int rotate[] = {1,1,1,1,1,1,1,1};
void pyramid(float height, int levels) {
if (levels <= 0) return;
if (strangerotation) {
//Washing machine style
if (theta < 0) {theta = theta -.1;} else {theta = theta + .1;}
theta = -theta;
} else {
//Normal rotation
//Only updated once per frame
if (levels == detail) {if (theta > 360) {theta = 1;} else {theta++;}}
}
if (rotate[detail - levels]) {
//Washing machine again
if (strangerotation) {glRotatef(theta,0,0,1);} else {
//Normal
if (levels %2 > 0) {glRotatef(theta,0,0,1);} else {glRotatef(-theta,0,0,1);}
}
}
// glColor3ub(red[levels - 1], green[levels - 1], blue[levels - 1]); //Pallette colors
//The primary pyramid shape
glBegin(GL_POLYGON);
// glNormal3f(-5,0,0);
glColor3ub(red[8 - levels], green[8 - levels], blue[8 - levels]);
glVertex3f(0,0,0);
glColor3ub(red[levels - 1], green[levels - 1], blue[levels - 1]);
glVertex3f(-height,-height,height);
glColor3ub(red[8 - levels], green[8 - levels], blue[8 - levels]);
glVertex3f(-height,height,height);
glEnd();
glBegin(GL_POLYGON);
// glNormal3f(0,5,0);
glColor3ub(red[8 - levels], green[8 - levels], blue[8 - levels]);
glVertex3f(0,0,0);
glColor3ub(red[levels - 1], green[levels - 1], blue[levels - 1]);
glVertex3f(-height,height,height);
glColor3ub(red[8 - levels], green[8 - levels], blue[8 - levels]);
glVertex3f(height,height,height);
glEnd();
glBegin(GL_POLYGON);
// glNormal3f(5,0,0);
glColor3ub(red[8 - levels], green[8 - levels], blue[8 - levels]);
glVertex3f(0,0,0);
glColor3ub(red[levels - 1], green[levels - 1], blue[levels - 1]);
glVertex3f(height,height,height);
glColor3ub(red[8 - levels], green[8 - levels], blue[8 - levels]);
glVertex3f(height,-height,height);
glEnd();
glBegin(GL_POLYGON);
// glNormal3f(0,-5,0);
glColor3ub(red[8 - levels], green[8 - levels], blue[8 - levels]);
glVertex3f(0,0,0);
glColor3ub(red[levels - 1], green[levels - 1], blue[levels - 1]);
glVertex3f(height,-height,height);
glColor3ub(red[8 - levels], green[8 - levels], blue[8 - levels]);
glVertex3f(-height,-height,height);
glEnd();
glBegin(GL_POLYGON);
// glNormal3f(0,0,5);
glColor3ub(red[levels - 1], green[levels - 1], blue[levels - 1]);
glVertex3f(-height,-height,height);
glColor3ub(red[8 - levels], green[8 - levels], blue[8 - levels]);
glVertex3f(-height,height,height);
glColor3ub(red[levels - 1], green[levels - 1], blue[levels - 1]);
glVertex3f(height,height,height);
glColor3ub(red[8 - levels], green[8 - levels], blue[8 - levels]);
glVertex3f(height,-height,height);
glEnd();
//Now four more, half size, at the corners
glPushMatrix();glTranslatef(-height,-height,height);glRotatef(-90,0,1,0);glRotatef(45,1,0,0);
pyramid(height / 2, levels - 1);glPopMatrix();
glPushMatrix();glTranslatef(-height,height,height);glRotatef(-90,1,1,0);
pyramid(height / 2, levels - 1);glPopMatrix();
glPushMatrix();glTranslatef(height,height,height);glRotatef(90,0,1,0);glRotatef(-45,1,0,0);
pyramid(height / 2, levels - 1);glPopMatrix();
glPushMatrix();glTranslatef(height,-height,height);glRotatef(90,1,1,0);
pyramid(height / 2, levels - 1);glPopMatrix();
}
void display(void) {
float isize = 5;
glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glColor3ub(0x0,0x0,0xFF);
glTranslatef(light0_pos[0],light0_pos[1],light0_pos[2]);
glutWireSphere(1,5,5);
glPopMatrix();
glPushMatrix();
glColor3ub(0xFF,0x0,0x0);
glTranslatef(light1_pos[0],light1_pos[1],light1_pos[2]);
glutWireSphere(1,5,5);
glPopMatrix();
glPushMatrix();
glColor3ub(0x0,0xFF,0x0);
glTranslatef(light2_pos[0],light2_pos[1],light2_pos[2]);
glutWireSphere(1,5,5);
glPopMatrix();
glPushMatrix();
pyramid(isize,detail);
glPopMatrix();
glutSwapBuffers();
}
void idle(void) {
glutPostRedisplay();
}
void asckey(unsigned char keyid, int x, int y) {
switch (keyid) {
case '+':
if (detail < 8)
detail++;
break;
case '-':
if (detail > 0)
detail--;
break;
case '/': //Funny rotation?
if (strangerotation) { strangerotation = 0;
} else { strangerotation = 1;}
break;
case 'q': case 'Q': //Tilt
glRotatef(-10,0,1,0);
break;
case 'a': case 'A': //Tilt
glRotatef(10,0,1,0);
break;
case 'W': case 'w': //Zoom
glScalef(1.5,1.5,1.5);
break;
case 's': case 'S': //Zoom
glScalef(.5,.5,.5);
break;
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8':
if (rotate[atoi((const char *)&keyid) - 1]) { rotate[atoi((const char *)&keyid) - 1] = 0;
} else { rotate[atoi((const char *)&keyid) - 1] = 1;}
break;
case '.':
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
break;
case ',':
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
break;
case '>':
light0_pos[1]++;light0_pos[0]++;glLightfv(GL_LIGHT0, GL_POSITION, light0_pos);
break;
case '<':
light0_pos[1]--;light0_pos[0]--;glLightfv(GL_LIGHT0, GL_POSITION, light0_pos);
break;
case ';':
if (conesize[0] < 85)conesize[0]+=10;
glLightfv(GL_LIGHT1, GL_SPOT_CUTOFF, conesize);
break;
case 'l':
if (conesize[0] > 5)conesize[0]-=10;
glLightfv(GL_LIGHT1, GL_SPOT_CUTOFF, conesize);
break;
case '!':
if (lightswitch[0]) {lightswitch[0] = 0;glDisable(GL_LIGHT0);
} else {lightswitch[0] = 1;glEnable(GL_LIGHT0);}
break;
case '@':
if (lightswitch[1]) {lightswitch[1] = 0;glDisable(GL_LIGHT1);
} else {glEnable(GL_LIGHT1);lightswitch[1] = 1;}
break;
case '#':
if (lightswitch[2]) {lightswitch[2] = 0;glDisable(GL_LIGHT2);
} else {glEnable(GL_LIGHT2);lightswitch[2] = 1;}
break;
case ']': case '[':
light2_dir[1] = -light2_dir[1];glLightfv(GL_LIGHT2, GL_SPOT_DIRECTION, light2_dir);
break;
}
glutPostRedisplay();
}
void init(void) {
GLfloat light_specular[] = {1,1,1,1};
GLfloat light_diffuse[] = {.5,.5,.5,1};
GLfloat mat_shininess[] = {100};
GLfloat light_emission[] = {0,0,0,1};
GLfloat light_ambient[] = {1,1,1,1};
GLfloat light_ambient_low[] = {.1,.1,.1,1};
GLfloat light_ambient_half[] = {.2,.2,.17,1};
GLfloat indexes[] = {1,0,1};
GLfloat light1_dir[] = {0,-1,0};
GLfloat conesize2[] = {90};
glClearColor(0,0,0,0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluPerspective(30, 1.2, .1, 10000);
gluLookAt(50,0,-5,0,0,10,0,0,1);
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
// glEnable(GL_DEPTH_TEST);
glLightModelf(GL_LIGHT_MODEL_TWO_SIDE,1);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0); // We'll use this as a point light
glEnable(GL_LIGHT1); // This will be a spotlight
glEnable(GL_LIGHT2); // Distant light
//glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_emission);
//glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
//glMaterialfv(GL_FRONT_AND_BACK, GL_COLOR_INDEXES, indexes);
glLightfv(GL_LIGHT0, GL_POSITION, light0_pos);
glLightfv(GL_LIGHT1, GL_POSITION, light1_pos);
glLightfv(GL_LIGHT2, GL_POSITION, light2_pos);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.3);
glPushMatrix();
glRotatef(90,0,0,1);
glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, light1_dir);
glLightfv(GL_LIGHT1, GL_SPOT_CUTOFF, conesize);
glPopMatrix();
glLightfv(GL_LIGHT2, GL_AMBIENT, light_ambient_low);
glLightfv(GL_LIGHT2, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT2, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT2, GL_SPOT_DIRECTION, light2_dir);
glLightfv(GL_LIGHT2, GL_SPOT_CUTOFF, conesize2);
// glEnable(GL_AUTO_NORMAL);
glEnable(GL_NORMALIZE); //Do I need this?
//
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
glEnable(GL_BLEND);
//
glShadeModel(GL_SMOOTH);
//This should cause setting of the color to change material properties.
glColorMaterial(GL_FRONT_AND_BACK,/*GL_EMISSION*/GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB /*| GLUT_DEPTH*/);
glutInitWindowSize(250,250);
glutInitWindowPosition(100,100);
glutCreateWindow("Junk");
init();
glutIdleFunc(idle);
glutDisplayFunc(display);
glutKeyboardFunc(asckey);
glutMainLoop();
return 0;
}