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;
}
![](https://img-my.csdn.net/uploads/201212/02/1354438047_2332.png)
三维
/*****************************************************************************
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;
}
![](https://img-my.csdn.net/uploads/201212/02/1354438079_6852.png)
参考:Sierpinski镂垫程序-http://www.codeforge.com/read/45707/Sierpinski%E9%95%82%E5%9E%AB%E7%A8%8B%E5%BA%8F.txt__html