You are on page 1of 35
2126123, 0:47 PM. Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial yet another insignificant programming rates... | TABLE OF CONTENTS (HIDE) 1. Setting Up OpenGL OpenGL Tutorial 2 oct ererene 3, Vertex, Primitive and Color An Introduction on 3.1 Example 2: Vertex, Primitive ar 3.2 OpenGLas a State Machine OpenGL with 2D 33 Naming Convention for Open 3.4 One-time Initialization initot Gra p hics 35 Callback Handler display() To set up OpenGl, depending on your programming platform, read: 1 How to write OpenGL programs in C/C++ Setting Up OpenGL 3.6 Setting up GLUT - main() 37 Color 3.8 Geometric Primitives 3.9 2D Coordinate System and the 4, Clipping-Area & Viewport 4.1 Example 3: Clipping-area and 5. Translation & Rotation 5.1 Example 4: Translation and Ro 6. Animation = How to write OpenGL programs in Java: JOGL or LWIGL. 6.1 Idle Function = How to write OpenGL{ES programs in Android, 62 Double Buffering 1.1 Example 1: Setting Up OpenGL and GLUT 63 Example 5: Animation using le 64 Double Buffering & Refresh R 65 Timer Function (sheaHetto- cpp) 6.6 Example 6: Animation via Time Make sure that you can run the "GLeiNello. cpp" described in “How to 67 More GLUT functions write OpenGL programs in C/C++", reproduced below: 6.8 Example 7: A Bouncing Ball (6 7. Handling Keyboard inputs with + 7.1 Example 8: Switching between 72 Example 9: Key-Controlled (GL 8, Handling Mouse Inputs with GLI 8.1 Example 10: Mouse-Controlle 82 Example 11: A Simple Paint pr ar 2 * GLOiHello.cpp: Test OpenGL/GLUT C/C++ Setup 3 * Tested under Eclipse COT with MinGa/Cygwin and CodeBlocks with MinGw 4 * To compile with -lfreegiut -1glu32 -lopengl32 soy 6 include // for MS Windows 7 include // GLUT, include glu.h and gl-h 8 8 /* Handler for window-repaint event. Call back when the window first appears and 1@ whenever the window needs to be re-painted. */ 3M void display() ( 12 glClearColor(9.0f, @.0F, @.0f, 1.0f); // Set background color to black and opaque 13. giClear(GL_COLOR_BUFFER_BIT); JJ Clear the color buffer (background) 4 1S _// Draw a Red 1x1 Square centered at origin tps: ntu.edusihomelehchualprogramminglopenglieg introduction. html 188 2126029, 9:47 PM Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial 16 glBegin(Gt_QuaDs) ; // Each set of 4 vertices form a quad v glColor3#(1.0F, @.0F, @.0f); // Red 18 glvertex2F(-0.5F, 8.57); // x,y 19 glvertex2f( 0.5f, -0.5#); 20 glvertex2f( 0.5f, 0.5F); 2 glvertex2f(-0.5f, 0.5); 22 glend(); 23 24 glFlush(); // Render now 2} 26 27 /* Main function: GLUT runs as a console application starting at main() */ 28 int main(int argc, char** argv) { 29 glutInit(&argc, argv); // Initialize GLUT 30 glutCreateWindow("OpenGL Setup Test"); // Create a window with the given title 31 glutInitWindowsize(32@, 328); // Set the window's initial width & height 32 glutTnitwindowPosition(s8, 58); // Position the window's initial top-left corner 33 glutDisplayFunc(display); // Register display callback handler for window re-paint 34 glutMainLoop(); // Enter the event-processing loop 35 return 0; 36) include ‘The header "windows." is needed for the Windows platform only. include We also included the GLUT header, which is guaranteed to include "glu-h* (for GL Utlity) and Opens). ‘The rest of the program will be explained in due course. 2. Introduction OpenGL (Open Graphics Library) is a cross-platform, hardware-accelerated, language-independent, industrial standard APL for producing 30 (including 2D) graphics. Modern computers have dedicated GPU (Graphics Processing Unit) with its own memory to speed up graphics rendering. OpenGL. is the software interface to graphics hardware. In other words, OpenGL graphic rendering commands issued by your applications could be directed to the graphic hardware and accelerated, We use 3 sets of libraries in our OpenGL programs 1.Core OpenGL (GL): consists of hundreds of commands, which begin with a prefix "gl" (eg. glColor, glvertex, giTranslate, glRotate). The Core OpenGL models an object via a set of geometric primitives such as point, line and polygon. 2. OpenGL Utility Library (GLU): built on-top of the core OpenGl to provide important utilities (such as setting camera view and projection) and more building models (such as qradric surfaces and polygon tessellation). GLU commands start with a prefix “glu” (e.g, gluLookAt, gluPerspective). 3. OpenGL Utilities Toolkit (GLUT): OpenGL is designed to be independent of the windowing system or ‘operating system, GLUT is needed to interact with the Operating System (such as creating a window, handling key and mouse inputs; it also provides more building models (such as sphere and torus). GLUT commands start with a prefix of "glut" (eg, glutCreatewindow, glutMouseFunc). GLUT is platform independent, which is built on top of platform-specific OpenGL extension such as GLX for X Window System, WGL for Microsoft Window, and AGL, CGL or Cocoa for Mac OS. Quoting from the openglorg: “GLUT is designed for constructing small to medium sized OpenGL. programs While GLUT is well-suited to learning OpenGL and developing simple OpenGL. applications, GLUT is not a full- featured tookit so large applications requiring sophisticated user interfaces are better off using native window tps: ntu.edu.sihomelehchualprogramminglopenglieg introduction. html 2135, 2126123, 0:47 PM Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial system toolkits. GLUT is simple, easy, and smalt” Alternative of GLUT includes SDL, 4,OpenGL Extension Wrangler Library (GLEW): "GLEW is a cross-platform open-source C/C++ extension loading library. GLEW provides efficient run-time mechanisms for determining which OpenGL extensions are supported on the target platform." Source and re-build binary available at httpy/glew.sourceforgenet/. A standalone utilty called "glewinfo.exe" (under the "bin" directory) can be used. to produce the list of OpenGL functions supported by your graphics system, 5, Others. 3. Vertex, Primitive and Color 3.1 Example 2: Vertex, Primitive and Color (GL@2Primitive. cpp) Try building and runnng this OpenGl. C/C++ program: 1 2 * GlozPrimitive.cpp: Vertex, Primitive and Color 3 * Draw Simple 20 colored Shapes: quad, triangle and polygon. ay 5 include // for MS Windows 6 include // GLUT, incluce glu.h and gl.h 7 8 /* Initialize Opensl Graphics */ 9 void sniesL() { 38 // Set “clearing” or background color 11 giclearcolor(e.eF, 9.0f, 8.0f, 1.@f); // Slack and opaque 2) 2 14 /* Handler for window-repaint event. Call back when the window first appears and 15 whenever the window needs to be re-painted. */ 16 void display() { 17 gilear(6l_CoLOR_BUFFER BIT); // Clear the color buffer with current clearing color 8 39 _// Define shapes enclosed within a pair of glBegin and glEnd 20 glegin(Gt_QuaDs); 1/ Bach set of 4 vertices form a quad 21 glcolor3#(1.ef, @.8f, @.0F); // Red 22 glvertex2f(-@.8f, @.1F); // Define vertices in counter-clockwise (CCW) order 23 glvertex2f(-@.2f, @.1F); // so that the normal (front-face) is facing you 24 glvertex2f(-0.2f, 8.7F); 2s glvertex2F(-@.8F, 0.74); 26 7 glcolor3f(@.ef, 1.0f, @.0f); // Green 28 glvertex2f(-@.7f, -0.6f); 29 glvertex2(-2.1f, -0.6f); 30 givertex2f(-0.1f, @.0f)3 31 glvertex2f(-0.7F, @.0f); 32 33, glColor3f(@.2f, @.2f, @.2f); // Dark Gray 34 glvertex2F(-8.9f, -@.74)3 35 glcolor2f(1.ef, 1.0, 1.0f); // wnite 36 glvertex2f(-0.5f, -0.7f); 37, glColor3f(@.2f, @.2f, @.2f); // Dark Gray 38 glvertex2f(-@.5f, -0.3f); 39 glcolor3#(1.eF, 1.0f, 1.0f); // white 10 glvertex2F(-0.9F, -@.3f)3 41 glend(); a 43° glBegin(GL_TRIANGLES); // Fach set of 3 vertices form a triangle 44 glcolor3#(@.ef, @.0f, 1.0F); // Blue tps: ntu.edu.sihomelehchualprogramminglopengliog introduction. html 385 2126029, 9:47 PM Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial 45 glvertex2f(a.1f, -0.6F); 46 glvertex2(a.7F, -0.6F); 47 glvertex2(@.4f, -0.1f); 43 49 glcolor3f(1.0f, 8.0f, 0.0F); // Red 50 plvertex2f(a.3f, -0.4F); 31 glcolor3f(@.0f, 1.0f, @.0f)3 // Green 52 glvertex2(9.9f, -0.4f); 33 gicolor3f(@.0f, 0.0f, 1.0f); // Blue 54 glvertex2F(a.6f, -0.94); 35 glend(); 56 37 glBegin(Gl_POLYGON) ; // These vertices form a closed polygon 58 glColor3#(1.0f, 1.0f, @.@f); // Yellow 59 glvertex2F(a.4f, @.2F); 60 plvertex2(0.6f, @.2f); 61 glvertex2f(@.7F, @.4f); 62 glvertex2(0.6F, @.6F); 63 glvertex2f(@.4f, @.6F); 64 glvertex2#(0.3f, 2.4); 65 glend(); 66 67 elFlush(); // Render now 6} 69 7@ /* Main function: GLUT runs as a console application starting at main() */ 71 int main(int arge, char** argv) { n glutInit(8argc, argv); JI Initialize GLUT B glutCreateWindow("Vertex, Primitive & Color"); // Create window with the given title "4 glutInitWindowSize(326, 320); // Set the window's initial width & height 75 BlutInitWindowPosition(s®, $8); // Position the window's initial top-left corner 76 glutoisplayFunc (display); // Register callback handler for window re-paint event 7 inteL(); 11 Our own OpenGL initialization 78 glutMainLoop(); // Enter the event-processing loop 79 return @; 80) The expected output and the coordinates are as follows. Take note that 4 shapes have pure color, and 2 shapes have color blending from their vertices, (m'| Vertex, Primitive & Color | = | shall explain the program in the following sections. hitps:twwn3.ntu.edu.sgihomelehchualprogramminglopenglieg_introduction html 405 2126029, 9:47 PM Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial 3.2 OpenGL as a State Machine OpenGL operates as a state machine, and maintain a set of state variables (such as the foreground color, background color, and many more). Ina state machine, once the value of a state variable is set, the value persists until anew value is given For example, we set the “clearing” (background) color to black once in initGL(). We use this setting to clear the window in the display() repeatedly (display() is called back whenever there is a window re-paint request) - the clearing color is not changed in the entire program. // Tm init6L(), set the “clearing” on background color glclearcolor(@.0f, 0.0f, @.eF, 1.0F); // black and opaque // In display(), clear the color buffer (i-e., set background) with the current “clearing glClear(Gl_cOLOR_SUFFER SIT); color Another example: If we use glColor function to set the current foreground color to "red", then “red” will be used for all the subsequent vertices, until we use another g1Color function to change the foreground color. Ina state machine, everything shall remain until you explicitly change it! 3.3. Naming Convention for OpenGL Functions ‘An OpenGL functions: = begins with lowercase gl (for core OpenGL}, glu (for OpenGL Utility) or glut (for OpenGL Utility Toolkit). «= followed by the purpose of the function, in camel case (intial-capitalized), e.g, g1Color to specify the drawing color, glVertex to define the position of a vertex, «= followed by specifications for the parameters, e.g, glColor3¢ takes three Float parameters. glVectex2i takes two int parameters. (This is needed as C Language does not support function overloading, Different versions of the function need to be written for different parameter ists) ‘The convention can be expressed as follows: returntype glfunction(234]{sifd] (type value, ...); // 2, 3 or 4 paraneters returntype glfunction{234][sifd]v (type *vatue); // an array parameter ‘The function may take 2, 3, or 4 parameters, in type of s (GLshort), i (GLint), F (GLfloat) or d (GLdouble). The 'v' (for vector) denotes that the parameters are kept in an array of 2, 3, of 4 elements, and pass into the function as an array pointer. OpenGL defines its own data types: « Signed Integers: GLbyte (-bit), Lshort (16-bit), GLint (32-bit) = Unsigned Integers: GLubyte (8-bit) , GLushort (16-bit), GLuint (32-bit. Floating-point numbers: GL#loat (82-bit), GLdouble (64-bit), LcLanpf and GLeanpé (between 00 and 1.0) ® GLboolean (unsigned char with 0 for false and non-0 for true) ® GLsizei (32-bit non-negative integers) = GLenum (32-bit enumerated integers) ‘The OpenGL types are defined via typedef in "gl." as follows: typedef unsigned int GLenun; typedef unsigned char GLboolean; typedef unsigned int GLbitfield; typedef void Gvoid; typedef signed char typedef short typedef int typedef unsigned char [+ A-byte signed */ /* 2-byte signed */ / a-byte signed */ /* a-byte unsigned */ hitps:wwn3.ntu.edu.sihomelehchualprogramminglopenglieg_introduction.htm| 5135 2126029, 9:47 PM Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial typedef unsigned short Glushort; /* D-byte unsigned */ typedef unsigned int GLuint; /* a-byte unsigned */ typedef int Gisizei; 7 a-byte signed */ typedef float GiFloat; /* single precision float */ typedef float GLclampf; /* single precision float in [8,1] */ typedef double Gtdouble; /* double precision float */ typedef double Guclampd; /* double precision float in [8,1] */ OpenGl’s constants begins with "GL GL_COLOR_BUFFER_BIT. ‘GLU_" or "GLUT", in uppercase separated with underscores, e.g, For examples, glvertex3f(L.1f, 2.2, 3.34); // 3 GLfloat paraneters glvertex2i(a, 5)3 // 2 GLint paranaters glcolora#(@.0F, 0.0f, @.0f, 1.0F); // 4 GLFloat paraneters Gidouble aVertex{] = (1.1, 2.2, 3.3}; glvertex3fv(avertex) ; 11 an array of 3 GLfloat values 3.4 One-time Ini lization initGL() ‘The initGL() is meant for carrying out one-time OpenGL i imitGL() is invoked once (and only once) in main(). lization tasks, such as setting the clearing color. 3.5 Callback Handler display() ‘The function display() is known as a callback event handler. An event handler provides the response to a particular event (such as key-press, mouse-click, window-paint). The function display() is meant to be the handler for window- paint event. The OpenGL graphics system calls back display() in response to a window-paint request to re-paint the window (e.g, window first appears, window is restored after minimized, and window is resized). Callback means that ‘the function is invoked by the system, instead of called by the your program. The Display() runs when the window first appears and once per subsequent re-paint request. Observe that we included OpenGL. graphics rendering code inside the display() function, so as to re-draw the entire window when the window frst appears and upon each re-paint request. 3.6 Setting up GLUT - main() GLUT provides high-level utilities to simplify OpenGL programming, especially in interacting with the Operating System (such as creating a window, handling key and mouse inputs). The following GLUT functions were used in the above program: = glutinit: initializes GLUT, must be called before other GL/GLUT functions. It takes the same arguments as the rain(). void glutinit(int targc, char **argy) = glutcreateWindow: creates a window with the given ttle int glutcreateWindow(char *titLe) = glutinitwindowsize: specifies the initial window width and height, in pixels void gluttnitWindowSize(int width, int height) i thindowPos: = glutn jon: positions the top-left corner of the initial window at (x, y). The coordinates (x,y), in term of pixels, is measured in window coordinates, ie, origin (0, 0) is at the top-left comer of the screen; x-axis pointing right and y-axis pointing down, void glutInitWindowPosition(int x, int y) tps: ntu.edu.sihomelehchualprogramminglopenglieg introduction. html 895 2126029, 9:47 PM Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial = glutDisplayFunc: registers the callback function (or event handler) for handling window-paint event. The OpenGL graphic system calls back this handler when it receives a window re-paint request. In the example, we register the function display() as the handler. void glutDisplayFune(void (*Func)(void)) = gluttainLoop: enters the infinite event-processing loop, ie, put the OpenGL graphics system to wait for events (such as re-paint), and trigger respective event handlers (such as display()}. void gluthainLoop() In the main() function of the example: glutinit(Rargc, argv) glutCreateWindon("Vertex, Primitive & Color’ BlutInitWindowsize(320, 328); glutinitwindowPosition(se, 58); We initialize the GLUT and create a window with a tite, an initial size and positon. glutDisplayFunc(display); We register display() function as the callback handler for wincow-paint event. That is, display() runs when the window first appears and whenever there is a request to re-paint the window. aniesto; We call the initGL() to perform all the one-time initialization operations. In this example, we set the clearing (background) color once, and use it repeatably in the display() function gluttainLoop(); We then put the program into the event-handling loop, awaiting for events (such as window-paint request) to trigger off the respective event handlers (such as display()) 3.7 Color We use g]Color function to set the foreground color, and giClearColor function to set the background (or clearing) color. void glcolor3#( V2 » DMs GL_POLYGON GL_TRTANGLES: GL_TRIANGLE STRIP 4 vy Ys V3 vi V aN 2 va “Vo GL_QUAD_STRIP acc LE_FAN Gt_quaps. OpenGL Primitives [A geometric primitive is defined by specifying its vertices via glVertex function, enclosed within a pair g1Begin and glend void glBegin(sLenum shape) void glvertex{234][sifd] (type x, type y, type 2, ...) void glVertex[234][sifd]v (type *coords) void glend() glBegin specifies the type of geometric object, such as GL_POINTS, GL_LINES, GlL_QUADS, GL_TRTANGLES, and GL_POLYGON. For types that end with 'S', you can define multiple objects of the same type in each g1Begin/glénd pair. For example, for GL_TRIANGLES, each set of three glVertex’s defines a triangle. ‘The vertices are usually specified in float precision. It is because integer is not suitable for trigonometric operations (needed to carry out transformations such as rotation). Precision of float is sufficient for carrying out intermediate operations, and render the objects finally into pixels on screen (with resolution of says 800x600, integral precision). double precision is often not necessary. In the above example glBegin(GL_QUAns); sees @ quads with 12x glvertex() .... elend(); wwe define 3 color quads (GL_QUADS) with 12x glVertex() functions. tps: ntu.edu.sihomelehchualprogramminglopenglieg introduction. html 8135, 2126123, 0:47 PM, ‘Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial glcolor3#(1.0F, 0.0f, 0.0); glvertex2F(-0.8F, @.1F); glvertex2f(-2.2F, @.1f); glvertex2F(-8.2F, 2.74); glvertex2F(-8.8F, 0.74); We set the color to red (R=1, G=0, B=0). All subsequent vertices will have the color of red. Take note that in OpenGl, color (and many properties) is applied to vertices rather than primitive shapes. The color of the a primitive shape is, interpolated from its vertices. We similarly define a second quad in green. For the third quad (as follows), the vertices have different color, The color of the quad surface is interpolated from its vertices, resulting in a shades of white to dark gray, as shown in the output. elcolor3¢(@.2F, 0.2f, @.2f); // Dark Gray glVertex2F(-8.9F, -8.7F); gicolor3#(1.0, 1.0f, 1.04); // white glvertex2F(-0.5F, -2.7F); glcolor3#(2.2, @.2f, 0.2); // Dark Gray glvertex2F(-2.5F, -2.3f); glcolor3¢(1.0F, 1.0f, 1.0f); // white glVertex2F(-2.5, -8.3f); 3.9 2D Coordinate System and the Default View The following diagram shows the OpenGL 2D Coordinate System, which corresponds to the everyday 2D Cartesian coordinates with origin located at the bottom-left corner. +y(up) 4y(up) valle +x (right) wth +x (right) OpenGL20 Coordinates Viewport Coordinates Clipping-Area ena (default of 2x2 square (width-by-height in pixels) centered at origin) ‘The default OpenGL 2D clipping-area (ic, what is captured by the camera) is an orthographic view with x and y in the range of -1.0 and 1.0, ie, a 2x2 square with centered at the origin. This clipping-area is mapped to the viewport on the screen, Viewport is measured in pixels. Study the above example to convince yourself that the 2D shapes created are positioned correctly on the screen. 4. Clipping-Area & Viewport ‘Try dragging the corner of the window to make it bigger or smaller. Observe that all the shapes are distorted, tps: ntu.edu.sihomelehchualprogramminglopenglieg introduction. html 935 2126128, 9:47 PM ‘An introdution on OpenGL wth 20 Graphics - OpenGl. Tutorial We can handle the re-sizing of window via a callback handler reshape(), which can be programmed to adjust the ‘Openst clipping-area according to the window's aspect ratio. Viewport Clipping Area Clipping Area and Viewport: Objects will be distorted if the aspect ratios of the clipping area and viewport are different. Clipping Area: Clipping area refers to the area that can be seen (ie,, captured by the camera), measured in OpenGL. coordinates. ‘The function gluortho2d can be used to set the clipping area of 2D orthographic view. Objects outside the clipping area will be clipped away and cannot be seen, Void gluortho20(GLdouble Left, GLéouble right, GLdouble bottom, GLdouble top) // The default clipping area is (-1.0, 1.0, -1.0, 1.0) in OpenGL coordinates, 1] i.e., 22 square centered at the origin. ‘To set the clipping area, we need to issue a series of commands as follows: we first select the so-called projection matrix for operation, and reset the projection matrix to identity. We then choose the 2D orthographic view with the desired clipping area, via gluortho20(). J Set to 20 orthographic projection with the specified clipping area giMatrixtode(GL_PROJECTION); __// Select the Projection matrix for operation glLoadidentity()3 J/ Reset Projection matrix gluOrtho20(-1.0, 1.0, -1.0, 1.0); // Set clipping area's left, right, botton, top Viewport: Viewport refers to the display area on the window (screen), which is measured in pixels in screen coordinates (excluding the title ba). ‘The clipping area is mapped to the viewport. We can use glViewport function to configure the viewport, void glViewport(cLint xTopLeft, GLint yTopleft, GLsizei width, GLsizei height) Suppose the the clipping area's (left, right, bottom, top) is (-1.0, 1.0, -1.0, 1.0) (in OpenGL coordinates) and the viewport’ (xTopLeft, xTopRight, width, height) is (0, 0, 640, 480) {in screen coordinates in pixels), then the bottom-left ‘comer (-1.0, -1.0) maps to (0, 0) in the viewport, the top-right comer (1.0, 1.0) maps to (639, 479) It is obvious that if the aspect ratios for the clipping area and the viewport are not the same, the shapes wil be distorted. Take note that in the earlier example, the windows! size of 320x320 has a square shape, with a aspect ratio consistent with the default 2x2 squarish clipping-area 4.1 Example 3: Clipping-area and Viewport (GL@3Viewport. cpp) - + GLe3Viewport.cpp: Clipping-area and Viewport * Implementing reshape to ensure same aspect ratio between * clipping-area and the viewport. ” #include // for MS Windows include // GLUT, include glu.h and gl.h eyoununn tps: ntu.edusihomelehchualprogramminglopenglieg introduction. html 10135 2126123, 0:47 PM, 9 10 un 2 3 1a 15 16 v 18 19 20 2 2 2B 24 25 26 27 28 29 30 31 32 3 34 35 36 37 38 39 40 4a 42 43 44 45 46, 47 48 43 50 51 52 33 5a 55 56 57 58 59 68 61 62 3 6a 65 66 67 6a 68 78 Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial /* Initialize OpenGL Graphics */ void initeL() ¢ // Set “clearing” or background color glClearColor(9.0F, 0.0f, 8.0F, 1.0f); // Black and opaque y void display() { glClear(GL_cOLOR_BUFFER_BIT); us // Define shapes enclosed within a glBegin(Gt_QuaDs); glColor3f(1.0F, @.0f, 0.0F); glvertex2f(-0.8f, @.1f); glvertex2#(-0.2f, @.1f); glvertex2#(-@.2f, @.74)} glvertex2f(-0.8f, 2.7); glcolor3#(0.0F, 1.0F, 0.0F)5 glvertex2#(-0.7F, -8.6F); givertex2#(-0.1F, -0.6F); givertex2t(-0.1F, 0.0f); glvertex2t(-0.7F, 8.0F); glcolor3#(0.2F, 0.2, 0.2F)5 glvertex2#(-0.9F, -0.7#); glcolor3¢(1.0F, 1.0F, 1.8F)5 glvertex2f(-0.5F, -8.7F); glColor3#(9.2F, @.2F, 0.2); glvertex2F(-0.5¢, -0.3¢); glcolor3#(1.0f, 1.0f, 1.0F)5 glvertex2#(-0.9F, -0.3#); glend(); glBegin(GL_TRIANGLES) ; glColor3#(0.F, @.0f, 1.0F); glvertex2F(@.1F, -0.6f); glvertex2#(@.7F, -@.6f); glvertex2F(@.4f, -@.1f); gicolorsé(1.0F, 0.0F, 0.0F)5 glvertex2#(0.3f, -0.4F); Elcolor3#(9.0F, 1.0F, 8.0F); glvertex2#(0.9f, -0.4F); gicolor3#(0.0F, 0.0F, 1.0F)5 glvertex2#(2.6F, -0.9f); glend(); elBegin(GL_POLYGON); glColor3#(1.0f, 1.0F, 0.0F)5 glvertex2#(@.4f, 0.2F); givertex2#(@.6F, 0.2f); glvertex2f(@.7F, 0.4f); glvertex2F(@.6F, 0.6F); glvertex2#(@.4f, 0.6F); glvertex2#(@.3f, 0.4f); glnd(); glFlush(); // Render now } Ww uv uv uw “ “ uw us uw “ Ww uw uw uw u“ u Clear the color buffer with current clearing color pair of glBegin and glénd Each set of 4 vertices form a quad Red Define vertices in counter-clockwise (CCW) order so that the normal (front-face) is facing you Green Dark Gray Uhite Dark Gray white Each set of 3 vertices form a triangle Blue Red Green Blue These vertices form a closed polygon Yellow /* Handler for window re-size event. Called back when the window first appears and whenever the window is re-sized with its new width and height */ Hitps:wwn3.ntu.edsihomelehchualprogramminglopenglieg introduction. html 1188 2126123, 0:47 PM Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial 71 void reshape(GLsizei width, GLsizei height) { // GLsizei for non-negative integer 72 IJ Compute aspect ratio of the new window 73 Af (height == @) height = 4; 11 To prevent divide by @ 74 Gl float aspect = (Glfloat)width / (GLFloatheight; 5 76 JJ Set the viewport to cover the new window 77 ——-glViewport(@, @, width, height); 8 79‘ Set the aspect ratio of the clipping area to match the viewport 80 glMatrixitode(GL_PROJECTION); // To operate on the Projection matrix 81 glLoadrdentity(); // Reset the projection matrix 82 Af (width >= height) { 8 // aspect >= 1, set the height from -1 to 1, with larger width Ba gluortho20(-1.0 * aspect, 1.0 * aspect, -1.0, 1.0); 8 else { 86 // aspect <1, set the width to -1 to 1, with larger height 7 gluortho20(-1.0, 1.0, -1.0 / aspect, 1.0 / aspect); so} 8} 20 91 /* Nain function: GLUT runs as a console application starting at main() */ 92 int main(int arge, char** argy) ( 93 glutinit(Sargc, argv); // Initialize GLUT 94 glut InitWindowSize(64@, 480); // Set the window's initial width & height - non-square 95 glut InitWindowPosition(5e, 58); // Position the window's initial top-left corner 96 _glutCreateWindow("Viewport Transform”); // Create window with the given title 97 —_glutDisplayFunc(display); // Register callback handler for window re-paint event 98 glutReshapeFunc(reshape) ; // Register callback handler for window re-size event 99 initeL(); // Our onn OpenGL initialization 1@@ ——_glutMainLoop(); // Enter the infinite event-processing loop 101 return 8; 02} ‘A reshape() function, whichis called back when the window first appears and whenever the window is re-sized, can be used to ensure consistent aspect ratio between clipping-area and viewport, as shown in the above example. The graphics sub-system passes the window's width and height. in pixels, into the reshape(). GiFloat aspect = (GLfloat)width / (6Lfloat)height; We compute the aspect ratio of the new re-sized window, given its new width and height provided by the graphics ‘sub-system to the callback function reshape(). glViewport(®, ®, width, height); We set the viewport to cover the entire new re-sized window, in pixels. ‘Try setting the viewport to cover only a quarter (lower-right qradrant) of the window via glViewport(a, @, width/2, height/2) iglMat rixtode(GL_PROJECTION) ; glLoadidentity() Af (width >= height) ( gluortho20(-1.8 * aspect, 1.@ * aspect, -1.8, 1.6); } else { gluortho20(-1.8, 1.0, -1.8 / aspect, 1.0 / aspect); » We set the aspect ratio of the clipping area to match the viewport. To set the clipping area, we first choose the operate on the projection matrix via gIMatrixode(GL_PROJECTION). OpenGL has two matrices, a projection matrix (which deals with camera projection such as setting the clipping area) and a model-view matrix (for transforming the objects {from their local spaces to the common world space). We reset the projection matrix via glLoadTdentity(). Finally, we invoke gluortho20() to set the clipping area with an aspect ratio matching the viewport. The shorter side has the range from -1 to +1, as illustrated below: tps: ntu.edu.sihomelehchualprogramminglopenglieg introduction. html 12135 2126123, 0:47 PM Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial Clipping Area Viewport Viewport % Transform / (0,0) aspect = w/h -1x aspect 1x aspect Clipping Area and Viewport: same aspect ratio for the clipping area and viewport to ensure that the objects are not distorted. We need to register the reshape() callback handler with GLUT via glutReshapeFunc(.) in the main() as follows: Ant main(int argc, char** argv) { glutinitwindowSize(64@, 480); glutReshapeFunc(reshape); y In the above main() function, we specity the initial window size to 640x480, which is non-squarish. Try re-sizing the window and observe the changes. Note that the reshape() runs at least once when the window first appears. Its then called back whenever the window is re-shaped. On the other hand, the initGL() runs once (and only once); and the display() runs in response to window re-paint request (eg. after the window is re-sized). 5. Translation & Rotation In the above sample, we positioned each of the shapes by defining their vertices with respective to the same origin (called world space). It took me quite a while to figure out the absolute coordinates of these vertices Instead, we could position each of the shapes by defining their vertices with respective to their own center (called ‘model space or lacal space). We can then use translation and/or rotation to position the shapes at the desired locations in the world space, as shown in the following revised display() function 5.1 Example 4: Translation and Rotation (GL@4Mode1Transform. cpp) 1 2 * GL@4ModelTransform.cpp: Model Transform - Translation and Rotation 3. * Transform primitives from their model spaces to world space. ay 5 include // for MS Windows 6 include // GLUT, include glu.h and gl-h 7 8 /* Initialize OpenGL Graphics */ 9 void initeL() { 18 // Set “clearing” or background color 31 glClearColor(9.0F, 0.0f, 8.8f, 1.8F); // Black and opaque n> B 14 /* Handler for window-repaint event. Call back when the window first appears and 15 whenever the window needs to be re-painted. */ 16 void display() 17 giClear(Gl_COLOR_SUFFER BIT); // Clear the color buffer tps: ntu.edusihomelehchualprogramminglopenglieg introduction. html 13935 2126/29, 9:47 PM 18 19 20 a 2 23 28 25 26 27 28 29 30 31 32 33 3a 35 36 37 38 39 40 a 42 43 44 45 46 47 48 49 50 51 52 53 5a 55 56 37 sa 59 60 61 62 63 6a 65 66 67 68 69 70 n n B os 75 76 n 78 79 Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial glMatrixMode(GL_MODELVIEW) ; 11 To operate on Model-View matrix glLoadtdentity()3 11 Reset the model-view matrix glTranslatef(-0.5f, @.4f, 0.0f); // Translate left and up glBegin(GL_QUADS); // Each set of 4 vertices form a quad gicolorsf(1.0F, 0.0, 0.0f); // Red glvertex2#(-0.3f, -0.3f); // Define vertices in counter-clockwise (CCH) onder glvertex2#( 0.3F, -8.36); // so that the normal (front-face) is facing you givertex2#( 0.3, 0.3f); glvertex2#(-0.3F, 0.36); elend(); glTranslatef(@.1f, -6.7F, @.0F)3 // Translate right and down glBegin(GL_QUADS); // Each set of 4 vertices form a quad gicolor3f(@.ef, 1.0F, @.0f); // Green glvertex2#(-0.3f, -0.3#); glvertex2#( 0.3, -0.34); glvertex2#( 0.3, 0.36); glvertex2#(-0.3, 0.38); glend(); glTranslatef(-0.3f, -@.2F, @.0f); // Translate left and down elBegin(Gt_QUADS); // Each set of 4 vertices form a quad glcolor3#(0.2f, @.2F, @.2); // Dark Gray glvertex2#(-0.2F, -0.2F); glColor3#(1.0f, 1.0f, 1.0F); // white glvertex2f( 0.2F, -0.26); glcolor3#(@.2f, 0.2F, @.2f); // Dark Gray glvertex2#( 0.2, 0.2F); glColor3#(1.0F, 1.0f, 1.F); // white glvertex2#(-0.2, 0.2F); glend(); glTranslatef(1.1#, 8.2f, @.0f); // Translate right and up glBegin(Gl_TRIANGLES); // Each set of 3 vertices form a triangle gicoloraf(0.0F, 0.0F, 1.0f); // slue glvertex2#(-0.3F, -0.2#); gvertex2#( 0.36, -0.26); glvertex2#( 0.0, 0.3f); glend(); gltranslatef(9.2F, -0.3f, 0.0f); // Translate right and down glRotatef(180.0f, 0.0f, 0.0f, 1.0f); // Rotate 180 degree glBegin(GL_TRIANGLES) ; // Each set of 3 vertices form a triangle glColor3#(1.0F, 0.0f, @.0F); // Red glvertex2#(-0.3F, -0.2F); glColor3#(2.0F, 1.0F, @.0F); // Green glvertex2#( 0.36, -0.26); glColor3#(0.0f, 8.0f, 1.0F); // Blue givertex2#( 0.0, 0.34); glend(); glRotatef(-180.0F, 0.0f, @.0f, 1.0f); // Undo previous rotate gltranslatef(-0.1f, 1.0f, 0.0f)5 // Translate right and down glBegin(GL_POLYGON) ; 1/ The vertices form one closed polygon glcolor3f(1.eF, 1.0F, @.0f)5 // Yellow elvertex2#(-0.1f, -0.2#); glvertex2#( 0.1f, -0.2#); givertex2#( 0.2f, 9.0f); givertex2#( 0.1f, 0.24); glvertex2#(-0.1f, 9.26); glvertex2#(-0.2f, 0.0F); hitps:twwn3ntu.edu.sgihomelehchualprogramminglopenglieg_introduction html 14035 2126123, 0:47 PM, Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial ae glend()3 a1 82 glFlush();// Render now 3 > 24 85 /* Handler for window re-size event. Called back when the window first appears and 86 whenever the window is re-sized with its new width and height */ 87 void reshape(GLsizei width, Glsizei height) { // Glsizei for non-negative integer 88 // Compute aspect ratio of the new window 29 if (height == @) height = 1; // To prevent divide by @ 98 -GLFlloat aspect = (GLfloat)width / (GLfloat height; 91 92 // Set the viewport to cover the new window 93 glViewport(®, @, width, height); 94 95 // Set the aspect ratio of the clipping area to match the viewport. 96 glMatrixtode(GL_PROJECTION); // To operate on the Projection matrix 7 glloadrdentity(); 98 if (width >= height) { 99 J/ aspect >= 1, set the height fron -1 to 1, with larger width 100 gluortho20(+1.8 * aspect, 1.0 * aspect, -1.0, 1.6); 101 } else ¢ 102 // aspect <1, set the width to -1 to 1, with larger height 103 gluOrtho20(-1.8, 1.0, -1.8 / aspect, 1.8 / aspect); 104 y 105) 106 107 /* Main function: GLUT runs as a console application starting at main() */ 108 int main(int argc, char** argv) { 409 glutinit(argc, argv); J/ initialize GLUT 110 glutinitwindowsize(sao, 480); // Set the window's initial width & height ~ non-square 31 gluttnitiindowPosition(se, 5@); // Position the window's initial top-left corner 112 __glutcreateWindox("Nodel Transform"); // Create window with the given title 413 glutDisplayFunc(display); 1/ Register callback handler for window re-paint event 114 _glutReshapeFunc(reshape); // Register callback handler for window re-size event 115 initet(; // ur oun OpenGL initialization 316 glutMaintoop(); // Enter the infinite event-processing loop 117 return @; us} glMatrixtode(GL_MODELVIEW); // To operate on model-view matrix glLoadidentity(); 11 Reset ‘Translation and rotation are parts of so-called model transform, which transform from the objects from the local space (or model space) to the commen world space. To carry out model transform, we set the matrix mode to mode-view matrix (6L_MODELVIEW) and reset the matrix. (Recall that in the previous example, we set the matrix mode to projection ‘matrix (GL_PROJECTION) to set the clipping area) OpenGL is operating as a state machine. That is, once a state is set, the value of the state persists until it is changed. In other words, once the coordinates are translated or rotated, all the subsequent operations will be based on this coordinates. ‘Translation is done via gl Translate function: void gitransiatef (GLfloat x, Glfloat y, GLfloat 2) Uf where (x, y» 2) is the translational vector Take note that glTranslatef function must be placed outside the glegin/glénd, where as glColor can be placed inside g1Begin/glend. Rotation is done via glRotatef function: tps: ntu.edu.sihomelehchualprogramminglopenglieg introduction. html 15135 2126123, 0:47 PM, ‘Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial void glRotatef (cLfloat angle, GLfloat x, GLfloat y, GLfloat 2) Jf where angle specifies the rotation in degree, (x, y, z) forms the axis of rotation. Take note that the rotational angle is measured in degrees (instead of radians) in OpenGL. In the above example, we translate within the x-y plane ( plane). and rotate about the z-axis (which is normal to the x-y 6. Animation 6.1 Idle Function To perform animation (eg, rotating the shapes), you could register an idle() callback handler with GLUT, via glutIdleFunc command. The graphic system will call back the idle() function when there is no other event to be processed. void glutidleFunc(void (*fune)(void)) In the idle() function, you could issue glutPostRedi splay command to post a window re-paint request, which in turn will activate display() function. void idle() { glutPostRedisplay(); // Post 2 re-paint request to activate display() » ‘Take note that the above is equivalent to registering display() as the idle function 1 wain gluttdleFunc(display); 6.2 Double Buffering Double buffering uses two display buffers to smoothen animation. The next screen is prepared in a back butter, while the current screen is held in a front buffer. Once the preparation is done, you can use glut SwapBuffer command to swap the front and back buffers. To use double butfering, you need to make two changes: 1-In the wain(), include this line before creating the window. sluttnitossplayhode(GLUT_DOUBLE); // Set double buffered node 2. Inthe display() function, replace glFlush() with glutSwapButfers(), which swap the front and back buffers. Double buffering should be used in animation, For static display, single buffering is sufficient. (Many graphics hardware always double buffered, so itis hard to see the differences) 6.3 Example 5: Animation using Idle Function (GLO5IdleF unc. cpp) The following program rotates all the shapes created in our previous example using idle function with double buffering, 17 2 * GLoSIdleFunc.cpp: Translation and Rotation 3 * Transform primitives from their model spaces to world space (Model Transform). ay 5 include // for MS Windows 6 include // GLUT, include glu.h and gl.h 7 8 // Global variable 9 GLfloat angle = 0.0f; // Current rotational angle of the shapes tps: ntu.edusihomelehchualprogramminglopenglieg introduction. html 16135 2126123, 0:47 PM, 10 nu 2 3 a 15 16 v7 18 19 20 2 2 2B 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 a 42 43 44 45 46 47 43 49 50 51 52 53 54 55 56 37 58 59 6 61 62 63 6a 65 66 67 68 6 70 n Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial /* Initialize Opens Graphics */ void inite() ¢ 11 Set “clearing” or background color giclearColor(9.0f, @.0f, @.0f, 1.0F); // Black and opaque > /* called back when there is no other event to be handled */ void idle() { glutPostRedisplay(); // Post a re-paint request to activate display() > /* Handler for window-repaint event. Call back when the window first appears and whenever the window needs to be re-painted. */ void display() { giClear(Gl_COLOR_BUFFER_BIT); // Clear the color buffer glMatrixtode(GL_MODELVIEW); // To operate on Model-View matrix glloadrdentity(); 11 Reset the model-view matrix glPushMatrix(); // Save model-view matrix setting gltranslatef(-0.5f, 0.4f, 0.0); // Translate glRotatef(angle, 0.0f, @.0f, 1.0f); // rotate by angle in degrees g1Begin(GL_Quans) ; J] Each set of 4 vertices form a quad glcolor3#(1.0F, @.0f, @.0f); // Red glvertex2#(-0.3f, -0.3¢); glvertex2f( @.3f, -0.3F); glvertex2f( @.3f, 0.36); glvertex2#(-0.3f, 0.34); elend(); glPopMatrix() // Restore the model-view matrix glPushMatrix(); // Save model-view matrix setting elTranslatef(-0.4f, -0.3f, @.0F); // Translate glRotatef(angle, 0.0f, @.8F, 1.0f); // rotate by angle in degrees giBegin(Gt_QUADS); glcolor3#(8.0f, 1.0f, 8.8F); // Green glvertex2f(-0.3#, -0.34); elvertex2f( 0.36, -0.34); glvertex2#( 0.3, 0.34); glvertex2#(-0.3#, 8.34); glend(); elPophatrix(); // Restore the model-view matrix elPushatrix(); // Save model-view natrix setting gltranslatef(-0.7f, -0.5f, @.0f); // Translate glRotatef(angle, 0.0f, @.F, 1.0f); // rotate by angle in degrees elBegin(Gl_Quads); glColor3#(0.2F, 0.2, .2F)5 // Dark Gray glvertex2F(-0.2F, -0.2F); glcolor3#(1.0F, 1.0f, 1.8F); // hhite glvertex2f( 0.2F, -0.2F); glColor3#(8.2f, 8.2F, 8.2F)5 // Dark Gray glvertex2F( 0.2, 0.26); glColor3#(1.0F, 1.0f, 1.0); // bhite glvertex2#(-0.2F, 8.24); elend(); eiPophatrix(); // Restore the model-view matrix elPushtatrix(); // Save model-view natrix setting glTranslatef(0.4f, -0.3f, 0.0); // Translate elRotateF (angle, 0.0f, 0.0f, 1.0); // rotate by angle in degrees elBegin(GL_TRTANGLES); Hitps:wwn3.ntu.edsihomelehchualprogramminglopenglieg introduction. html 17135 2126123, 0:47 PM, R B 74 5 76 n 78 79 80 a1 82 83 34 85 26, 87 88 89 90 on 22 93 94 95 96 97 98 99 100 101 102 103 108 105 106 107 108 109 ue aa a2 13 1a 1s 116 uy 18 19 120 aa 122 123 124 25 126 27 18 129 130 131 132 133 Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial glcolor3#(0.0F, @.0f, 1.0F); // Blue glvertex2f(-0.3f, -0.2F); glvertex2f( @.3f, -0.2F); glvertex2f( 0.0f, 0.3); glénd(); glPoptatrix(); // Restore the model-view matrix elPushtatrix(); // Save model-view matrix setting elTranslatef(0.6F, -0.6f, 0.0f); // Translate glRotatef(180.0F + angle, 0.0F, @.0F, 1.0F); // Rotate 18@rangle degree glBegin(Gl_TRIANGLES); glColor3#(1.0F, 8.0F, 8.0F); // Red elvertex2f(-0.36, -0.2F); glColor3#(8.0F, 1.0f, 8.0F); // Green glvertex2#( 0.3, -0.24); glcolor3#(0.0f, @.0F, 1.0F); // Blue glvertex2f( 0.0f, 8.34); glend(); glPopMatrix(); // Restore the model-view matrix glPushMatrix(); // Save model-view matrix setting gliranslatef(9.5#, @.4f, @.0f); — // Translate ElRotatef (angle, 9.0F, 0.0f, 1.0F); // rotate by angle in degrees glBegin(Gt_POLYGON) ; glcolor3#(1.0f, 1.0f, 8.F); // Yellow glvertex2f(-0.1f, -0.2F); glvertex2f( 0.1f, -8.2F); glvertex2#( 0.2, 8.0F); glvertex2F( 0.1f, 0.2F); glvertex2#(-0.1, 0.24); glertex2#(-0.2F, 8.04); glend(); elPoptatrix()5 // Restore the model-view matrix glutswapBuffers()3 // Double buffered - swap the front and back buffers // Change the rotational angle after each display() angle += 0.245 y /* Handler for window re~size event. Called back when the window first appears and whenever the window is re-sized with its new width and height */ void reshape(GLsizei width, Glsizei height) { // GLsizei for non-negative integer // Compute aspect ratio of the new window if (height == @) height = 1; // To prevent divide by @ Gtfloat aspect = (GLfloat)width / (GLfloatyheight; 1/ Set the viewport to cover the new window glViewport(a, ©, width, height); 1/ Set the aspect ratio of the clipping area to match the viewport elMatrixtode(GL_PROJECTION); // To operate on the Projection matrix glloadidentity(); if (width >= height) ( // aspect >= 1, set the height fron -1 to 1, with larger width gluortho20(-1.0 * aspect, 1.0 * aspect, -2.0, 1.0); } else ( // aspect < 1, set the width to -1 to 1, with larger height gluortho20(-1.0, 1.0, -1.8 / aspect, 1.0 / aspect); ) Hitps:wwn3.ntu.edsihomelehchualprogramminglopenglieg introduction. html 18135 2126123, 0:47 PM Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial 134 /* Main function: GLUT runs as a console application starting at main() */ 135 int main(int arge, char** argv) { 136 glutInit(@arge, argv); // initialize GLUT 137 _glutTnitDisplayMode(GLUT_DOUBLE); // Enable double buffered mode 138 glutinitwindowSize(640, 480); // Set the window's initial width & height - non-square 139 glutInitkindowPosition(5@, 5@); // Position the window's initial top-left corner 142 —_glutcreateWindow("Animation via Tdle Function"); // Create window with the given title a41__glutDisplayFune(display); // Register callback handler for window re-paint event 442 _glutReshapeFunc(reshape); 1/ Register callback handler for window re-size event 443 glutIdleFunc(idle); // Register callback handler it no other event 14a init; 1/ Our own OpenGL initialization 145 glutNaintoop(); 1/ Enter the infinite event-processing loop 145 return @; ur} In the above example, instead of accumulating all the translations and undoing the rotations, we use glPushMatrix to save the current state, perform transformations, and restore the saved state via g1PopMatrix. (In the above example, we can also use glLoadidentity to reset the matrix before the next transformations) GiFloat angle = 9.0f; // Current rotational angle of the shapes We define @ global variable called angle to keep track of the rotational angle of all the shapes. We will later use glRotatef to rotate all the shapes to this angle. angle + 0.26; At the end of each refresh (in display()), we update the rotational angle of all the shapes, glutswapautfers(); 1/ Swap front and back Frarebutfer glutInitDisplayMode(GLUT_DOUBLE); // In main(), enable double buffered mode Instead of g1Flush() which flushes the framebuffer for display immediately, we enable double buffering and use glutSwapBufer() to swap the front- and back-buffer during the VSync for smoother display. void idie() glutPostRedisplay(); // Post a re-paint request to activate display() > glutidleFunc(idle); // In main() ~ Register callback handler if no other event We define an idle() function, which posts a re-paint request and invoke display(), if there is no event outstanding We register this idle() function in main() via glutTdleFune() 6.4 Double Buffering & Refresh Rate When double buffering is enabled, glutSwapBuffers synchronizes with the screen refresh interval (VSync). That is, the buffers will be swapped at the same time when the monitor is putting up a new frame, As the result, idle() function, at best, refreshes the animation at the same rate as the refresh rate of the monitor (60Hz for LCD/LED monitor). It may operates at half the monitor refresh rate (if the computations takes more than 1 refresh interval), one-third, one-fourth, and so on, because it need to wait for the VSyne. 6.5 Timer Function With idle(), we have no control to the refresh interval. We could register a Timer() function with GLUT via glutTimerFunc. The Timer() function will be called back at the specified fixed interval. void glutTinerFunc(unsigned int miltis, void (*func)(int value), value) J/ where millis is the delay in milliseconds, value will be passed to the timer function. tps: ntu.edu.sihomelehchualprogramminglopenglieg introduction. html 19135 2126123, 0:47 PM Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial 6.6 Example 6: Animation via Timer Function (GL@6TimerFunc.cpp) ‘The following modifications rotate all the shapes created in the earlier example counter-clackwise by 2 degree per 30 milliseconds. 1 /* 2 * GLo6TimerFunc.cpp: Translation and Rotation 3 * Transform primitives from their model spaces to world space (Model Transform). a4 5 include // for MS Windows 6 Hinelude // GLUT, include glu.h and gl.h 7 8 // global variable 9 GLfloat angle = 9.0f; // rotational angle of the shapes 18 int refreshitills = 30; // refresh interval in milliseconds nu 12 /* Initialize OpenGL Graphics */ 13 void initeL() ¢ 44 // Set “clearing” or background color 15 glclearcolor(@.0F, @.0f, 8.0f, 1.0f); // Black and opaque ww) v 18 /* Called back when timer expired */ 19 void Timer(int value) { 28 glutPostRedisplay(); J/ Post re-paint request to activate display() 2 BlutTimerFunc(refreshMills, Timer, @); // next Timer call milliseconds later 2} 2B 24 /* Handler for window-repaint event. Call back when the window first appears and 25 whenever the window needs to be re-painted. */ 26 void display() { 27 glClear(Gl_COLOR_BUFFER_BIT); // Clear the color buffer 28 glMatrixMode(GL_MODELVIEW) ; // To operate on Model-View matrix 29° glLoadIdentity(); // Reset the model-view matrix 38 31 glPushMatrix(); // Save model-view matrix setting 32 gltranslatef(-@.5f, @.4f, @.@f); // Translate 33 glRotatef(angle, @.0f, @.0f, 1.0); // rotate by angle in degrees 34 giBegin(GL_Qua0s); // Each set of 4 vertices form a quad 35 glcolor3#(1.0f, @.0F, .0F); — // Red 36 glvertex2#(-0.3f, -0.3#); 37 glvertex2f( 0.3f, -8.3f); 38 glvertex2f( @.3f, 8.3); 39 glvertex2#(-0.3f, 0.34); 48 glend(); 4 ‘glPopMatrix() 5 // Restore the model-view matrix a2 43 glPushMatrix(); // Save model-view matrix setting 44 glTranslatef(-0.4f, -0.3#, @.0f); // Translate 45 giRotatef (angle, @.0f, @.0f, 1.0f); // rotate by angle in degrees 46 glBegin(Gl_Quaps) ; 47 glcolor3f(8.ef, 1.0f, @.ef); // Green 48 glvertex2#(-@.3f, -6.3F); 49 glvertex2#( 0.37, -0.34); 5e glvertex2f( @.3f, 8.3F); 51 glvertex2f(-0.3f, 8.3); 52 glEnd(); 53 —_gPopttatrix(); // Restore the nodel-view matrix 5a 55 _glPushMatrix(); /1 Save nodel-view natrix setting 56 _giTranslatef(-0.7f, -0.5f, 8.0f); // Translate tps: ntu.edusihomelehchualprogramminglopenglieg introduction. html 20135 2126123, 0:47 PM, Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial 57 giRotatef(angle, @.0F, @.0f, 1.0f); // rotate by angle in degrees 58 _glBegin(Gt_QuaDs); 59 glcolor3#(8.2, @.2F, @.2f)5 // Dark Gray 60 glvertex2#(-0.2F, -0.2F); oa glcolor3#(1.0f, 1.0F, 1.0f); // White 2 givertex2F( 0.2F, -0.2F); 8 glcolor3#(0.2F, @.2F, 8.26); // Dark Gray 68 elvertex2f( 0.2f, 8.2F); 6s glolor3#(1.0f, 1.0f, 1.0f)5 // White 66 glvertex2#(-0.2F, 0.2#); 67 glend(); 68 glPopMatrix(); J] Restore the model-view matrix 69 7@ —— glPushMatrix(); // Save nodel-view natrix setting 71 _giTranslatef(@.4f, -0.3f, @.0f); —// Translate 72 glRotatef (angle, @.0F, @.0f, 1.0f); // rotate by angle in degrees 73 glBegin(GL_TRTANGLES) ; ” glcolor3#(9.0f, @.0F, 1.06); // Blue 7 glvertex2#(-0.3¢, -0.26); 76 glvertex2#( 0.3#, -0.24); n glvertex2t( 0.0f, 8.3¢); 7a glend(); 79 glPopMatrix(); J Restore the model-view matrix 80 81 giPushMatrix()3 // Save model-view matrix setting 82 giranslatef(0.6F, -0.6F, @.0f); —// Translate 83 —_glRotatef(180.0F + angle, 0.0f, @.0F, 1.0F); // Rotate 18@tangle degree 84 ——_glBegin(GL_TRTANGLES); 85 glcolor3#(1.0f, @.0f, 8.0f)5 // Red 86 glvertex2#(-0.3¢, -0.24); 87 glcolor3#(8.0f, 1.0F, 8.0F); // Green 88 elvertex2f( 0.3f, -8.2F); 89 glcolor3¢(0.0f, 0.0f, 1.06); // Blue 90 glvertex2#( 0.0, 8.34); st glend(); 92 glPoptiatrix(); /] Restore the model-view matrix 3 94 glPushMatrix()s /I Save nodel-view natrix setting 95 giranslatef(0.5f, @.4f, 0.0); // Translate 96 —_giRotatef(angle, @.0f, 0.0f, 1.6F); // rotate by angle in degrees 97 —_glBegin(GL_POLYGoN); 98 glcolor3#(1.0F, 1.0, @.0f)5 // Yellow 99 glvertex2#(-0.1F, -0.26); 100 glvertex2#( @.1#, -0.24); 10 glvertex2#( 0.2f, 0.0F); 302 glvertex2t( 9.1f, @.2F); 103 glvertex2f(-0.1F, 8.2F); 108 glvertex2#(-0.2F, 8.0); 305 glend(); 106 glPopMatrix(); J] Restore the model-view matrix 107 108 glutSwapBuffers(); // Double buffered - swap the front and back buffers 109 410 —_// Change the rotational angle after each display() ani angle += 2.0; m2} 13 114 /* Handler for window re-size event. Called back when the window first appears and 115 whenever the window is re-sized with its new width and height */ 116 void reshape(GLsizei width, Glsizei height) { // GLsizei for non-negative integer 117 // Compute aspect ratio of the new window 118 if (height == @) height = 1; /1 To prevent divide by 0 Hitps:wwn3.ntu.edsihomelehchualprogramminglopenglieg introduction. html 21135 2126123, 0:47 PM, 19 120 aa 122 123 aa 125 126 27 128 129 130 131 132 133 134 135 136 137 138 139 140 141 az 143 14a 145 146 147 1a 149 Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial GlFloat aspect = (GLfloat)width / (GLfloat)heights // Set the viewport to cover the new window glViewport(8, @, width, height); // Set the aspect ratio of the clipping area to match the viewport. giMatrixMode(GL_PROJECTION); // To operate on the Projection matrix glloadTdentity(); if (width >= height) { J/ aspect >= 1, set the height fron -1 to 1, with larger width gluortho20(+1.8 * aspect, 1.0 * aspect, -1.0, 1.0); y else ¢ // aspect <1, set the width to -1 to 1, with larger height gluortho2D(-1.8, 1.0, -1.8 / aspect, 1.0 / aspect); } ? 7* Main function: GLUT runs as a console application starting at main() */ int main(int argc, char** argv) { glutinit(@argc, argv); // initialize GLUT glutInitDisplayMode(6LUT_DOUBLE); // Enable double buffered mode BlutTnitWindowsize(64e, 480); // Set the window's initial width & height ~ non-square glutInitWindowPosition(5®, 5@); // Position the window's initial top-left corner glutCreateWindow("Animation via Idle Function”); // Create window with the given title glutoisplayFunc(display); 1/ Register callback handler for window re-paint event glutReshapeFunc(reshape); 1/ Register callback handler for window re-size event glutTimerFunc(@, Timer, @); // First timer call inmediately init6L(); 1/ ur own OpenGL. initialization glutMainLoop(); 1/ Enter the infinite event-processing loop return @3 , void Timer(int value) ¢ glutPostRedisplay(); 11 Po! glutTinerFunc(refreshMills, Timer, 0); // next re-paint request to activate display() Timer call milliseconds later We replace the idle() function by a timer() function, which post a re-paint request to invoke display(), after the timer expired glutTinerFunc(®, Timer, 0); // First timer call inmediately In main(), we register the timer() function, and activate the timer() immediately (with intial timer 0. 6.7 More GLUT functions = glutinitDisplayMode: requests a display with the specified mode, such as color mode (GLUT_RGB, GLUT_RG3A, GLUT_INDEX), single/double buffering (GLUT_SINGLE, GLUT_DOUBLE), enable depth (GLUT_DEPTH), joined with a bit ort" void gluttnitDisplayMode(unsigned int dispLayMode) For example, glutinitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); 11 Use GBA color, enable double buffering and enable depth buffer 6.8 Example 7: A Bouncing Ball (GL@7BouncingBall. cpp) ‘This example shows a ball bouncing inside the window. Take note that circle is not a primitive geometric shape in Openct, This example uses TRIANGLE_FAN to compose a circle tps: ntu.edu.sihomelehchualprogramminglopenglieg introduction. html 22135 2126029, 9:47 PM Anintroduction on OpenGL with 20 Graphics - OpenGL. Tutorial Bouncing Bal % ” 1 2 * GLo7BouncingBall.cpp: A ball bouncing inside the window 3 Oy 4 include // for MS Windows 5 include // GLUT, includes glu.h and gl-h 6 include —// Needed for sin, cos 7 define PL 3.14159265¢ a 9 2 J/ Global variables 1 char title[] = "Bouncing Ball (2D)"; // Windowed mode's title 11 int windowhidth = 649; // Windowed node's width 12 int windowHeight = 48; // Windowed node's height 13 int windowPosx = 58; // Windowed node's top-left corner x 14 int windowPosy = 58; —// Windowed node's top-left corner y 15 16 GLfloat ballRadius = 9.5f; // Radius of the bouncing ball 17 GLFloat ballx = 0.0F5 11 Ball's center (x, y) position 18 Glfloat bally = @.0f; 19 GLfloat ballxMax, ballx¥in, ballYMax, ballYMin; // Ball's center (x, y) bounds 20 Glfloat xSpeed = @.02F; // Ball's speed in x and y directions 21 Glfloat ySpeed = @.007F; 22 int refreshMillis = 30; // Refresh period in milliseconds 24 // Projection clipping area 25 Gldouble clipAreaXLeft, clipAreaxRight, clipAreaYBottom, clipAreaYTop; 27 /* Initialize OpenGL Graphics */ 28 void initsl() { 29 glClearColor(9., 0.8, 0.8, 1.8); // Set background (clear) color to black 30} 32 /* Callback handler for window re-paint event */ 33 void display() ( 34 giClear(GL_COLOR_BUFFER BIT); // Clear the color buffer 35 giMatrixMode(GL_MODELVIEW); —// To operate on the model-view matrix 36 _glloadidentity(); // Reset nodel-view natrix 37 38 —_giTranslatef(balIX, bally, 8.0f); // Translate to (xPos, yPos) 39 // Use triangular segments to form a circle 40 glBegin(Gl_TRTANGLE_FAN); aa glcolor3#(9.0f, @.0F, 1.0f)3 // Blue a2 glvertex2#(0.0f, 0.0F); 11 Center of circle 43 int nunsegnents = 109; 48 GLfloat angle; 45 for (int i = @; i <= munSegnents; its) { // Last vertex same as first vertex 46 angle = i * 2.0f * PI / nunSegnents} // 360 deg for all segnents ar glvertex2#(cos(angle) * ballRadius, sin(angle) * ballRadius); 48 ) 49 glénd(); hitps:twwn3ntu.edu.sgihomelehchualprogramminglopenglieg_introduction html 23195 2126123, 0:47 PM, se 51 52 53 54 55 56 37 58 59 a en 62 63 64 65 66 o7 68 6 70 n n B 1 75 76 7 78 79 88 a1 82 83 24 85 86 87 88 a9 98 on 92 33 94 95 96 7 98 99 100 101 102 103 10a 105 106 107 108 109 110 an Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial glutswapsuffers(); // Swap front and back buffers (of double buffered mode) // Animation Control - compute the location for the next refresh ballx += xSpeed; ballY += ySpeed; // Check if the ball exceeds the edges if (ballx > ballxmax) { ballx = ballxtax; xSpeed = -xSpeed; } else if (ballx < ballxMin) { ballx = ballxin; xSpeed = -xSpeed; } Af (ball > ballymax) { ballY = ballymax; ySpeed = -ySpeed; } else if (ballY < ballyMin) ¢ ally = ballYMin; ySpeed = -ySpeed; } /* Call back when the windows is re-sized */ void reshape(Glsizei width, Glsizei height) ( // Compute aspect ratio of the new window if (height == @) height = 1; // To prevent divide by & GLfloat aspect = (GLfloat)width / (GLfloat)height; // Set the viewport to cover the new window glViewport(@, @, width, height); 11 Set the aspect ratio of the clipping area to match the viewport glMatrixtode(GL_PROJECTION); // To operate on the Projection matrix giLoadIdentity(); J/ Reset the projection matrix Af (width >= height) ( clipareaxteft = -1.0 * aspect; clipAreaxRight = 1.0 * aspect; clipAreaYBottom = -1.0; clipAreayTop = 1.03 y else ¢ clipAreaxleft. = -1. cLipAreaxRight = 1.0; cLipareaysottom = -1.8 / aspect; ClipfreayTop = 1.0 / aspect; x gluortho20(clipAreaxLeft, clipAreaxRight, clipAreayBotton, clipAreaYTop) ; ballxiin = clipAreaxLeft + ballRadius; ballxitax = clipAreaxRight - ballRadius; ballYMin = clipAreavBotton + ballRadius; ballYMax = clipareavTop - ballRedius; } /* Called back when the timer expired */ void Timer(int value) { glutPostRedisplay(); _// Post @ paint request to activate display() glutTimerFunc(refreshMillis, Timer, @); // subsequent timer call at milliseconds } /* Main function: GLUT runs as a console application starting at main() */ int main(int argc, char** argv) { glutInit(@argc, argv); J/ Initialize GLUT Hitps:wwn3.ntu.edsihomelehchualprogramminglopenglieg introduction. html 24035, 2126123, 0:47 PM Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial a2 13 aa 1s 116 7 a 19 120 aaa 122 glutInitDisplayMode(6LUT_DOUBLE); // Enable double buffered mode glutInitwindowsize(windowWidth, windowHeight); // Initial window width and height ElutInithindowPosition(windowPosx, windowPos¥); // Initial window top-left corner (x, y) glutCreateWindow(title) ; // Create window with given title glutDisplayFunc(display); _// Register callback handler for window re-paint glutReshapeFunc(reshape); __// Register callback handler for window re-shape glutTimerFunc(@, Timer, @); // First timer call innediately initoL(); // Our own OpenGL initialization glutMainLoop(); // Enter event-processing loop return @; d {TODO} Explanation 7. Handling Keyboard Inputs with GLUT We can register callback functions to handle keyboard inputs for normal and special keys, respectively. = glutkeyboardFunc: registers calloack handler for keyboard event. void glutkeyboardFune (void (*func)(unsigned char key, nt x, int y) 11 key is the char pressed, e.g., ‘a’ or 27 for ESC 11 Q& y) 4s the mouse location in Windows' coordinates = glutSpecial Func: registers callback handler for special key (such as arrow keys and function keys). void glutspecialFunc (void (*func)(int spectalkey, int x, int y) 11 speciatkey: GLUT_KEY_* (* for LEFT, RIGHT, UP, DOMN, HOME, END, PAGE_UP, PAGE_OOWN, F1,. 11 ( y) 4s the mouse Tocation in Windows" coordinates F12). 7.1 Example 8: Switching between Full-Screen and Windowed-mode (GLe8Ful1screen. cpp) For the bouncing ball program, the following special-key handler toggles between full-screen and windowed modes using FY key. tr 2 * GL@BFulIScreen.cpp: Switching between full-screen mode and windowed-node 3047 4 ftinclude // for MS Windows: 5S #include // GLUT, includes glu.h and gl.h 6 #include —_// Needed for sin, cos 7 define PI 3.14159265¢ 8 9 // Global variables 1@ char title[] = "Full-Screen & Windowed Mode"; // Windowed mode's title 11 int windowWidth = 649; // Windowed node's width 12 int windowHeight = 48; // Windowed mode's height 13° int windowPosk = 5@; 1/ Windowed node's top-left corner x 14 int windowPosy = 50; /1 Windowed mode's top-left corner y 15 36 GLfloat ballRadius = 8.5; // Radius of the bouncing ball 17 GLfloat ballx = 8.6F; // Ball's center (x, y) position 18 GLfloat ballY = 8.0f; 19 GLfloat ballxMax, ballxMin, ball¥Max, ball¥Min; // Ball's center (x, y) bounds 28 GLfloat xSpeed = 0.02F; // Ball's speed in x and y directions 21 GLfloat ySpeed = 0.00745 22 int refreshitillis = 36; // Refresh period in milliseconds 23 24 // Projection clipping area 25 GLdouble clipAreaXLeft, clipAreaxRight, clipAreaYBotton, clipAreaYTop; tps: ntu.edusihomelehchualprogramminglopenglieg introduction. html 25135 2126123, 0:47 PM, 26 27 28 29 30 31 32 33 34 35 36 37 38 39 48 4a a2 43 44 45 46 47 43 49 se 51 52 53 54 55 56 37 58 59 a on 62 63 64 6s 66 o7 68 6 70 n n 2B cy 78 76 7 78 9 20 a1 82 83 284 85 86 87 Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial bool fullscreenMode = true; // Full-screen or windowed mode? /* Initialize OpenGL Graphics */ void initeL() { giClearColor(9.8, 0.6, 0.8, 1.8); // Set background (clear) color to black , /* Callback handler for window re-paint event */ void display() { giClear(Gt_COLOR_BUFFER BIT); // Clear the color buffer giMatrixMode(GL_MODELVIEW); // To operate on the model-view matrix glloadrdentity(); JI Reset model-view matrix giiranslatef(ballx, ballY, @.0f); // Translate to (xPos, yPos) // Use triangular segments to form a circle ‘elBegin(GL_TRIANGLE_FAN); glColor3#(0.0F, 0.0f, 1.0); // Blue glvertex2F(2.0F, 0.0f); // Center of circle int nunSegnents = 160; Gifloat angle; for (int i = @; i <= nunSegnents; i++) { // Last vertex sane as first vertex angle = i * 2.0F * PI / nunSegnents; // 360 deg for all segments glVertex2#(cos(angle) * ballRadius, sin(angle) * ballRadius); , glend(); glutswapBuffers(); // Swap front and back buffers (of double buffered mode) // Knimation Control - compute the location for the next refresh balix += xSpeed; bally += ySpeed; // Check if the ball exceeds the edges if (ballXx > ballxmax) { ballx = ballxiax; xSpeed = -xSpeed; } else if (ballx < ballxMin) ¢ ballx = ballxMin; xSpeed = -xSpeed; y Af (ally > ballymax) { bally = ballymax; ySpeed = -ySpeed; } else if (ballY < ballyMin) { ballY = ballYMin; ySpeed = -ySpeed; } /* Call back when the windows is re-sized */ void reshape(Gisizei width, Glsizei height) ( 11 Compute aspect ratio of the new window if (height == 0) height = 1; // To prevent divide by 0 GLfloat aspect = (GLfloat)width / (GLfloat)height; // Set the viewport to cover the new window glViewport(@, @, width, height); // Set the aspect ratio of the clipping area to match the viewport giMatrixMode(GL_PROJECTION); // To operate on the Projection matrix glloadrdentity(); // Reset the projection matrix if (width >= height) ( Hitps:wwn3.ntu.edsihomelehchualprogramminglopenglieg introduction. html 26135 2126123, 0:47 PM, 88 89 98 on 92 93 9a. 95 96 7 98 99 100 101 102 103 108 105 106 107 108 109 110 aa 12 13 aa 1s 116 7 ag ns 128 aaa 122 123 128 125 126 7 128 129 130 131 132 133, 134 135 136 137 138 139 140 141 az 143 14a 145, Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial Cliptreaxteft = -1.0 * aspects cLipAreaxRight = 1.0 * aspect; cLipAreayaottom = -1.0; clipAreayTop = 1.0; } else ( cliptreaxleft = -1.0; cLipAreaxRight = 1.0; cLipareaysottom = -1.0 / aspect; clipAreaTop = 1.0 / aspect } gluOrtho20(clipareaxLeft, clipAreaxRight, clipAreaYBottom, clipAreayTop) ; ballXMin = clipAreaxLeft + ballRadius; ballXMax = clipAreaxRight - ballRadius; ballYitin = clipAreayBottom + ballRadius; ballYMax = clipreaYTop - ballRadius; ? /* Called back when the timer expired */ void Timer(int value) { glutPostRedisplay(); _// Post a paint request to activate display() glutTimerFunc(refreshitillis, Timer, @); // subsequent timer call at milliseconds } /* Callback handler for special-key event */ void specialkeys(int key, int x, int y) { switch (key) { case GLUT_KEY_F1: _// Fi: Toggle between full-screen and windowed mode fullscreenMode = !fullscreentode; // Toggle state if (fullScreenMode) { // full-screen mode wWindowPosX = glutGet(GLUT_WINDOW_X); // Save paraneters for restoring later windowPosY = glutGet(GLUT_WINOOW_Y); windowWidth = glutGet (GLUT_WINDOW_WIDTH) ; windowHeight = glutGet (GLUT_WINDOW_HEIGHT) ; glutFuliscreen(); // Switch into full screen } else { // Windowed mode glutReshapeliindow(windowwidth, windowHeight); // Switch into windowed mode glutPositionlindow(windowPosX, windowPosx); // Position top-left corner ) break; ) 7* Nain function: GLUT runs as a console application starting at main() */ int main(int argc, char** argv) { glutinit(@argc, argv); // Initialize GLUT glutInitDisplayMode(GLUT_DOUBLE); // Enable double buffered node glutInitWindowsize(windowdidth, windowHeight); // Initial window width and height ElutInitWindowPosition(windowPosx, windowPos¥); // Initial window top-left corner (x, y) glutcreateWindow(title); _// Create window with given title glutDisplayFunc(display); _// Register callback handler for window re-paint glutReshapeFunc(reshape); __// Register callback handler for window re-shape glutTimerFunc(®, Tiner, ); // First timer call inmediately glutSpecialFunc(specialKeys); // Register callback handler for special-key event glutFullscreen(); // Put into full screen intel ()5 // Our own OpenGl initialization glutMainLoop(); 1/ Enter event-processing loop return @; } [TODO] Explanation tps: ntu.edu.sihomelehchualprogramminglopenglieg introduction. html 27135 2126123, 0:47 PM Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial [TODO] Using glVertex to draw a Circle is inefficient (due to the compute-intensive sin() and cos() functions). Try using GLU's quadric. 7.2 Example 9: Key-Controlled (GL@9KeyControl.cpp) For the bouncing ball program, the following key and special-key handlers provide exits with ESC (27), increase/decrease y speed with up-/down-arrow key, increase/decrease x speed with left-/right-arrow key, increase/decrease balls radius with PageUp/PageDown key. 1 2 * GLosKeyControl.cpp: A key-controlled bouncing ball BY 4 include // for MS Windows 5S include // GLUT, include glu.h and gl.h 6 include —// Needed for sin, cos 7 Wdefine PL 3.14159265¢ 8 9 // Global variables 10 char title[] = “Full-Screen & Windowed Mode"; // Windowed mode's title 11 int windowdidth = 640; // Windowed mode's width 12 int windowHeight = 480; // Windowed mode's height 13 int windowPosx = 50; // Windowed mode's top-left corner x 14 int windowPosY = 50; // Windowed mode's top-left corner y 45 16 GLfloat ballRadius = @.5#; // Radius of the bouncing ball 17 GLfloat ballX = 0.0f; // Ball's center (x, y) position 18 GLfloat ballY = 8.0F; 19 GLfloat ballxMax, balLotin, ballYMax, ballYMin; // Ball's center (x, y) bounds 28 GLfloat xSpeed = 0.02; 11 Ball's speed in x and y directions 21 GLfloat ySpeed = 0.007; 22 Int refreshMillis = 30; // Refresh period in milliseconds 23 24 // Projection clipping area 25. Gldouble clipAreaxLeft, clipAreaxRight, clipAreaYBotton, clipAreaYTop; 26 27 bool FullScreenMode = true; // Full-screen or windowed mode? 28 29 /* Initialize OpenGL Graphics */ 38 void initeL() ¢ 31 giClearColor(9.8, 0.8, 8.8, 1.0); // Set background (clear) color to black 32) 33 34 /* Callback handler for window re-paint event */ 35 void display() { 36 —-giClear(Gl_COLOR_SUFFER BIT); // Clear the color buffer 37 __glMatrixMode(GL_MODELVIEW); // To operate on the model-view matrix 38 —_glloadTdentity(); // Reset model-view matrix 39 49 giranslatef(ballX, ballY, @.8F); // Translate to (xPos, yPos) 41 // Use triangular segnents to form a circle 42 glBegin(GL_TRIANGLE_FAN); 43 glColor3#(8.0F, 8.0f, 1.0F); // Blue 48 glvertex2#(2.0F, 0.0f); // Center of circle 45 int nunSegnents = 100; 46 GLfloat angle; a7 for (int 1 = 0; i <= nunsegnents; it+) { // Last vertex same as first vertex 48 angle = i * 2.0F * PI / nunSegnents; // 360 deg for all segments 49 glVertex2f(cos(angle) * ballRadius, sin(angle) * ballRadius); 50 } 51 glend(); 32 tps: ntu.edusihomelehchualprogramminglopenglieg introduction. html 28135 2126123, 0:47 PM, 83 5a 55 56 57 58 59 62 61 62 63 6a 65 66 67 68 6 78 n n 3 os 6 76 n 78 79 80 a1 22 83 84 85 86, 87 88 89 98 on 92 93 94 95 96 7 98 99 108 101 102 103 108 105 106 107 108 109 ae aun 12 13 aa Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial glutswapauffers(); // Swap front and back buffers (of double buffered mode) 11 Animation Control ~ compute the location for the next refresh ballx += xSpeed; ballY += ySpeed; // Check if the ball exceeds the edges if (ballx > ballxmax) { ballx = ballxNax; xSpeed = -xSpeed; } else if (baLIX < ballXMin) ¢ ballX = ballxsing xSpeed = -xSpeed; } if (pally > ballymax) { ally = ballvtax; ySpeed = -ySpeed; } else if (ballY < ballyMin) ( bally = ballyMin; ySpeed = -ySpeed; > 7* Call back when the windows is re-sized */ void reshape(GLsizei width, Glsizei height) { // Compute aspect ratio of the new window Af (height == @) height = 1; // To prevent divide by & GLfloat aspect = (GLfloat)width / (GLfloat)height; // Set the viewport to cover the new window giViewport(@, @, width, height); // Set the aspect ratio of the clipping area to match the viewport glMatrixMode(GL_PROJECTION); // To operate on the Projection matrix glloadrdentity(); // Reset the projection matrix if (width >= height) ¢ cliptreaxteft. = -1.0 * aspects clipAreaxRight = 1.0 * aspect; cLipAreaYsottom = -1.05 clipareayTop = 1.0; y else ¢ clipareaxteft = -1.0; clipareaxRight = 1.0; cLipAreaYsottom = -1.0 / aspect; clipareayTop = 1.0 / aspects y gluOrtho20(clipareaxteft, clipAreaxRight, clipAreayBottom, clipAreayTop); ballxMin = clipareaxLeft + ballRadius; ballxMax = clipAreaxRight - ballRadius; ballYitin = clipAreaYBotton + ballRadius; ballYMax = clipAreaYTop - ballRadius; > /* Called back when the timer expired */ void Timer(int value) { glutPostRedisplay(); _// Post a paint request to activate display() glutTimerFunc(refreshMillis, Timer, @); // subsequent timer call at } /* Callback handler for normal-key event */ void keyboard(unsigned char key, int x, int y) { switch (key) { case 27: // ESC key Hitps:wwn3.ntu.edsihomelehchualprogramminglopenglieg introduction. html Liseconds 29135 2126029, 9:47 PM Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial 1s exit(e)5 116 break; 7 } us} 19 120 /* Callback handler for special-key event */ 121 void specialKeys(int key, int x, int y) { 122 switch (key) { 3. case GLUT_KEY_Fi: // Fi: Toggle between full-screen and windowed mode 128 fullscreenMode = !fullscreentode; // Toggle state as if (fullScreenMode) { // full-screen mode 126 windowPosX = glutGet(GLUT_WINDOW_X); // Save paraneters for restoring later 27 windowPosY = glutGet(GLUT_WINDOW_Y); 128 windowidth = glutGet (GLUT_WINDOW_WIDTH) ; 129 windowHeight = glutGet (GLUT_WINOOW_HEIGHT) ; 130 glutFullscreen(); // Switch into full screen 131 } else { 11 Windowed mode 132 glutReshapeWindow(windowiidth, windowHeight); // Switch into windowed mode 133 glutPositionWindow(windowPosx, windowPosx); // Position top-left corner 134 > 135 break; 136 case GLUT_KEY_RIGHT: —// Right: increase x speed 137 xSpeed *= 1.05f; break; 138 case GLUT_KEY_LEFT: —// Left: decrease x speed 139 xSpeed *= .95f; break; 140 case GLUT_KEY_UP: // Up: increase y speed 1a ySpeed *= 1.05f; break; 142 case GLUT_KEY_DOWN 11 Down: decrease y speed 143, ySpeed *= 0.95f; break; aaa case GLUT_KEY_PAGE_UP: // Page-Up: increase ball's radius 14s ballRadius *= 1.055 as. ballxMin = clipareaxLeft + ballRadius; 147 ballxMax = clipAreaxRight - ballRadius; 14s. ballYMin = clipAreaYBottom + ballRadius; 19 ballYMax = clipAreaYTop - ballRadius; 150 break; 151 case GLUT_KEY_PAGE_DOWN: // Page-Down: decrease ball's radius 152 ballRadius *= 0.954; 153, ballXMin = clipAreaxLeft + ballRadius; 154 ballxmax = clipAreaxRight - ballRadius; 15s ballYMin = clipAreaYBottom + ballRadius; 156 ballYMax = clipAreaYTop - ballRadius; 157 break; 158 y 159} 160 161 /* Main function: GLUT runs as a console application starting at main() */ 162 int main(int argc, char** argv) { 163, glutinit(@argc, argv); J/ Initialize GLUT 164 glutInitDisplayMode(6LUT_DOUBLE); // Enable double buffered mode 165 BlutInitWindowsize(windowidth, windowHeight); // Initial window width and height 166 glutTnitWindowPosition(windowPosX, windowPosY); // Initial window top-left corner (x, y) 167 glutCreateWindow(title) ; // Create window with given title 168 glutDisplayFunc(display); _// Register callback handler for window re-paint 169 glutReshapeFunc(reshape); _// Register callback handler for window re-shape 170 glutTimerFunc(@, Timer, @); // First tiner call inmediately m1 glutspecialFunc(specialkeys); // Register callback handler for special-key event a7. glutKeyboardFunc(keyboard); // Register callback handler for special-key event 173 glutFullscreen(); // Put into full screen 174 initeL(); // Our own OpenGL initialization 175 glutMainLoop(); // Enter event-processing loop Hitps:wwn3.ntu.edsihomelehchualprogramminglopenglieg introduction. html 30035 2126123, 0:47 PM Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial 176 v7 return 0; > {TODO Explanation 8. Handling Mouse Inputs with GLUT Similar rly, we can register callback function to handle mouse-click and mouse-motion, = glutMouseFunc: registers callback handler for mouse click. void glutMouseFunc(void (*func)(int button, int stete, int x, int y) 11 Ge y) is the mouse-click location. // button: GLUT_LEFT_BUTTON, GLUT_RIGHT_BUTTON, GLUT_MTODLE_sUTTON // state: GLUT_UP, GLUT_DOwN = glutMotionFunc: registers callback handler for mouse motion (when the mouse is clicked and moved). 8.1 For th void glutMotiontunc(void (*func)(int x, int y) 11 where (x, y) is the souse location in Window's coordinates Example 10: Mouse-Controlled (GL1@MouseControl . cpp) e bouncing ball program, the following mouse handler pause the movement with left-mouse click, and resume with right-mouse click 1 2 3 4 s 6 7 8 8 10 n 2 B 14 as 16 v 18 19 28 2 2 23 24 25 26 27 28 29 30 31 32 33 34 35 * GL1@MouseControl.cpp: A mouse-controlled bouncing ball ” include // for MS Windows include <6L/glut.h> // GLUT, include glu.h and gl-h include // Needed for sin, cos define PI 3.14159265¢ // Global variables char title[] = "Full-Screen & Windowed Mode"; // Windowed mode's title int windowwidth = 649; // Windowed mode's width int windowHeight = 488; // Windowed mode's height int windowPosx = 50; // Windowed mode's top-left corner x int windowPosy = 50; 1/ Windowed mode's top-left corner y GLfloat ballRadius = @.5f; // Radius of the bouncing ball GLfloat ballx = 8.0f; // Ball's center (x, y) position GLfloat ballY = 0.0f; GLfloat ballxMax, balLetin, ballYMax, ballYMin; // Ball's center (x, y) bounds GLfloat xSpeed = 2.02; // Ball's speed in x and y directions Gifloat ySpeed = @.007F; int refreshMillis = 3; // Refresh period in milliseconds JI Projection clipping area Gldouble clipAreaxLeft, clipAreaxRight, clipAreayBottom, clipAreaYTop; bool fullscreenMode = true; // Full-screen or windowed mode? bool paused = false: 11 Movement paused or resuned GLfloat xSpeedSaved, ySpeedSaved; // To support resume /* Initialize OpenGL Graphics */ void initL() ¢ giclearColor(@.0, 0.0, 0.0, 1.0); // Set background (clear) color to black , tps: ntu.edusihomelehchualprogramminglopenglieg introduction. html 31135, 2126123, 0:47 PM, 36 37 38 39 40 a a2 43 44 45 46 47 43 49 5e 51 52 53 54 55 56 37 58 59 se 61 62 63 6a 6s 66 o7 68 68 70 n n B 74 78 76 7 8 79 88 a1 82 83 24 a5 86 87 88 89 90 on 22 93 94 95 96 7 ‘An introdution on OpenGL wth 20 Graphics - OpenGl. Tutorial /* Callback handler for window re-paint event */ void display() ( elClear(Gl_COLOR_BUFFER_BIT); // Clear the color buffer giMatrixMode(GL_MODELVIEW); — // To operate on the model-view matrix glloadrdentity(); // Reset nodel-view matrix gliranslateF(ballx, ballY, 6.9f); // Translate to (xPos, yPos) // Use triangular segments to form a circle glBegin(GL_TRIANGLE_FAN); glcolor3#(8.0f, @.0F, 1.0f); // Blue glvertex2#(2.eF, 0.0f); // Center of circle int nunSegnents = 160; GLfloat angle; for (int £ = 0; 4 <= numSegnents; it+) { // Last vertex same as first vertex angle = i * 2.0f * PI / nunSegnents; // 360 deg for all segnents glVertex2f (cos(angle) * ballRadius, sin(angle) * ballRadius); y glend(); glutswapsuffers(); // Swap front and back buffers (of double buffered node) // Animation Control - compute the location for the next refresh ballx += xSpeed; ballY += ySpeed; // Check if the ball exceeds the edges Af (bal1X > ballxmax) { ballx = ballxtax; xSpeed = -xSpeed; } else if (ballx < ballxMin) { ballx = ballxtin; xSpeed = -xSpeed; x if (ballY > ballymax) { ally = ballvtax; ySpeed = -ySpeed; } else if (ballY < ballyMin) { bally = ballymin; ySpeed = -ySpeed; > /* Call back when the windows is re-sized */ void reshape(GLsizei width, Glsizei height) { // Compute aspect ratio of the new window if (height == @) height = 1; // To prevent divide by @ Gtfloat aspect = (GLfloat)width / (GLfloat)height; 11 Set the viewport to cover the new window glViewport(9, ©, width, height); J/ Set the aspect ratio of the clipping area to match the viewport glMatrixMode(GL_PROJECTION); // To operate on the Projection matrix glLoadIdentity(); // Reset the projection matrix if (width >= height) { Clipfreaxleft = -1.0 * aspect cLipAreaxRight = 1.0 * aspect; cLipAreaYaottom = -1.0; clipareayTop = 1.05 y else ¢ clipfreaxLeft = -1.0; cLipAreaxRight = 1.0; cLipAreayBottom = -1.0 / aspect; Hitps:wwn3.ntu.edsihomelehchualprogramminglopenglieg introduction. html 32135, 2126/29, 9:47 PM 98 99 100 101 102 103 198 105 106 107 108 109 18 aun 12 113 aa 15 1s 7 18 9 120 aaa 122 123 18 5 126 27 18 29 130 131 132 133 134 135 136 137 138 139 140 aaa az 143 14a 145 14s 147 1g 149 150 151 152 153, 154 155 156 157 158 159 Hitps:wwn3.ntu.edsihomelehchualprogramminglopenglieg introduction. html Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial clipareaytop x = 1.0 / aspect; gluOrtho20(clipareaxteft, clipAreaxRight, clipAreayBottom, clipAreaYTop) ; balixmin = ballxitax ballviin ballYmax = } clipareaxLeft + ballRadius; clipareaxRight - ballRadius; clipAreaYBottom + ballRadius; clipareayTop - ballRadius; /* Called back when the timer expired */ void Timer(int value) { glutPostedisplay(); // Post @ paint request to activate disp glutTimerFunc(refreshiillis, Timer, @); // subsequent timer call at milliseconds y /* Callback handler for normal-key event */ void keyboard(unsigned char key, switch (key) { case 27: exit(@); break; I/ ESC key } /* Callback handler for special-key ever void specialkeys(int key, int x, switch (key) { case GLUT_KEY_F1: fullscreentode if (fullScreenMode) { windowPosx dF windowPosY windowwidth windowHleight glutFullscreen(); p else { fullscreentode; int x, int y) int y) { Toggle between full-screen and windowed mode // Toggle state // Full-screen mode = glutGet(GLUT_MINDOW_x); // Save parameters for restoring later glutGet (GLUT_WINDOW_Y) ; glutGet (GLUT_WINDOW_WIDTH) ; glutGet (GLUT_WINDOW_HEIGHT) ; // Switch into full screen // Windowed mode glutReshapeWindow(windowWidth, windowHeight); // Switch into windowed mode glutPositionWindow(windowPosx, windowPosx) ; > break; case GLUT_KEY_RIGHT: —// xSpeed *= 1.05f; break; case GLUTLKEY_LEFT: —// xSpeed *= 0.95; breaks case GLUT_KEY_UP: u ySpeed *= 1.05f; breaks case GLUTKEY_DOW: = // ySpeed *= 0.95; break; case GLUT_KEY_PAGE_UP: // ballRadius *= 1.05%; ballxin ball xMax ballYMin ballYMax break; case GLUT_KEY_PAGE_DOWN: ballRadius *= 0.95¢; ballxMin ballxMax ballYMin ballYMax = clipAreaYTop break; cLipareavTop // Position top-left corner Right: increase x speed Left: decrease x speed uy increase y speed Donn: decrease y speed Page-Up: increase ball's radius LipAreaxLeft + ballRadius; cLipAreaxright - ballRadius; ‘LipAreaYBottom + ballRadius; ~ ballRadius; // Page-own: decrease ball's radius LipAreaxLeft + ballRadius; clipAreaxRight - ballRadius; clipAreayaottom + ballRadius; ~ ballRadius; 33135 2126123, 0:47 PM, 160 161 162 163, 164 165 166 167 168 169 170 am 172 173 174 175 176 77 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial ? 7* Callback handler for mouse event */ void mouse(int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON && state == GLUT_DOMN) { // Pause/resume paused = !paused; // Toggle state if (paused) { xSpeedSaved = xSpeed; // Save parameters for restore later ySpeedSaved = ySpeed; xSpeed = 0; // Stop movement ySpeed = 0; } else { xSpeed = xSpeedSaved; // Restore parameters ySpeed = ySpeedSaved; ? /* Main function: GLUT runs as a console application starting at nain() */ int main(int arge, char** argv) { glutinit(@arge, argv); // initialize GLUT glutinitoisplayMode(GLUT_DOUBLE); // Enable double buffered node glutinitWindowSize(windowdidth, windowHeight); // Initial window width and height glutinitWindowPosition(windowPosk, windowPosY); // Initial window top-left corner (x, y) glutcreateWindow(title) ; // Create window with given title glutDisplayFunc(display); _// Register callback handler for window re-paint glutReshapeFunc(reshape); __// Register callback handler for window re-shape glutTinerFunc(®, Timer, 0); // First tiner call innediately glutspecialFunc(specialkeys); // Register callback handler for special-key event glutkeyboardFunc(keyboard); // Register callback handler for special-key event glutFullscreen(); // Put into full screen gluthouseFunc(mouse); // Register callback handler for mouse event initaL(); 7/ Our own OpenGL initialization glutMainLoop(); // Enter event-processing loop return 0; } {TODO] Explanation 8.2 Example 11: A Simple Paint program [TODO] Use mouse-motion and GL_LINE_STRIP. Link to OpenGL/Computer Graphics References and Resources Hitps:wn3.ntu.edu.sihomelehchualprogramminglopenglieg introduction. html 34035 2126123, 0:47 PM ‘Anintroduction on OpenGL with 2D Graphics - OpenGL. Tutorial Latest version tested: Eclipse COT /MinGw Las! modified: July, 2012 Feedback, comments, corrections, and erate can be sent fo Chua Hock-Chuan (ehchua@ntu.edusg) | HOME hitps:wwn3.ntu.edu.sihomelehchualprogramminglopenglieg_introduction.htm| 35135

You might also like