CSE 457: Introduction to Computer Graphics
Project 0 help session
This page is here to help you become familiar with the SGI Indy workstations
as quickly as possible. The following are quick tutorials for using subsets
of OpenGL, libui, and CaseVision -- basically enough to get you through
project 0 -- and, for those of you who have not created your own home page,
there is a tutorial for creating a very basic one, as well.
Lecture slides.
OpenGL - 2D/3D Graphics Library developed at Silicon Graphics Inc.
Basic features:
- C language interface
- Graphic primitives:
- points, line segments, or polygons
- defined by a group of one or more vertices
- subject to several drawing modes which affect color, pattern,...
- Manipulation of frame buffer contents:
- useful for displaying images (arrays of data)
- also useful for handling expose events
Other features:
- Clipping, Shading, Texture mapping, etc.
Graphics Primitives
Graphics primitives (points, squares, lines) are one thing you'll use
OpenGL for: mainly to draw zoom boxes and vectors. Here's
a brief introduction (you'll find more in the man pages and reference
manuals)
- glColor - specify the color in which to draw primitive(s)
- glBegin, glEnd - delimit the vertices of a primitive or
a group of like primitives
- void glBegin( GLenum mode )
-
- GL_POINTS - treats each vertex as a single point
- GL_POLYGON - vertices define a solid, convex polygon
- see OpenGL manual for other modes
- glVertex - specify a vertex
- void glVertex2i( GLint x, GLint y )
- glFlush() - tells OpenGL to draw primitives now.
Example Code -- primitives:
The following bits of code show you how draw single-pixel dots,
a triangle outline (see OpenGL manual for other ways to do this), and a filled triangle
(as a three-sided polygon).
uiSetCurrentWindow( drawWind, 0 ); // libui call
glColor3f( red, green, blue );
// drawing a single-pixel dot to the
// window, at pixel coordinate (x,y)
glBegin( GL_POINTS );
glVertex2i( x, y );
glEnd();
// drawing an outlined triangle (many ways to
// do this) having vertices A, B, and C
glBegin( GL_LINE_STRIP );
glVertex2i( Ax, Ay );
glVertex2i( Bx, By );
glVertex2i( Cx, Cy );
glVertex2i( Ax, Ay );
glEnd();
// drawing a filled triangle having
// vertices A, B, and C
glBegin( GL_POLYGON );
glVertex2i( Ax, Ay );
glVertex2i( Bx, By );
glVertex2i( Cx, Cy );
glEnd();
glFlush(); // don't forget this!
Drawing images and other data
You could draw images one pixel at a time -- setting the color each time, telling
OpenGL to explicitly draw each pixel at each coordinate -- but this would be very
inefficient and doesn't always work anyway. That's why OpenGL provides the following
routines (and others).
The main routines:
- glReadBuffer, glDrawBuffer : used to specify the buffer that will be
read from or drawn to (e.g. GL_FRONT)
- glReadPixels, glDrawPixels : does the actual reading/writing
- void glReadPixels( GLint x,
GLint y,
GLsizei width,
GLsizei height,
GLenum format,
GLvoid type,
Glvoid *pixels )
-
- x, y - window coordinates of lower left corner of read source rectangle
- width, height - width and height of read source rectangle
- see OpenGL manual for details on other parameters
Other useful ones:
- glCopyPixels : copies a specified rectangular region of pixels from the ReadBuffer to the DrawBuffer relative to the current raster position
- glRasterPosxx : sets the raster position to start drawing, (0,0) is the lower left corner of an OpenGL window
- glPixelZoom : how much to scale the data when converting to pixels
Example Code: raster routines
// this routine will read the data from one window,
// and draw it on another
// allocates a chunk of memory to store enough data for 3 channels (r,g,b)
// of data for width*height pixels
unsigned char data[DRAW_HEIGHT][DRAW_WIDTH][3]
// read the data on one window
uiSetCurrentWindow( drawWind, uiNormal ); // libui call
glReadBuffer( GL_FRONT );
glReadPixels( 0, 0, DRAW_WIDTH, DRAW_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE,
&data[0][0][0] );
// now send it back out
uiSetCurrentWindow( otherWind, uiNormal ); // libui call
// set the right buffer and the right position, just in case
glDrawBuffer( GL_FRONT );
glRasterPos2i( 0, 0 );
glDrawPixels( DRAW_WIDTH, DRAW_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE,
&data[0][0][0] );
Notice that this example uses data stored as three bytes representing RGB (24-bit)
color. Since you'll be using indexed color for project 0, you'll want to see the
documentation for glReadPixels and glDrawPixels for how to handle this.
Handling exposure events two schools:
- Redraw just redraw all the primitives to recreate the
window's contents -- useful for simple things like zoom boxes
- Backing store store all the data in your own structure
and redraw (like above).
Libui is fully documented on the web (libui documentation),
and you really don't need to know much about libui to handle the basics of project 0.
- Basics user interface library with one or more drawing
areas, buttons, toggle buttons, sliders, textfields, file-selection dialogs,
and menus
- Event handling user-driven programming, where events
(such as mouse
movement and clicks) cause a particular callback function to be evoked
Some example procedures:
- uiSetCurrentWindow
- uiGetSliderValue
- uiAddButton
Example uses:
// following OpenGL calls will draw to
// normal (vs overlay plane) buffer of my_window
uiSetCurrentWindow( my_window, uiNormal );
// read the current slider value
value = uiGetSliderValue( mySlider );
// to add a button to the GUI that,
// when pushed, evokes my_Callback
uiAddButton( "my_button", my_Callback );
Look at the documentation and starting-point project 0 for more information
on how to use these procedures.
CaseVision is a very handy graphical debugging tool that will help you
greatly. Unfortunately (and quite ironically), it has a few bugs. These
are namely in how it handles killing processes, so be sure to check for
stray ones. Also, there are a few problems in debugging C++ code, but
it should be fine for projects 0 through 2.
- Compile with the -g option (Makefile is already set appropriately)
% cvd
(executable_name)
- Load an executable (and core) choose the
Admin/Switch Executable menu option
- Load C/C++ source file to set breakpoints within - choose the
Source/Open menu option
- Set/remove breakpoints scroll through the source code, left-mouse-click
to select a breakpoint, and again to remove a breakpoint
- Control flow options:
- Step Over
- Step Into
- Return
- Continue
- Browsing options (some):
- Views/Variable browser
- Views/Call stack
- Views/Structure browser
- Views/Array browser
- Views/Expression browser
- Views/...
You'll be filling in three procedures, this is basically what they do:
calculateFractal
:
this procedure needs to loop through the pixels,
calculate a complex number based on the screen position
(i.e. [0, DRAW_WIDTH] -> [rangeLeft, rangeRight]), and
call mandelbrot()
with that complex number.
This will return
the number of iterations it took to diverge, and you'll use
that number as a color index for that pixel.
exposeCallback
:
this procedure is called whenever the drawing window is
obscured by another window (or actuallly, after it is brought
back to the foreground). you'll need to add code that will
redraw the window (without recalculating the fractal).
zoomCallback
:
this is called when the user hits the Zoom In button.
the pixel-coordinates of the zoom box are stored as
zoom[Left,Right,Top,Bottom]. Use this info to change
range[Left,Right,Top,Bottom], and recalculate the fractal.
For the bells and whistles, you'll want to check with the OpenGL reference
manual (which is available on the Indys -- from the toolchest in the
upper left corner, select Help / Online Books,
and the libui documentation.
You can also find a truckload of information on fractals on the web
(use your favorite search engine); here's a few, anyway:
- Take a picture of yourself
- Log into an Indy workstation, slide away the IndyCam's lens cover, and remove
the lens cap - yes, obvious
% capture
- Select the still-camera icon from the menu button (lower left corner)
- If needed, adjust the settings (under Actions menu); you might want to
White Balance the IndyCam using the Video Panel (under Tools). You can
also focus the IndyCam (rotate the lens, like a normal camera).
- Center yourself in the red crop box
- Left-mouse-click on the record button to take a picture. Resulting
image is automatically saved as capture.rgb. To preview the image you
just made, hit the preview button.
- If you don't like the picture, take another one. Remember, though, that this
will write over your previous "capture.rgb". You might want to copy any
semi-decent ones to another filename, just in case you can't seem to get a better
one!
- Next, convert the image file to GIF format using
XView
% xv capture.rgb
This will load in your rgb file; to get the xv menu, click the
right-mouse button inside the image.
To save the file in the "gif" format, hit the Save button. You'll then
get a dialog box. Click the "gif" radio button, and change the name as
needed. Click Ok, and then Quit.
I'll leave any other exploration of xv (Color Editing, Cropping, etc.)
up to you.
- Doctor image as desired (scale, crop, etc.), then save image
in the GIF format with a .gif extension as in
your_name.gif
- Make a www sub-directory in your home directory on lynx, wolf,
or grizzly, and move your .gif image into the new directory.
You can reach your home directory (on wolf/lynx/grizzly) from the SGI's with:
/homes/iws/yourname
You cannot, however, reach the SGI directories from wolf/lynx/grizzly.
- For starters look at one of the TA's or a friends home page
(or click here for a dummy page), and
save the HTML source for that page by choosing the File/Save As
menu option and then selecting the HTML format. Load the file into a text
editor and modify it to your liking, and save it as index.html in your
www directory. There will be a line of HTML text like
< img src="tas_name.gif">
that you should change to
< img src="your_name.gif">
- Access
- To have your page appear in the CSE department pages,
create a file called .www-publish-me in your
home directory (on wolf/lynx/grizzly).
- To allow access to your page to users outside the CSE net,
save
this file in your www directory (on wolf/lynx/grizzly)
as ".htaccess"
- Browse the web to get ideas for your home page, and when you find
one you like, select the File/View Source menu option to see the HTML
source code will appear in the window. This is a great way to learn the features
of HTML -- well, the way I learned.
- For an official HTML primer,
click here
Send questions or comments to Fred Pighin (pighin@cs.washington.edu)