{"id":255,"date":"2023-07-18T13:19:33","date_gmt":"2023-07-18T13:19:33","guid":{"rendered":"https:\/\/www.infodreams.it\/main\/?page_id=255"},"modified":"2023-07-18T13:30:11","modified_gmt":"2023-07-18T13:30:11","slug":"dev-132-using-opengl-part-2-of-4","status":"publish","type":"page","link":"https:\/\/www.infodreams.it\/main\/publications\/dev-magazine\/dev-132-using-opengl-part-2-of-4\/","title":{"rendered":"Dev 132 \u2013 Using OpenGL \u2013 part 2 of 4"},"content":{"rendered":"<p><img decoding=\"async\" src=\"https:\/\/i0.wp.com\/www.infodreams.it\/Assets\/pubblicazioni\/dev\/132\/01_copertina.png?w=800&#038;ssl=1\" data-recalc-dims=\"1\" \/><\/p>\n<blockquote class=\"has-medium-font-size\"><p>\nDevoting some space to the GLUT library before we start to see how to use OpenGL will save us a lot of time later by not addressing issues related to a specific operating system.<\/p><\/blockquote>\n<div class=\"entry-content\">\n<h2><span id=\"Introduction\" class=\"ez-toc-section\"><\/span>Introduction<\/h2>\n<p class=\"has-medium-font-size\">As already said, by its nature OpenGL is a sophisticated API for creating 3D graphics and has more than 300 commands that allow us to generate very complex and realistic scenes.<\/p>\n<p class=\"has-medium-font-size\">It is normal to marvel agains the complete lack of functions for display management. There is not even a system to receive commands from the keyboard, to detect mouse activity and use the audio capabilities. The motivation for such a choice stems from the desire of the creators of the API to make it as platform independent as possible. In fact a single function for opening windows will lead to an implementation based on direct calls to the host operating system\u2019s API of, which is in conflict with the original idea.<\/p>\n<h2><span id=\"Some_preliminary_specifications\" class=\"ez-toc-section\"><\/span>Some preliminary specifications<\/h2>\n<p class=\"has-medium-font-size\">The first rule that OpenGL developers have followed to maintain a high level of portability has been to create a standard nomenclature for functions and for the declaration of data types. For the first is used a system which allows to identify at a glance the library to which a function belongs, the command, the number of arguments it requires and the type of data used. In <strong>Figure 1<\/strong> there is shown an example of a function where is visible the suffix \u2018gl\u2019 which indicates that the function belongs to the OpenGL library, the name of Vertex command, the number of arguments equal to 3, and the final \u2018f\u2019 that indicates that float is the type to use for parameters.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" class=\"wp-image-4633\" src=\"https:\/\/i0.wp.com\/www.infodreams.it\/Assets\/pubblicazioni\/dev\/132\/Figura1_2.png?w=800\" sizes=\"(max-width: 320px) 100vw, 320px\" alt=\"\" data-recalc-dims=\"1\" data-recalc-dims=\"1\" \/><figcaption>Figure 1 \u2013 An example of naming conventions of functions in OpenGL<\/figcaption><\/figure>\n<\/div>\n<p class=\"has-medium-font-size\">It \u2018s important to keep in mind another factor when using the OpenGL functions, most C++ compilers consider the numerical values being of type double by default\u200b\u200b, so you need to add the symbol \u2018f\u2019 to each argument passed to a function that accepts float data type, as shown:<\/p>\n<pre class=\"wp-block-code\"><code>glColor4f (0.0f, 1.0f, 0.0f);\r\nglVertex3f (0.0f, 10.0f, 0.0f);<\/code><\/pre>\n<p class=\"has-medium-font-size\">When we write a program normally we use data types that are defined by the compiler, but that somehow are related to the underlying machine architecture. We can not, in fact, be sure that a given type of float or int C is treated the same on different platforms. This leads, of course, to problems about portability; so OpenGL has been provided with its own set of data types that can be used with confidence that they will be interpreted in the same manner everywhere.<\/p>\n<p class=\"has-medium-font-size\">Following you can find a list of all defined types, their corresponding C and the internal representation all with the standard suffixes identical to those used for the functions naming:<\/p>\n<table class=\"wp-block-table aligncenter is-style-stripes\">\n<tbody>\n<tr>\n<td><strong>Data type<\/strong><\/td>\n<td><strong>Internal representation<\/strong><\/td>\n<td><strong>C type<\/strong><\/td>\n<td><strong>C literal suffix<\/strong><\/td>\n<\/tr>\n<tr>\n<td>GLbyte<\/td>\n<td>8bit integer<\/td>\n<td>signed char<\/td>\n<td>b<\/td>\n<\/tr>\n<tr>\n<td>GLshort<\/td>\n<td>16bit integer<\/td>\n<td>short<\/td>\n<td>s<\/td>\n<\/tr>\n<tr>\n<td>GLint,<br \/>\nGLsizei<\/td>\n<td>32bit integer<\/td>\n<td>long<\/td>\n<td>l<\/td>\n<\/tr>\n<tr>\n<td>GLfloat,<br \/>\nGLclampf<\/td>\n<td>32bit floating point<\/td>\n<td>float<\/td>\n<td>f<\/td>\n<\/tr>\n<tr>\n<td>GLdouble,<br \/>\nGLclampd<\/td>\n<td>64bit floating point<\/td>\n<td>double<\/td>\n<td>d<\/td>\n<\/tr>\n<tr>\n<td>GLubyte,<br \/>\nGLboolean<\/td>\n<td>8bit unsigned integer<\/td>\n<td>unsigned char<\/td>\n<td>ub<\/td>\n<\/tr>\n<tr>\n<td>GLushort<\/td>\n<td>16bit unsigned integer<\/td>\n<td>unsigned short<\/td>\n<td>us<\/td>\n<\/tr>\n<tr>\n<td>GLuint,<br \/>\nGLenum,<br \/>\nGLbitfield<\/td>\n<td>32bit unsigned integer<\/td>\n<td>unsigned long<\/td>\n<td>ui<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\"has-medium-font-size\">As you can see also the data types uses a standard naming structure with the \u2018GL\u2019 prefix to distinguish them from the types defined by C. The significance of most of them is clear and known, but they have added a lot more and useful ones. First, the type GLbitfield is useful for those variables that must contain bit fields. GLenum is used for the enumerated variables, while GLclamp, with suffix \u2018f\u2019 or \u2018d\u2019 represents a single or double-precision floating-point type which values can vary only between 0.0 and 1.0. Such type is useful because many functions take values \u200b\u200bwhich vary within this range. For example, the function glColor3f wants as parameters the RGB values of a color but in this case the intensity of the single component is defined in the range 0.0 to 1.0 and not between 0 and 255 as we could expect.<\/p>\n<h2><span id=\"The_GLUT_library\" class=\"ez-toc-section\"><\/span>The GLUT library<\/h2>\n<p class=\"has-medium-font-size\">To facilitate the learning process of OpenGL and accelerate development was created an auxiliary library called AUX, but due to some problems of implementation and compatibility was soon replaced by GLUT, written by Silicon Graphics.[(br)][(br)]<\/p>\n<p class=\"has-medium-font-size\">The GLUT acronym stands for \u2018OpenGL Utility Toolkit\u2019, not to be confused with GLU the \u2018OpenGL utility library\u2019. GLUT is a cross-platform library that contains many functions for creating windows, pop-up menu and allows the management of the keyboard, joystick and video in full screen mode. Even developers without programming experience of GUIs, in a particular operating system, are thus able to achieve complete functional and fully portable programs.<\/p>\n<p class=\"has-medium-font-size\">As the old AUX, however, GLUT is unable to meet the development needs of commercial applications, but is excellent in teaching for testing ideas or creating presentation programs. For these reasons GLUT will be used throughout the course of this special. References to download GLUT can be found directly from the site <a href=\"http:\/\/www.opengl.org\/\">www.opengl.org<\/a><\/p>\n<h2><span id=\"Our_first_program_with_GLUT\" class=\"ez-toc-section\"><\/span>Our first program with GLUT<\/h2>\n<p class=\"has-medium-font-size\">After many introductory words we finall can begin to actually use these libraries so now we will study how to build a full executable that opens a blank window. This code can be used as a template for all programs you will made. Following the complete source code<\/p>\n<pre class=\"wp-block-code\"><code>void SetupRC()\r\n{\r\n    glClearColor(0.0f,0.0f,0.0f,1.0f);\r\n}\r\n\r\nvoid ChangeSize(GLsizei w, GLsizei h)\r\n{\r\n    glViewport(0, 0, w, h);\r\n}\r\n\r\nvoid RenderScene()\r\n{\r\n    glClear(GL_COLOR_BUFFER_BIT);\r\n    glutSwapBuffers();\r\n}\r\n\r\nvoid main()\r\n{\r\n    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);\r\n    glutInitWindowSize(640, 480);\r\n    glutCreateWindow(\"My first GLUT program\");\r\n\r\n    SetupRC();\r\n\r\n    glutReshapeFunc(ChangeSize);\r\n    glutDisplayFunc(RenderScene);\r\n    glutMainLoop();\r\n}<\/code><\/pre>\n<p class=\"has-medium-font-size\">Looking at the following code we analyze, then each function. We start from the main() where we find the following call<\/p>\n<pre class=\"wp-block-code\"><code>glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA);<\/code><\/pre>\n<p class=\"has-medium-font-size\">containing a parameter consists of several flags. The first, GLUT_RGBA, tells GLUT to initialize a window that supports a 32Bit video mode \u2013 the suffix RGBA stands for Red, Green, Blue and Alpha, where alpha is the transparency channel. GLUT_DOUBLE tells to the library info about format of the two buffers used for the final images storage.<\/p>\n<p class=\"has-medium-font-size\">Theese buffers are used to achieve the mechanism known as \u2018double-buffering\u2019 that allows you to use a memory location at which all drawing operations remains hidden behind the scenes. After the drawing process the image is swapped quickly with that still visible on the screen. In this manner is possible to avoid the annoying and well-known effect of flickering. This setting is the opposite of GLUT_SINGLE in which case each drawing command will cause an immediate update on the displayed window. To swap the buffers just mentioned we must launch the \u2018glutSwapBuffers()\u2019 that we will soon explain.<\/p>\n<p class=\"has-medium-font-size\">Then we find the call<\/p>\n<pre class=\"wp-block-code\"><code>glutInitWindowSize(640, 480)<\/code><\/pre>\n<p class=\"has-medium-font-size\">which does nothing but make GLUT set a size of 640\u00d7480 pixels for the window to be created. Inside the official GLUT documentation are also mentioned functions to position and move the window on the screen or even switch to fullscreen mode.<\/p>\n<p class=\"has-medium-font-size\">Finally arrived the time to create our display window and that can be obtained by calling<\/p>\n<pre class=\"wp-block-code\"><code>glutCreateWindow(\"My first GLUT program\")<\/code><\/pre>\n<p class=\"has-medium-font-size\">it also sets the text displayed as windows caption. The last line of code<\/p>\n<pre class=\"wp-block-code\"><code>glutMainLoop()<\/code><\/pre>\n<p class=\"has-medium-font-size\">causes GLUT to launch a cycle that \u201ckeeps alive\u201d the program until the close button of the window will be clicked.<\/p>\n<p class=\"has-medium-font-size\">So far these instructions, by themselves, are sufficient to run a minimal program which does not perform any operation: it just displays a blank window. In our applications, presentations or games we essentially need that:<\/p>\n<ul>\n<li>At application start must there is an environment initialization procedure<\/li>\n<li>At regular intervals the program will draw a frame on the window<\/li>\n<li>It will reacts to the window resize signals<\/li>\n<\/ul>\n<p class=\"has-medium-font-size\">The first and second conditions are quite obvious and will be implemented by the functions SetupRC() and RenderScene(). The third, however, means that every time a user resizes the window or minimize the program it must, somehow, change the size of the displayed image. This operation will be performed by ChangeSize().<\/p>\n<p class=\"has-medium-font-size\">We observe that we have no way to know in advance how to handle system events. GLUT once again comes to help us solve this problem using a few commands that take as pointer to our function as a parameter and link it to a particular system event. So, whenever there a downsizing is reached, GLUT will launch the function passed as an argument to:<\/p>\n<pre class=\"wp-block-code\"><code>glutReshapeFunc((void (* func GLUTCALLBACK) (int width, int height))<\/code><\/pre>\n<p class=\"has-medium-font-size\">In our case we have<\/p>\n<pre class=\"wp-block-code\"><code>glutReshapeFunc(ChangeSize)<\/code><\/pre>\n<p class=\"has-medium-font-size\">where the function ChangeSize() should accept two integer values \u200b\u200bas the width and height of the window after resizing. In practice, as shown in the listing, the function is declared in this manner<\/p>\n<pre class=\"wp-block-code\"><code>void ChangeSize(int w, int h);<\/code><\/pre>\n<p class=\"has-medium-font-size\">For the less experienced we want to clarify that the function names and parameters are not significant and can change them at will.<\/p>\n<p class=\"has-medium-font-size\">The drawing function, which has the task of producing the scene, is passed to the<\/p>\n<pre class=\"wp-block-code\"><code>glutDisplayFunc(void (* func GLUTCALLBACK) (void))<\/code><\/pre>\n<p class=\"has-medium-font-size\">In our listing we find<\/p>\n<pre class=\"wp-block-code\"><code>glutDisplayFunc(RenderScene)<\/code><\/pre>\n<p class=\"has-medium-font-size\">with RenderScene() declared with no parameters.<\/p>\n<p class=\"has-medium-font-size\">The function glClearColor() within SetupRC() code indicates to OpenGL what color should be used for to clear the drawing buffer. We chose the black color by setting the values \u200b\u200bof the RGB components to 0.0f.<\/p>\n<p class=\"has-medium-font-size\">In the function RenderScene() we can find two instructions, the first of which,<\/p>\n<pre class=\"wp-block-code\"><code>glClear(GL_COLOR_BUFFER_BIT)<\/code><\/pre>\n<p class=\"has-medium-font-size\">erases the contents of the color buffer, ie, that contains the rendered image. In this way we prepared the buffer to be filled by another frame of the scene.<\/p>\n<p class=\"has-medium-font-size\">After you have completed every drawing operations becomes necessary to display the image produced by copying the contents of the \u2018color buffer\u2019 into \u200b\u200bthe visible area of the window. That operation can be obtained by calling the function glutSwapBuffers(). This function internally calls the glFlush() that determines the processing of all instructions previously stored in the Command Buffer, triggering the process of rendering.<\/p>\n<h2><span id=\"Managing_the_viewport\" class=\"ez-toc-section\"><\/span>Managing the viewport<\/h2>\n<p class=\"has-medium-font-size\">In almost every applications users has the ability to resize the window where the program is running. It\u2019s our intention to write programs that display the correct output in all conditions; both when the user enlarges the window to full screen or when makes it smaller the output must be properly scaled.<\/p>\n<p class=\"has-medium-font-size\">Next listing presents the new version of the ChangeSize().<\/p>\n<pre class=\"wp-block-code\"><code>void ChangeSize(GLsizei w, GLsizei h)\r\n {\r\n     GLfloat aspectRatio;\r\n     if (h == 0) h = 1;\r\n\r\n     aspectRatio = (GLfloat) w \/ (GLfloat) h;\r\n\r\n     glViewport(0, 0, w, h);\r\n\r\n     glMatrixMode(GL_PROJECTION);\r\n     glLoadIdentity();\r\n\r\n     if (w &lt;= h)\r\n         glOrtho(CV_SINISTRA, CV_DESTRA, CV_ALTO \/ aspectRatio, CV_BASSO \/ aspectRatio, CV_VICINO, CV_LONTANO);\r\n     else\r\n         glOrtho(CV_SINISTRA * aspectRatio, CV_DESTRA * aspectRatio, CV_ALTO, CV_BASSO, CV_VICINO, CV_LONTANO);\r\n\r\n     glMatrixMode(GL_MODELVIEW);\r\n     glLoadIdentity();\r\n}<\/code><\/pre>\n<p class=\"has-medium-font-size\">The first operation performed calling the function<\/p>\n<pre class=\"wp-block-code\"><code>void glViewport(GLint x, GLint y, GLsizei width, GLsizei height)<\/code><\/pre>\n<p class=\"has-medium-font-size\">The parameters x and y are related to the position from the bottom-right in which makes OpenGL produces output inside the window. Usually to make this area coincide with the entire window the parameters x and y are set to 0 while width and height assume the value of the parameters w and h passed from GLUT as follows:<\/p>\n<pre class=\"wp-block-code\"><code>glViewport(0, 0, w, h)<\/code><\/pre>\n<p class=\"has-medium-font-size\">Then you have to set the clipping volume. In the previous article we talked about clipping area for images in two dimensions. Adding a further dimension no longer makes sense to talk about areas; so, we can set the volume within which the objects of the scene are represented by calling the function<\/p>\n<pre class=\"wp-block-code\"><code>glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top,GLdouble near, GLdouble far)<\/code><\/pre>\n<p class=\"has-medium-font-size\">The left and right parameters define the range of coordinates along the x-axis within which images are displayed. Bottom and top define the same type of interval but on the y axis, while near and far on the axis of z.<\/p>\n<p class=\"has-medium-font-size\">The function glOrtho also indicates to OpenGL to use an orthographic system of projection where there is not the typical effect of perspective. All the lines that make up an object appear having the same size even if they lie close to the observer or at a great distance.<\/p>\n<p class=\"has-medium-font-size\">Other instructions will be discussed in future articles, but for now is sufficient to know that they inform OpenGL to which matrix apply the shown settings.<\/p>\n<p class=\"has-medium-font-size\">Finally it may happen that, by resizing the application window, the ratio between width and height changes determining a non-desired deformation to the final image. However, by calculating the ratio between the size of the window, based on the values \u200b\u200bpassed to the function ChangeSize(), we can make the output immune to any distortion<\/p>\n<pre class=\"wp-block-code\"><code>if (w &gt;= h)\r\n    glOrtho (-100.0, 100.0, -100.0 \/ aspect ratio, 100.0 \/ aspect ratio, 1.0, -1.0);\r\nelse\r\n    glOrtho (-100.0 * Aspect ratio, aspect ratio * 100, -100, 100, 1.0, -1.0);\r\n\r\naspectRatio = (GLfloat) w \/ (GLfloat h)<\/code><\/pre>\n<h2><span id=\"Creating_a_simple_animation\" class=\"ez-toc-section\"><\/span>Creating a simple animation<\/h2>\n<p class=\"has-medium-font-size\">Unlikely we would like to write programs that generate static images, and that is why we will learn to use another feature of GLUT who worthily fulfills this purpose. Indeed, there is a command that allows us to specify what function to run each time interval<\/p>\n<p class=\"has-medium-font-size\">Unlikely we would like to write programs that generate static images, and that is why we will learn to use another feature of GLUT who worthily fulfills this purpose. Indeed, there is a command that allows us to specify what function to run each time interval<\/p>\n<pre class=\"wp-block-code\"><code>glutTimerFunc void (unsigned int msecs, void (* func) (int value), int value)<\/code><\/pre>\n<p class=\"has-medium-font-size\">The first parameter specifies the number of milliseconds GLUT must wait before running the function specified in the parameter (* func). Following listing carries an example:<\/p>\n<pre class=\"wp-block-code\"><code>void Timer(int v)\r\n{\r\n    glutPostRedisplay();\r\n    glutTimerFunc(1, Timer, 1);\r\n}\r\n\r\nvoid main()\r\n{\r\n    ...\r\n    ...    \r\n    glutTimerFunc(1, Timer, 1);\r\n    ...\r\n    ...\r\n}<\/code><\/pre>\n<p class=\"has-medium-font-size\">Here the function is called after 1 millisecond of delay, causing the redraw of the entire scene through the function RenderScene() aside from further activation of the timer.<\/p>\n<h2><span id=\"Conclusions\" class=\"ez-toc-section\"><\/span>Conclusions<\/h2>\n<p class=\"has-medium-font-size\">This article has covered all the basics needed to use GLUT to implement our test applications. Anyone wishing to know more about and\/or wishing to learn the use of joystick, mouse, 3D texts and more into programs, can refer to the documentation inside the attached package.<\/p>\n<h2><span id=\"Bibliography\" class=\"ez-toc-section\"><\/span>Bibliography<\/h2>\n<ol class=\"has-medium-font-size\">\n<li>Richard S.Wright jr. and Benjamin Lipchak, \u201cOpenGL SuperBible \u2013 Third Edition\u201d, SAMS, 2005, ISBN 0-672-32601-9<\/li>\n<\/ol>\n<h2><span id=\"Original_article\" class=\"ez-toc-section\"><\/span>Original article<\/h2>\n<ul class=\"wp-block-gallery columns-3 is-cropped\">\n<li class=\"blocks-gallery-item\">\n<figure><a href=\"https:\/\/i0.wp.com\/www.infodreams.it\/Assets\/pubblicazioni\/dev\/132\/01_copertina.png?ssl=1\"><img decoding=\"async\" class=\"wp-image-4581\" src=\"https:\/\/i0.wp.com\/www.infodreams.it\/Assets\/pubblicazioni\/dev\/132\/01_copertina.png?w=800&#038;ssl=1\" alt=\"\" data-id=\"4581\" data-recalc-dims=\"1\" data-recalc-dims=\"1\" \/><\/a><\/figure>\n<\/li>\n<li class=\"blocks-gallery-item\">\n<figure><a href=\"https:\/\/i0.wp.com\/www.infodreams.it\/Assets\/pubblicazioni\/dev\/132\/02_editoriale.png?ssl=1\"><img decoding=\"async\" class=\"wp-image-4583\" src=\"https:\/\/i0.wp.com\/www.infodreams.it\/Assets\/pubblicazioni\/dev\/132\/02_editoriale.png?w=800&#038;ssl=1\" sizes=\"(max-width: 684px) 100vw, 684px\" data-id=\"4583\" data-recalc-dims=\"1\" data-recalc-dims=\"1\" \/><\/a><\/figure>\n<\/li>\n<li class=\"blocks-gallery-item\">\n<figure><a href=\"https:\/\/i0.wp.com\/www.infodreams.it\/Assets\/pubblicazioni\/dev\/132\/03_indice.png?ssl=1\"><img decoding=\"async\" class=\"wp-image-4585\" src=\"https:\/\/i0.wp.com\/www.infodreams.it\/Assets\/pubblicazioni\/dev\/132\/03_indice.png?w=800&#038;ssl=1\" sizes=\"(max-width: 684px) 100vw, 684px\" data-id=\"4585\" data-recalc-dims=\"1\" data-recalc-dims=\"1\" \/><\/a><\/figure>\n<\/li>\n<li class=\"blocks-gallery-item\">\n<figure><a href=\"https:\/\/i0.wp.com\/www.infodreams.it\/Assets\/pubblicazioni\/dev\/132\/04_indice_2.png?ssl=1\"><img decoding=\"async\" class=\"wp-image-4587\" src=\"https:\/\/i0.wp.com\/www.infodreams.it\/Assets\/pubblicazioni\/dev\/132\/04_indice_2.png?w=800&#038;ssl=1\" sizes=\"(max-width: 684px) 100vw, 684px\" alt=\"\" data-id=\"4587\" data-recalc-dims=\"1\" data-recalc-dims=\"1\" \/><\/a><\/figure>\n<\/li>\n<li class=\"blocks-gallery-item\">\n<figure><a href=\"https:\/\/i0.wp.com\/www.infodreams.it\/Assets\/pubblicazioni\/dev\/132\/09_articolo_pg5.png?ssl=1\"><img decoding=\"async\" class=\"wp-image-4597\" src=\"https:\/\/i0.wp.com\/www.infodreams.it\/Assets\/pubblicazioni\/dev\/132\/09_articolo_pg5.png?w=800&#038;ssl=1\" sizes=\"(max-width: 683px) 100vw, 683px\" alt=\"\" data-id=\"4597\" data-recalc-dims=\"1\" data-recalc-dims=\"1\" \/><\/a><\/figure>\n<\/li>\n<li class=\"blocks-gallery-item\">\n<figure><a href=\"https:\/\/i0.wp.com\/www.infodreams.it\/Assets\/pubblicazioni\/dev\/132\/10_articolo_pg6.png?ssl=1\"><img decoding=\"async\" class=\"wp-image-4599\" src=\"https:\/\/i0.wp.com\/www.infodreams.it\/Assets\/pubblicazioni\/dev\/132\/10_articolo_pg6.png?w=800&#038;ssl=1\" sizes=\"(max-width: 683px) 100vw, 683px\" alt=\"\" data-id=\"4599\" data-recalc-dims=\"1\" data-recalc-dims=\"1\" \/><\/a><\/figure>\n<\/li>\n<li class=\"blocks-gallery-item\">\n<figure><a href=\"https:\/\/i0.wp.com\/www.infodreams.it\/Assets\/pubblicazioni\/dev\/132\/11_articolo_pg7.png?ssl=1\"><img decoding=\"async\" class=\"wp-image-4601\" src=\"https:\/\/i0.wp.com\/www.infodreams.it\/Assets\/pubblicazioni\/dev\/132\/11_articolo_pg7.png?w=800&#038;ssl=1\" sizes=\"(max-width: 683px) 100vw, 683px\" alt=\"\" data-id=\"4601\" data-recalc-dims=\"1\" data-recalc-dims=\"1\" \/><\/a><\/figure>\n<\/li>\n<li class=\"blocks-gallery-item\">\n<figure><a href=\"https:\/\/i0.wp.com\/www.infodreams.it\/Assets\/pubblicazioni\/dev\/132\/12_articolo_pg8.png?ssl=1\"><img decoding=\"async\" class=\"wp-image-4603\" src=\"https:\/\/i0.wp.com\/www.infodreams.it\/Assets\/pubblicazioni\/dev\/132\/12_articolo_pg8.png?w=800&#038;ssl=1\" sizes=\"(max-width: 683px) 100vw, 683px\" alt=\"\" data-id=\"4603\" data-recalc-dims=\"1\" data-recalc-dims=\"1\" \/><\/a><\/figure>\n<\/li>\n<\/ul>\n<h2><span id=\"Downloads\" class=\"ez-toc-section\"><\/span>Downloads<\/h2>\n<div class=\"wp-block-file\"><a href=\"https:\/\/www.infodreams.it\/Assets\/pubblicazioni\/dev\/132\/132_demo.zip\">132_demo<\/a><a class=\"wp-block-file__button\" href=\"https:\/\/www.infodreams.it\/Assets\/pubblicazioni\/dev\/132\/132_demo.zip\" download=\"\">Download<\/a><\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Devoting some space to the GLUT library before we start to see how to use OpenGL will save us a lot of time later by not addressing issues related to &#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":33,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-255","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.infodreams.it\/main\/wp-json\/wp\/v2\/pages\/255","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.infodreams.it\/main\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.infodreams.it\/main\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.infodreams.it\/main\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.infodreams.it\/main\/wp-json\/wp\/v2\/comments?post=255"}],"version-history":[{"count":10,"href":"https:\/\/www.infodreams.it\/main\/wp-json\/wp\/v2\/pages\/255\/revisions"}],"predecessor-version":[{"id":260,"href":"https:\/\/www.infodreams.it\/main\/wp-json\/wp\/v2\/pages\/255\/revisions\/260"}],"up":[{"embeddable":true,"href":"https:\/\/www.infodreams.it\/main\/wp-json\/wp\/v2\/pages\/33"}],"wp:attachment":[{"href":"https:\/\/www.infodreams.it\/main\/wp-json\/wp\/v2\/media?parent=255"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}