Presentation is loading. Please wait.

Presentation is loading. Please wait.

Selection Mode, Introduction to Widgets Glenn G. Chappell U. of Alaska Fairbanks CS 381 Lecture Notes Monday, October 6, 2003.

Similar presentations


Presentation on theme: "Selection Mode, Introduction to Widgets Glenn G. Chappell U. of Alaska Fairbanks CS 381 Lecture Notes Monday, October 6, 2003."— Presentation transcript:

1 Selection Mode, Introduction to Widgets Glenn G. Chappell CHAPPELLG@member.ams.org U. of Alaska Fairbanks CS 381 Lecture Notes Monday, October 6, 2003

2 6 Oct 2003CS 3812 Where Are We? We have covered: Chapter 1. Intro. to CG. Chapter 2. Basic CG Programming. Much of Chapter 3. GUI’s & picking. Now we continue with picking, and discuss widgets. Next week, we switch to 3-D CG: Chapter 4. Math of 3-D CG. Chapter 5. 3-D Viewing. Chapter 6. Lighting.

3 6 Oct 2003CS 3813 Review: Picking Methods [1/2] Method #1: Extent Testing The “obvious” way to do picking: Figure out the extent of each object. For each, test whether the mouse position is inside it. In a 2½-D interface (e.g., overlapping windows), can test in front-to-back order. Disadvantage Complex object shapes can make for tricky testing.

4 6 Oct 2003CS 3814 Review: Picking Methods [2/2] Method #2: Buffer Reading If we can read the frame buffer: Draw each object in a different, solid color. Read the color of the pixel at the mouse position to determine what was clicked on. Double buffering makes this nicer. Draw to and read from the back buffer, without swapping. Then users don’t need to see the strangely colored version of the scene. Method #3: Selection Mode We examine this method in detail today.

5 6 Oct 2003CS 3815 Selection Mode: Introduction Our third picking method uses OpenGL’s “selection mode”. A “name” can be given to a primitive. As usual, a name is actually a number. In selection mode, drawing commands produce no output. Instead, we get a list of the names of primitives that were not discarded by during clipping. If we set the clipping region to be a small area around the mouse position, then we can use selection mode to determine what was clicked on (i.e., to do picking). Example code can be found in selectionmode.cpp, on the web page. Also select.c, which is from the red book.

6 6 Oct 2003CS 3816 Selection Mode: The Method When the mouse is clicked: Allocate a selection buffer. This will hold the hits: names of objects at the mouse position. Initialize selection mode and the name stack. In selection mode, “drawing” produces no output, only hits. The name stack keeps track of the current name. Set up the projection. Redo the projection, just like normal, only putting a call to gluPickMatrix just before **the call to gluOrtho2D. This sets up the required clipping region. **“Draw” the scene, with names inserted into the pipeline. No output, so THE RULES are not being broken. Restore the old projection and the “normal” rendering mode. And, as a side benefit, find out the number of hits. Now the hits are in the selection buffer. At this point, I usually put the hit data into a simpler format.

7 6 Oct 2003CS 3817 Selection Mode: Organizing the Code The **’s on the previous slide mark things that need to be done in two places. The call to gluOrtho2D needs to be made both in the reshape (or init) function and during selection mode. Drawing the named objects in the scene needs to be done both in the display function and during selection mode. Idea: Make separate functions for each of these. Both functions are called in two places. In selectionmode.cpp, I call these functions “ set_up_coords ” and “ draw_with_names ”, respectively. Now write a function to do all the selection mode stuff. Mine is called “ doselect ”. You can probably use doselect without modification.

8 6 Oct 2003CS 3818 Selection Mode: Function doselect [1/7] The “magic” in this program happens in doselect, which is called from the mouse & motion functions. Function doselect is given the mouse position. It returns a list of hits. Along the way, it calls set_up_coords and draw_with_names. Despite the drawing calls, doselect produces no output, so it can (and should!) be called outside the display function. void doselect(int x, int y, int & hitcount, int hitarray[100]) I return at most 100 hits. You want more? That’s your problem.

9 6 Oct 2003CS 3819 Selection Mode: Function doselect [2/7] First, allocate a selection buffer. This is an array of GLuint ’s. 512 seems to be everyone’s favorite size. const int buffersize = 512; GLuint selectionbuffer[buffersize]; This array will hold the hit records. OpenGL will not write past the end of the buffer. We need to make sure we do not read past the end of the buffer.

10 6 Oct 2003CS 38110 Selection Mode: Function doselect [3/7] Next, initialize selection mode and the name stack. glSelectBuffer(buffersize, selectionbuffer); glRenderMode(GL_SELECT); glInitNames(); glPushName(0); We tell OpenGL about the selection buffer. Then we set selection mode. Now drawing commands now produce no output, only hits. Then we initialize the name stack. Lastly, we stick a “dummy” name on the stack.

11 6 Oct 2003CS 38111 Selection Mode: Function doselect [4/7] We are almost ready to draw. We need only set up the picking region. This is done with the projection matrix. glMatrixMode(GL_PROJECTION); glPushMatrix(); // save old projection glLoadIdentity(); // Insert the following three lines just before // your standard gluOrtho2D call. GLint vp[4]; glGetIntegerv(GL_VIEWPORT, vp); gluPickMatrix(x, vp[3]-y, 1, 1, vp); set_up_coords(); This is the code straight from the reshape function, with three magic lines inserted. Do not insert them in the reshape function. The glPushMatrix call is an easy way to save the old projection. Restore it later with glPopMatrix.

12 6 Oct 2003CS 38112 Selection Mode: Function doselect [5/7] Now, we draw, just as in the display function. We need names inserted in the pipeline (more on this later). glMatrixMode(GL_MODELVIEW); draw_with_names(); glFlush(); // Empty the pipeline It is generally good to be in model/view mode when drawing. More on this later in the course. Note the glFlush call. This program is doubly buffered. Thus, in the display function we flush using glutSwapBuffers. But we do not want to swap during selection mode. Right? Thus, we do not do any flushing in draw_with_names. And, thus, we need to do it here.

13 6 Oct 2003CS 38113 Selection Mode: Function doselect [6/7] Now we restore the old projection and the “normal” rendering mode. When we restore the rendering mode, we get the number of hits as a return value. // Done with pick matrix glMatrixMode(GL_PROJECTION); glPopMatrix(); // Restore the old projection glMatrixMode(GL_MODELVIEW); // Done with selection mode hitcount = glRenderMode(GL_RENDER); Now, we know how many hits there were. Details (names) are in the selection buffer. In a tricky format …

14 6 Oct 2003CS 38114 Selection Mode: Function doselect [7/7] At this point, I could just return the selection buffer. But I decided to simplify things a bit. The selection buffer holds a sequence of hit records, which may vary in length. Numbers in the hit record are: 1 GLuint : Name stack depth for this hit. 1 GLuint : Min depth for this hit. See doc’s for format. 1 GLuint : Max depth for this hit. 0 or more GLuint ’s: Name stack contents for this hit. # of values here is the stack depth, above. In a simple 2-D program, the number of interest is the last one in the hit record (the top of the name stack for this hit). So, for each hit, I collect the relevant value. This is the name of the object that was hit. I put all these values in an array and return it.

15 6 Oct 2003CS 38115 Selection Mode: Function draw_with_names Function draw_with_names is just the normal drawing code out of the display function, except: No clearing. No flushing or swapping. Only draw the things we want to do hit testing with. So, in this program, I draw the text instructions in the main display function. Add names. We put names in the name stack with glLoadName. If we are not in selection mode, this is ignored. If we are in selection mode, the name stack must be nonempty. Remember the glPushName call. Once a name is loaded, it applies to all primitives drawn until the name is changed. Just like any well-behaved OpenGL state.

16 6 Oct 2003CS 38116 Introduction to Widgets: What is a Widget? In a GUI, when a user specifies an action to be performed, a “widget” is often used. A widget (also called a control, esp. in MacOS) is a portion of the screen dedicated to mouse input. So widgets are a great application of picking! Examples: Checkboxes Radio buttons Scroll bars Buttons Menu pop-ups Some text boxes We will look at issues involved in the inclusion of widgets in a GUI and their implementation.

17 6 Oct 2003CS 38117 Introduction to Widgets: Issues Widgets often mimic physical objects. So: When a user deals with a widget, it must react immediately. The feedback must appear reasonable. Often shading suggests movement toward/away from the user (2 ½-D). Other issues: User must be able to predict what a widget will do. Nonstandard widgets may not be used. Generic do-anything widgets (like buttons) should be labeled. Scroll bars need to be next to what they scroll. Widgets that produce immediate actions (like buttons) should be easy to distinguish from those that do not (like checkboxes). Physical boundaries of widget should be clear to user. For fast feedback, must be able to draw widgets quickly. Widgets should not waste valuable screen space. Next time we discuss an implementation of a simple widget (a button).


Download ppt "Selection Mode, Introduction to Widgets Glenn G. Chappell U. of Alaska Fairbanks CS 381 Lecture Notes Monday, October 6, 2003."

Similar presentations


Ads by Google