0% found this document useful (0 votes)
8 views19 pages

Module 3 MJS

Module 3 covers interactive input methods and graphical user interfaces, detailing input devices, their classifications, and functions in computer graphics. It discusses physical and logical input devices, input modes, and the client-server model in computer graphics architecture. Additionally, it explains display lists and text generation methods in OpenGL for efficient graphics rendering.

Uploaded by

kshavmk
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views19 pages

Module 3 MJS

Module 3 covers interactive input methods and graphical user interfaces, detailing input devices, their classifications, and functions in computer graphics. It discusses physical and logical input devices, input modes, and the client-server model in computer graphics architecture. Additionally, it explains display lists and text generation methods in OpenGL for efficient graphics rendering.

Uploaded by

kshavmk
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Module 3

Module 3 Interactive Input Methods and Graphical User Interfaces


Interactive Input Methods and Graphical User Interfaces: Graphical Input Data, Logical Classification of Input Devices,
Input Functions for Graphical Data, Interactive Picture-Construction Techniques,
Virtual-Reality Environments, OpenGL Interactive Input-Device Functions, OpenGL Menu Functions, Designing a
Graphical User Interface.
Computer Animation: Design of Animation Sequences, Traditional Animation Techniques, General Computer-
Animation Functions, Computer-Animation Languages, Character Animation, Periodic Motions, OpenGL Animation
Procedures.

Textbook 1: Chapter -11, 18

INPUT DEVICES
Input devices can be understood in two distinct ways
a) Based on physical properties of input devices, in this we understanding. physical devices, such as a keyboard or a
mouse, and to discuss how they work.
b) The other way is to understand from the perspective of an application programmer. In this we know which function
must be invoked for accepting values from input devices. In this we treat input devices as logical devices whose properties
are specified in terms of what they do from the perspective of the application program.
A logical device is characterized by its high-level interface with the application program rather than by its physical
characteristics
int x;
scanf(&x);
printf("%d", x);
Even if we use the keyboard and display, the use of scanf and printf requires no knowledge of the properties of the
physical devices, such as the keyboard codes or the resolution of the display. Rather scanf and printf are logical functions
that are defined by how they handle input or output character strings from the perspective of the C program.
PHYSICAL INPUT DEVICES
The two major categories in physical input devices are:
Key board devices like standard keyboard, flexible keyboard, handheld keyboard etc. These are used to provide
character input like letters, numbers, symbols etc.
Pointing devices like mouse, track ball, light pen etc. These are used to specify the position on the computer screen.
Keyboard: It is a general keyboard which has set of characters. We make use of ASCII value to represent the character
i.e. it interacts with the programmer by passing the ASCII value of key pressed by programmer.
Mouse And Trackball: These are pointing devices used to specify the position. Mouse and trackball interacts with the
application program by passing the position of the clicked button.
Both these devices are similar in use and construction. In these devices, the motion of the ball is converted to signal sent
back to the computer by pair of encoders inside the device. These encoders measure motion in 2-orthogonal directions.
1
Dr Sudhamani M J, Associate Professor, Dept of CSE
Module 3

The values passed by the pointing devices can be considered as positions and converted to a 2-D location in either screen
or world co-ordinates. Thus, as a mouse moves across a surface, the integrals of the velocities yield x,y values that can
be converted to indicate the position for a cursor on the screen as shown below:

These devices are relative positioning devices because changes in the position of the ball yield a position in the user
program.
Data Tablets: It provides absolute positioning. It has rows and columns of wires embedded under its surface. The
position of the stylus is determined through electromagnetic interactions between signals travelling through the wires
and sensors in the stylus.

Light Pen: It consists of light-sensing device such as “photocell”. The light pen is held at the front of the CRT. When
the electron beam strikes the phosphor, the light is emitted from the CRT. If it exceeds the threshold then light sensing
device of the light pen sends a signal to the computer specifying the position.

The major disadvantage is that it has the difficulty in obtaining a position that corresponds to a dark area of the screen
Joystick: The motion of the stick in two orthogonal directions is encoded, interpreted as two velocities and integrated to
identify a screen location. The integration implies that if the stick is left in its resting position, there is no change in
cursor position. The faster the stick is moved from the resting position; the faster the screen location changes. Thus,
joystick is variable sensitivity device.

2
Dr Sudhamani M J, Associate Professor, Dept of CSE
Module 3

The advantage is that it is designed using mechanical elements such as springs and dampers which offer resistance to the
user while pushing it. Such mechanical feel is suitable for application such as the flight simulators, game controllers etc.
Space Ball: It is a 3-Dimensional input device which looks like a joystick with a ball on the end of the stick. Stick
doesn‟t move rather pressure sensors in the ball measure the forces applied by the user. The space ball can measure not
only three direct forces (up-down, front-back, left-right) but also three independent twists. So totally device measures
six independent values and thus has six degree of freedom.
Other 3-Dimensional devices such as laser scanners, measure 3-D positions directly. Numerous tracking systems used
in virtual reality applications sense the position of the user and so on.

LOGICAL CLASSIFICATION OF INPUT DEVICES


Two major characteristics describe the logical behavior of an input device:
(1) the measurements that the device returns to the user program, and
(2) the time when the device returns those measurements.
Following are the six classes of logical input devices.
String: A string device is a logical device that provides the ASCII values of input characters to the user program. This
logical device is usually implemented by means of physical keyboard.
Locator: A locator device provides a position in world coordinates to the user program. It is usually implemented by
means of pointing devices such as mouse or track ball.
Pick: A pick device returns the identifier of an object on the display to the user program. It is usually implemented with
the same physical device as the locator but has a separate software interface to the user program.
Choice: A choice device allows the user to select one of a discrete number of options. In OpenGL, we can use various
widgets provided by the window system. A widget is a graphical interactive component provided by the window system
or a toolkit. The Widgets include menus, scrollbars and graphical buttons. For example, a menu with n selections acts as
a choice device, allowing user to select one of “n‟ alternatives.
Valuators: They provide analog input to the user program on some graphical systems; there are boxes or dials to provide
value.
Stroke: A stroke device returns array of locations. Example, pushing down a mouse button starts the transfer of data into
specified array and releasing of button ends this transfer.
INPUT MODES

3
Dr Sudhamani M J, Associate Professor, Dept of CSE
Module 3
The manner by which input devices provide input to an application program can be described in terms of two entities: a
measure process and a device trigger.
The measure of a device is what the device returns to the user program. The trigger of a device is a physical input on
the device with which the user can signal the computer.
Example, the measure of a keyboard should include a single character or a string of characters, and the trigger can be the
Return or Enter key. The measure of a mouse is the position of the cursor whereas the trigger is when the mouse button
is pressed.
The application program can obtain the measure of a device in three distinct modes. Each mode is defined by the
relationship between the measure process and the trigger.
Request Mode: In this mode, measure of the device is not returned to the program until the device is triggered.
For example, consider a typical C program which reads a character input using scanf(). When the program needs the
input, it halts when it encounters the scanf() statement and waits while user type characters at the terminal. The data is
placed in a keyboard buffer (measure) whose contents are returned to the program only after enter key (trigger) is pressed.

Sample Mode: In this mode, input is immediate. As soon as the function call in the user program is executed, the measure
is returned. Hence no trigger is needed.
In sample mode, the user must have positioned the pointing device or entered data using the keyboard before the function
call, because the measure is extracted immediately from the buffer.

Event Mode: This mode can handle the multiple interactions.


 Suppose that we are in an environment with multiple input devices, each with its own trigger and each running
a measure process.
 Whenever a device is triggered, an event is generated. The device measure including the identifier for the device
is placed in an event queue.
 If the queue is empty, then the application program will wait until an event occurs. If there is an event in a queue,
the program can look at the first event type and then decide what to do.

Another approach is to associate a function called a callback with a specific type of event. From the perspective of the
window system, the operating system queries or polls the event queue regularly and executes the callbacks corresponding
to events in the queue.
CLIENT AND SERVER
The computer graphics architecture is based on the client-server model. I.e., if computer graphics is to be useful for
variety of real applications, it must be connected over the network.
In this architecture the building blocks are entities called as “servers” perform the tasks requested by the “client”

4
Dr Sudhamani M J, Associate Professor, Dept of CSE
Module 3
Servers and clients can be distributed over a network or can be present within a single system. Today most of the
computing is done in the form of distributed based and network based as shown below

Most popular examples of servers are print servers – which allow using high speed printer devices among multiple users.
File servers – allow users to share files and programs.
Users or clients will make use of these services with the help of user programs or client programs. The OpenGL
application programs are the client programs that use the services provided by the graphics server.
DISPLAY LISTS
Display lists illustrate how we can use clients and servers on a network to improve interactive graphics performance.
Display lists have their origins in the early days of computer graphics. The architecture is shown below

computers were slow and expensive and hence the frame buffer not saved. The solution to this problem was to build a
special-purpose computer, called a display processor.

The display processor had a limited instruction set, most of which was oriented toward drawing primitives on the display.
The user program was processed in the host computer, resulting in a compiled list of instructions that was then sent to
the display processor, where the instructions were stored in a display memory as a display file, or display list.
For a simple noninteractive application, once the display list was sent to the display processor, the host was free for other
tasks, and the display processor would execute its display list repeatedly at a rate sufficient to avoid flicker.

5
Dr Sudhamani M J, Associate Professor, Dept of CSE
Module 3
There are two modes in which objects can be drawn on the screen:
Immediate Mode: This mode sends the complete description of the object which needs to be displayed to the server.
For geometric primitives, this transfer includes sending vertices and attributes. As soon as the program executes a
statement that defines a primitive, that primitive is sent to the server for possible display and no memory of it is retained
in the memory.
To redisplay the primitive after a clearing of the screen the program must resend the information through the display
process. For complex objects and in interactive applications, this process can cause display problems.
Retained-mode : The object is defined once and its description is stored in a display list which is at the server side and
redisplay of the object can be done by a simple function call issued by the client to the server. The advantage is that
processing of same command for rendering can be avoided. Complex scenes can be saved and displayed when required.
The main disadvantage of using display list is it requires memory at the server architecture and server efficiency decreases
if the data is changing regularly.
Definition and Execution of Display Lists
Display lists are defined using glNewList() and glEndList() functions. glNewList() specifies the beginning of the list
and after mentioning all the primitives, we end the display list using glEndList() .
Each display list must have a unique identifier which is passed as an argument in glNewList()
glNewList(22, GL_COMPILE);
since it is a constant and can be mentioned using #define statement
#define box 22
glNewList(box, GL_COMPILE);
For example, the following code defines a red box
#define BOX 22 /* or some other unused integer */
glNewList(BOX, GL_COMPILE);
glBegin(GL_POLYGON);
glColor3f(1.0, 0.0, 0.0);
glVertex2f(-1.0, -1.0);
glVertex2f( 1.0, -1.0);
glVertex2f( 1.0, 1.0);
glVertex2f(-1.0, 1.0);
glEnd();
glEndList();
The flag GL_COMPILE tells the system to send the list to the server but not to display its contents. If we want an
immediate display of the contents while the list is being constructed, we can use the GL_COMPILE_AND_EXECUTE
flag instead.
Each time that we wish to draw the box on the server, we execute the function as follows:
glCallList(BOX);
OpenGL provides an API to retain the information by using stack
6
Dr Sudhamani M J, Associate Professor, Dept of CSE
Module 3
We can save the present values of the attributes and the matrices by pushing them into the stack, usually the below
function calls are placed at the beginning of the display list,
glPushAttrib(GL_ALL_ATTRIB_BITS);
glPushMatrix();
We can retrieve these values by popping them from the stack, usually the below function calls are placed at the end of
the display list,
glPopAttrib();
glPopMatrix();
Text and Display Lists
There are two types of text generation methods
Raster text and
Stroke text
In raster text display each character is stored as an 8 × 13 pattern of bits. It takes 13 bytes to store each character. If we
want to display a character appropriate raster is embedded on to the existing display buffer.
In stroke text generation explicitly characters are defined using primitives.

From the above figure we can observe to draw letter “I” we can use lines. Circle generation algorithm can be used for
generating letter ‘O’. Performance of the graphics system will be degraded for the applications that require large quantity
of text if stroke text generation is used.
A more efficient strategy is to define the font once, using a display list for each char and then store in the server. We
define a function OurFont() which will draw any ASCII character stored in variable “c”
void OurFont(char c)
{
switch(c)
{
case ’a’:
...
break;
case ’A’:
...
break;
...
}
}

For the character “O” the code sequence is of the form as shown below:
case ‘O’:
glTranslatef(0.5, 0.5, 0.0); /* move to center */
glBegin{GL_QUAD_STRIP);

7
Dr Sudhamani M J, Associate Professor, Dept of CSE
Module 3
for (i=0; i<=12; i++) /* 12 vertices */
{
angle = 3.14159 /6.0 * i; /* 30 degrees in radians */
glVertex2f(0.4*cos(angle)+0.5; 0.4*sin(angle)+0.5);
glVertex2f(0.5*cos(angle)+0.5, 0.5*sin(angle)+0.5);
}
glEnd();
break;

Suppose that we want to generate a 256-character set. The required code, using the OurFont function, is as follows:
base = glGenLists(256); /* return index of first of 256 consecutive available ids */
for(i=0; i<256; i++)
{
glNewList(base + i, GL_COMPILE);
OurFont(i);
glEndList();
}
When we wish to use these display lists to draw individual characters, rather than offsetting the identifier of the display
lists by base each time, we can set an offset as follows:
glListBase(base);
Finally, our drawing of a string is accomplished in the server by the function call
char *text_string;
glCallLists( (GLint) strlen(text_string), GL_BYTE, text_string);
which makes use of the standard C library function strlen to find the length of input string text_string. The first argument
in the function glCallLists is the number of lists to be executed. The third is a pointer to an array of a type given by the
second argument.
Fonts in Glut
In general, we prefer to use an existing font rather than to define our own. GLUT provides a few raster and stroke fonts.
glutStrokeCharacter(GLUT_STROKE_MONO_ROMAN, int character)
We usually control the position of a character by using a translation before the character function is called.
glTranslatef(x, y, 0);
8
Dr Sudhamani M J, Associate Professor, Dept of CSE
Module 3
glutStrokeCharacter(GLUT_STROKE_ROMAN, ‘a’);
Raster and bitmap characters are produced in a similar manner. For example, a single 8 × 13 character is obtained using
the following:
glutBitmapCharacter(GLUT_BITMAP_8_BY_13, int character)
Positioning of bitmap characters is considerably simpler than the positioning of stroke characters is because bitmap
characters are drawn directly in the frame buffer. The position where the next raster primitive to be placed can be set
using the glRasterPos*(). glutBitmapCharacter function automatically advances the raster position, so typically we do
not need to manipulate the raster position until we want to define a string of characters elsewhere on the display.
void output(int x, int y, char *string)
{
int len, i;
glRasterPos2f(x, y);
len = (int) strlen(string);
for (i = 0; i < len; i++) {
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, string[i]);
}
}
PROGRAMMING EVENT DRIVEN INPUT
In this we understand various events that are recognized by the window system and based on application, we write callback
functions that indicate how the application program responds to these events.
Using Pointing Devices
Pointing devices like mouse, trackball, data tablet allow programmer to indicate a position on the display.
There are two types of event associated with pointing device
A move event is generated when the mouse is moved with one of the buttons pressed. If the mouse is moved without a
button being held down, this event is called a passive move event.
After a move event, the position of the mouse—its measure—is made available to the application program.
A mouse event occurs when one of the mouse buttons is either pressed or released. The information returned includes the
button that generated the event(left button/right button/center button), the state of the button after the event (up or down),
and the position of the cursor in window coordinates (with the origin in the upper-left corner of the window).
We register the mouse callback function, usually in the main function as
glutMouseFunc(myMouse);
The mouse callback function must be defined in the form:
void myMouse(int button, int state, int x, int y)
When a user presses and releases mouse buttons in the window, each press and each release generates a mouse callback.
The button parameter is one of GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, or GLUT_RIGHT_BUTTON.
The state parameter is either GLUT_UP or GLUT_DOWN. The value of x & y is according to window, measured from
topmost left corner as

9
Dr Sudhamani M J, Associate Professor, Dept of CSE
Module 3

For example,
void myMouse(int button, int state, int x, int y)
{
if(button==GLUT_LEFT_BUTTON && state == GLUT_DOWN)
exit(0);
}
The above code ensures whenever the left mouse button is pressed down, execution of the program gets terminated.

Write an OpenGL program to display square when a left button is pressed and to exit the program if right button
is pressed.
#include<stdio.h>
#include<stdlib.h>
#include<GL/glut.h>
int wh=500, ww=500; float siz=3;
void myinit()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, wh, 0, ww);// xmin, xmax, ymin, ymax
glMatrixMode(GL_MODELVIEW);
}
void drawsq (int x, int y)
{
y=wh-y;
glBegin(GL_POLYGON);
glVertex2f(x+siz, y+siz);
glVertex2f(x-siz, y+siz);
glVertex2f(x-siz, y-siz);
glVertex2f(x+siz, y-siz);
glEnd();
glFlush();
}
void display()
{
glClearColor(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
}
void myMouse(int button, int state, int x, int y)
{
if(button==GLUT_LEFT_BUTTON && state == GLUT_DOWN)
drawsq(x,y);
if(button==GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
exit(0);

10
Dr Sudhamani M J, Associate Professor, Dept of CSE
Module 3
}
void main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE);
glutInitWindowSize(wh,ww);
glutCreateWindow(“square”);
glutDisplayFunc(display);
glutMouseFunc(myMouse);
myinit();
glutMainLoop();
}

Window Events
A window event is occurred when the corner of the window is dragged to new position or size of window is minimized
or maximized by using mouse.
The information returned to the program includes the height and width of newly resized window. The window callback
function must be registered in the main function as
glutReshapeFunc(myReshape);
Window call back function must be defined as
void myReshape(GLsizei w, GLsizei h)
Returns width and height of new window. Code segment of reshape function
void myReshape(GLsizei w, GLsizei h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION_MATRIX);
glLoadIdentity();
float t1 = (float)w/(float)h;
float t2 = (float)h/(float)w;
if(w>h)
gluOrtho2D(-100*t1,100*t1,-100,100);
else
gluOrtho2D(-100,100,-100*t2,100*t2);
glMatrixMode(GL_MODELVIEW);
glutPostRedisplay();
}

Keyboard Events
Keyboard devices are input devices which return the ASCII value to the user program. Keyboard events are generated
when the mouse is in the window and one of the keys is pressed or released. The GLUT function glutKeyboardFunc is
the callback for events generated by pressing a key, whereas glutKeyboardUpFunc is the callback for events generated by
releasing a key.
When a keyboard event occurs, the ASCII code for the key that generated the event and the location of the mouse are
returned.
glutKeyboardFunc(myKey);
The keyboard callback function must be defined in the form:

11
Dr Sudhamani M J, Associate Professor, Dept of CSE
Module 3
void mykey (unsigned char key, int x, int y)
key is the ASCII value of the char entered. The x and y callback parameters indicate the mouse location in window relative
coordinates when the key was pressed.
For example,
void mykey(unsigned char key, int x, int y)
{
if(key== “q‟ || key== “Q‟)
exit(0);
}

The above code ensures when “Q‟ or “q‟ key is pressed, the execution of the program gets terminated.
The Display and Idle Callbacks
Display callback is specified by GLUT using glutDisplayFunc(myDisplay). It is invoked when GLUT determines that
window should be redisplayed. Re-execution of the display function can be achieved by using glutPostRedisplay().
The idle callback is invoked when there are no other events. It is specified by GLUT using glutIdleFunc(myIdle).
Window Management
GLUT also supports multiple windows and subwindows of a given window. We can open a second top-level window
id=glutCreateWindow("second window");
The returned integer value allows us to select this window as the current window into
which objects will be rendered as follows:
glutSetWindow(id);
Furthermore, each window can have its own set of callback functions because callback specifications refer to the present
window.
MENUS
Menus are an important feature of any application program. OpenGL provides a feature called “Pop-up-menus” using
which sophisticated interactive applications can be created.
Menu creation involves the following steps:
1. Define the actions corresponding to each entry in the menu.
2. Link the menu to a corresponding mouse button.
3. Register a callback function for each entry in the menu.

For example
We can demonstrate simple menus with the example of a pop-up menu that has three entries.
The first selection allows us to exit our program.
The second and third change the size of the squares in our drawSquare function.
We name the menu callback demo_menu. The function calls to set up the menu and to link it to the right mouse button
should be placed in our main function. They are as follows:

glutCreateMenu(demo_menu);
glutAddMenuEntry("quit",1);
glutAddMenuEntry("increase square size", 2);
12
Dr Sudhamani M J, Associate Professor, Dept of CSE
Module 3
glutAddMenuEntry("decrease square size", 3);
glutAttachMenu(GLUT_RIGHT_BUTTON);

The glutCreateMenu() registers the callback function demo_menu. The function glutAddMenuEntry() adds the entry in
the menu whose name is passed in first argument and the second argument is the identifier passed to the callback when
the entry is selected.
void demo_menu(int id)
{
switch(id)
{
case 1: exit(0);
break;
case 2: size = 2 * size;
break;
case 3: if(size > 1) size = size/2;
break;
}
glutPostRedisplay( );
}

GLUT also supports hierarchical menus, as shown in the below Figure

For example,
suppose that we want the main menu that we create to have only two entries. The first entry still causes the program to
terminate, but now the second causes a submenu to pop up. The submenu contains the two entries for changing the size
of the square in our square-drawing program.
sub_menu = glutCreateMenu(size_menu);
glutAddMenuEntry("Increase square size", 2);
glutAddMenuEntry("Decrease square size", 3);
glutCreateMenu(top_menu);
glutAddMenuEntry("Quit",1);
glutAddSubMenu("Resize", sub_menu);
glutAttachMenu(GLUT_RIGHT_BUTTON);

PICKING
Picking is the logical input operation that allows the user to identify an object on the display.
The action of picking uses pointing device but the information returned to the application program is the identifier of an
object not a position.
It is difficult to implement picking in modern system because of graphics pipeline architecture. Therefore, converting
from location on the display to the corresponding primitive is not direct calculation.

There are at least three ways to deal with this difficulty


Selection: It involves adjusting the clipping region and viewport such that we can keep track of which primitives lies in
a small clipping region and are rendered into region near the cursor. These primitives are sent into a hit list that can be
examined later by the user program.

13
Dr Sudhamani M J, Associate Professor, Dept of CSE
Module 3
Bounding boxes or extents: A simple approach is to use (axis-aligned) bounding boxes, or extents, for objects of interest.
The extent of an object is the smallest rectangle, aligned with the coordinates axes, that contains the object.
For two-dimensional applications, it is relatively easy to determine the rectangle in screen coordinates that corresponds
to a rectangle point in object or world coordinates.

Usage of back buffer and extra rendering: When we use double buffering it has two color buffers: front and
back buffers. The contents present in the front buffer is displayed, whereas contents in back buffer is not
displayed so we can use back buffer for other than rendering the scene
Suppose that we render our objects into the back buffer, each in a distinct color. The application program will identify the
object based on the color saved.

Picking can be performed in four steps that are initiated by user defined pick function in the application:
We draw the objects into back buffer with the pick colors.
We get the position of the mouse using the mouse callback.
Use glReadPixels() to find the color at the position in the frame buffer corresponding to the mouse position.
We search table of colors to find the object corresponds to the color read.

PICKING AND SELECTION MODE


The difficult problem in implementing picking within the OpenGL pipeline is that we cannot go backward directly from
the position of the mouse to primitives that were rendered close to that point on the screen.
OpenGL provides a somewhat complex process using a rendering mode called selection mode to do picking at the cost of
an extra rendering each time that we do a pick.

Initially the application will be in GL_RENDER which is the default mode. When there is a click, we reduce the viewport
to the region of click and change the mode to GL_SELECT. In GL_SELECT the objects primitives can be retrieved and
It can be identified.
The function glRenderMode lets us select one of three modes: normal rendering to the color buffer (GL_RENDER),
selection mode (GL_SELECT), or feedback mode (GL_FEEDBACK).
When we enter selection mode and render a scene, each primitive within the clipping volume generates a message called
a hit that is stored in a buffer called the name stack.
The following functions are used in selection mode:
void glInitNames() // initializes the name stack.
void glPushName(GLuint name) // pushes name on the name stack.
void glPopName() // pops the top name from the name stack.
void glLoadName(GLuint name) // replaces the top of the name stack with name.
OpenGL allow us to set clipping volume for picking using gluPickMatrix() which is applied before gluOrtho2D.
gluPickMatrix(x,y,w,h,*vp) : creates a projection matrix for picking that restricts drawing to a w x h area and centered at
(x,y) in window coordinates within the viewport vp.

void mouse(int button, int state, int x, int y )


{
GLuint nameBuffer[SIZE]; /* define SIZE elsewhere */
GLint hits;
GLint viewport[4];
If( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
/* initialize the name stack */
glInitNames( );
glPushName( 0 );
glSelectBuffer( SIZE, nameBuffer);
/* set up viewing for selection mode */
glGetIntegerv(GL_VIEWPORT, viewport);
glMatrixMode(GL_PROJECTION);
14
Dr Sudhamani M J, Associate Professor, Dept of CSE
Module 3
/* save original viewing matrix */
glPushMatrix();
glLoadIdentity( );
/* N x N pick area around cursor */
/* must invert mouse y to get in world coords */
gluPickMatrix( (GLdouble) x, (GLdouble)( viewport[3] - y), N, N, viewport);
/* same clipping window as in reshape callback */
gluOrtho2D (xmin, xmax, ymin, ymax);
draw_objects(GL_SELECT);
glMatrixMode(GL_PROJECTION);
/* restore viewing matrix */
glPopMatrix();
glFlush();
/* return to normal render mode */
hits = glRenderMode(GL_RENDER);
/* process hits from selection mode rendering */
processHits(hits, nameBuff);
/* normal render */
glutPostRedisplay();
}
}
void display( )
{
glClear( GL_COLOR_BUFFER_BIT);
draw_objects(GL_RENDER);
glFlush();
}
void drawObjects(GLenum mode)
{
if(mode == GL_SELECT) glLoadName(1);
glColor3f(1.0, 0.0, 0.0);
glRectf(-0.5, -0.5, 1.0, 1.0);
if(mode == GL_SELECT) glLoadName(2);
glColor3f(0.0, 0.0, 1.0);
glRectf(-1.0, -1.0, 0.5, 0.5);
}
void processHits (GLint hits, GLuint buffer[ ])
{
unsigned int i, j;
GLuint names, *ptr;
printf ("hits = %d\n", hits);
ptr = (GLuint *) buffer;
/* loop over number of hits */
for (i = 0; i < hits; i++)
{
names = *ptr;
/* skip over number of names and depths */
ptr += 3;
/* check each name in record */
for (j = 0; j < names; j++)
{
if(*ptr==1) printf ("red rectangle\n");
else printf ("blue rectangle\n");

15
Dr Sudhamani M J, Associate Professor, Dept of CSE
Module 3
/* go to next hit record */
ptr++;
}
}
}
ANIMATING INTERACTIVE PROGRAMS
In OpenGl, the programmer can design interactive programs. Programs in which objects are not static rather they appear
to be moving or changing is considered as “Interactive programs”.

Rotating a square
Consider the following two-dimensional point:
x = cos θ
y = sin θ
This point lies on a unit circle regardless of the value of θ. The three points (− sin θ , cos θ), (− cos θ , − sin θ), and (sin θ
, − cos θ) also lie on the unit circle. These four points are equidistant along the circumference of the circle, as shown in
the above Figure.
we can display this square with the following display function

void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON);
thetar = theta*(3.14159/180.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();
}
suppose that we change θ as the program is running, thus rotating the square about the origin. We can display the rotated
cube by simply reexecuting the display function through a call to glutPostRedisplay.
we want to increase θ by a fixed amount whenever nothing else is happening. We can use the idle callback for this
operation.
glutIdleFunc(idle);

void idle()
{
theta+=2; /* or some other amount */
if(theta >= 360.0 theta-=360.0;
glutPostRedisplay();
}

This program will work, but we must make one further change: We want to be able to turn on and turn off the rotation
feature. We can accomplish this change by using the mouse function to change the idle function.

16
Dr Sudhamani M J, Associate Professor, Dept of CSE
Module 3
void mouse(int button, int state, int x, int y)
{
if(button==GLUT_LEFT_BUTTON&&state==GLUT_DOWN)
glutIdleFunc(idle);
if(button==GLUT_MIDDLE_BUTTON&&state=GLUT_DOWN)
glutIdleFunc(NULL);
}
Thus, the left mouse button starts the cube rotating, and the middle mouse button stops the rotation.

Double Buffering
Double buffering is a must in such animations where the primitives, attributes and viewing conditions are changing
continuously.
Double buffer consists of two buffers: front buffers and back buffers. Double buffering mode can be initialized:
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
Further in the display function, we have to include: glutSwapBuffers() to exchange the contents of front and the back
buffer. Using this approach, the problems associated with flicker can be eliminated.

The front and back buffers are color buffers that hold information that can be displayed on the screen. Normally, when
we use double buffering, we would like OpenGL to draw into the back buffer, but we can control which color buffer is
used for drawing through the function glDrawBuffer(). The default, when double buffering has been enabled, is equivalent
to the following:
glDrawBuffer(GL_BACK);
If we use
glDrawBuffer(GL_FRONT_AND_BACK);

Using Timer:
To understand the usage of timer, consider cube rotation program and its execution is done by using fast GPU (modern
GPUs can render tens of millions of primitives per second) then cube will be rendered thousands of time per second and
we will see the blur on the display.
Therefore, GLUT provides the following timer function:

glutTimerFunc(int delay, void(*timer_func (int), int value)

Execution of this function starts timer in the event loop that delays for delay milliseconds. When timer has counted down,
timer_func is executed the value parameter allow user to pass variable into the timer call back.

int n = 60; /* desired frame rate */


glutTimerFunc(100, myTimer, n);

in main and then define the callback as follows:


void myTimer(int v)
{
glutPostRedisplay);
glutTimerFunc(1000/n, myTimer, v);
}

LOGIC OPERATIONS

17
Dr Sudhamani M J, Associate Professor, Dept of CSE
Module 3

Rubberbanding, a technique used for displaying line segments (and other primitives) that change as they are manipulated
interactively.
When a program specifies a primitive that is visible, OpenGL renders it into a set of colored pixels that are written into
the present drawing buffer. In the default mode of operation, these pixels simply replace the corresponding pixels that are
already in the frame buffer.
this mode, called copy, or replacement, mode, it does not matter what color the original pixels under the rectangle were
before

The pixel that we want to write is called the source pixel. The pixel in the drawing buffer that the source pixel will affect
is called the destination pixel. In copy mode, the source pixel replaces the destination pixel.
The second mode is the exclusive OR or XOR mode in which corresponding bits in each pixel are combined using the
exclusive or logical operation. If s and d are corresponding bits in the source and destination pixels, we can denote the
new destination bit as di, and it is given by
di = d ⊕ s,
where ⊕ denotes the xor operation. The most interesting property of the xor operation is that if we apply it twice, we
return to the original state. That is,
d = (d ⊕ s) ⊕ s.
Thus, if we draw something in xor mode, we can erase it by simply drawing it a second time.

To change mode, we must enable logic operation, glEnable(GL_COLOR_LOGIC_OP) and then it can change to XOR
mode glLogicOp(GL_XOR). GL_COPY is the default operator.

Drawing Erasable Lines


We use the mouse to get the first endpoint and store this point in object coordinates as follows:
xm = x/500.;
ym = (500-y)/500.;
We then can get the second point and draw a line segment in xor mode:
xmm = x/500.;
ymm = (500-y)/500.;
glLogicOp(GL_XOR);
glBegin(GL_LINES);
glVertex2f(xm, ym);
glVertex2f(xmm, ymm);
glLogicOp(GL_COPY);
glEnd();
glFlush();
18
Dr Sudhamani M J, Associate Professor, Dept of CSE
Module 3

The callbacks are registered as as follows:


glutMouseFunc(mouse);
glutMotionFunc(move);
void mouse(int btn, int state, int x, int y)
{
if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
xm = x/500.;
ym = (500-y)/500.;
glColor3f(0.0, 0.0, 1.0);
glLogicOp(GL_XOR);
first = 0;
}
if(btn==GLUT_LEFT_BUTTON && state == GLUT_UP)
{
glRectf(xm, ym, xmm, ymm);
glFlush();
glColor3f(0.0, 1.0, 0.0);
glLogicOp(GL_COPY);
xmm = x/500.0;
ymm = (500-y)/500.0;
glLogicOp(GL_COPY);
glRectf(xm, ym, xmm, ymm);
glFlush();
}
}
void move(int x, int y)
{
if( first == 1)
{
glRectf(xm, ym, xmm, ymm);
glFlush();
}
xmm = x/500.0;
ymm = (500-y)/500.0;
glRectf(xm, ym, xmm, ymm);
glFlush();
first = 1;
}

**************************************

19
Dr Sudhamani M J, Associate Professor, Dept of CSE

You might also like