Byteorder.net: How's my driving?

Got something to say? I'd love to hear from you, but I'm afraid that if I publish my email address on a web page these days, people will write me lots of mail about how I can "increase my manhood" or purchase inexpensive V1@gra. So instead let's try this. Just put your message in, give your return address, and if you're not trying to sell me questionable goods, I'll do my best answer you. Trust me; it's so simple, even a former Nigerian general with lots of regretably inaccessible cash could do it.

My email address is
 and I'd like to say:

#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;
}