#include <GL/glut.h>

#define DEPTH 5

void myInit () {

	glClearColor (1.0, 1.0, 1.0, 1.0);
	glEnable (GL_DEPTH_TEST);
	
	glMatrixMode (GL_PROJECTION);
	glLoadIdentity();
	glOrtho (-6.0, 6.0, -6.0, 6.0, -6.0, 6.0);
	glMatrixMode (GL_MODELVIEW);
}
void sierpinski (GLfloat p1[], GLfloat p2[], GLfloat p3[], GLfloat p4[], int depth) {

	int i;
	GLfloat mid1[3], mid2[3], mid3[3];
	
	if (depth == DEPTH) {
	/* draw triangles */
		glBegin (GL_TRIANGLES);
			glColor3f (1.0, 0.0, 0.0);
			glVertex3fv (p1);
			glVertex3fv (p2);
			glVertex3fv (p3);
			glColor3f (0.0, 1.0, 0.0);
			glVertex3fv (p1);
			glVertex3fv (p2);
			glVertex3fv (p4);
			glColor3f (0.0, 0.0, 1.0);
			glVertex3fv (p1);
			glVertex3fv (p3);
			glVertex3fv (p4);
			glColor3f (0.0, 0.0, 0.0);
			glVertex3fv (p4);
			glVertex3fv (p2);
			glVertex3fv (p3);

		glEnd();
		return;
	}
	else {
	
		/* draw four sub-tetrahedrons */
		for (i = 0; i < 3; i++) {
			mid1[i] = (p1[i]+p2[i])/2.0;
			mid2[i] = (p2[i]+p3[i])/2.0;
			mid3[i] = (p2[i]+p4[i])/2.0;
		}
		sierpinski (p2, mid1, mid2, mid3, depth+1);
		
		for (i = 0; i < 3; i++) {
			mid1[i] = (p1[i]+p2[i])/2.0;
			mid2[i] = (p1[i]+p3[i])/2.0;
			mid3[i] = (p1[i]+p4[i])/2.0;
		}
		sierpinski (p1, mid1, mid2, mid3, depth+1);	
		
		for (i = 0; i < 3; i++) {
			mid1[i] = (p3[i]+p2[i])/2.0;
			mid2[i] = (p4[i]+p3[i])/2.0;
			mid3[i] = (p3[i]+p1[i])/2.0;
		}
		sierpinski (p3, mid1, mid2, mid3, depth+1);
		
		for (i = 0; i < 3; i++) {
			mid1[i] = (p1[i]+p4[i])/2.0;
			mid2[i] = (p4[i]+p3[i])/2.0;
			mid3[i] = (p2[i]+p4[i])/2.0;
		}
		sierpinski (p4, mid1, mid2, mid3, depth+1);
	}
}
			
void display() {
	
	GLfloat tetra[4][3] = {{0.0, 0.0, 5.0}, {-5.0, 5.0, 0.0}, {5.0, 5.0, 0.0}, {0.0, -5.0, 0.0}};
	glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	sierpinski (tetra[0], tetra[1], tetra[2], tetra[3], 1);
	glFlush();
}

int main (int argc, char *argv[]) {

	glutInit (&argc, argv);
	glutInitDisplayMode (GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
	glutInitWindowPosition (0, 0);
	glutInitWindowSize (400, 400);
	glutCreateWindow ("Sierpinski3D");
	glutDisplayFunc (display);
	myInit();
	glutMainLoop();
	
	return 0;
}




