Sierpinski镂垫是一个非常有趣的图案, 有着悠久的历史, 在分形几何中等领域里引起了人们极大地兴趣, 是用递归和随机方式定义的几何形状, 在极限情况下, 它所表现的性质并没有随机性.
生成算法如下:
(1)在三角形内部随机选取一个点作为初始点
(2)在三角形的3个顶点中随机选取一个,求出该顶点与初始点连线的中点,画出该中点
(3)将(2)中的中点作为初始点,转到(2)

下面利用SDL+OpenGL分别在二维和三维中来实现。


二维

/***************************************************************************** Copyright: 2012, ustc All rights reserved. contact:k283228391@126.com File name: main.c Description:Sierpinski 2d. Author:Silang Quan Version: 1.0 Date: 2012.12.02 *****************************************************************************/ #include <SDL/SDL.h> #include <GL/gl.h> #include <GL/glu.h> #include <stdio.h> #include <stdlib.h> SDL_Surface *screen; void quit( int code ) {     SDL_Quit( );     /* Exit program. */     exit( code ); } void handleKeyEvent( SDL_keysym* keysym ) {     switch( keysym->sym ) 	{     case SDLK_ESCAPE:         quit( 0 );         break;     case SDLK_SPACE:         break;     default:         break;     } } void resizeGL(int width,int height) {     if ( height == 0 )       {           height = 1;       }       //Reset View      glViewport( 0, 0, (GLint)width, (GLint)height );       //Choose the Matrix mode      glMatrixMode( GL_PROJECTION );       //reset projection     glLoadIdentity();       //set perspection      gluPerspective( 45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0 );       //choose Matrix mode     glMatrixMode( GL_MODELVIEW );       glLoadIdentity();   } void handleEvents() {     // Our SDL event placeholder.      SDL_Event event;     //Grab all the events off the queue.      while( SDL_PollEvent( &event ) ) {         switch( event.type ) {         case SDL_KEYDOWN:             // Handle key Event             handleKeyEvent( &event.key.keysym );             break;         case SDL_QUIT:             // Handle quit requests (like Ctrl-c).              quit( 0 );             break;         case SDL_VIDEORESIZE: 			//Handle resize event             screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 16,                                       SDL_OPENGL|SDL_RESIZABLE);             if ( screen )              {                 resizeGL(screen->w, screen->h);             }             break;         }     } }  void initSDL(int width,int height,int bpp,int flags) {     // First, initialize SDL's video subsystem.      if( SDL_Init( SDL_INIT_VIDEO ) < 0 )      {         fprintf( stderr, "Video initialization failed: %s\n",                  SDL_GetError( ) );         quit( 1 );     }     atexit(SDL_Quit); 	//Set some Attribute of OpenGL in SDL     SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );     SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );     SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );     SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );     SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );          //Set the video mode       screen= SDL_SetVideoMode( width, height, bpp,flags);     if(!screen )      {         fprintf( stderr, "Video mode set failed: %s\n",SDL_GetError( ) );         quit( 1 );     }     resizeGL(screen->w, screen->h);     //Set caption     SDL_WM_SetCaption( "Sierpinski 2D", NULL );  } void renderGL() {     // Clear the color and depth buffers.      glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );     // We don't want to modify the projection matrix. */     glMatrixMode( GL_MODELVIEW );     glLoadIdentity( );     // Move down the z-axis.      glTranslatef( -20.0, -20.0, -60.0 ); 	//Draw a square      /* A triangle */       GLfloat vertices[3][2]={{0.0,0.0},{25.0,50.0},{50.0,0.0}};          int i, j, k;       srand(10);        /* standard random number generator */       GLfloat p[2] ={7.5,5.0};  /* an arbitrary initial point inside                                traingle */       glClear(GL_COLOR_BUFFER_BIT);  /* clear the window */       glBegin(GL_POINTS);       /* compute and plots 5000 new points */       for( k=0; k<500000; k++)       {           j=rand()%3; /* pick a vertex at random */           /* Compute point halfway between selected vertex and old point */           p[0] = (p[0]+vertices[j][0])/2.0;           p[1] = (p[1]+vertices[j][1])/2.0;           /* plot new point */           glVertex2fv(p);       }       glEnd();      SDL_GL_SwapBuffers( ); } void initGL( int width, int height ) {     float ratio = (float) width / (float) height;     // Our shading model--Gouraud (smooth).      glShadeModel( GL_SMOOTH );     // Set the clear color.      glClearColor( 0, 0, 0, 0 );     // Setup our viewport.      glViewport( 0, 0, width, height );     //Change to the projection matrix and set our viewing volume.     glMatrixMode( GL_PROJECTION );     glLoadIdentity();     gluPerspective( 60.0, ratio, 1.0, 100.0 ); } int main( int argc, char* argv[] ) {          // Dimensions of our window.         int width = 640;     int height = 480;     // Color depth in bits of our window.      int bpp = 32;     int flags= SDL_OPENGL|SDL_RESIZABLE;     //Set the SDL     initSDL(width, height, bpp,flags);     //Set the OpenGL     initGL( width, height );          //main loop     while(true)  	{         /* Process incoming events. */         handleEvents( );         /* Draw the screen. */         renderGL( );     }     return 0; }



三维

/***************************************************************************** Copyright: 2012, ustc All rights reserved. contact:k283228391@126.com File name: main3D.c Description:Sierpinski 3D. Author:Silang Quan Version: 1.0 Date: 2012.12.02 *****************************************************************************/ #include <SDL/SDL.h> #include <GL/gl.h> #include <GL/glu.h> #include <stdio.h> #include <stdlib.h> SDL_Surface *screen; GLfloat colors[4][3]={{1.0,0.0,0.0},{0.0,1.0,0.0},{0.0,0.0,1.0},{0.0,1.0,1.0}}; void quit( int code ) {     SDL_Quit( );     /* Exit program. */     exit( code ); } void handleKeyEvent( SDL_keysym* keysym ) {     switch( keysym->sym ) 	{     case SDLK_ESCAPE:         quit( 0 );         break;     case SDLK_SPACE:         break;     default:         break;     } } void resizeGL(int width,int height) {     if ( height == 0 )       {           height = 1;       }       //Reset View      glViewport( 0, 0, (GLint)width, (GLint)height );       //Choose the Matrix mode      glMatrixMode( GL_PROJECTION );       //reset projection     glLoadIdentity();       //set perspection      gluPerspective( 45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0 );       //choose Matrix mode     glMatrixMode( GL_MODELVIEW );       glLoadIdentity();   } void handleEvents() {     // Our SDL event placeholder.      SDL_Event event;     //Grab all the events off the queue.      while( SDL_PollEvent( &event ) ) {         switch( event.type ) {         case SDL_KEYDOWN:             // Handle key Event             handleKeyEvent( &event.key.keysym );             break;         case SDL_QUIT:             // Handle quit requests (like Ctrl-c).              quit( 0 );             break;         case SDL_VIDEORESIZE: 			//Handle resize event             screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 16,                                       SDL_OPENGL|SDL_RESIZABLE);             if ( screen )              {                 resizeGL(screen->w, screen->h);             }             break;         }     } }  void initSDL(int width,int height,int bpp,int flags) {     // First, initialize SDL's video subsystem.      if( SDL_Init( SDL_INIT_VIDEO ) < 0 )      {         fprintf( stderr, "Video initialization failed: %s\n",                  SDL_GetError( ) );         quit( 1 );     }     atexit(SDL_Quit); 	//Set some Attribute of OpenGL in SDL     SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );     SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );     SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );     SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );     SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );          //Set the video mode       screen= SDL_SetVideoMode( width, height, bpp,flags);     if(!screen )      {         fprintf( stderr, "Video mode set failed: %s\n",SDL_GetError( ) );         quit( 1 );     }     resizeGL(screen->w, screen->h);     //Set caption     SDL_WM_SetCaption( "Sierpinski 3D", NULL );  }  void triangle( GLfloat *va, GLfloat *vb, GLfloat *vc) {        glVertex3fv(va);        glVertex3fv(vb);        glVertex3fv(vc); }  void tetra(GLfloat *a, GLfloat *b, GLfloat *c, GLfloat *d) {        glColor3fv(colors[0]);       triangle(a,b,c);       glColor3fv(colors[1]);      triangle(a,c,d);       glColor3fv(colors[2]);       triangle(a,d,b);       glColor3fv(colors[3]);       triangle(b,d,c); }  void divide_tetra(GLfloat *a, GLfloat *b, GLfloat *c, GLfloat *d, int m) {     GLfloat mid[6][3];     int j;     if(m>0)        {                        /* compute six midpoints */         for(j=0; j<3; j++) mid[0][j]=(a[j]+b[j])/2;         for(j=0; j<3; j++) mid[1][j]=(a[j]+c[j])/2;         for(j=0; j<3; j++) mid[2][j]=(a[j]+d[j])/2;         for(j=0; j<3; j++) mid[3][j]=(b[j]+c[j])/2;         for(j=0; j<3; j++) mid[4][j]=(c[j]+d[j])/2;         for(j=0; j<3; j++) mid[5][j]=(b[j]+d[j])/2;                /* create 4 tetrahedrons  by subdivision */         divide_tetra(a,mid[0],mid[1],mid[2], m-1);         divide_tetra(mid[0],b,mid[3],mid[5], m-1);         divide_tetra(mid[1],mid[3],c,mid[4], m-1);         divide_tetra(mid[2],mid[4],d,mid[5], m-1);      }     else     tetra(a,b,c,d); /* draw tetrahedron at end of recursion */ }  void renderGL() {     //Define a triangle in space     GLfloat v[4][3]={{0.0, 0.0, 1.0},{0.0, 0.942809, -0.33333},{-0.816497, -0.471405, -0.333333},{0.816497, -0.471405, -0.333333}};      // Clear the color and depth buffers.      glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );     // We don't want to modify the projection matrix. */     glMatrixMode( GL_MODELVIEW );     glLoadIdentity( );     // Move down the z-axis.      glTranslatef( 0.0, 0.0, -2.0 );     glRotatef(50,0,1,0);     glRotatef(30,1,0,0);      glClear(GL_COLOR_BUFFER_BIT);  /* clear the window */       glBegin(GL_TRIANGLES);           divide_tetra(v[0],v[1],v[2],v[3],3);     glEnd();     SDL_GL_SwapBuffers( ); } void initGL( int width, int height ) {     float ratio = (float) width / (float) height;     // Our shading model--Gouraud (smooth).      glShadeModel( GL_SMOOTH );     // Set the clear color.      glClearColor( 0, 0, 0, 0 );     // Setup our viewport.      glViewport( 0, 0, width, height );     //Change to the projection matrix and set our viewing volume.     glMatrixMode( GL_PROJECTION );     glLoadIdentity();     gluPerspective( 60.0, ratio, 1.0, 100.0 ); } int main( int argc, char* argv[] ) {          // Dimensions of our window.         int width = 640;     int height = 480;     // Color depth in bits of our window.      int bpp = 32;     int flags= SDL_OPENGL|SDL_RESIZABLE;     //Set the SDL     initSDL(width, height, bpp,flags);     //Set the OpenGL     initGL( width, height );               //main loop     while(true)  	{         /* Process incoming events. */         handleEvents( );         /* Draw the screen. */         renderGL( );     }     return 0; }



参考:Sierpinski镂垫程序-http://www.codeforge.com/read/45707/Sierpinski%E9%95%82%E5%9E%AB%E7%A8%8B%E5%BA%8F.txt__html