FAQ for Computer Graphics

This FAQ is your document. I add anything that someone runs into and tells me about. If you run into some "gotcha" that you'd like to pass on to others, please tell me about it.

Printing a program

You can get a nicely formatted printout of a C program using "a2ps" as follows. The second form gives you line numbers as well. The last form prints usage information.

a2ps foo.cc
a2ps -C foo.cc
a2ps --help

Submitting a program

To submit a program, you will use the "drop" command in Linux. If you want to submit a program called "house.cc" use the following:

drop cs307 house.cc

The "drop" command only drops one file. If you need to drop several files (such as when we do texture mapping and you need to drop the texture files as well as the source code), you can use the following:

submit cs307 house.cc *.ppm

Emacs

If you're unfamiliar with Emacs or you've forgotten what you knew, there are many resources for learning more. There is my Emacs Introduction, and the following page has some other resources. I also highly recommend running the built-in Emacs tutorial, which you can get to by typing "C-h t" which is control-h followed by the letter "t."

You can also google for "Emacs introduction" or "Emacs tutorial" and you'll get many hits. If you find a really good one, please share!

Unix/Linux

If you're unfamiliar with Unix and Linux (almost the same thing) or you've forgotten what you knew, there are many resources for learning more. There is my Unix Introduction, and the following page has some other resources.

A web search may help as well. Look for "Unix commands introduction" and phrases like that. If you find a really good one, please share!

Making an X connection between Mac and Linux

The X11 protocol allows you to run graphics programs across a network. The machine that you're physically at is called the "server," and the machine that needs to do graphical output is called the "client." In our situation, the Linux machines will be the clients, and the OSX Macs in E101 will be the servers.

In the following example, I will use "herring" as the example of the linux machine I'm connecting to. You may use whatever machine you like, and it's probably best if we don't all use "herring." You can get a list of CS department Linux computers.

  1. login to the Mac.
  2. launch the X11 utility program, which will also open an X11 terminal window.
  3. connect via ssh to Herring (or Bass or Carp or any of the Linux machines). Feel free to experiment to see if there's a performance difference. Don't connect to Puma or Sampras; they can't compile OpenGL right now.
    ssh -Y username@herring
    

    the -Y handles all the X11 stuff about opening displays and such. If you omit it, you'll get some sort of error like "cannot open display."

  4. Continue with the directions for working on a Linux machine

Using OpenGL on Linux

  1. Create an OpenGL source file. To copy the barn code, use a command like the following. Notice the final "dot" that is the second command-line argument. It's easy to overlook. That dot means "the current directory," or just "here."
    cp ~cs307/public_html/demos/early/Barn.cc .
    
  2. Compile it using "make-tw," which is a command that references a Makefile that specifies libraries and such. Note that you say the name of the thing you're trying to make (Barn), not the file you're making it out of (Barn.cc).
    make-tw Barn
    
  3. Run it. You run a program in Unix by just giving its name on the command line:
    Barn
    

Details of Compiling OpenGL and TW Programs on Linux

OpenGL has a bunch of libraries that must be included in the compiled program. Also the libraries for X11 and TW must be included. The result is a little complicated, so we will use a Makefile that captures all this complexity. The make-tw command described in the previous section hides a reference to a special Makefile for compiling TW programs. This section describes how to compile if you don't want to use the make-tw command.

To compile a program for this class, we will use make. By default, make looks for a file called Makefile in your current directory. The Makefile that will work is in our TW directory. Copy it to your current directory. Notice the tiny "dot" at the end of the command, which means that the destination of the copy is the current directory.

cp ~cs307/public_html/tw/Makefile .

You can then compile a program. Let's copy one of the demo programs as an example:

cp ~cs307/public_html/demos/early/Barn.cc .
make Barn

You can now run the program just by giving its name as a command

Barn

If you need to customize that Makefile, say to add additional libraries, you can edit it with emacs; it's just an ordinary text file.

A few tips on programming in C/OpenGL

In C, the order in which you write your methods (functions) is important. You cannot call a function unless the function definition precedes the call in your code. Thus, the organization is often "bottom up," with all the low-level functions first, and "main" last.

The order of OpenGL functions in main() is very important. For example, it doesn't work to set up a keyboard callback before you create the window. Since there aren't any deep principles here, it's best just to stick to the order in the demos.

Many C and OpenGL functions have entries in the online manuals. To learn more than you ever wanted to know about function "foo," do "man foo" at the shell or "M-x man RET foo RET" in Emacs. Reading man pages via Emacs is highly recommended, since it allows you to search, scroll up and down, and follow cross-references.

Compiler Error Messages

Here's a confusing error message:

filename.cc:57: no matching function for call to `twColor(double, double,
   double, int, int)'
/home/cs307/pub/tw/tw.h:229: candidates are: void twColor(GLfloat*, float,
   float)
/home/cs307/pub/tw/tw.h:231:                 void twColor(float, float, float,
   float)

If we look in our filename.cc on line 57, we see something like this:

    twColor(0.8,0.5,0.3,0,0);   // brown

What this error message means is that there are two functions that are candidates to match this call (because they have the same name), but neither has the right "signature" (number and types of arguments). You're calling the function with 3 doubles and 2 ints (see the first line), but the candidats are either an array of floats and two floats or four floats.

Solution: decide which you want and correct your function call.

Run-time and other errors

Using pure OpenGL, I had a problem with program execution failing on Fedora because the library file "/usr/lib/libstdc++.so.5" is missing. (It's replaced by "/usr/lib/libstdc++.so.6"). I only had two include files:

#include <GL/glut.h>
#include <stdlib.h>

Both are necessary, but switching the order of these two, so that the "stdlib.h" was included first, eliminated the problem.

Debugging

If you put in a "print" statement (actually, "printf" is the function), be sure to end the format string with a "\n". If you omit that, the system may "buffer" the output, waiting for additional input for this line, instead of printing it to the screen. Then, if your program crashes, you may not ever see the output, which is very confusing, since you'll think the program crashed before getting to that print statement.

How many slices and stacks do I need?

If a function takes a number like "slices" or "stacks," consider 3 to be the minimum (yielding a triangle). The more slices and stacks, the more smooth the silhouette will be.

Why is my surface all speckly?

This often happens when, in fact, there are two surfaces that exactly overlap. For example, a surface of a brown table with a white placemat on top of it. If the top of the table is at y=5 and so is the placemat, OpenGL sometimes draws brown table pixels and sometimes white placemat pixels. There are ways to fix this using depth functions, but the easiest is to make the placemat just slightly higher than the table. Say y=5.01. As long as that distance is something that OpenGL can still distinguish after all the projection and other transformations, this technique will work perfectly.

Why am I getting "Stack Overflow" run-time errors from OpenGL?

Usually the stack that is overflowing is the stack of MODELVIEW matrices. Typically, this is caused by a mismatched pairs of pushMatrix() and popMatrix(). Particularly if you rotate the scene, these can quickly build up and overflow the stack.

Blank Screen Appears Instead of Image

IMAGE FLIES OFF THE SCREEN WHEN YOU CLICK ON IT

In this case it's most likely that you forgot to put glPushMatrix() and glPopMatrix() in the display method. If you are doing any affine transformations then each time the display method is called (if you do not use glPushMatrix() and glPopMatrix()), then the image will be redrawn from where the last screen stopped drawing. That is, if you draw a box, then translate -40 in the x direction and draw another box, each time the display method is called it will start -40 more in the x direction, meaning that pretty soon you won't see your image anymore!

INCORRECT LIGHTING EFFECTS WITH ANIMATION

when you want a light that does not move with respect to the eye (meaning that you are physically moving your object, not the camera), then you want to set up a light before display() is called.

EXTRA LIGHTING TIPS

The fourth coordinate of the light position is very important! For example, the light position {1.0,2.0,3.0,0.0} means that the light is a distant light source with a direction vector (1.0,2.0,3.0). When the fourth coordinate is 1.0, then the light is a point source (what you need for a spotlight effect).

Drawing Axes

The axes are drawn, optionally, by twCamera. If you want to set up your own camera, you'll have to draw your own axes. (You can call twAxes.). Make sure you haven't enable lighting, though, because twAxes uses direct color.

SETTING UP TEXTURE MAPPING

Also:

What Happened to my Coordinate System?

You're developing your program and somehow things are getting messed up so that when you use the mouse to drag the viewpoint, the scene moves in funny ways.

Answer: Make sure you don't have a glTranslate(), glRotate() or glScale that isn't contained inside an glPushMatrix() and glPopMatrix(). The transformation may end up affecting every subsequent operation, including click-and-drag.

MATH TIPS

Written by Scott D. Anderson
scott.anderson@acm.org
Creative Commons License
This work is licensed under a Creative Commons License.

Valid HTML 4.01!