%preamble 3jan02 for skeldoc 
\documentclass{article}
\usepackage{verbatim}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{graphicx}
\title{illiSkel in C/OpenGL/GLUT}
\author{George Francis}
\date{3 January 2002}
\input{abbrevia}
\def\skel{{\bf skel.c}}
\def\exercise#1{{\bf Exercise.} #1 \;}
\begin{document}
\maketitle
%\begin{comment}
\section{History of the program.}
The real-time interactive computer animation (\rtica) {\bf illiSkeleton.c} 
is a practical derivative of the classic 1994 {\bf illiShell.c}.
It maintains the general structure of its parent but is restricted 
to animating the monitor of the console. The {\bf illiShell.c} is a fully
functional prototype application for the CAVE which also compiles  
and runs on the console without proprietary CAVE libraries.  

Originally written in C and IrisGL, the illiShell and its evolutes 
have gone through many linguistic permutations, including C++ and OpenGL, with 
and without the GLUT extensions. Its C/OpenGL/GLUT derivative \skel 
has been the basis of almost all \rticas  written since 1997 by
students in illiMath courses and workshops. As such, the illiSkel lends
some kind of minimal structural unity to illiMath, without resorting to 
proprietary libraries and packages which impede portability and hamper
creativity.  The 2002 version of illiSkel is introduced here. A subsequent
chapter treats the extension to a CAVE and a CUBE application.

\section{Programming with illiSkel.}
To minimize the time it takes to master the illiSkel, and maximize the
freedom to modify, extend or rewrite it, the program consists of a single
source file of fewer than 365 lines of code. We assume only the most 
rudimentary programming skills, and have kept things brief and simple. 
The {\tt main()} function appears at the end of the program, in keeping 
with the (now unpopular) philosophy of not working with a concept before 
knowing exaclty what it means. In particular, factors of a function  
precede it in the linear order of the code. Like listing the
ingredients of a recipe before the instructions on how to cook the soup,
you have to be able to read the program backwards as well as forward.
Thus keystroke editors with nimble searching (vi or emacs) are better 
for studying \skel than menu-driven scrolling editors. 
The reader displeased with this design is encouraged to rewrite the skel 
in a more conventional style, but with an agreement that every feature will 
work at least as well in the improved version. 

To work with the illiSkel
means to subtract and add functions, factor functions that are
getting too verbose, and divide the functions into affinity groups by
what they do and how they relate to each other. Such ``arithmetic" also
leads to a better understanding of the illiMath system of writing 
real-time interactive computer animation. 

By subtracting
functions you produce a derivative \rtica which is more easily understood 
and built up again into a different one. You add functions to produce
an extension of the original, integrating new features, better graphics,
subtler navigation, etc. When a concept has grown too big to keep in mind
all at once, we factor it into smaller concepts. Similarly, a function
that has grown so big that it no longer fits on a page or a screen 
should be factored into more manageable bites. But also when you plan
to make many experimental modifications to the same piece of a longer
function, it wise to factor that section out. Finally, functions 
fit into groups by how they share variables and purposes.   
\newpage
\section{Function dependency tree.}
To get an idea of how how the \rtica works when it is running (rather
than compiling) we use an easily edited function dependency tree. 
For the illiSkel this might look like this. 

\begin{verbatim}
main()
  arguments()     
  deFault()
  glut-initializions
  glut-mainloop 
  with callbacks:
    drawcons()
      open-gl functions 
      glFrustum() 
      drawstars()
        random()
      drawall()
        drawtor()
          drawvert()
        drawcube()
      messages()
        char2wall()
        speedometer()
      glutSwapBuffers()
    keyboard()
      deFault() 
        autotymer()
      bump()
        hasnumber()
        getnumber()
    specialkeybo()
    mousepushed()
    mousemoved()
    reshaped()
    idle()
      autotymer()
      glutPostRedisplay()
      chaptrack()
\end{verbatim}

Here is how to read this dependency tree.  The {\tt main()} function 
executes {\tt arguments(), deFault()} and registers the names of the
callback functions {\tt drawcons(), keyboard(), ... , idle()}. Then
the \rtica enters an endless main-loop. The display function here is
called {\tt drawcons()} and its alternative in the illiShell,
{\tt drawcave()}, is a callback function for the CAVE library. On a single
processor computer the display function is executed (almost) as
frequently as the speed of the graphics card allows. This loop is 
interrupted when a key is
pressed on the keyboard, a button pushed on the mouse, the mouse 
is moved, or the window is reshaped, and
the corresponding callback function is executed. The global parameters
and flags changed by the suite of input callbacks are processed by 
the  {\tt idle()} function, which may be thought to be called at least
once per display cycle.\footnote{On a multiprocessor computer, or in 
a distributed graphics cluster, the idle function may be executed 
asynchronously with the graphics display functions. Thus, graphics
calls should should be made only by the display function, and data 
should be updated in the idle function and its factors. That the
navigation function {\tt chaptrack} appears to violate this rule
is discussed below.}

We distinguish three groups of functions in the illiSkel:

\begin{tabular}{ll}
\hline
Parameter management functions   & {\tt steering} \\ \hline
{\tt arguments()}& //takes command line input \\
{\tt deFault()}  & //re-usable initialization   \\
{\tt keyboard()} & //non-queued keypress input  \\
{\tt messages()} & //optional heads-up display \\ 
{\tt speedometer()}& //reports average frame rate \\
{\tt autotymer()} & //a simple clockwork animator \\ 
{\tt idle()}      & //done between graphics frames \\
\hline
Scenery production functions:  &  {\tt scenery} \\ \hline
{\tt initstars(), drawstars() } & // factored star drawer \\
{\tt drawall()} & //  draw everything else like  \\
{\tt drawtor()} & //  a painted torus \\ 
{\tt drawcube()} & // a hypercube  \\
{\tt drawcons()} & // graphics on the console  \\
\hline  
Navigation functions:  & {\tt navigation} \\ \hline
{\tt chaptrack()} & //mouse operated navigator  \\
\end{tabular}

\marginpar{This document normally fits into a sequence of lessons,
starting with the illiOctahedron, illiTorus, illiQub, and the exercises
associated with them. However, it is self-contained and can be 
profitably mastered with, perhaps, one or two micro-derivatives (ca
100 lines of code) such as {\bf oc1.c, qub.c}.}


\section{Defines, includes and global variables.}

In the interest of compactness, items usually found in a 
private header file appears at the top of \skel. After
including the public header files associated with the standard
libraries, we list a sequence of useful if debatable compiler directives,
also known a {\it pound-defines}. They are a species of {\it macros}.
The precompiler rewrites the 
code you hand it\footnote{Originally, before C++ specific compilers were
created, the C++ precompiler rewrote the code into C before  
submitting to a standard C-compiler.} by substituting one string of
symbols for another. Thus, we shorten Brahma-Gupta's constant 
(355/113) approximating $\pi$ to {\tt M\_PI}.\footnote{In Unix this 
actually redefines a more accurately defined constant by the same name.
The windows compiler is happy to be told a value of $pi$.} The parenthesis
are advisable, because the precompiler just substitutes strings, not
values. Many a bug develops by ignoring this fact of life.\footnote{The 
less permissive syntax of C++ methodically uses {\it inline functions} 
instead of pound-defined macros.}  

The precompiler is, however, more obliging than that: it also substitutes
functional argument names. Thus the string {\tt MAX(foo, 5)} 
in your code is rewritten to {\tt (((foo)<(5)?(5):(foo))}. The extra
parentheses prevent possible misunderstandings in more complicated 
contexts.\footnote{ And, for the reader meeting the expression 
{\tt B?T:F} for the first time, know that the compiler evaluates it 
to the expression {\tt F} if the value of {\tt B} is 0, and otherwise
to {\tt T}.} 

Macros make subsequent code shorter and more readable. It is cutomary to
use all caps for their names to make them easier to spot in the source 
code. Do not expect to find them in compiler error messages, because the
compiler sees only only their expansions. 
Though replacing macros with function calls is an alternative, it makes the 
program run more slowly and leads to verbose, tortured code.
Take the macro {\tt IFCLICK}, which uses the function {\tt getbutton()}
\marginpar{\bf getbutton()}
to set a switch bypassing a segement of code. The argument of 
{\tt getbutton()} is the name of a key, and the function returns 1  
if the key had been pressed.\footnote{In IrisGL, {\tt getbutton()} 
was a system function which really interrupted the program flow and 
told the truth. In OpenGL, such interrupts are not allowed for reasons
of inter-system portability. So we must simulate this function as
explained further on.} Inserting an IFCLICK macro anywhere in a function
creates a block with a static flag whose value persists from one call
to the next. A keypress toggles the flag. If the flag is down, the code
segment is bypassed. In the {\tt idle()} function, for example, 
pressing the (=)-key will freeze navigation because the function 
{\tt chaptrack()}, which updates navigation, is {\it not} called again until
you press (=). Try the (--)-key and see what the OpenGL depth
test does for a living.\footnote{Using IFCLICK transgresses the very 
tidy habit of processing 
all keypresses in the same (two) input funtions 
{\tt keyboard(), specialkeyo()}. Moreover, some C++ evangelists say that 
one should not use such tricks at all. Too many {\tt IFCLICKs} scattered
throughout your code will make the operation of your \rtica amusing,
if not aggravating. Use it sparingly during development or your code 
and for analysing someone elses code. Use it for hacking, debugging and 
experimenting, especially when it is not clear yet what features should
become permanent options.}
%make an \excersize numbered object once and for all later

\exercise{Since all interrupts from the keyboard or the mouse are mediated
by the GLUT mainloop, you cannot bypass a callback function as easily. But
you can prevent the effect of a function by setting a flag right at
its beginning which makes it return empty-handed, as it were. For instance,
write {\tt IFCLICK('+', return;)} as the first line of {\tt mousemoved()}
and mouse motion will be ignored when you toggle the (+)-key. 
This won't work right for the 
keyboard callback. Why? Sometimes you'll really want to write text
into one window while watching the \rtica in another, and wish that the 
\rtica were deaf. Modify the code of {\tt keyboard()} which solves this
problem.
}

\exercise{
Some macros are temporary constants, which you wish to change between
recompilations. For instance, the default \skel has 32 meridians
and latitudes on its torus. After you have understood how  illiGadget
work, write one which makes it possible to change how many strings make
up the mesh of the torus while it is running.} 



\section{Parameter management functions.}

We next discuss the those functions which are involved with the 
management of control parameters. They are concerned with {\em how} 
something is rendered by the \rtica, not with {\em what} is rendered. The 
clockwork animation function {\tt autotymer()} appears first in the
source code only for convenience of editing. The first factor of 
of {\tt main()} is {\tt arguments}, which picks up the input you 
wrote on the command line. It is not possible to settle on a best
linear ordering of the functions in the source code, so we keep
the historical order for easier comparison with \rticas based on
older versions. Use your editor to find the functions in the code,
and to trace its variables forward and backward.  

A typical factor of {\tt main(int argc, char **argv)} 
\marginpar{\bf arguments()}
is a function that manages the command line {\tt arguments()}. 
The system reads the entire command line and provides {\tt main()}
with a counter, {\tt argc}, and a pointer of pointers, {\tt argv}. 
Initially, {\tt argc} equals the number of words on your command 
line, {\tt argv[0][0]} is the the first character in the
first word. The {\tt arguments()} function we use in \skel 
was designed by Pat Hanrahan to make it easy for you to add and 
subtract {\em command line switches}. These are items marked with a 
single ``dash-letter'' followed by one or more integers or 
floats.\footnote{Hanrahan's ingenious code is not for the fainthearted.
It also does not suffere fools gladly. It expects to be used by people
who know what they're doing. Therefore, it had been superceded in 
illiMath \rticas by the much more robust but different {\tt getopt()} 
command line argument handlers. Hanrahan's code was revived 
when we found just how awkward it was to make the ``getoptery" work in
Windows. You are welcome to replace replace Hanrahan's arguments with 
something more foolproof as long as the functionality remains.} 

Entering a command line that looks like this,

{\bf iris \% } \hskip .2in {\tt skel.x -w 0 -L 0. 0. 10. -g .8} 

sets the global flag {\tt win} to 0. This specifies a particular size 
and location of the drawing window, as specified by the calls to the
GLUT library initialization in {\tt main()}.  The function {\tt atoi()}  
converts alphameric strings to integers, while {\tt atof()}  does the 
same thing for floats. Thus, the final {\tt -g .8} sets the default
{\tt gap0} size to .8.\footnote{ The reason we need two gap variable is
this. The {\tt deFault()} functions resets all variables to their 
current default values. Most of these are numbers. But some can be
managed from the command line.}

The light direction vector also comes twice, {\tt lux[], luxx[]}, but
for different reasons. The default direction is (1,2,3), but it 
can be changed on the command line with the {\tt -L} option. We have capitalized
the flag to remind you that is a vector, not a number.  In order for
the bright spot (signifying the light source) to move across a rotating
object correctly, our lighting method, {\it illiLight} rotates the 
light direction appropriately with {\tt luxx[]}.

All parameters should be assigned their default values in the 
{\tt deFault()} function.\footnote{ The 
capital F distinguishes this function from one with a similar name
in some Iris header files.} It is also possible to assign constant
parameters at the time of their definition. This was done for the
the light direction vector, {\tt lux[]}.  Note that we make sure that
{\tt lux[]} is really a unit vector. In {\tt deFault()} we also
reset the two navigation matrices, {\tt aff[], starmat[]}, to the
identity.\footnote{Note the clever way someone in the past
discovered how to get a 1 exactly for {\tt ii}=\{0,5,10,15\}. Integer
division yields the quotient, the mod function yields the remainder.} 
The clockwork {\tt autotymer()} is also reset by {\tt deFault()}.
As you hack an \rtica you should resist the temptation of neglecting
to update {\tt deFault()}.


The {\tt keyboard()} function converts the user's wishes into the 
current state \marginpar{\bf keyboard()} of the \rtica by means of
{\it illiGadgets}.\footnote{We call these objects ``gadgets" to distinguish
them from ``widgets", which serve the same purpose. Unlike widgeteers, we
discourage pull-down menus, scroll-bars, simulated dashboards and the like,
all of which distract you from using your eyes to look at the \rtica, 
and your hands from controlling its performance. 
Imagine puppeteers or airline pilots applying their hands and eyes to 
pull-down menus.}  
The code here is heavily aliased with macros to make it easier for you
to add and subtract gadgets. Since the precompiler handles these, their
effective scope is global, but you can wait to define them to just
before their first use.

The arguments of {\tt keyboard()} are the key name and location of the mouse
(which we don't use yet). The first thing we do is raise a flag in the
key-vector {\tt clefs[]} corresponding to the pressed key.\footnote{We
also guard against overrunning the array by making sure that key-numbers
higher than 127 are registered in {\tt clef[0]}.} This way functions other
than the current one can know which keys were pressed. We can even 
register that several keys were pressed. It is the duty of the {\tt clefs[]}  
readers, such as {\tt getbutton()} to unset the flags.   

Five classes of illiGadgets are defined here by macros, though we 
use only the first three here. If you press the key described by the 
string {\tt K}, then {\tt PRESS(K,A,b)} will execute code fragment
{\tt A} if the key is capitalized, and otherwise {\tt b}. The 
{\tt TOGGLE, CYCLE} macros do as they are named. There is an integer
and a float slider wannabe, which you can use advisedly. Be sure to
experiment on a running illiSkel before reading further. Note, in 
particular, that repeater keys also repeat the action. This can cause
trouble on particularly fast computers and other measures have to
be introduced into the macros to unpredictable values. 

This particular {\tt keyboard()} has Stuart Levy's advanced gadgetry
partially installed. With it, you do not need to hunt for a particular
value, say of the {\tt speed, torq} parameters\footnote{These influence the
power behind your mouse. Slow computers need higher values
of {\tt speed, torq} and vice-versa.} by pressing keys. You type a 
decimal number, such as 0.0, or .9, before pressing the (Q)-key, and
that is the value of the parameter. To preserve the ability of
changing a value quickly by a keypress, the {\tt bump()} function
multiplies the current value by $(1 + \epsilon)$. Dividing by that
sum is close to multiplying by $1-\epsilon)$. 

\exercise{The ways of wizards are not lightly to be tampered with.
You could bump the {\tt nose, focal, mysiz, wfar, gap, amb, and
pwr} gadgets. But the multiplicative nature of bump suggests that
it is inappropriate for some of these. Which? To demonstrate your
understanding of SLevy's gadgets, write an additive bump, which
is useful in integral gadgets, like cyclers.}  

The function of the keys is discussed later, at the place where their 
parameters and flags are implemented.  But the last two gadgets merit 
some discussion. The {\tt ZKEY}  here simply calls the 
{\tt deFault()}  function. There is room here for a second set of defaults
on the shifted-{\tt ZKEY}. However, it is easily converted to a cycler that
permits an even larger choice alternative initial conditions.\footnote{We 
encourage this and similar programming devices to reduce the waste of 
time in recompiling or the waste of space in duplicating nearly identical
versions of the same program.} 

A discussion of two more input functions belongs here but are
deferred. The {\tt specialkeybo()} is needed because the GLUT 
library recognizes that the keycode returned by the non-ascii keys 
are system dependent. The second is the function that interprets
mouse gestures. Since we use the mouse exclusively for navigation
its discussion is also deferred.
 

The {\tt messages()} function manages the (optional) heads-up display
\marginpar{\bf messages()}
of data on the graphics screen. Such {\it graffiti} grabs your attention
and invites immediate experimentation independent of other 
documentation.\footnote{ We retain the name, ``messages'', for back
compatibility. The recommended new name, ``graffiti", is more descriptive
and less likely to be confused with other program function. In the 
older illiShell's heads-up writing was done differently on the console
and the CAVE.}
The indispensible companion feature to keyboard and mouse input is a verbal 
echo on the screen.  While most keypresses also have a visible echo in the 
effect on the animation they produce, these tend to be qualitative. 
At screen location {\tt (x,y)} the macro {\tt LABEL(x,y,W,u)} write 
text {\tt W}, formatted as in the printf family of C-functions, and uses
one variable {\tt u}. The {\tt char2wall()} factor uses a handy character
generator which will prove useful for placing text into a 3D scene as well.
We use a 2-dimensional coordinate system for the graphics window, calibrated
from lower-left at (0,0) to upper right at (3000,3000). Thus the bullseye
is reliably in the dead center of whatever window we choose to look through.

There is a mnemonic embedded in the graffiti in that keys that can be
pressed are enclosed in parentheses. The square-bracket indicates SLevy
gadgets. If you want to add graffiti, note that the current spacing 
for letters is 70 units vertically.    

The {\tt autotymer()} is a poor-man's clockwork animator. It is designed
\marginpar{\bf autotymer()} to make it easy to simulate keypresses which
manage parameters. When you toggle the (H)-key, the torus shrinks nearly 
into a rectangle, and then expands again to almost close up. Here is how
the {\tt autotymer()} does it. The first time it is called, a static
flag called {\tt first} is set. It is also set when the autotymer is 
re-called as part of the (Z)ap gadget. It is, once again set at the 
end of the animation so it can start over.  

Each instance of the {\tt TYME} macro has an internal counter which we 
can give a mnemonic name to, or you can just call each one {\tt foo}, 
if you like. The first time through, each counter is set to its maximum 
value, given by the second argument of {\tt TYME}. Once all clocks are
wound up, {\tt first=0}, and the animation begins. 
The first 150 times the {\tt autotymer()}
is called is decrements the {\tt shrink} counter, and executes the 
code written into the third argument of {\tt TYME}. Namely, the minimum
angles {\tt th0, ta0} are incrmented by one degree, and the maximum values
are decremented. When this clock is exhausted ( {\tt shrink==0}, the
second clock is addressed. It does nothing for 20 cycles, and then 
the third clock grows the rectangle back into the torus. 
You can insert and delete as many {\tt TYME}s as you please, but
 the last one must be the {\tt finish} clock, which resets {\tt first}. 

You should experimentally design an different animation before checking
out just how the {\tt TYME} macro does its job. It is a block with a
static integer {\tt cnt} which the {\tt first} time is set to its {\tt max}
value. Thereafter, it is decremented.
If {\tt cnt==0}, it skips its act and passes the ball to the next clock. 
Otherwise,it decrements {\tt cnt}, does its {\tt act}, and jumps to 
the {\tt :Break} label.   Yes, Virginia, contrary to what your high-school 
computer science teachers told you, C does have a {\em goto} command, 
which on rare occasions such as here, is quite useful.    


\section{Scenery generating functions.}

The illiSkel has a two objects equipped with their own place matrices.
They are the stars and the torus. The stars do not move across the screen 
in {\tt TURNMODE}, but rotate with the object in {\tt FLYMODE}.  
Being fixed to the virtual firmament, they do not translate. The torus,
on the other hand, can be made to do all of these motions.   
Let us examine each of these objects before we look at their interaction.

The function {\tt drawstars()} is self-initializing. The first time it
is called it loads up {\tt MANYSTARS} into the {\tt star[]} array.
First, it puts them into a unit cube, then it projects them to the unit
sphere.\footnote{Lucky that the random generator is likely to miss
the dead center of the cube, eh?} Then, and thereafter, it multiplies
a duplicate of the current matrix on the the \verb!GL_MODELVIEW! stack 
by its proper matrix {\tt starmat[]}. It chooses a bluish-white color,
and plots the stars by handing the OpenGL graphics library the 
3-vector of floats marking the star's position on the unit sphere.  
You might prefer the wire-fram teapot to the stars. Try it!

Take a peek at {\tt drawcons()} where {\tt drawstars()} is called
before the function {\tt drawall()} which draws the rest. We do not
want the stars to appear in front of stuff beyond the unit sphere. So
{\tt drawstars()} clears \verb/GL_DEPTH_BUFFER_BIT/, effectively 
putting them at ``infinity".  

The {\tt drawtor()} comes in two pieces. One vertex is created and 
\marginpar{\bf drawtor}
lighted in {\tt drawvert()}, given the $\theta, \tau$ angular 
coordinates of the torus. This function is usually factored again into
functions that calculate the position of the vertex, the color of the
vertex, and the color modified by the angle between the light source
and the normal of the surface. For compactness, all three are 
shoehorned into one funciton, making it easy to survey in one screen, 
but a chore to puzzle out the details.  

Recall that a torus is a circle of circles. Indeed, so is a sphere, except
that it is more properly a circle's worth (the equator) of semicircles 
(the meridians.) To make a torus, you merely push each meridian great
circle a distance away from the polar axis. That's done in the very end
of {\tt drawvert()}. So, using polar coordinates, {\tt nn[]} is both a 
position on the sphere and a normal to it there. The Lambert 
cosine {\tt lmb} is a fraction that measures how close the point is to
noon.\footnote{The sun is directly overhead where your normal points to it.} 
The {\it Lambert} or {it diffuse-lighting} model applies only this 
fraction to each componenet color. It is appropriate to
an ideal surface which scatters light energy received equally in all 
directions. A {\it blackbody} absorbs all light, and a {\it mirror} 
reflects light in a purely specular way. 

Since objects tend to look surreal without some backlighting, we
re-value the back-facing {\tt lmb} to 20 percent. Even for front facing
patches, there is always some ambient light, and we take this into account by
not letting {\tt lmb} drop below the {\tt amb} parameter. You can 
interactively play with {\tt amb} and the pseudo-specular {\tt pwr}.  

The specular point of a light-source on a surface is where the normal
bisects the light and the viewing directions. We save ourselves extra 
computation by using the caustic point, which depends only on {\tt lmb}.  
Furthermore, Phong lighting uses a power of the specular cosine. We 
use only the tangent of that power function at 1, since that's all that
really matters. You should draw the graph of {\tt spec} as a function
of {\tt lmb, pwr} to see what I mean. After deciding on the color of
the vertex with Chris Hartman's illiPaint, we take the larger of 
the diffuse and the specular components.\footnote{Standard lighting
models, such as the one proper to OpenGL, uses a polynomial of 
fractions rather than the maximal envelope of ambient, diffuse and 
specular components. This difference makes illiLight simpler to 
understand, easier to handle, and more robust, but all at the expense
of sublety and versatility.}

The illiPaint method is a poor-man's texture map. Each vertex is
given a color whose RGB components are linear function of two 
variables {\tt dog, cat}. These, in turn, are fractions of the way
across the source patch $[\tau_0,\tau_1] \times [\theta_0,\theta_1]$.
Thus, the red component varies linearly with {\tt dog}, and the 
blue component varies contra-linearly with {\tt cat}. Can you explain
what the green component does?

\exercise{Knowing this little about {\tt drawvert()} you should be able
to create remarkable surfaces and painting effects. How about a toroidal
surface both of whose radii vary with the parameter angles. For now
only the {\tt autotymer()} can change the source patch. Make this interactive
with new gadgets. Make the surface fine and coarse meshed on demand.} 

All the {\tt drawtor()} function has left to do is create the mesh of
triangles which constitutes the numerical torus. Depending on how fine
we want this mesh (good colors) and how nimbly we want it to move (few
vertices) we will choose the number of {\tt MERIDIANS, LATITUDES}. 
The torus is actually drawn as a series of parallel strips. And that's 
why we can have such a cheap {\tt gap} making gadget.

\exercise{Install a second object in the same world as the torus.
For instance, a cube or a hypercube in {\tt drawcube()}.}

The collection of all objects in the world (not the stars, though) 
are packed into {\tt drawall()}. Once you have several objects you
can practice your {\tt IFCLICK} skills to place, size, and color
them properly.

The final function is the display callback of the GLUT-libary, here
called {\tt drawcons()}. 
\marginpar{\bf drawcons()}
This is where we integrate our own functions with those of OpneGL and
GLUT. Line by line, this is what happens each time through the 
glut-mainloop. The color buffer bit and the depth buffer bit are cleared.
By default, the color is black. But you can put a nicer background in
here with {\tt glClearColor(0.1,0.2,0.3,0)}.  We set one or two 
viewports, depending on whether the binocular flag is up or not. The 
viewport is usually coextensive with the drawing window. Here is an
illustration why there is a difference: the same window has two viewports.

First we call for a perspective\footnote{ 
Photographers and computer graphics systems that are less versatile 
than OpenGL favor on-axis or centered perspective with 
parameters based on the aperture angle, aspect ration, near and 
far. It is simple to implement this in the Frustum command.} 
projection with {\tt glFrustum(xmin,~xmax,~ymin,~ymax,~near,~far)}. 
In the raw, the six arguments of this funtion describe 
the frustum of a cone. The cone is 
produced by looking from the origin through a rectangular 
window\footnote{Indeed, this command is more aptly named ``window" in
IrisGL. It is unfortunate that this aptly named function had to be 
renamed in the OpenGL vocabulary. The term ``window" 
had become too strongly tied to a resizeable viewport. So, avoid
misunderstanding, OpenGL adopted the hardly euphonic word ``fructrum", 
meaning a section of any solid between two parallel planes, often
mispelled as ``frutrum".} 
located a distance {\tt near} down the {\it negative} z-axis, and
clipped in \mbox{\tt -far < z < -near < 0}. This eternally confusing 
convention guaranteess a right-handed coordinate system with the 
x-axis pointing to the right, and the y-axis pointing upward. You
may notice how we have rewired the conical viewing box to be 
controlled by more geometrical parameters. First we make sure that
the aspect ratio remains constant so that when you re-mouse the 
window, the object doesn't become oblongated. Second, we have a
fraction {\tt mysiz}, which couples the focal distance 
{\tt near=mysize*focal} with the size of the rectangular canvas
the view is painted on at {\tt near}. The name derives from the 
task of making yourself so small that you can fly into an object 
without having it clipped by a large value of {\tt near}.  
Try it! Play with the f(O)cal and the my s(I)ze gadgets. 

We next modify affine (or \verb:GL_MODEL_VIEW: )  matrix, 
which will be multiplied into the projection matrix eventually. 
Starting with the identity we draw the stars. (Recall, the stars
manage their own place with the {\tt starmat[]}.) We then
shift a little off center to account for the left-eye right-eye
displacement, equal to twice the {\tt nose} to eye distance. 
Now multiply by {\tt aff[]}, the matrix that places the world
relative to the origin in the way it would look if you moved
about a stable world.\footnote{The Copernican versus  the Ptolemaic   
weltanschauung. OpenGL favors the latter.}   

We next draw the entire scene into the other eye, widen the viewport
fully for the graffiti, and swap graphics buffers. This last 
call to GLUT draws all that is currently in the frame buffer to the
screen, repeatedly, until a new frame complete and ready to replace
the old one. 


\section{Navigation in Euclidean space.}

Since we are construcing a graphics program, the management of the 
geometry pipeline for each frame is truly the main activity. The 
principle of OpenGL is very simple but its ramifications are extensive
and can be mysterious and confusing without a clear mathematical idea
to guide us. A geometrical figure is constructed out of points, 
line segments and planar patches. Even is the lines and patches appear
curved (and they are intended to so appear), they are nevertheless 
made up of subliminally small straight lines and flat patches. A 
polylateral\footnote{There is some difference between common math speak,
and common computer graphics lingo. In graphics, a ``polygon" means
a patch enclosed by a polylateral. In geometry, a ``polylateral" is
synonymous with a polygon.  We will deviate from common speech only
to avoid misunderstanding.}
curve is completely described the succession of vertices along it. 
Moreover, these vertices can be placed anywhere in space, so the 
polytaerals aren't planar, or convex, and we won't call them polygons.

The first problem to be solved in drawing surfaces is how to reduce their
description to vertex streams.  A surface made up of planar, polylateral
patches is a {\it polyhedral surface}. Only a triangle (or ``trilateral") 
is unambiguously planar. Consider four non-coplanar vertices in space
and tetrahedron so formed. A particular succesion of the vertices 
separates the skin of the tetrahedron into two {\it dihedrals} corresponding
to the two ways of triangulating a quadrilateral. Thus the triangle is
the geometrical primitive, and all surfaces in computer graphics are
triangulated. 

There are two useful ways a succession of vertices \forml{V_0,V_1,...,V_n} 
describes a succession of triangles. The \verb!GL_TRIANGLE_STRIP!  
produces a ribbon with with two rails, one traced out by the 
even vertices, \forml{V_0,V_2,V_4,... }, and the other by the odd 
vertices, \forml{V_1,V_3,V_5, ...}. The polylateral following the 
original vertex stream zig-zags back and forth between the rails, 
like the rungs of a bridge tressle. Of course, vertices may be 
repeated in the list. For example, if $V_4=V_0, V_5=V_1$  then
the triangle strip covers a tetrahedron.

\exercise{An intriguing geometrical question is which polyhedral 
surfaces can be drawn by a single triangle strips, without covering
a facet twice. Maybe you can so ``bandage" every polyhedral surface. 
For instance,  how would you ``bandage" a cube, an 
octahedron, dodecahedron, and icosahedron? What about the graph 
$z=f(x,y)$ over a rectangular grid in the $xy$-plane? 
Hint: There is a ``Columbus Egg" solution to this problem.}

So, being vertex based, the geometry pipeline\footnote{Strictly speaking,
a pipeline refers to a process which accepts new input before having
finished its job on the previous input. Think of Ford's assembly line.
But whether the pipeline is real or virtual, the conceptual structure
is the same in OpenGL.} feeds on a stream of vertices, bracketed by 
the appropriate {\tt glBegin()} and {\tt glEnd()}, performing a series
of geometric transformations on each vertex, and producing the 
desired graphic on the screen. Regardless how these transformations 
are implemented (hardware, high or low level library functions, etc) 
they are represented by a 4x4 matrix of real numbers. The composition
of operations is represented by matrix multiplication. 

Each vertex stream, $X$, encounters three matrices at the top of their
respective pushdown stacks: the current modelling (a.k.a. affine) matrix
$A$, followed by the current projection matrix $\Pi$, followed by the
viewport matrix, $\Psi$, about which we say very little. Thus, column 
mode\footnote{After ten years of writing vectors as rows on the left
of their matrix transformations in IrigGL, OpenGL reverted to the
scientific notation which writes vectors as columns on the right of
their matrix multipliers. This way, linear transformations compose
like functions, from right-to left. You'll have to learn how to 
handle this source of confusion and errors effectively. Algebra is
the right language for this.} we see the effect of $\Psi \Pi A X $. 

A useful way to relate the viewport to the window is to imagine
\marginpar{There is some expository redundancy here. Maybe saying
it again isn't so bad for now.}
looking at the scene with the camera at the origin, and looking
through a rectangular window with corners as specified, and a
distance {\tt near}  from the camera, all in world coordinates. However,
the image in the window is magnified or shrunk to fit into the
viewport. Only the portion of the world located in the frustum
of a rectangular cone between {\tt near}  and {\tt far}  is  visible. Thus 
the {\tt near}  parameter serves two purposes: it establishes the 
perspective proportion and the near clipping plane. 
We decouple these functions by extracting a common factor, called
{\tt mysiz}. Note that changing {\tt mysiz} with the {\tt IKEY}
  slides the window 
back and forth in the rectangular viewing cone. Thus the scene does
not change size, shape or location in the viewport. The front clipping
plane can thus be moved back and forth at will. To change the angle of
the viewing cone, it is necessary to change the effective focal distance
with the {\tt OKEY}. The two keys are so calibrated that pressing both 
at the same time, with or without the {\tt SHIFT-KEY,} has the desirable effect
of keeping the near clipping plane in the same place.  

The stars are drawn next. Being infinitely far away, they are seen the 
same way by both eyes. But, to see the finite scene in binocular vision,
the object needs to be shifted right or left half the distance between
the eyes, as given by nose parameter on the {\tt NKEY}. Since the left viewport
is to be seen by the right eye in the crossed-eye\footnote{Some people
call it the ``cross-eyed'' mode, since it is (erroneously) thought to
induce this malady.} viewing mode, we shift
the first image to the left, $E^R$. Thus $\Pi E^RAX$ is the order of matrix
multiplication on a vertex $X$ for the right eye. 
In the monocular viewing mode, $E^R=I$, is the identity and 
we are wasting a matrix multiplication, but skip the left eye projection
to the right viewport, $\Pi E^LAX$. It is useful to associate the 
matrix products $\Pi^R=\Pi E^R$ and $\Pi^L=\Pi E^L$. The multiple 
viewport may be used to other purposes than for binocular pairs. 
For example, the front
and rear view of the same object. Or, using many more viewports, a succession
of small multiples in a homotopy. 

\exercise{ Small Multiples.
Modify {\tt drawcons()}  to show the front and rear view of the same object.
Use four viewports, placing orthographic plan and elevation in three
of them, with a perspective in the fourth. Use four viewports to show
the four orthographics projections of a 4D object into 3D. Devise a 
system of many viewports that display a homotopy some time steps apart
in a system of temporal small multiples in the sense of Tufte.\footnote{
Edward Tufte, {\em The Visual Display of Quantitative Information,} Graphics 
Press, 1983.} }

The principal navigation is effected in {\tt chaptrack()}, whose arguments
\marginpar{\bf chaptrack(), mousepushed()} 
are the input from the mouse (or the wand in the CAVE) as reported by the 
callback function {\tt mousepushed()}.
\footnote{For illustrative purposes, this callback
includs some arcane code which translates which of the three buttons 
were pressed into a 3-bit flag {\tt PAW}, a 1-bit flag, {\tt SHIF} 
for the shift-button on the keyboard, and two integral coordinates of
the mouse, {\tt XX, YY}. It is not essential that {\tt mousepushed()}
be written this way, but you will find such constructions elsewhere and
you may want to use them yourself for special purposes. In particular,
in many cased bit-field flags are more efficient for passing and storing
control messages than streams of entire integers.}  
The output is an update of the two affine matrices, {\tt aff[], starmat[]}. 

The displacements, {\tt dx, dy} of the mouse from the center of the 
window {\tt (xwide/2, yhigh/2)} are clamped to have a 100 square-pixel
dead zone, whihc makes the mouse less responsive. These displacements
are interpreted as a small rotation about the x-axis, which points East,
and the y-axis, which points North. The left and right mouse buttons
are used to effect a large or small rotation about the z-axis, which
points into the screen. The fraction, {\tt torq}, adjusts the 
responsiveness of the mouse. Since rotations are non-destructive,\footnote{
Most pipeline operations are cumulative, i.e. they act on what is already
there by matrix multiplication.} one starts by 
loading the identity matrix onto the stack. In the {\tt FLYMODE}, which
is easier to understand, the incremental rotation, $U$, on the stack 
is relative to the camera, which assumed to be at he origin of the world 
coordinate system.\footnote{The letter $R$ is unsuitable for the name of 
a rotation matrix. We use $U$ instead.} Since the stars are only rotated, 
we make a duplicate of $U$ on the stack with a  
{\tt glPushMatrix(), glPopMatrix()} bracket. Inside this bracket, we
update {\tt starmat[]} on the left.   It updates the star matrix
by multiplication. Thus, if the mouse is parked slightly off the bullseye,
a succession of small rotations are applied, so that after n-cycles later,
a star is placed at \forml{U_n U_{n-1}...U_2U_1X}.

Pressing the middle mouse button effects a translation in the Z-direction
by a vector increment, $dZ$. The fraction {\tt speed} adjusts the 
apparent speed of forward motion. The shifted middle mouse flies 
backwards. We may regard
the composition $dA = dU\,dZ$ as an incremental change of the affine matrix
in the Euclidean group. After $n$ cycles, the affine matrix,
\forml{ A = I\,dA_n\,dA_{n-1}\,...\,dA_2\,dA_1\,}, is just the integral of 
all the little differential affine motions {\tt chaptrack()} has 
implemented.

It should be noted here, that just like a Euclidean translation matrix, 
$T(m)$ depends on a single vector $m$ of motion, a Euclidean rotation 
matrix, $U(a)$ depends on a vector $a$ whose direction $\hat a$ and 
magnitude $\alpha$ is the axis and angle of rotation. 
We shall consider the arithmetic of the group of rotations later, and
suppress the rotation vector in the notation.
For now it is useful to know that the affine matrix of a 
Euclidean motion may be factored, $A = T(m)U$, with composition, 
commutation and inversion rules given by:
\[T(m_1)U_1 T(m_2)U_2 = T(m_1 + U_1 m_2)U_1U_2 \]
\[T(m)U = UT(U^Tm)\] 
\[  (T(m)U)^{-1}= T(-U^Tm)U^T. \]

The superscript $T$ emphasizes the fact that the inverse of a 
rotation matrix is just its transpose.\footnote{Care must be taken to
distinguish between Euclidean transformations in 3-space, and their
representation as 4-dimensional matrices as they apply to the 
so-called homogeneous coordinates of points in 3-space. }

However, in the {\tt TURNMODE}  
the object is to be rotated about its own center.
In that case, we use the translation vector,$m$, of $A=T(m)\,U$
to translate a point $X$ back to the origin, apply $dA$, 
and translate back.
In the column vector mode, the affine matrix $A = T(m)U$ is 
\[
{\tt aff[]}= 
                     \left[ \begin{array}{cccc}
                     A[0] & A[4] & A[8] & A[12] \\ 
                     A[1] & A[5] & A[9] & A[13] \\ 
                     A[2] & A[6] & A[10] & A[14] \\ 
                     A[3] & A[7] & A[11] & A[15] 
                     \end{array} \right].
           =         \left[ \begin{array}{cccc}
                     U_{00}& U_{10}& U_{20}& m_{0} \\
                     U_{01}& U_{11}& U_{21}& m_{1} \\
                     U_{02}& U_{12}& U_{22}& m_{2} \\
                       0   &  0    &   0   &  1 
                     \end{array} \right].
.\]

Thus once through {\tt chaptrack()} in {\tt TURNMODE}  with $dA = dT dU$, 
has the effect of replacing $A$ by 
\[A_1 = T\; dA\; T^{-1}\; A 
      = T\; dT\; dU\; T^{-1}\; T\; U = dT\; T\; dU\; U. \]
Consequently, after $n$ iterations, the net change
is, 
\[A_n = dT_n\; dT_{n-1} ... dT_1\; T\; dU_n\;dU_{n-1}\,...\,dU_1\; U. \]
and the {\em illiRotor} has smoothly accumulated the translation and rotation
intended by the mouse displacements. 

The last thing {\tt chaptrack()} does is to rotate the light source
direction by the inverse of the rotation component of {\tt aff[]}. The
the inverse of an affine matrix is 
\[ (T(m) U(a))^{-1} = U(a)^{-1}T(m)^{-1} = U(a)^T T(-m) \]. Since we 
don't translate the stars, we need only the matrix multiplication by
the transpose of to top-left 3x3 minor of {\tt aff[]}. 

\exercise{ Six-way Navigator. \\
Build a navigator which has all six translations. For example, 
let a click of the middle mouse button represent a switch into
translation mode, with the mouse deviation from the center 
representing translation. Note that this way it is not possible
to fly because the mouse manages two modes consecutively instead
of simultaneously. To recover the simultaneity, use buttons to
manage translations.} 

All that remains is to assemble all of these components into
{\tt main()}.  
In the {\it overture} of {\tt main()} 
we set up the state of the \rtica. These 
routines are done only once, and the order in which they occur
does matter somewhat. We read the {\tt arguments()} from the 
command line after the {\tt deFault()} in case the user wishes
some changes. Since {\tt deFault()} is called by the {\tt (Z)}ap-key,
and at present, {\tt arguments()} does not change the default
values, zapping reverts to the hard coded defaults. Note that
a useful modification would be for (Z)ap to become a cycler
which moves through various default sets, including the one
from the command line (exercise!)

Since the star-object was factored into {\tt initstars()} and
{\tt drawstars()}, the former is called here, the latter in 
the eternal loop. Recall that the other object, {\tt drawcube()},
initializes `itself' the first time it is called. 

The switch on the window flag defaults to a voluntary window for
{\tt win=0}, to a borderless window in the correct position for shipping
to an NTSC\footnote{To fit into a standard NTSC video screen we use 
 640$\times$480 pixels} projector for {\tt win=1}, 
and a full screen for{\tt  win=2}. 
Since we now use the GLUT library, the remainder of {\tt main()}
has already been described a the beginning of this chapter.


\exercise{ illiOctahedron\\
Put the octahedron from {\bf oc1.c}l into {\bf skel.c} to obtain
{\bf illiOctahedron}.  }
%\end{comment}
\newpage
\input{sourcecode.tex}
\end{document}
