02/09/05

We talked about how the mouse could be used in drawing.  We talked about the following program:

// This program allows users to draw lines (freelance) using the left mouse button
// Rahman Tashakkori - Spring 2004

#include <GL/glut.h>
int anchorx, anchory;

void myinit(void)
{

        /* attributes */
        glClearColor(1.0, 1.0, 1.0, 1.0); /* white background */
        glColor3f(1.0, 0.0, 0.0); /* draw in black */
        /* set up viewing */
        /* 50 x 50 window with origin lower left */
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluOrtho2D(0.0, 500.0, 0.0, 500.0);
        glMatrixMode(GL_MODELVIEW);
}

void display( void )

{
        glClear(GL_COLOR_BUFFER_BIT);  /*clear the window */
        // add "connect the dots" code here
        glFlush(); /* clear buffers */
}

void mouse(int button, int state,int x, int y)
{
        anchorx=x;
        anchory=500-y;
}

void mousemove(int x,int y)
{
        glColor3f(1.0, 0.0, 0.0); /* draw in black */

        glBegin(GL_LINES);
                glVertex2f(anchorx,anchory);
                glVertex2f(x,500-y);
        glEnd();
        anchorx=x;
        anchory=500-y;
        glFlush(); /* clear buffers */

}
void main(int argc, char** argv)
{
        /* Standard GLUT initialization */
        glutInit(&argc,argv);
        glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); /* default, not needed */
        glutInitWindowSize(500,500); /* 500 x 500 pixel window */
        glutInitWindowPosition(0,0); /* place window top left on display */
        glutCreateWindow("Test"); /* window title */
        glutDisplayFunc(display); /* display callback invoked when window opened */
        glutMouseFunc(mouse);
        glutMotionFunc(mousemove);
        myinit(); /* set attributes */
        glutMainLoop(); /* enter event loop */
}


This will produce a screen that looks like this:
draw1

Among things we need to notice is how we converted the mouse coordinate (y) to that of the screen.

We talked about the Display and idle call back functions.  We have seen the display callback:glutDisplayFunc(display);
It is invoked when GLUT determines that the window should be redisplayed.  One such situation is when the window is open initially.
Since the display event will be generated when the window is first opened, the display callback is a good  place to put the code that generates most non-interactive output.  GLUT requires all programs to have a display function, even if it is empty.
Some of the things we can do with the display callback:
    1) Animation – various values defined in the programs may change
    2) Opening multiple windows
    3) iconifying a window – replacing a window with a small symbol or     picture.
Interactive and animation programs may contain many calls for re-execution of the display function. Rather than calling it directly, we use the GLUT function glutPostRedisplay(); The idle callback is invoked when there are no other events.  Its default is the null function.

GLUT supports both multiple windows and subwindows of a given window.
id = glutCreateWindow(“Second Window” );
The returned integer value allows us to select this window as the current window:
glutSetWindow(id);
Menus
We can use our graphics primitives and our mouse callback to construct various graphical input devices.
How do you think we can create this one?
GLUT provides pop-up menus.
Using menus involves:
    1) Must define the entries in the menu,
    2) must link the menu to a particular mouse button, and
    3) must define a callback function corresponding to each menu entry.

glutCreateMenu(demo_menu);
glutAddMenuEntry(“quit”, 1);
glutAddMenuEntry(“increase square size”, 2);
glutAddMenuEntry(“decrease square size”, 3);
glutAttachMenu(GLUT_RIGHT_BUTTON);
The second argument in each entry’s definition is the identifier passed to the callback when the entry is selected.  The callback function looks like this:
void demo_menu(int id)
{
     if(id == 1)  exit(1);
    else if (id == 2) size = 2*size;
    else size = size / 2;
    glutPostRedisplay( );
}

Suppose we want  the main menu that we create to have two entries:
    1) the first one to terminate the program
    2) the second to pop-up a submenu.
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);

Now we have to write the call back functions, size_menu and top_menu.

Here is an example in which we are using a menu.  This is the same program as the above one with menu to select the size for the line using the right button.

// This program allows users to draw lines (freelance) using the left mouse button
// It provides a simple menu for changing the line width
// Rahman Tashakkori - Spring 2004

#include <GL/glut.h>
int anchorx, anchory;

int size = 4;

void myinit(void)
{

        /* attributes */
        glClearColor(1.0, 1.0, 1.0, 1.0); /* white background */
        glColor3f(1.0, 0.0, 0.0); /* draw in black */
        /* set up viewing */
        /* 50 x 50 window with origin lower left */
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluOrtho2D(0.0, 500.0, 0.0, 500.0);
        glMatrixMode(GL_MODELVIEW);
}

void display( void )

{
        glClear(GL_COLOR_BUFFER_BIT);  /*clear the window */
        // add "connect the dots" code here


        glFlush(); /* clear buffers */
}

void mouse(int button, int state,int x, int y)
{
        anchorx=x;
        anchory=500-y;
//        if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
//              glPointSize(size);

}

void mousemove(int x,int y)
{
        glColor3f(1.0, 0.0, 0.0); /* draw in black */
 
        glLineWidth(size);
        glBegin(GL_LINES);
                glVertex2f(anchorx,anchory);
                glVertex2f(x,500-y);
        glEnd();

        anchorx=x;
        anchory=500-y;

        glFlush(); /* clear buffers */

}

void sizemenu(int id)
{
    if(size < 4) size = 4;

    if(id == 1) size /= 4;
    if(id == 2) size /= 2;
    if(id == 3) size *= 2;
    if(id == 4) size *= 4;

}

void main(int argc, char** argv)
{
        int s_menu;

        /* Standard GLUT initialization */
        glutInit(&argc,argv);
        glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); /* default, not needed */
        glutInitWindowSize(500,500); /* 500 x 500 pixel window */
        glutInitWindowPosition(0,0); /* place window top left on display */
        glutCreateWindow("Test"); /* window title */
        glutDisplayFunc(display); /* display callback invoked when window opened */

        s_menu = glutCreateMenu(sizemenu);
        glutAddMenuEntry("Thiner",1);
        glutAddMenuEntry("Thin",2);
        glutAddMenuEntry("Thick",3);
        glutAddMenuEntry("Thicker",4);
        glutAttachMenu(GLUT_RIGHT_BUTTON);

        glutMouseFunc(mouse);
        glutMotionFunc(mousemove);
        myinit(); /* set attributes */
        glutMainLoop(); /* enter event loop */
}


This produces a screen that looks like this:
draw2