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

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

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

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

More on Drawing in OpenGL: Examples

CSC 2141Introduction to Computer Graphics

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

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

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

GLUT Event Loop

Recall that the last line in main.c for a program using GLUT must beglutMainLoop();

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

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

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 functionmydisplay(){}

main() function same as before

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

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();

}

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

Drawing squares at cursor locationvoid 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();}

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

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

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

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

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

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

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

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.

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

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.

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

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();}

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

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}

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

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);

}

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

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_ALTis depressed byglutGetModifiers()

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

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)

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

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);

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

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 += dtglutPostRedisplay();

}

Void mydisplay() {glClear();

/* draw something that depends on t */glutSwapBuffers();

}

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

Example animation: rotating square

x=cosƟ

y=sinƟ

The point lies on a unit circle regardless of the value of Ɵ

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

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 */

}

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

Change Ɵ as the program runs…

In main() function specify callbackglutIdleFunc(myIdle);

And, define callback function as void myIdle () {

theta += 2;

if (theta >= 360.0)

theta -= 360.0;

glutPostRedisplay();

}

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

One further change..

Turn on and off the rotation feature by mouse input Register mouse callback as

glutMouseFunc(myMouse);

Define mouse callback asvoid 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);

}

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

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.

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

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

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

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.

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

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

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

Defining a simple menu

In main.c

glutCreateMenu(myMenu);glutAddMenuEntry(“clear Screen”, 1);

glutAddMenuEntry(“exit”, 2);

glutAttachMenu(GLUT_RIGHT_BUTTON);

entries that appear whenright button depressed

identifiers

clear screen

exit

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

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);

}

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

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 menuglutAddMenuEntry(“Increase square size”,2); glutAddMenuEntry(“decrease square size”,3);glutCreateMenu(top_menu);glutAddMenuEntry(“Quit”, 1);glutAddSubMenu(“Resize”, sub_menu);glutAttachMenu(GLUT_MIDDLE_BUTTON);

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

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…

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

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!)

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

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

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

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;

}

}

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

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.