100 likes | 115 Views
Learn about efficient data structures for 2½-D GUI design, including issues like picking and clipping, with examples and implementations in C++.
E N D
More on Picking Glenn G. ChappellCHAPPELLG@member.ams.org U. of Alaska Fairbanks CS 381 Lecture Notes Wednesday, October 1, 2003
Data Structure for 2½-D • Issues involved in designing a 2½-D GUI: • Picking. • Clipping. • Also, structure to hold overlapping objects (windows?). • Data structure requirements: • Can quickly iterate through objects front-to-back. • Can quickly iterate through objects back-to-front. • Can quickly insert a new object at the front. • Can quickly move any object to the front. • Solution: • A doubly linked list. • The C++ Standard Template Library has a nice implementation of a doubly linked list: std::list in the <list> header. CS 381
Review:Picking Methods [1/3] • 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. CS 381
Review:Picking Methods [2/3] • 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. CS 381
Review:Picking Methods [3/3] • Method #3: Selection Mode • OpenGL allows “names” to be given to primitives. • In selection mode, the application can get a list of the names of primitives that were not discarded during clipping. • The Method • Name each object in the scene. Assign a name to each primitive according to what object it is part of. • Set the clipping region to be a very small rectangle at the mouse position. • Set selection mode and draw the scene. • Get the list. It contains the names of objects that were clicked on. CS 381
Extent Testing:Implementation • To do picking via the extent testing method: • Store objects in a doubly linked list, front-to-back. • This is optional. • When a mouse click happens: • Iterate through objects (in front-to-back order). • For each object, test whether the mouse is in its extent. • The first successful test gives the selected object. • If no tests are successful, then no hit. • Or hit on background. • We need to be able to test whether a mouse position is in the extent of an object. • This is easiest for: a screen-aligned rectangle. • See mouseinrect.cpp. CS 381
Buffer Reading:Using glReadPixels[1/2] • We need to be able to read a pixel from a color buffer. • The OpenGL command glReadPixels reads a rectangular block of pixels from a color buffer. • The block can be 11 (a single pixel). • Watch out for precision! The color returned may not be exactly the color that was drawn. • See readpixel.cpp. • Important buffer issues: • Which buffer are we drawing in. • Which buffer are we reading from. CS 381
Buffer Reading:Using glReadPixels[2/2] • Function glReadPixels reads a block of pixels into a user-provided array. 7 parameters: • x, y: GLint’s. window coordinates (in pixels) of lower-left corner of block of pixels to read. • Remember, OpenGL starts from the bottom of the window. • width, height: GLsizei’s (integer type). Width and height of block, in pixels. • format: The kind of data you want. Usually either GL_RGB (for R, G, and B) or GL_RGBA (for R, G, B, and A). • type: The data type of the elements of the array. I suggest GL_FLOAT. (GLdouble is unsupported.) • pixels: A pointer to the array (which must be big enough!). CS 381
Buffer Reading:Setting the Drawing Buffer • Function glDrawBuffer sets which color buffer is drawn to. • This affects all subsequent rendering. • 1 parameter: generally GL_FRONT (default) or GL_BACK. • When double buffering is enabled (GLUT_DOUBLE), GLUT does “glDrawBuffer(GL_BACK);”. • So you probably do not need to call glDrawBuffer yourself. • But if you do, call glDrawBufferbefore drawing the scene. • Program readpixel.cpp does not demonstrate the use of this function. CS 381
Buffer Reading:Setting the Reading Buffer • Function glReadBuffer sets which color buffer is read from. • … by subsequent calls to glReadPixels, for example. • 1 parameter: generally GL_FRONT (default) or GL_BACK. • If you wish to draw into and read from the back buffer, then you will need to call glReadBuffer. • Call glReadBufferbefore calling glReadPixels. • Program readpixel.cpp does not demonstrate the use of this function. CS 381