Presentation is loading. Please wait.

Presentation is loading. Please wait.

More on Drawing in OpenGL: Examples CSC 2141 Introduction to Computer Graphics.

Similar presentations


Presentation on theme: "More on Drawing in OpenGL: Examples CSC 2141 Introduction to Computer Graphics."— Presentation transcript:

1 More on Drawing in OpenGL: Examples CSC 2141 Introduction to Computer Graphics

2 Recall: Callbacks  Programming interface for event-driven input  Define a callback function for each type of event the graphics system recognizes  This user-supplied function is executed when the event occurs  GLUT example: glutMouseFunc(mymouse) void mymouse(GLint button, GLint state, GLint x, GLint y) mouse callback function

3 GLUT Event Loop  Recall that the last line in main.c for a program using GLUT must be glutMainLoop(); which puts the program in an infinite event loop  In each pass through the event loop, GLUT  looks at the events in the queue  for each event in the queue, GLUT executes the appropriate callback function if one is defined  if no callback is defined for the event, the event is ignored

4 Using the mouse position  In the next example, we draw a small square at the location of the mouse each time the left mouse button is clicked  This example does not use the display callback but one is required by GLUT; We can use the empty display callback function mydisplay(){}  main() function same as before

5 Globals and myInit() Glsizei wh =500, ww=500; /* window dimensions */ GLfloat size = 3.0; /* one-half of side length of square */ myInit(void) { /* set viewing conditions */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D (0.0, (GLdouble) ww, 0.0, (GLdouble) wh ); glMatrixMode(GL_MODELVIEW); /* adjust viewport */ glViewport(0, 0, ww, wh); glClearColor(0.0, 0.0,0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glFlush(); }

6 Drawing squares at cursor location void mymouse(int btn, int state, int x, int y) { if(btn==GLUT_RIGHT_BUTTON && state==GLUT_DOWN) exit(0); /*terminate the program through OpenGL */ if(btn==GLUT_LEFT_BUTTON && state==GLUT_DOWN) drawSquare(x, y); } void drawSquare(int x, int y) /* (x,y) is the center */ { y=wh-y; /* invert y position */ glColor3ub( (char) rand()%256, (char) rand ()%256, (char) rand()%256); /* a random color */ glBegin(GL_POLYGON); glVertex2f(x+size, y+size); glVertex2f(x-size, y+size); glVertex2f(x-size, y-size); glVertex2f(x+size, y-size); glEnd(); glFlush(); }

7 Positioning The position in the screen window returned by callback functions is with respect to the origin at the top-left corner (GLUT convention) Consequence of refresh done from top to bottom OpenGL uses a world coordinate system with origin at the bottom left Must invert y coordinate returned by mouse callback using the height of the window y = wh – y; (0,0) wh ww y h-y

8 Obtaining the window size  To invert the y position we need the window height  Height can change during program execution  New height returned to reshape callback  Track with a global variable

9 Recall: The Reshape callback glutReshapeFunc(myreshape) void myreshape( int w, int h)  Returns width and height of new window (in pixels)  A redisplay is posted automatically at end of execution of the callback  The reshape callback is good place to put viewing functions because it is invoked when the window is first opened

10 Recall: The Reshape callback  Do we redraw all the objects that were in the window before it was resized?  We need a mechanism to store and recall them  Typically done by encapsulating all drawing in the display callback and reposting the display redraws all.  In this example: our drawing is interactive based on mouse input and unless we store the squares drawn, we cannot recall them  Let’s choose to clear the window if resized.

11 Recall: The Reshape callback  What do we do if the aspect ratio of the new window is different from that of the old window?  No single answer  Distortions may be okay  Or not  then set the viewport such that it has the same aspect ratio as the drawing area.  Part of the window may not be used.  In this example, we clear the window when resized so no distortion to old squares. New squares are drawn with the same fixed size.

12 Example Reshape  This reshape preserves shapes by making the viewport and the idealized drawing window have the same aspect ratio void myReshape(GLsizei w, GLsizei h) { ww = w; /* update window dimensions */ wh = h; /* adjust clipping box */ glMatrixMode(GL_PROJECTION); /* switch matrix mode */ glLoadIdentity(); gluOrtho2D (0.0, (GLdouble) w, 0.0, (GLdouble) h ); glMatrixMode(GL_MODELVIEW); /* return to modelview mode */ /* adjust viewport */ glViewport(0, 0, w, h); /* clear the window each time it is resized */ glClear(GL_COLOR_BUFFER_BIT); glFlush(); }

13 Using globals  The form of all GLUT callbacks is fixed  void mydisplay()  void mymouse(GLint button, GLint state, GLint x, GLint y)  Must use globals to pass information to callbacks float size; /*global */ void mydisplay() { /* draw something that depends on size }

14 Recall: Using the keyboard glutKeyboardFunc(myKeyboard) void myKeyboard(unsigned char key, int x, int y)  Returns ASCII code of key depressed and mouse location void myKeyboard(unsigned char key, int x, int y) { if(key == ‘Q’ || key == ‘q’) exit(0); }

15 Special and Modifier Keys  GLUT defines the special keys in glut.h  Function key 1: GLUT_KEY_F1  Up arrow key: GLUT_KEY_UP  if(key == ‘GLUT_KEY_F1’ ……  Can also check of one of the modifiers  GLUT_ACTIVE_SHIFT  GLUT_ACTIVE_CTRL  GLUT_ACTIVE_ALT is depressed by glutGetModifiers()

16 Using the motion callback  We can draw squares (or anything else) continuously as long as a mouse button is depressed by using the motion callback  glutMotionFunc(drawSquare)  We can draw squares without depressing a button using the passive motion callback  glutPassiveMotionFunc(drawSquare)

17 Changing and disabling callback functions  We can change most callback functions during program execution by specifying a new callback function  We can also disable a callback function by setting it to NULL glutIdleFunc(NULL);

18 Using the idle callback  The idle callback is executed whenever there are no events in the event queue  glutIdleFunc(myidle)  Useful for animations void myidle() { /* change something */ t += dt glutPostRedisplay(); } Void mydisplay() { glClear(); /* draw something that depends on t */ glutSwapBuffers(); }

19 Example animation: rotating square x=cosƟ y=sinƟ The point lies on a unit circle regardless of the value of Ɵ

20 myDisplay() void myDisplay() { glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_POLYGON); thetar = theta * (2 * 3.14159) / 360.0; /* convert degrees to radians */ glVertex2f(cos(thetar), sin(thetar)); glVertex2f(-sin(thetar), cos(thetar)); glVertex2f(-cos(thetar), -sin(thetar)); glVertex2f(sin(thetar), -cos(thetar)); glEnd(); glutSwapBuffers(); /* double buffering */ }

21 Change Ɵ as the program runs…  In main() function specify callback glutIdleFunc(myIdle);  And, define callback function as void myIdle () { theta += 2; if (theta >= 360.0) theta -= 360.0; glutPostRedisplay(); }

22 One further change..  Turn on and off the rotation feature by mouse input  Register mouse callback as glutMouseFunc(myMouse);  Define mouse callback as void myMouse(int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON)&&(state == GLUT_DOWN) glutIdleFunc(myIdle); if (button ==GLUT_RIGHT_BUTTON)&&(state == GLUT_DOWN) glutIdleFunc(NULL); }

23 Too fast?  Use a timer callback instead  Which in turn will execute the display callback at a fixed rate (e.g. n frames per second) glutTimerFunc(1000/n, myTimer, 0);  But no support for cancelling a timer callback.  instead you can ignore a callback based on its value.

24 Try running this with single buffering  Do you notice partial display of rotated square?

25 Multiple Windows  GLUT supports multiple windows id = glutCreateWindow(“Second window”); And select this as the current window by glutSetWindow(id);  You can make this window have different properties by invoking glutInitDisplayMode before glutCreateWindow  Each window can set its own callback functions  Callback registrations refer to the current window.

26 Menus  GLUT supports pop-up menus  A menu can have submenus  Three steps  Define entries for the menu  Define action for each menu item  Action carried out if entry selected  Attach menu to a mouse button

27 Defining a simple menu  In main.c glutCreateMenu(myMenu); glutAddMenuEntry(“clear Screen”, 1); glutAddMenuEntry(“exit”, 2); glutAttachMenu(GLUT_RIGHT_BUTTON); entries that appear when right button depressed identifiers clear screen exit

28 Menu actions  Menu callback  Note each menu has an id that is returned when it is created void myMenu(int id) { if(id == 1) glClear(); if(id == 2) exit(0); }

29 Menu actions  Hierarchical menus are allowed  Add submenus by glutAddSubMenu(char *submenu_name, int submenu_id) int sub_menu; sub_menu=glutCreateMenu(size_menu); //add to the current menu glutAddMenuEntry(“Increase square size”,2); glutAddMenuEntry(“decrease square size”,3); glutCreateMenu(top_menu); glutAddMenuEntry(“Quit”, 1); glutAddSubMenu(“Resize”, sub_menu); glutAttachMenu(GLUT_MIDDLE_BUTTON);

30 Text  We often want to control size, color and font  Two ways in OpenGL  1. Stroke Text:  constructed as other graphics primitives  Use vertices to draw line segments or curves outlining the character  Advantage: define once and apply transformations to generate any size and orientation  Disadv: defining a full character set is complex…

31 Text  2. Raster text  Simple and fast  Character is defined as rectangular array of bits (0s or 1s) called bit blocks or bitmap  A raster character can be placed in frame buffer directly. When you overlay a bitmap on the frame buffer, the pixels that correspond to 1s are set to the current color.  You can increase character size only by replicating pixels.  Larger characters: blocky appearance  Transformations like rotation do not make sense (can’t rotate pixel positions!)

32 Raster text glutBitmapCharacter(GLUT_BITMAP_8_BY_13, c)  GLUT_BITMAP_8_BY_13: is a set of bitmaps predefined in GLUT. It’s a fixed width font, i.e. all characters have the same width.  c is the integer equivalent of an ASCII character  Above function places c at the “current” raster position (part of state) and automatically advances the current position by the character width after the character is drawn.  Position can be altered by glRasterPos*(rx, ry); glutBitmapWidth(GLUT_BITMAP_8_BY_13, c)  Returns the width of the character c in pixels

33 Typical function to display a string void bitMapString( float x, float y, char s[]) { int i = 0; glRasterPos2f( x, y); while (s[i] != '\0') { glutBitmapCharacter( GLUT_BITMAP_8_BY_13, s[i]); ++i; }

34 Stroke Text glutStrokeCharacter(GLUT_STROKE_MONO_ROMAN, c)  You can use a predefined font as GLUT_STROKE_MONO_ROMAN  Or, you can define your own fonts!  Be careful: the way this function works may affect OpenGL state (the transformation matrices, you might need to save them)  For now use raster text.


Download ppt "More on Drawing in OpenGL: Examples CSC 2141 Introduction to Computer Graphics."

Similar presentations


Ads by Google