简体   繁体   中英

OpenGL zoom efficiency

I am a beginner with OpenGL and as my first application I tried to to generate a fractal using the method of barycentric subdivision of a triangle. Not knowing the functions of OpenGL for perspective change, my first idea of a zoom and change of viewpoint algorithm was to simply redraw the entire fractal with different starting point coordinates and scaling factor every time a key is pressed (arrows for camera movement and +/- for zoom).

Given the fact that for 6 iterations of barycentric subdivision about 56 000 triangles are drawn (6^0+6^1+6^2+6^3+6^4+6^5+6^6 triangles) this algorithm is very inefficient. So I tried to use the gluPerspective() for zooming, the result was sadly a black screen, instead of a fractal. I have two main questions:

  • Does OpenGL functions for perspective change and viewpoint ( gluPerspective(), gluLookAt(), glFrustum(), etc) redraw the entire figure with different coordinates, or use more efficient methods of obtaining the same result? Will their use be more efficient in my case?
  • What did I do wrong in my code. Why am i getting a black screen?

     #include <GL/glfw.h> #include <iostream> #include <math.h> using namespace std; struct punct{ GLdouble x, y;}; //"punct" means "point" in my native language punct A, B, C; int n=0, mode=1; double l=1.6, ox=0, oy=0, scale=1; punct mid (punct A, punct B); void initiate (); void line (punct A, punct B); void triangle (punct A, punct B, punct C); void divide (punct A, punct B, punct C,int i); int main () { int width, height; bool running = true; char input=NULL; glfwInit(); if( !glfwOpenWindow( 800, 800, 0, 0, 0, 0, 0, 0, GLFW_FULLSCREEN ) ) { glfwTerminate(); return 0; } glfwSetWindowTitle("Baricentric"); while(running) { glfwGetWindowSize( &width, &height ); height = height > 0 ? height : 1; glViewport( 0, 0, width, height ); glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); glClear( GL_COLOR_BUFFER_BIT ); //This functions make my screen black //glMatrixMode(GL_MODELVIEW); //glLoadIdentity(); //gluPerspective (50*scale, width/height, 10.0, 100.0); initiate (); if(glfwGetKey(GLFW_KEY_KP_ADD) && glfwGetKey(GLFW_KEY_LCTRL)) input='+'; if(!glfwGetKey(GLFW_KEY_KP_ADD) && input=='+') { if(n<7) n++; input='\\n'; } if(glfwGetKey(GLFW_KEY_KP_SUBTRACT) && glfwGetKey(GLFW_KEY_LCTRL)) input='-'; if(!glfwGetKey(GLFW_KEY_KP_SUBTRACT) && input=='-') { if(n>0)n--; input='\\n'; } if(glfwGetKey(GLFW_KEY_KP_1)||glfwGetKey('1')) input='1'; if(!glfwGetKey(GLFW_KEY_KP_1) && input=='1') { mode=1; input='\\n'; } if(glfwGetKey(GLFW_KEY_KP_0)||glfwGetKey('0')) input='0'; if(!glfwGetKey(GLFW_KEY_KP_0) && input=='0') { mode=0; input='\\n'; } if(glfwGetKey(GLFW_KEY_KP_ADD) && !glfwGetKey(GLFW_KEY_LCTRL)) l+=0.002*(n+0.5); //'l' is replaced with 'scale' when using gluPerspective() if(glfwGetKey(GLFW_KEY_KP_SUBTRACT) && !glfwGetKey(GLFW_KEY_LCTRL)) l-=0.002*(n+0.5); //'l' is replaced with 'scale' when using gluPerspective() if(glfwGetKey(GLFW_KEY_UP)) oy-=0.002*(n+0.5); if(glfwGetKey(GLFW_KEY_DOWN)) oy+=0.002*(n+0.5); if(glfwGetKey(GLFW_KEY_RIGHT)) ox+=0.002*(n+0.5); if(glfwGetKey(GLFW_KEY_LEFT)) ox-=0.002*(n+0.5); if (n) divide (A,B,C,1); glfwSwapBuffers(); running = !glfwGetKey(GLFW_KEY_ESC) && glfwGetWindowParam( GLFW_OPENED); } glfwTerminate(); return 0; } punct mid (punct A, punct B) { punct C; Cx=(A.x+Bx)/2; Cy=(A.y+By)/2; return C; } void initiate () { Ax = -(l/2)+ox; Ay = -(l*sqrt(3)/4)+oy; Bx = l/2+ox; By = Ay; Cx = 0+ox; Cy = (l*sqrt(3)/4)+oy; glBegin (GL_QUADS); glColor3f(0.93,0.84,0.82); glVertex3d(-1, 1, 0); glColor3f(0.01,0.95,0.83); glVertex3d(-1, -1, 0); glColor3f(0.80,0.71,0.80); glVertex3d(1, -1, 0); glColor3f(0.8,1,0.8); glVertex3d(1, 1, 0); glEnd (); glBegin (GL_TRIANGLES); glColor3f(0,0.6,0.88); glVertex3d(Cx, Cy, 0); glColor3f(0,0.77,0.73); glVertex3d(Bx, By, 0); glColor3f(0.01,0.66,0.62); glVertex3d(Ax, Ay, 0); glEnd (); if (mode==0) { glLineWidth (0.1); glColor3f(0,0,0.36); glBegin (GL_LINE_LOOP); glVertex3d(Cx, Cy, 0); glVertex3d(Bx, By, 0); glVertex3d(Ax, Ay, 0); glEnd (); } } void divide (punct A, punct B, punct C, int i) { if(i<=n) { punct a, b, c, G; c=mid(A,B); b=mid(A,C); a=mid(B,C); Gx=(A.x+B.x+Cx)/3; Gy=(A.y+B.y+Cy)/3; if(mode==1) { triangle(G,a,C); triangle(G,b,C); triangle(G,a,B); triangle(G,c,B); triangle(G,c,A); triangle(G,b,A); } line(c,C); line(a,A); line(b,B); divide(G,a,C,i+1); divide(G,b,C,i+1); divide(G,a,B,i+1); divide(G,c,B,i+1); divide(G,c,A,i+1); divide(G,b,A,i+1); } } void line (punct A, punct B) { glBegin (GL_LINE_STRIP); glVertex3d(Ax,Ay,0); glVertex3d(Bx,By,0); glEnd (); } void triangle (punct A, punct B, punct C) { glBegin (GL_TRIANGLES); glColor3f(0,0.6,0.88); glVertex3d(Cx, Cy, 0); glColor3f(0,0.77,0.73); glVertex3d(Bx, By, 0); glColor3f(0.01,0.66,0.62); glVertex3d(Ax, Ay, 0); glEnd (); } 

Like so many before, you've fallen for the misconception of thinking OpenGL was a scene graph. This is not the case.

OpenGL is a drawing API. Your OS provides a canvas (window, PBuffer, Pixmap, etc.) and OpenGL provides the drawing tools in form of points, lines or triangles.

Does OpenGL functions for perspective change and viewpoint ( gluPerspective(), gluLookAt(), glFrustum(), etc) redraw the entire figure with different coordinates,

All they do is change the values of a few matrices. Nothing on the screen is changed by this. You have to redraw the whole thing to make a visible change.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM