#include float r, g, b; /* this is the depth (the steps of recursion) * the variable is set through the first param of the * command line. */ int i=0; /* the init function initializes all of the tools * used to draw (color, the background color), * as well as setting the modes for the renderer */ void myinit(void) { glClearColor(1.0, 1.0, 1.0, 0.0); glColor3f(0.0, 0.0, 1.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, 1280.0, 0.0, 1024.0); glMatrixMode(GL_MODELVIEW); } /* main display function; * this function will call the recursive point * generator for the koch snowflake, named * "snowflake()" snowflake will do all of the * drawing, and eat up a tremendous ammount * of memory by saving each of its recursive steps */ int snowflake(int iterations, int level, GLfloat Xx, GLfloat Xy, GLfloat Yx, GLfloat Yy) { /* the snowflake function takes 6 variables; iterations and level are to keep track * of which recursive step we are in and lets us stop the loop. * the rest of the 4 varibles are GLfloat coordinates for 2 points that (previously) * make up the line we are performing the koch snowflake iteration on. */ GLfloat Ax; GLfloat Ay; GLfloat Bx; GLfloat By; GLfloat Cx; GLfloat Cy; double change_in_x = (Yx - Xx)/3.0; double change_in_y = (Yy - Xy)/3.0; /* declared 3 "points" vertex by vertex, and two double variables that * describe the change in x and the change in Y between the two points. * these values are useful in order to calculate where the two points we * need to create on the line are */ Ax = Xx + change_in_x; Ay = Xy + change_in_y; Bx = Xx + change_in_x*2; By = Xy + change_in_y*2; /* in my experience, rather than having the 2nd point "b" subtracted from the * second (higher) initial point "Y", its safer to multiply it. */ Cx = Ax + change_in_x/2 - 0.866025 * change_in_y; Cy = Ay + change_in_y/2 + 0.866025 * change_in_x; /* finding the point C off the triangle was the difficult part of the assignment * it involved the most mathematical thought and created the most pain. * basically, setting the coordinates to the value of B rotated around A 60 degrees * (I built in the values because the precision was enough.. 1/2 for cos(60) and .8... * for sqrt(3)/2 or sin(60)... having the code perform the square root of 3 1 million * times just seemed stupid when I could substitute 6 digit accurate numbers */ if(iterations == level) { /* if the iteration is == to the level, then the end of the * line has come, and its time to draw. I threw in a simple color * modification scheme with 3 global floats to make things interesting; * what they do is pretty self explanatory */ if(r < .99) { r+=.01; } else r=0.0; if(g < .98) { g+=.02; } else g=0.0; if(b < .97) { b+=.03; } else b=0.0; glColor3f(r, g, b); glBegin(GL_LINES); glVertex2f(Xx, Xy); glVertex2f(Yx, Yy); glEnd(); } /* if we aren't done, we run snowflake on each "line segment" that we created * by generating the 4 points; X to A, X to C, C to B, and B to X */ else { snowflake(iterations, level+1, Xx, Xy, Ax, Ay); snowflake(iterations, level+1, Ax, Ay, Cx, Cy); snowflake(iterations, level+1, Cx, Cy, Bx, By); snowflake(iterations, level+1, Bx, By, Yx, Yy); } return 0; } void display () { // snowflake takes 2 points as 4 seperate variables // as arguments, and a level and depth "variable" // these variables make up the triangle GLfloat Xx = 200.0; GLfloat Xy = 300.0; GLfloat Yx = 600.0; GLfloat Yy = 986.8; GLfloat Zx = 1000.0; GLfloat Zy = 300.0; /* these coordinates were a pain to get, and the innacuracy of them caused * the program to seemingly "not work" for a good while */ glClear(GL_COLOR_BUFFER_BIT); /* run snowflake on all 3 line segments; X to Y, Y to Z, and Z back to X. */ snowflake(i, 0, Xx, Xy, Yx, Yy); snowflake(i, 0, Yx, Yy, Zx, Zy); snowflake(i, 0, Zx, Zy, Xx, Xy); /* at this point our raster has been filled and we can * put it on the screen */ glFlush(); } int main(int argc, char ** argv) { /* this simple line lets me control the number of iterations from the command line * it defaults to 0 */ if(argc > 1) i=atoi(argv[1]); /* all of the glut window initializations */ glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(800, 600); glutInitWindowPosition(0,0); glutCreateWindow("Koch's Multicolored Snowflake"); glutDisplayFunc(display); myinit(); glutMainLoop(); return 0; }