OpenGL :: 3D (Part 2/2) :: Material 5
consists of :
- A cube
- The Z-Buffer
- Animation
A cube
The example of the cube is quite simple and we will continue with when creating our first scene textured. Let us first how a cube is made:
Coordinates of the vertices of the cube
A cube has 8 vertices and 6 faces, each face involving 4 vertices.
We're not going to just draw each of the 8 vertices, we would not have solid faces. So we need to describe the faces one by one, indicating that they involve heights.
Here we define three coordinates for each vertex X, Y and Z. We can therefore use the basic glVertex2d we used before. So we'll have to use the version with three arguments is glVertex3d . Example:Code: C + +-Select
Faces are squares, we will use the mode GL_QUADS to describe the vertices.
To differentiate the faces we assign them a different color and we will do the first (the one with the arrows) in red. Regarding the camera, I chose to place it in (3,4,2) to watch the cube centered at (0,0,0) , as this will give a good viewing angle (the position used for the diagram above). Which therefore gives:Code: C + +-Select
Easy! Simply choose a starting point and follow the contour of the face to describe the vertices one by one.
Therefore continue with 2 e face, say that the first left (when looking at the diagram) and make it green.Code: C + +-Select
What gives me the following result:
Right now because I want to show you an important problem, let us get back to the front we will ... guess ... blue! Nothing complicated, just follow the pattern of earlier for quick contact and write the appropriate code.Code: C + +-Select
And here is the result:
In fact you do not dream, the blue face that was supposed to be behind, so mostly hidden by the red and green just to draw over them.
And it is quite logical, OpenGL drawing squares in the order in which they are defined . He cares not for the moment whether there is already something where he designs and has therefore overwrite previous faces. Solution? Z-Buffer !
Coordinates of the vertices of the cube
A cube has 8 vertices and 6 faces, each face involving 4 vertices.
We're not going to just draw each of the 8 vertices, we would not have solid faces. So we need to describe the faces one by one, indicating that they involve heights.
Describe peaks in 3D
Here we define three coordinates for each vertex X, Y and Z. We can therefore use the basic glVertex2d we used before. So we'll have to use the version with three arguments is glVertex3d . Example:Code: C + +-Select
1 | glVertex3d ( 1 , 1 , 1 ); |
The 3d glVertex3d does not mean " yeah I do 3D! ". Remember the chapter Basics , 3 specifies the number of arguments and of the fact that the arguments are given in two (real).
Describe the cube
Faces are squares, we will use the mode GL_QUADS to describe the vertices.
To differentiate the faces we assign them a different color and we will do the first (the one with the arrows) in red. Regarding the camera, I chose to place it in (3,4,2) to watch the cube centered at (0,0,0) , as this will give a good viewing angle (the position used for the diagram above). Which therefore gives:Code: C + +-Select
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | void Draw () { glClear ( GL_COLOR_BUFFER_BIT ); glMatrixMode ( GL_MODELVIEW ); glLoadIdentity ( ); gluLookAt ( 3 , 4 , 2 , 0 , 0 , 0 , 0 , 0 , 1 ); glBegin ( GL_QUADS ); glColor3ub ( 255 , 0 , 0 ) / / red face glVertex3d ( 1 , 1 , 1 ); glVertex3d ( 1 , 1 , - 1 ); glVertex3d ( - 1 , 1 , - 1 ); glVertex3d ( - 1 , 1 , 1 ); glEnd (); glFlush (); SDL_GL_SwapBuffers (); } |
Easy! Simply choose a starting point and follow the contour of the face to describe the vertices one by one.
I advise you to describe, imagine yourself facing the front (hum. .. ) and list them one by one in the opposite direction clockwise . Indeed we will see later that this will be useful when we want to avoid drawing the hidden faces. Again whatever direction you decide to use, everything is to be consistent and keep the same direction.
Therefore continue with 2 e face, say that the first left (when looking at the diagram) and make it green.Code: C + +-Select
1 2 3 4 5 | glColor3ub ( 0 , 255 , 0 ) / / green face glVertex3d ( 1 , - 1 , 1 ); glVertex3d ( 1 , - 1 , - 1 ); glVertex3d ( 1 , 1 , - 1 ); glVertex3d ( 1 , 1 , 1 ); |
What gives me the following result:
Right now because I want to show you an important problem, let us get back to the front we will ... guess ... blue! Nothing complicated, just follow the pattern of earlier for quick contact and write the appropriate code.Code: C + +-Select
1 2 3 4 5 | glColor3ub ( 0 , 0 , 255 ) / / blue face glVertex3d ( - 1 , - 1 , 1 ); glVertex3d ( - 1 , - 1 , - 1 ); glVertex3d ( 1 , - 1 , - 1 ); glVertex3d ( 1 , - 1 , 1 ); |
And here is the result:
In fact you do not dream, the blue face that was supposed to be behind, so mostly hidden by the red and green just to draw over them.
And it is quite logical, OpenGL drawing squares in the order in which they are defined . He cares not for the moment whether there is already something where he designs and has therefore overwrite previous faces. Solution? Z-Buffer !
The Z-Buffer
The Z-Buffer or Depth-Buffer (for depth buffer) is used to avoid the problem that we have encountered.
The Z-Buffer is a buffer (buffer) which stores the depth (hence the Z, X and Y on the screen is the position in pixels) of each pixel on the screen.
then when OpenGL application to draw a pixel in one place, it compares the depth of the point to display and that present in the buffer. If the new pixel is located at the former, then it is drawn and the value of the depth buffer is updated. Otherwise, the pixel was then behind and therefore has no place to be displayed . To understand this, follow the path that is done.
Fortunately for us OpenGL handles very well this technique , we just need to modify our program to activate it and use it well! For this we need:
This gives us a complete code (with the beginning of our cube):Code: C + +-Select
And indeed by running our new code we get this:
Phew! We finally have what we wanted. This handy z-buffer!
At this stage it remains for you to complete the code with the three remaining sides and choose beautiful colors.
Remember that you can use the scheme from start to easily find the coordinates of the vertices of the face being . Here is my code for those who do not want to try it themselves, or simply to compare:Code: C + +-Select
And the result corresponding graph:
Since you have the code in front of you know you have not cheated and that the code is indeed a 3D cube. But personally I see 3 quads of color, I can do the same as Paint in 30 seconds , proof:
Ok this is ugly and poorly done but with a little care I could have the same! So it's time to enjoy the power of real-time 3D and animate the cube to see every angle!
Principle of Z-Buffer
The Z-Buffer is a buffer (buffer) which stores the depth (hence the Z, X and Y on the screen is the position in pixels) of each pixel on the screen.
then when OpenGL application to draw a pixel in one place, it compares the depth of the point to display and that present in the buffer. If the new pixel is located at the former, then it is drawn and the value of the depth buffer is updated. Otherwise, the pixel was then behind and therefore has no place to be displayed . To understand this, follow the path that is done.
- Starting buffer (here 3x3 for example) is set to infinite distances (as far as possible to the bottom of your screen).
- OpenGL application to draw a pixel (2,2,5) .
requested Value: 5.
Present Value: infinite.
5 <= infinity> OK for drawing
Drawing pixel + Updated Z-buffer with the value 5. - Design Application of a pixel (2,2,10) .
requested value: 10.
Present Value: 5.
10> 5 => Drawing refused
Application in OpenGL
Fortunately for us OpenGL handles very well this technique , we just need to modify our program to activate it and use it well! For this we need:
- enable its use: after creating the OpenGL window must simply call:Code: C + +-Select
1
glEnable ( GL_DEPTH_TEST );
- reset each new image , at the same time as the pixel buffer:Code: C + +-Select
1
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
This gives us a complete code (with the beginning of our cube):Code: C + +-Select
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | <SDL/SDL.h> # Include # include <GL/gl.h> <GL/glu.h> # include # include <cstdlib> void Draw (); int main ( int argc , char * argv []) { SDL_Event event ; SDL_Init ( SDL_INIT_VIDEO ) atexit ( SDL_Quit ) SDL_WM_SetCaption ( "SDL GL Application" , NULL ); SDL_SetVideoMode ( 640 , 480 , 32 , SDL_OPENGL ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluPerspective(70,(double)640/480,1,1000); glEnable(GL_DEPTH_TEST); Draw (); for (; ;) { SDL_WaitEvent ( & event ); switch ( event . kind ) { case SDL_Quit: exit ( 0 ); break ; } Draw (); } return 0 ; } void Draw () { glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glMatrixMode ( GL_MODELVIEW ); glLoadIdentity ( ); gluLookAt ( 3 , 4 , 2 , 0 , 0 , 0 , 0 , 0 , 1 ); glBegin ( GL_QUADS ); glColor3ub ( 255 , 0 , 0 ) / / red face glVertex3d ( 1 , 1 , 1 ); glVertex3d ( 1 , 1 , - 1 ); glVertex3d ( - 1 , 1 , - 1 ); glVertex3d ( - 1 , 1 , 1 ); glColor3ub ( 0 , 255 , 0 ) / / green face glVertex3d ( 1 , - 1 , 1 ); glVertex3d ( 1 , - 1 , - 1 ); glVertex3d ( 1 , 1 , - 1 ); glVertex3d ( 1 , 1 , 1 ); glColor3ub ( 0 , 0 , 255 ) / / blue face glVertex3d ( - 1 , - 1 , 1 ); glVertex3d ( - 1 , - 1 , - 1 ); glVertex3d ( 1 , - 1 , - 1 ); glVertex3d ( 1 , - 1 , 1 ); glEnd (); glFlush (); SDL_GL_SwapBuffers (); } |
And indeed by running our new code we get this:
Phew! We finally have what we wanted. This handy z-buffer!
Finish the cube
At this stage it remains for you to complete the code with the three remaining sides and choose beautiful colors.
Remember that you can use the scheme from start to easily find the coordinates of the vertices of the face being . Here is my code for those who do not want to try it themselves, or simply to compare:Code: C + +-Select
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | glBegin ( GL_QUADS ); glColor3ub ( 255 , 0 , 0 ) / / red face glVertex3d ( 1 , 1 , 1 ); glVertex3d ( 1 , 1 , - 1 ); glVertex3d ( - 1 , 1 , - 1 ); glVertex3d ( - 1 , 1 , 1 ); glColor3ub ( 0 , 255 , 0 ) / / green face glVertex3d ( 1 , - 1 , 1 ); glVertex3d ( 1 , - 1 , - 1 ); glVertex3d ( 1 , 1 , - 1 ); glVertex3d ( 1 , 1 , 1 ); glColor3ub ( 0 , 0 , 255 ) / / blue face glVertex3d ( - 1 , - 1 , 1 ); glVertex3d ( - 1 , - 1 , - 1 ); glVertex3d ( 1 , - 1 , - 1 ); glVertex3d ( 1 , - 1 , 1 ); glColor3ub ( 255 , 255 , 0 ) / / yellow face glVertex3d ( - 1 , 1 , 1 ); glVertex3d ( - 1 , 1 , - 1 ); glVertex3d ( - 1 , - 1 , - 1 ); glVertex3d ( - 1 , - 1 , 1 ); glColor3ub ( 0 , 255 , 255 ) / / cyan face glVertex3d ( 1 , 1 , - 1 ); glVertex3d ( 1 , - 1 , - 1 ); glVertex3d ( - 1 , - 1 , - 1 ); glVertex3d ( - 1 , 1 , - 1 ); glColor3ub ( 255 , 0 , 255 ) / / magenta face glVertex3d ( 1 , - 1 , 1 ); glVertex3d ( 1 , 1 , 1 ); glVertex3d ( - 1 , 1 , 1 ); glVertex3d ( - 1 , - 1 , 1 ); glEnd (); |
And the result corresponding graph:
Since you have the code in front of you know you have not cheated and that the code is indeed a 3D cube. But personally I see 3 quads of color, I can do the same as Paint in 30 seconds , proof:
Ok this is ugly and poorly done but with a little care I could have the same! So it's time to enjoy the power of real-time 3D and animate the cube to see every angle!
Animation
To animate our cube we simply rotate using what you already know by heart: the rotation ! level of design we did not really change much, just rotate the marker before drawing the cube. We will run on both Z (vertical) and X so we need 2 * global variables for each angle control.
* In general programming we try to avoid global variables here but we somehow learn to prototyping and testing concepts OpenGL, so it's really no big deal.
code simplified, the program becomes:Code: C + +-Select
In terms of SDL code we want these angles are automatically changed with time. We can no longer afford to wait for events withSDL_WaitEvent and we will therefore use SDL_PollEvent to retrieve events if there is then animate our cube. therefore we modify our code display loop to increment our angles to each image:Code: C + +-Select
Testing the current code you see that the cube rotates too fast, we do not frankly see the time.
should therefore introduce speeds. These speeds should not depend on the computer on which the program is launched and therefore must take into account the real time.
To do this, each image (each time through the loop gives rise to an image), you must determine how time it has happened since the last frame and move the cube accordingly. So we need three variables:
The principle is the following.
Regarding the unit of measurement of speed , as the time is given in milliseconds and the angles used in glRotate are degrees, it is simply degrees per millisecond . In this case I will use 0.05 ° / ms . translation code in the principle just mentioned is as follows:Code: C + +-Select
In fact if you look at the CPU load imposed by our application we see that it is fully occupied to manage our program:
This does not mean that your program is slow it's just that we loop continuously and we never take a break. In reality we do not really need to loop all the time. We will use one possible technique (the one I prefer and therefore wishes to explain): limit the FPS (frames per second - fps).
Indeed for very fluid animation we need only 50 frames per second. By setting the number of frames per second that your desired application, it is possible to make some time to sleep if it goes faster than necessary, which will ease (even if he did not complain) processor . To do this we will calculate how long each image we have to draw it, if we were faster than the average time, we will stop running for a while. example , allow 50 frames per second gives each image to view 20 milliseconds. Imagine a picture put 5 ms to actually display it then remains to kill 15 ms. Rather than jump to the next image, we sleep the applicationfor the 15 ms. In terms of code we use SDL_GetTicks as before to determine the time elapsed between the beginning and end of the image creation . We will use SDL_Delay to temporarily suspend the application.Code: C + +-Select
Note that here we do not know how much time it has happened since the last time but how long our image took to draw (I have included event management). There is therefore a call to SDL_GetTicks the beginning of our loop and a call to the very end. I reuse ellapsed_time for convenience but not for other variables do not mix two concepts: FPS limitation and time management in animations. ultimate Code:Code: C + +-Select
In comparison, for an animation of the same fluidity, the average processor load is negligible :
Other notes:
* In general programming we try to avoid global variables here but we somehow learn to prototyping and testing concepts OpenGL, so it's really no big deal.
code simplified, the program becomes:Code: C + +-Select
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <SDL/SDL.h> # Include # include <GL/gl.h> <GL/glu.h> # include # include <cstdlib> void Draw (); Double Anglez = 0 ; dual AngleX = 0 ; int main ( int argc , char * argv []) { / / code hand } void Draw () { glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glMatrixMode ( GL_MODELVIEW ); glLoadIdentity ( ); gluLookAt ( 3 , 4 , 2 , 0 , 0 , 0 , 0 , 0 , 1 ); glRotated ( Anglez , 0 , 0 , 1 ); glRotated ( AngleX , 1 , 0 , 0 ); / / Draw the cube glFlush (); SDL_GL_SwapBuffers (); } |
In terms of SDL code we want these angles are automatically changed with time. We can no longer afford to wait for events withSDL_WaitEvent and we will therefore use SDL_PollEvent to retrieve events if there is then animate our cube. therefore we modify our code display loop to increment our angles to each image:Code: C + +-Select
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | for (; ;) { while ( SDL_PollEvent ( & event )) { switch ( event . kind ) { case SDL_Quit: exit ( 0 ); break ; } } Anglez + = 1 ; AngleX + = 1 ; Draw (); } |
Manage the animation speed
Testing the current code you see that the cube rotates too fast, we do not frankly see the time.
should therefore introduce speeds. These speeds should not depend on the computer on which the program is launched and therefore must take into account the real time.
To do this, each image (each time through the loop gives rise to an image), you must determine how time it has happened since the last frame and move the cube accordingly. So we need three variables:
- one to keep in mind the time he was in the last picture: last_time ;
- one time for the current frame: current_time ;
- one (for convenience) for time: ellapsed_time .
For the elapsed time, in milliseconds, since the launch of the application we use the instruction SDL_GetTicks ();
The principle is the following.
- It initializes the first time , before returning to our render loop last_time with the current time.
- Each picture is recovered in the current time current_time .
- We use the difference between the current time and the time he was in the old passage to know how much time has elapsed. It stores the result in ellapsed_time .
- It makes our movements in function of time.
- We finally assign last_time value current_time as we move to a new image and therefore the present becomes the past ( it's beautiful!) .
Regarding the unit of measurement of speed , as the time is given in milliseconds and the angles used in glRotate are degrees, it is simply degrees per millisecond . In this case I will use 0.05 ° / ms . translation code in the principle just mentioned is as follows:Code: C + +-Select
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | Uint32 last_time = SDL_GetTicks (); Uint32 current_time , ellapsed_time ; for (; ;) { while ( SDL_PollEvent ( & event )) { switch ( event . kind ) { case SDL_Quit: exit ( 0 ); break ; } } current_time = SDL_GetTicks (); ellapsed_time = current_time - last_time ; last_time = current_time ; Anglez + = 0.05 * ellapsed_time ; AngleX + = 0.05 * ellapsed_time ; Draw (); } |
Do not monopolize the CPU
That train! The program takes 100% CPU just to run a simple cube, I'll never be able to make a game!
In fact if you look at the CPU load imposed by our application we see that it is fully occupied to manage our program:
This does not mean that your program is slow it's just that we loop continuously and we never take a break. In reality we do not really need to loop all the time. We will use one possible technique (the one I prefer and therefore wishes to explain): limit the FPS (frames per second - fps).
Indeed for very fluid animation we need only 50 frames per second. By setting the number of frames per second that your desired application, it is possible to make some time to sleep if it goes faster than necessary, which will ease (even if he did not complain) processor . To do this we will calculate how long each image we have to draw it, if we were faster than the average time, we will stop running for a while. example , allow 50 frames per second gives each image to view 20 milliseconds. Imagine a picture put 5 ms to actually display it then remains to kill 15 ms. Rather than jump to the next image, we sleep the applicationfor the 15 ms. In terms of code we use SDL_GetTicks as before to determine the time elapsed between the beginning and end of the image creation . We will use SDL_Delay to temporarily suspend the application.Code: C + +-Select
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | Uint32 start_time , / / new variable for (; ;) { start_time = SDL_GetTicks (); while ( SDL_PollEvent ( & event )) { switch ( event . kind ) { case SDL_Quit: exit ( 0 ); break ; box SDL_KEYDOWN: Animation = ! entertainment ; break ; } } current_time = SDL_GetTicks (); ellapsed_time = current_time - last_time ; last_time = current_time ; Anglez + = 0.05 * ellapsed_time ; AngleX + = 0.05 * ellapsed_time ; Draw (); ellapsed_time = SDL_GetTicks () - start_time , if ( ellapsed_time < 10 ) { SDL_Delay ( 10 - ellapsed_time ); } } return 0 ; } |
Note that here we do not know how much time it has happened since the last time but how long our image took to draw (I have included event management). There is therefore a call to SDL_GetTicks the beginning of our loop and a call to the very end. I reuse ellapsed_time for convenience but not for other variables do not mix two concepts: FPS limitation and time management in animations. ultimate Code:Code: C + +-Select
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | <SDL/SDL.h> # Include # include <GL/gl.h> <GL/glu.h> # include # include <cstdlib> void Draw (); Double Anglez = 0 ; dual AngleX = 0 ; int main ( int argc , char * argv []) { SDL_Event event ; SDL_Init ( SDL_INIT_VIDEO ) atexit ( SDL_Quit ) SDL_WM_SetCaption ( "SDL GL Application" , NULL ); SDL_SetVideoMode ( 640 , 480 , 32 , SDL_OPENGL ); glMatrixMode ( GL_PROJECTION ); glLoadIdentity (); gluPerspective ( 70 , ( two ) 640 / 480 , 1 , 1000 ); glEnable ( GL_DEPTH_TEST ); Draw (); Uint32 last_time = SDL_GetTicks (); Uint32 current_time , ellapsed_time ; Uint32 start_time ; for (; ;) { start_time = SDL_GetTicks (); while ( SDL_PollEvent ( & event )) { switch ( event . kind ) { case SDL_Quit: exit ( 0 ); break ; } } current_time = SDL_GetTicks (); ellapsed_time = current_time - last_time ; last_time = current_time ; Anglez + = 0.05 * ellapsed_time ; AngleX + = 0.05 * ellapsed_time ; Draw (); ellapsed_time = SDL_GetTicks () - start_time , if ( ellapsed_time < 10 ) { SDL_Delay ( 10 - ellapsed_time ); } } return 0 ; } void Draw () { glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glMatrixMode ( GL_MODELVIEW ); glLoadIdentity ( ); gluLookAt ( 3 , 4 , 2 , 0 , 0 , 0 , 0 , 0 , 1 ); glRotated ( Anglez , 0 , 0 , 1 ); glRotated ( AngleX , 1 , 0 , 0 ); glBegin ( GL_QUADS ); glColor3ub ( 255 , 0 , 0 ) / / red face glVertex3d ( 1 , 1 , 1 ); glVertex3d ( 1 , 1 , - 1 ); glVertex3d ( - 1 , 1 , - 1 ); glVertex3d ( - 1 , 1 , 1 ); glColor3ub ( 0 , 255 , 0 ) / / green face glVertex3d ( 1 , - 1 , 1 ); glVertex3d ( 1 , - 1 , - 1 ); glVertex3d ( 1 , 1 , - 1 ); glVertex3d ( 1 , 1 , 1 ); glColor3ub ( 0 , 0 , 255 ) / / blue face glVertex3d ( - 1 , - 1 , 1 ); glVertex3d ( - 1 , - 1 , - 1 ); glVertex3d ( 1 , - 1 , - 1 ); glVertex3d ( 1 , - 1 , 1 ); glColor3ub ( 255 , 255 , 0 ) / / yellow face glVertex3d ( - 1 , 1 , 1 ); glVertex3d ( - 1 , 1 , - 1 ); glVertex3d ( - 1 , - 1 , - 1 ); glVertex3d ( - 1 , - 1 , 1 ); glColor3ub ( 0 , 255 , 255 ) / / cyan face glVertex3d ( 1 , 1 , - 1 ); glVertex3d ( 1 , - 1 , - 1 ); glVertex3d ( - 1 , - 1 , - 1 ); glVertex3d ( - 1 , 1 , - 1 ); glColor3ub ( 255 , 0 , 255 ) / / magenta face glVertex3d ( 1 , - 1 , 1 ); glVertex3d ( 1 , 1 , 1 ); glVertex3d ( - 1 , 1 , 1 ); glVertex3d ( - 1 , - 1 , 1 ); glEnd (); glFlush (); SDL_GL_SwapBuffers (); } |
In comparison, for an animation of the same fluidity, the average processor load is negligible :
Other notes:
- it is also possible to use timers to limit the FPS (see doc SDL_AddTimer as his example). This is not the solution here;
- followers of the doc will not fail to mention the issue of granularity of pause time (see SDL_Delay ). In tests to write this tutorial, pause real time never exceeded asked more than 1 millisecond. The actual number of frames per second is equal (or very close) to the fixed number;
- in terms of ergonomics it can scare some of the program to fall asleep some time. They are reassured, even in a 3D application much more complex, event management is in no way impaired.
video :
links for downloading the code files and the video :: click here for code
links :
https://docs.google.com/open?id=0B-Rb64QiDg8wRXdsT3ZSZmxwdFU
https://docs.google.com/open?id=0B-Rb64QiDg8wSFh3cTZoaVVJRUk
No comments:
Post a Comment