• OpenGL画三维分形


     前言(可以直接略过):  

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

     

    正文:

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

      右图是我用openGL画的,迭代了7次,在我的电脑上5秒左右可以画出来。

     

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

    #include <GL/glut.h>
    #define MAXCOLOR 7
    float colortab[MAXCOLOR][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[i], size/2, color);
        }
    }
    
    void Iteration(float center[3], float size, int nIter)
    {
        if(nIter<0)return;
    
        SurroundSquare(center, size, colortab[nIter]);
    
        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[i], 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;
    }

     

  • 相关阅读:
    Cookie的小知识
    ASP.NET 杂记
    Ajax方式的Banner总结
    客户端·优化
    SQL中灵活运用Group by 和 Order by
    怎样才能容易更换DB
    txt编写第一个控制台程序
    ASP.NET MVC3数据绑定到VIEW的方式
    XML和Xpath定位小结
    ASP.NET 服务器控件对应HTML标签
  • 原文地址:https://www.cnblogs.com/easymind223/p/2580835.html
Copyright © 2020-2023  润新知