基于OpenGL的LS分形演示程序
2011-11-27 16:59
302 查看
实现了一个基于LS(L系统)的二维分形演示程序。
实现这个演示程序的第一步当然是理解LS文法。咋看之下似乎有点难度,其实一点也不难。
举个例子就明白了:
LS文法先定义了绘图规则:
F:以当前方向前进一步,并画线;
f:以当前方向前进一步,不画线;
+:逆时针旋转角;
-:顺时针旋转角;
[:将海龟当前信息压栈;
]:将“[”时刻的海龟信息出栈。
Koch曲线的LS文法如下:
w:F(初始字母)
a :60(旋转角度)
P:F → F + F - - F + F(F的替代文法)
根据这一文法生成Koch曲线的步骤(假设迭代两次):
第一步: 得到迭代两次的文法。
第一次迭代结果:
F + F - - F + F
第二次迭代结果:(第一次迭代得到的结果的每一个F用规则P替换)
F + F - - F + F + F + F - - F + F - - F + F - - F + F + F + F - - F + F
第二步:按照迭代得到的文法绘图。
界面使用GLUI实现,写得比较简单。可以自己根据规则DIY文法,得到各种图形。全部演示程序代码如下:
实现这个演示程序的第一步当然是理解LS文法。咋看之下似乎有点难度,其实一点也不难。
举个例子就明白了:
LS文法先定义了绘图规则:
F:以当前方向前进一步,并画线;
f:以当前方向前进一步,不画线;
+:逆时针旋转角;
-:顺时针旋转角;
[:将海龟当前信息压栈;
]:将“[”时刻的海龟信息出栈。
Koch曲线的LS文法如下:
w:F(初始字母)
a :60(旋转角度)
P:F → F + F - - F + F(F的替代文法)
根据这一文法生成Koch曲线的步骤(假设迭代两次):
第一步: 得到迭代两次的文法。
第一次迭代结果:
F + F - - F + F
第二次迭代结果:(第一次迭代得到的结果的每一个F用规则P替换)
F + F - - F + F + F + F - - F + F - - F + F - - F + F + F + F - - F + F
第二步:按照迭代得到的文法绘图。
界面使用GLUI实现,写得比较简单。可以自己根据规则DIY文法,得到各种图形。全部演示程序代码如下:
#include <GL/glui.h> #include<iostream> #include<cmath> #include<string> #include<stack> #define PI 3.1415926 #define lsSize 14 using namespace std; /** These are the live variables passed into GLUI ***/ int wireframe = 0; int main_window; int curr_string = 0; int obj_type = 0; GLfloat startX = 0.0f; GLfloat startY = 0.0f; GLUI_Panel *obj_panel; GLUI_Panel *data_panel; GLUI_Panel *basic_data_panel; GLUI_Panel *tree_panel; GLUI_RadioGroup *radio; GLUI_EditText *textF; GLUI_EditText *textX; GLUI_EditText *textY; GLUI_EditText *textS; string diyS; string diyF; string diyX; string diyY; GLfloat diyAngle; GLfloat angle = 30.0; //步进角度 GLfloat len = 0.05f; //线段长度 GLint depth = 4; //递归深度 struct L_Sys{ string name; string startStr; string replaceF; string replaceX; string replaceY; GLfloat angle; L_Sys(string nname,string nstartStr,string nreplaceF,string nreplaceX,string nreplaceY,GLfloat nangle){ name = nname; startStr = nstartStr; replaceF = nreplaceF; replaceX = nreplaceX; replaceY = nreplaceY; angle = nangle; } }; struct L_Sys ls[] = { L_Sys("Koch curve","F","F-F++F-F","","",60.0), L_Sys("Quadratic Koch IsLand","F+F+F+F","F+F-F-FF+F+F-F","","",90.0f), L_Sys("Dragon Curve","X","F","X+YF+","-FX-Y",90.0f), L_Sys("Gosper hexagonal curve","XF","F","X+YF++YF-FX--FXFX-YF+","-FX+YFYF++YF+FX--FX-Y",60.0), L_Sys("Sierpinski gasket","FXF--FF--FF","FF","--FXF++FXF++FXF--","",60.0f), L_Sys("SIerpinski arrowhead","YF","F","YF+XF+Y","XF-YF-X",60.0f), L_Sys("Hilbert curve","X","F","-YF+XFX+FY-","+XF-YFY-FX+",90.0f), L_Sys("F[+F]F[-F]F","F","F[+F]F[-F]F","","",30.0f), L_Sys("F[+F]F[-F][F]","F","F[+F]F[-F][F]","","",20.0f), L_Sys("FF-[-F+F+F]+[+F-F-F]","F","FF-[-F+F+F]+[+F-F-F]","","",22.5f), L_Sys("F[+X]F[-X]+X","X","FF","F[+X]F[-X]+X","",20.0f), L_Sys("F[+X][-X]FX","X","FF","F[+X][-X]FX","",25.7f), L_Sys("F-[[X]+X]+F[+FX]-X","X","FF","F-[[X]+X]+F[+FX]-X","",22.5f), L_Sys("","","","","",0.0) }; /***************************************** myGlutIdle() ***********/ void myGlutIdle( void ) { if ( glutGetWindow() != main_window ) glutSetWindow(main_window); glutPostRedisplay(); } void control_cb( int control ) { if(control == 5){ ls[lsSize-1].angle = diyAngle; ls[lsSize-1].startStr = diyS; ls[lsSize-1].replaceF = diyF; ls[lsSize-1].replaceX = diyX; ls[lsSize-1].replaceY = diyY; curr_string = lsSize-1; } } /**************************************** myGlutReshape() *************/ void drawLine(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2){ glBegin(GL_LINES); glVertex2f(x1,y1); glVertex2f(x2,y2); glEnd(); } void changeSize(int w, int h) { if(h == 0) h = 1; float ratio = 1.0* w / h; glMatrixMode(GL_PROJECTION); glLoadIdentity(); glViewport(0, 0, w, h); gluPerspective(45,ratio,1,1000); gluLookAt(0.0,0.0,5.0, 0.0,0.0,-1.0, 0.0f,1.0f,0.0f); glMatrixMode(GL_MODELVIEW); } /***************************************** myGlutDisplay() *****************/ struct tpoint{ GLfloat x; GLfloat y; GLfloat delta; }; void fractal(){ string resultStr=ls[curr_string].startStr; GLfloat Delta= PI*(ls[curr_string].angle)/180;//生成角度 //第一步 得到推进文法 for(int i=0; i<depth;++i){ string tmpStr; for(int j=0;j<resultStr.size();++j){ if(resultStr[j]=='F'){ tmpStr=tmpStr+ls[curr_string].replaceF; }else if(resultStr[j]=='X'){ tmpStr=tmpStr+ls[curr_string].replaceX; }else if(resultStr[j]=='Y'){ tmpStr=tmpStr+ls[curr_string].replaceY; }else{ tmpStr=tmpStr+resultStr[j]; } } resultStr = tmpStr; } //解析文法,绘制 int k=0; tpoint bef={startX,startY,-PI/2},aft;//前一节点 和 后一节点 stack<tpoint> s; while(k<resultStr.size()){ switch(resultStr[k]) { case 'F': aft.x=bef.x+len*cos(bef.delta); aft.y=bef.y-len*sin(bef.delta); aft.delta = bef.delta; drawLine(bef.x,bef.y,aft.x,aft.y); bef=aft; break; case 'X': aft.x=bef.x+len*cos(bef.delta); aft.y=bef.y-len*sin(bef.delta); aft.delta = bef.delta; drawLine(bef.x,bef.y,aft.x,aft.y); bef=aft; break; case 'Y': aft.x=bef.x+len*cos(bef.delta); aft.y=bef.y-len*sin(bef.delta); aft.delta = bef.delta; drawLine(bef.x,bef.y,aft.x,aft.y); bef=aft; break; case '+': bef.delta += Delta; break; case '-': bef.delta -= Delta; break; case '[': s.push(bef); break; case ']': bef = s.top(); s.pop(); break; default: break; } ++k; } } void renderScene(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(0.0f,1.0f,0.0f); fractal(); glutSwapBuffers(); } /**************************************** main() ********************/ int main(int argc, char* argv[]) { /****************************************/ /* Initialize GLUT and create window */ /****************************************/ glutInit(&argc, argv); glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); glutInitWindowPosition( 100, 100 ); glutInitWindowSize( 500, 500 ); main_window = glutCreateWindow( "OpenGL Fractal " ); glutDisplayFunc( renderScene); glutReshapeFunc( changeSize ); glEnable(GL_DEPTH_TEST); GLUI *glui = GLUI_Master.create_glui( "Fractal" ); new GLUI_StaticText( glui, "OpenGL Fractal Control Board" ); basic_data_panel = new GLUI_Panel(glui,"basic data"); GLUI_Spinner *spinnerX = new GLUI_Spinner( basic_data_panel, "startX:", &startX); spinnerX->set_float_limits(-2.0, 2.0); spinnerX->set_alignment( GLUI_ALIGN_LEFT ); GLUI_Spinner *spinnerY = new GLUI_Spinner( basic_data_panel, "startY:", &startY); spinnerY->set_float_limits(-3.0, 3.0); spinnerY->set_alignment( GLUI_ALIGN_LEFT ); GLUI_Spinner *spinnerLen = new GLUI_Spinner( basic_data_panel, "lenth:", &len); spinnerLen->set_float_limits(0.0, 3.0); spinnerLen->set_alignment( GLUI_ALIGN_LEFT ); GLUI_Spinner *spinnerDepth = new GLUI_Spinner( basic_data_panel, "depth:", &depth); spinnerDepth->set_int_limits(1, 10); spinnerDepth->set_alignment( GLUI_ALIGN_LEFT ); data_panel = new GLUI_Panel(glui,"common curve"); GLUI_Listbox *list = new GLUI_Listbox( data_panel, "", &curr_string ); for(int i=0; i<7; ++i) list->add_item( i, ls[i].name.c_str()); tree_panel = new GLUI_Panel(glui,"2D fractal tree"); GLUI_Listbox *treeList = new GLUI_Listbox( tree_panel, "", &curr_string ); for(int j=7; j<lsSize; ++j) treeList->add_item( j, ls[j].name.c_str()); GLUI_Rollout *roll_diy = new GLUI_Rollout(glui, "DIY", false); GLUI_Panel *DIY_panel = new GLUI_Panel( roll_diy, "LS DIY" ); textS = new GLUI_EditText( DIY_panel, "start", diyS, 1, control_cb ); textF = new GLUI_EditText( DIY_panel, "F->", diyF, 2, control_cb ); textX = new GLUI_EditText( DIY_panel, "X->", diyX, 3, control_cb ); textY = new GLUI_EditText( DIY_panel, "Y->", diyY, 4, control_cb ); textS->set_w(50); textF->set_w(50); textX->set_w(50); textY->set_w(50); textS->set_alignment( GLUI_ALIGN_LEFT); GLUI_Spinner *spinnerAngle = new GLUI_Spinner( DIY_panel, "angle:", &diyAngle); spinnerAngle->set_float_limits(0.0, 90.0); spinnerAngle->set_alignment( GLUI_ALIGN_LEFT ); GLUI_Button *ok = new GLUI_Button(DIY_panel,"OK!!",5,control_cb); glui->set_main_gfx_window( main_window ); GLUI_Master.set_glutIdleFunc( myGlutIdle ); new GLUI_Button( glui, "iQuit", 0,(GLUI_Update_CB)exit ); glutMainLoop(); return EXIT_SUCCESS; } 部分截图:
相关文章推荐
- MFC三层模式标准版V1.5版演示源码(VC++代码生成,VC非托管代码,基于对话框程序)
- 基于vs08配置GLUT和建立我们第一个OpenGL程序
- 安装好cuda相关工具后发现原来基于mfc平台的opengl程序出现闪烁,最终解决
- 基于OpenGL的随机图动画演示框架与代码
- VS2012下基于Glut OpenGL显示一些立体图形示例程序:
- VS2012下基于Glut OpenGL绘制虚线示例程序:
- 基于MFC单文档的汉诺塔动画演示程序,手动输入盘子数
- 基于VS2010_Qt4.8.6(32位)的发起Http连接请求演示程序
- 基于TCP的网络通信程序演示[命令行程序]
- 第一个OpenGL程序--基于VS2005和GLUT
- VS2012下基于Glut OpenGL GL_STENCIL_TEST示例程序:
- 基于Win32SDK的OpenGL程序
- 第一个OpenGL程序--基于VS2005和GLUT
- 在MFC下使用OpenGL的一个简单的例子(基于单文档程序)
- [OpenGL - 游戏开发] 仿制《Minecraft/我的世界》 - 总结及演示程序
- 学习openGL灯光、视角,便于理解参数含义的几个演示程序
- VS2012下基于Glut OpenGL GL_TRIANGLES示例程序:
- 基于单文档的OpenGL图形程序的基本框架
- VS2012下基于Glut OpenGL GL_POLYGON示例程序:
- 基于MFC单文档SDI的OpenGL图形程序的基本框架