Title: Selection Mode, Introduction to Widgets
1Selection Mode,Introduction to Widgets
- Glenn G. ChappellCHAPPELLG_at_member.ams.org
- U. of Alaska Fairbanks
- CS 381 Lecture Notes
- Monday, October 6, 2003
2Where Are We?
- We have covered
- Chapter 1. Intro. to CG.
- Chapter 2. Basic CG Programming.
- Much of Chapter 3. GUIs 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.
3ReviewPicking 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.
4ReviewPicking 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 dont need to see the strangely
colored version of the scene. - Method 3 Selection Mode
- We examine this method in detail today.
5Selection ModeIntroduction
- Our third picking method uses OpenGLs 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.
6Selection ModeThe 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.
7Selection ModeOrganizing 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.
8Selection ModeFunction 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 hitarray100)
- I return at most 100 hits.
- You want more? Thats your problem.
9Selection ModeFunction doselect 2/7
- First, allocate a selection buffer.
- This is an array of GLuints.
- 512 seems to be everyones favorite size.
- const int buffersize 512
- GLuint selectionbufferbuffersize
- 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.
10Selection ModeFunction 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.
11Selection ModeFunction 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 vp4
- glGetIntegerv(GL_VIEWPORT, vp)
- gluPickMatrix(x, vp3-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.
12Selection ModeFunction 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.
13Selection ModeFunction 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
14Selection ModeFunction 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 docs for format.
- 1 GLuint Max depth for this hit.
- 0 or more GLuints 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.
15Selection ModeFunction 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.
16Introduction to WidgetsWhat 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.
17Introduction to WidgetsIssues
- 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).