可健康了 发表于 2012-12-30 11:51:14

OpenGL画三维分形

<div id="cnblogs_post_body">
http://pic002.cnblogs.com/images/2012/423745/2012070916015811.jpg

前言(可以直接略过):  
  最近paper写完了,空闲时间比较多,于是开始画分形几何来玩。在我的上一篇文章中,Julia集和Mandelbrot集已经画过了,这回我想画一点更有意思的东西,想来想去,最终我决定画一个三维的分形图案,于是到M67的网站去抠了一张图,打算自己把它画出来。最初困扰我的是用什么工具来画它,分形图案都有大量的递归,计算量极大,像matlab和mathematica这样的工具封装太厉害,肯定是不行,速度比较快的也就只有openGL了。为了画这个图形,我花了两天时间来学openGL,总算能把它的粗略样子画出来了,小有成就~~

正文:
  左图是实物的照片。它的生成法则是这样的:在一个正方体的6个面上分别生成一个长宽是原来正方体一半的小正方体。迭代了11次就是左图的样子了,其中红色正方体是最原始的正方体。这个图形无限迭代下去会形成一个四棱锥,它的每一面恰好是一个Sierpinski三角形。
  右图是我用openGL画的,迭代了7次,在我的电脑上5秒左右可以画出来。

--------------------华丽的分割线----------------------------------------------------------------------------------------

<div class="cnblogs_code">#include <GL/glut.h>#define MAXCOLOR 7float colortab[4]={    0.2,      0,            0.4,    0.0,    //紫    0.2,      0,            0.5,    0.0,    //紫    0.2,      0,            0.6,    0.0,    //紫    0.3,      0,            1.0,    0.0,    //紫    0.196,      0.3039,      0.296,    0.0,    //深绿    0.2784,      1.0,      0.1843,    0.0,    //浅绿    1.0,      0.3068,      0.1,    0.0      //橙};//画正方体void Square(float center[3], float size, float color[4]){    glPushMatrix();    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);// 将背景颜色和散射颜色设置成同一颜色    glTranslatef(center[0], center[1], center[2]);      //平衡坐标系    glutSolidCube(size);//利用库函数绘制一个半径为1的球体。    glPopMatrix();}void init(void){    glClearColor(0.5, 0.5, 0.5, 0.0);    //清理颜色,为黑色,(也可认为是背景颜色)    float light_diffuse[]= { 1.0, 1.0, 1.0, 1.0};       //有灯光才能体现材质的效果,他的灯光的强度是与的关系。貌似是两个相乘什么的。(0-1)范围。    float light_position[] = { 0, 3, 2.0, 0.0 };      //设置点光源的矩阵,这个向量也忒奇怪了,1不跟着变,0跟着变,设置为透视之后又是1跟着变,0不跟着变。    float light_specular[] = { 1.0, 1.0, 0.0, 1.0 };    //反射光    float light_ambient[] = {0.5, 0.5, 0.5, 1.0};    glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);      //,漫射光会产生漫射的效果和高光的效果    glLightfv(GL_LIGHT0, GL_POSITION, light_position);    //点光源没有漫射光的效果,会一直是黑色的。但会有高光反射的效果。    glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);      //反射光基本没有效果。可能是我不知道吧    GLfloat no_mat[] = {0.0, 0.0, 0.0, 1.0};    GLfloat mat_specular[] ={1.0, 1.0, 1.0, 1.0};    GLfloat hig_shininess[] = {100.0};    glMaterialfv(GL_FRONT,GL_SPECULAR, mat_specular);    glMaterialfv(GL_FRONT,GL_SHININESS, hig_shininess);    glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);    glEnable(GL_LIGHTING);    glEnable(GL_LIGHT0);    //如果什么都不设置,GL_LIGHT有默认的值。    glCullFace(GL_BACK);    glEnable(GL_CULL_FACE);    glDepthFunc(GL_LEQUAL);      glEnable(GL_DEPTH_TEST);}//在给定中心点周围画6个正方体void SurroundSquare(float center[3], float size, float color[4]){    //周围6个正方体的中心    float halfcenter[6][3] =   {      center[0] + size * 3/4.0, center[1], center[2],      center[0] - size * 3/4.0, center[1], center[2],      center[0] , center[1] + size * 3/4.0, center[2],      center[0] , center[1] - size * 3/4.0, center[2],      center[0] , center[1], center[2] + size * 3/4.0,      center[0] , center[1], center[2] - size * 3/4.0,    };    for (int i=0; i<6; i++)    {      Square(halfcenter, size/2, color);    }}void Iteration(float center[3], float size, int nIter){    if(nIter<0)return;    SurroundSquare(center, size, colortab);    float halfcenter[6][3] =   {      center[0] + size * 3/4.0, center[1], center[2],      center[0] - size * 3/4.0, center[1], center[2],      center[0] , center[1] + size * 3/4.0, center[2],      center[0] , center[1] - size * 3/4.0, center[2],      center[0] , center[1], center[2] + size * 3/4.0,      center[0] , center[1], center[2] - size * 3/4.0,    };    for (int i=0; i<6; i++)    {      Iteration(halfcenter, size/2, nIter-1);    }}void display(void){    //清除颜色缓存和深度缓存    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    glColor3f(1.0,1.0,1.0);    glLoadIdentity();    gluLookAt(1, -1, 3,   0, 0, 0,   0.4, -3, 0.5);      //视点转换    float center[] = {0.0f, 0.0f, 0.0f};    float radius = 2;    float color[] = {1.0, 0.1, 0.0, 0};    Square(center, radius, color);    Iteration(center, radius, 6);    glutSwapBuffers();      //交换双缓存}void reshape(int width,int height){    glViewport(0,0,width,height);    glMatrixMode(GL_PROJECTION);    glLoadIdentity();    glOrtho(-3.0, 3.0, -3.0 * height / width, 3.0* height / width, -5, 5);    //为了不变形,则要长和宽成比例    glMatrixMode(GL_MODELVIEW);    glLoadIdentity();}int main(int argc,char** argv){    glutInit(&argc,argv);    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);    //使用双缓存模式和深度缓存    glutInitWindowSize(600,600);    glutInitWindowPosition(200,200);    glutCreateWindow("三维分形");    init();    glutDisplayFunc(display);    glutReshapeFunc(reshape);    glutIdleFunc(display);   //设置空闲时用的函数    glutMainLoop();    return 0;}
页: [1]
查看完整版本: OpenGL画三维分形