OpenGL画三维分形

 

 前言(可以直接略过):  

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

 

正文:

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

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

 

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

 

// OpenGL画三维分形
#include <GL/glut.h>
#pragma comment(lib, "glut32.lib")

#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值