/* sierpinski.c */ /* Purpose: Demonstrate sierpinski gasket generation by recursion in the simplest possible manner. This code does _not_ implement efficiency measures such as display lists, vertex arrays, etc so as to clearly demonstrate the recursive fractal generation. */ #ifdef __APPLE__ #include #else #include #endif #include #define KEY_ESC 27 /* glut doesn't define this one for some reason */ /* Generate the sierpinski gasket by subdividing a given triangle into subtriangles. Then recursively do the same to the subtriangles. When we have finished recursing then draw a tiny little solid triangle. */ void generateGasket( float* p1, float* p2, float* p3, int level ) { if( 0 == level ) { glVertex2fv( p1 ); glVertex2fv( p2 ); glVertex2fv( p3 ); } else { /* Figure out the midpoints between the given points */ float midp1p2[2]; float midp2p3[2]; float midp1p3[2]; midp1p2[0] = ( p1[0] + p2[0] ) * 0.5; midp1p2[1] = ( p1[1] + p2[1] ) * 0.5; midp2p3[0] = ( p2[0] + p3[0] ) * 0.5; midp2p3[1] = ( p2[1] + p3[1] ) * 0.5; midp1p3[0] = ( p1[0] + p3[0] ) * 0.5; midp1p3[1] = ( p1[1] + p3[1] ) * 0.5; /* Now generate the subtriangles. Remember to leave out the middle subtriangles. */ generateGasket( p1, midp1p2, midp1p3, level - 1 ); generateGasket( midp1p2, p2, midp2p3, level - 1 ); generateGasket( midp1p3, midp2p3, p3, level - 1 ); } } void display( void ) { /* Select an initial triangle that fills the default orthographic projection */ float p1[2] = { -1.0 , -1.0 }; float p2[2] = { 1.0 , -1.0 }; float p3[2] = { 0.0 , 1.0 }; glClear( GL_COLOR_BUFFER_BIT ); glBegin( GL_TRIANGLES ); /* Now subdivide the triangle and make the sierpinski gasket */ generateGasket( p1, p2, p3, 8 ); glEnd(); glFlush(); } void keyboard( unsigned char key, int x, int y) { switch (key) { case KEY_ESC: /* exit when escape key is pressed */ exit(0); break; } } int main( int argc, char *argv[] ) { glutInit( &argc, argv ); glutCreateWindow( argv[0] ); glutDisplayFunc( display ); glutKeyboardFunc( keyboard ); glutMainLoop(); return 0; }