%%% -*-texinfo-*-
%%% \magnification=\magstep1
%%%
%%% NOTE:  this texinfo file uses a modified version of texinfmt.el.
%%%   Before processing this file using texinfo-format-buffer you
%%%   should load this modified texinfmt.el, which should be in the
%%%   same directory as this file.
%%%
%%% ANOTHER NOTE: the e-lisp file "texstuff.el", also in this directory,
%%%   contains some Emacs functions which are useful in editing this file.
%%%   In particular, it contains functions for "texifying" example code
%%%   and for inserting #included example files, e.g. "example1.c".
%%%
\def\figure#1{\vskip 2.0truein
	      \special{psfile=#1 hscale=30.0 vscale=30.0
	      voffset=-50 hoffset=90}}
\tolerance=2000
\def\myfindex#1{\findex{\code{#1}}}
\def\panel#1{\emph{#1}}
\def\widget#1{\emph{#1}}
\def\object#1{\emph{#1}}
\def\caption#1{\centerline{{\bf{#1}}}}
\input psfig
\input texinfo
@setfilename geomview
@settitle Geomview Manual
@c
@titlepage
@sp 1
@center @titlefont{Geomview Manual}
@sp 4
@center Geomview Version 1.6.1
@sp 1
@center for Unix Workstations
@sp 1
@center December 10, 1996
@sp 2
@center Mark Phillips et al.
@sp 4
@vskip 0pt plus 1filll
@center Copyright @copyright{} 1993, The Geometry Center

@end titlepage
@page

@node Top,What,,(DIR)

@menu
* What::		What is Geomview?.
* Authors::		The Authors of Geomview.
* Register::		Let Us Hear From You.
* Overview::		Overview of Geomview.
* Tutorial::		Introductory Tutorial.
* Interaction::		Interacting with Geomview.
* OOGL File Formats::	Formats for Geometry Input.
* Customization::	Modifying the behavior of Geomview.
* Modules::		Programs that use Geomview for graphics display.
* GCL::			gcl: the Geomview Command Language.
* Mathematica::		Mathematica Graphics in Geomview or RenderMan.
* Installation::	Installing Geomview on your computer.

* Function Index::	A node for each gcl function.
@end menu

@node What,Authors,Top,Top
@unnumbered What Is Geomview?

Geomview is an interactive program for viewing and manipulating geometric
objects, written by staff members of the Geometry Center.  It can be
used as a standalone viewer for static objects or as a display engine
for other programs which produce dynamically changing geometry.  It runs
on Silicon Graphics (SGI) IRIS workstatons and NeXT workstations,
and on a variety of systems using generic X graphics and Motif interface.
This manual describes SGI Geomview version 1.6.1. @refill

Geomview and this manual are available for free via anonymous ftp on the
Internet from host @file{geom.umn.edu} (IP address 128.101.25.35).
Permission is granted to make copies of this manual.

If you have questions or comments about Geomview or this manual, you can
email them to @file{software@@geom.umn.edu}.  We are always glad to hear
from users.  There is also a @file{geomview-users} mailing list for
announcements regarding Geomview and for Geomview users to communicate
with each other.  If you use Geomview please send an email note to
@file{geomview-users-request@@geom.umn.edu} requesting to be added to
this mailing list.@refill

@node Authors,Register,What,What
@unnumberedsec Authors

Tamara Munzner, Stuart Levy, and Mark Phillips are the original authors
of Geomview. Celeste Fowler, Charlie Gunn, and Nathaniel Thurston also
made significant contributions.  Daniel Krech and Scott Wisdom did the
NeXTStep and RenderMan port, and Daeron Meyer and Tim Rowley did the
port to X windows.

Mark Phillips wrote this manual, with substantial help from Stuart Levy
and Tamara Munzner.  Countless Geomview users have also been of great
help by reading it and pointing out mistakes.

@node Register,Overview,Authors,Top
@unnumbered Let Us Hear From You
We are very interested in hearing about how you are using Geomview.
Think of Geometry Center software as a new kind of shareware: you share
your science and successes with us, and we share our software and
support with you.  The Geometry Center is funded by the National Science
Foundation, and it is important that we be able to report to NSF the
ways in which our software is being used.

If you use Geomview, please send us a letter telling us what you are
doing with it. We need to know:

@enumerate
@item
What you are working on - an abstract of your work would be fine.

@item
How Geomview has helped you, for example, by increasing your
productivity or allowing you to do things you could not do before.  In
particular, if you feel that Geomview has had a direct bearing on your
work, please tell us about this.
@end enumerate

Please send the letter either via email to @code{register@@geom.umn.edu},
or via regular mail to the address below.

Moreover, if you use Geomview or other Geometry Center software in your
work, we encourage you to cite its use in your publications.

Thank you!



@example
Software Development Group
Geometry Center
1300 South 2nd St, Suite 500
Minneapolis, MN  55454
USA
@end example

@comment
@comment @node node-name, next, previous, up
@comment

@comment ****************************************************************
@node Overview,Tutorial,Register,Top
@chapter Overview

Geomview's main purpose is to display objects whose geometry is given,
allowing interactive control over details such as point of view, speed
of movement, appearance of surfaces and lines, and so on.  Geomview can
handle any number of objects and allows both separate and collective
control over them.  

The simplest way to use Geomview is as a standalone viewer to see
and manipulate objects.  It can display objects described in a variety
of file formats.  It comes with a wide variety of example objects, and
you can create your own objects.

You can also use Geomview to handle the display of data coming from
another program that is running simultaneously.  As the other program
changes the data, the Geomview image reflects the changes.  Programs
that generate objects and use Geomview to display them are called
@emph{external modules}.  External modules can control almost all
aspects of Geomview.  The idea here is that many aspects of the display
and interaction parts of geometry software are independent of the
geometric content and can be collected together in a single piece of
software that can be used in a wide variety of situations.  The author
of the external module can then concentrate on implementing the desired
algorithms and leave the display aspects to Geomview.  Geomview comes
with a collection of sample external modules, and this manual describes
how to write your own.

Geomview represents the current state of an ongoing effort at the
Geometry Center to provide interactive geometry software that is
particularly appropriate for mathematics research and education.  In
particular, Geomview can display things in hyperbolic and spherical
space as well as Euclidean space.

Geomview allows multiple independently controllable objects and
cameras.  It provides interactive control for motion, appearances
(including lighting, shading, and materials), picking on an object,
edge or vertex level, snapshots in SGI image file or Renderman RIB
format, and adding or deleting objects is provided through direct
mouse manipulation, control panels, and keyboard shortcuts.

Geomview supports the following simple data types: polyhedra with
shared vertices (.off), quadrilaterals, rectangular meshes, vectors,
and Bezier surface patches of arbitrary degree including rational
patches. Object hierarchies can be constructed with lists of objects
and instances of object(s) transformed by one or many 4x4 matrices.
Arbitrary portions of changing hierarchies may be transmitted by
creating named references.

Geomview can display 3-D graphics output from Mathematica and Maple.

@comment ****************************************************************
@node Tutorial,Interaction,Overview,Top
@chapter Tutorial

This chapter leads you through some of the basics of using Geomview.
Work through this chapter in front of a workstation where you can try
out the examples given here to get a feel for what you can do with
Geomview.

To start Geomview, login to the computer and get a shell window.  A
shell window is a window in which you can type unix commands; the prompt
in the window usually ends with a '%'.  In the shell window (the mouse
cursor must be in the window) type the following (@kbd{@key{RET}} here
means hit the "Enter" key):

@example
geomview tetra dodec @key{RET}
@end example

This command starts up Geomview and loads two example objects, a
tetrahedron and a dodecahedron.  After a few seconds three windows
should appear as shown in Figure 1.
@ifinfo
(The figures in this document appear only in the hardcopy version,
not the Info version.)
@end ifinfo
@html
<CENTER><IMG SRC="pix/initial.gif"><P>Initial Geomview display</CENTER>
@end html
@tex
\midinsert\vbox{
\centerline{\psfig{file=figs/initial.ps}}
\caption{Figure 1: Initial Geomview display}
}\endinsert
@end tex

The panel on the left is Geomview's main control panel; it's called
the @panel{Main} panel.  The skinny panel in the middle is the
@panel{Tools} panel and is for selecting different kinds of motions.
The window on the right is the camera window and in it you see a
large tetrahedron and a dodecahedron which is partially obscured
by the tetrahedron.

Geomview has lots of panels but by default it displays only these three.
We'll describe some aspects of these and a couple of the others in this
tutorial.  You can read more about these and other panels in the later
chapters of this manual.

Put the mouse cursor in the camera window and press down and hold the
left mouse button.  Now, while holding down the button, slowly move the
mouse around.  You should see the picture rotate in the direction you
move the mouse.    If you lift up on the mouse button while moving the
mouse, the picture continues rotating.  To stop it, hold the mouse very
still and click down and up on the left mouse button.

Geomview uses the @emph{glass sphere} model for mouse-based motion.  This
means you are supposed to think of the object as being inside an
invisible sphere and the mouse cursor is a gripper outside the sphere.
When you hold down the left mouse button, the gripper grabs the
sphere; when you let go of the button, the gripper releases the
sphere.  Moving the mouse while holding the button down causes the
sphere (and hence the object) to move in the same direction as the
mouse.

In addition to the two solids you should also see two wireframe
boxes in the camera window.  These are the "bounding boxes" of the two
objects.  By default Geomview puts a bounding box around each object
that it displays so that you have an idea of how large it is.

Notice that as you move the mouse around the tetrahedron and
dodecahedron move as a unit.  That is because by default what you are
actually moving is the "World".  To move an individual object instead of
the whole world, move the mouse cursor to the @widget{Targets} browser in
the @panel{Main} panel.  Click (any button) on the word @widget{tetra}.
This makes the tetrahedron be the "target object".  Now move the cursor
back to the camera window and you can rotate just the tetrahedron.

The motion that you have been applying up to now has been rotation,
because that is the motion mode that is selected in the @panel{Tools}
panel.  To translate instead, click on the @widget{Translate} button.
Now when you move the mouse in the camera window while holding down the
left button, the tetrahedron (which should still be the target object
from before) will translate in the direction you move the mouse.  Notice
that you can translate it beyond the edge of the window as long as you
keep holding the left mouse button down.  If you lift up on the mouse
button while moving the mouse, the tetrahedron will keep going.  It
moves rather rapidly so it is very easy to lose track of where it is.

If you accidentally lose the tetrahedron by translating it too far out
of the view of the window, you can get it back by clicking on the
@widget{Center} button in the @panel{Tools} panel.  This causes it to
come back to its initial position.

Click on the @widget{Center} button to bring the tetrahedron home, and
then translate it off to one side so that you can completely see the
dodecahedron.

Your world now has two objects in it that are beside each other.  You
should see the dodecahedron in the middle of the window and maybe part
of the tetrahedron off to one side.  Go back to the @widget{Targets}
browser in the @panel{Main} panel and click on "World" to select the
whole world again.  Now click on the @widget{Look At} button in the
@panel{Tools} panel.  You should see something like Figure 2 --- the
dodecahedron and the tetrahedron in the middle of the window next
to each other.  The @panel{Look At} button positions the camera in
such a way that the target object is centered in the window.
@html
<CENTER><IMG SRC="pix/world.gif"><P>Figure 2: Looking at the World</CENTER>
@end html
@tex
\midinsert\vbox{
\centerline{\psfig{file=figs/fig2.ps}}
\caption{Figure 2: Looking at the world}
}\endinsert
@end tex

Now put the cursor over the middle of the dodecahedron and double-click
the right mouse button.  This means click it down-and-up two times in
rapid succession.  Notice that the dodecahedron becomes the target
object; you can see this in the @widget{Targets} browser in the
@panel{Main} panel.  Double-clicking the right mouse button on an object
is another way to make it the target object.

Go to the @widget{Inspect} menu at the top of the @panel{Main} panel and select
@panel{Appearance}.  This brings up the @panel{Appearance}
panel.  When it appears, if it partially obscures another Geomview window
you can move it off to one side by dragging its frame with the middle
mouse button down.
@html
<CENTER><IMG SRC="pix/ap.gif"><P>Figure 3: The Appearance Panel</CENTER>
@end html
@tex
\midinsert\vbox{
\centerline{\psfig{file=figs/ap.ps}}
\caption{Figure 3: The Appearance Panel}
}\endinsert
@end tex

The @panel{Appearance} panel lets you control various things about the
way Geomview draws objects.  Note the buttons labeled @widget{[af] Faces} and
@widget{[ae] Edges}.  Click on the @widget{[ae] Edges} one, and notice
that Geomview is now drawing the edges of the dodecahedron.  Click on it
again and the edges go away.  Click several times and watch the edges
come and go.  When you've had enough of this, leave the edges on
and click the @widget{[af] Faces} button.  This toggles the faces
on and off.  Click the button again to turn them back on.

Now click on the @widget{[Cf] Faces} button under the word
@widget{COLOR}.   A color chooser panel like the one in Figure
4 should appear.
@html
<CENTER><IMG SRC="pix/color.gif"><P>Figure 4: Color Chooser Panel</CENTER>
@end html
@tex
\midinsert\vbox{
\centerline{\psfig{file=figs/color.ps}}
\caption{Figure 4: Color Chooser Panel}
}\endinsert
@end tex

@ifset forms
Put the cursor in the color hexagon in this panel and hold down the left
mouse button.  Slowly move the mouse around.  This drags the little
black point around to choose a new color for the dodecahedron.
@end ifset

@ifclear forms
Note the three sliders, @widget{H}, @widget{S}, and @widget{V},
controlling the color's hue, saturation, and value (lightness).
Clicking the @widget{HSV} button gives a different set of sliders,
one each for red, green, and blue.
Numerical values for both RGB and HSV color systems
can be seen or edited at the bottom of the panel.
@end ifclear
The dodecahedron's previous colors were specified in the file
@file{dodec} that you loaded when we started Geomview.  The color that
you specify with the color
panel overrides the old colors.  You can adjust the intensity of the
color with the @widget{Intensity} slider.  When you find a color that
you like, click the @widget{Done} button.  

Now put the cursor somewhere over the gray background and double-click
the right mouse button; this picks "World" as the target object.
Click the @widget{Look At} button to look at the world again.

Notice that in the @panel{Appearance} panel the settings of the buttons
have changed from the way you left them with the dodecahedron.  That's
because the @panel{Appearance} panel always displays the settings for
the target object, which is now the world, which still has its
default settings.

Click on the @widget{[ab] BBox} button under the word @widget{Draw}.
The bounding boxes go away.  Now put the cursor back in the camera
window.  At the keyboard, type the keys @kbd{a b}.  Notice that the
bounding boxes come back.  @kbd{a b} is the keyboard shortcut for
the bounding box toggle button; the string "[ab]" appears on the
button to indicate this.  Most of Geomview's buttons have keyboard
shortcuts that you can use instead if you want.  This is useful once
you are familiar with Geomview and don't want to have to move around
among lots of panels.

Now select the tetrahedron, either by double-clicking the right mouse
button on it, or by selecting "tetra" in the @widget{Targets} browser.
Then click on the @widget{Delete} button in the @panel{Main} panel.  The
tetrahedron should disappear.  This is how you get rid of an object.

You can also load objects from within Geomview.  Click on the @widget{File}
menu in the @panel{Main} panel and choose @widget{Open}.
The @panel{Files} panel will appear.
@html
<CENTER><IMG SRC="pix/secondlinelist.gif"><P>Figure 5: The Files Panel</CENTER>
@end html
@tex
\midinsert\vbox{
\centerline{\psfig{file=figs/secondlinelist.ps}}
\caption{Figure 5: The Files Panel}
}\endinsert
@end tex
Below the middle of this panel is a browser with three lines in it; the
second line is a directory with lots of Geomview example files
in it.  Click on that second line.  Your @panel{Files} panel should
then look something like Figure 5.  Scroll down in the list of files
until you see @file{tref.off}.  Click on that line, and then click
on the @widget{Add} button.  A large trefoil-shaped tube will appear
in your window.  Click the @widget{Done} button in the @panel{Files}
panel to dismiss the panel.

@html
<CENTER><IMG SRC="pix/trefdodecinter.gif"><P>Figure 6: Trefoil and Dodecahedron</CENTER>
@end html
@tex
\midinsert\vbox{
\centerline{\psfig{file=figs/trefdodecinter.ps}}
\caption{Figure 6: Trefoil and Dodecahedron}
}\endinsert
@end tex

Now click on the @widget{Reset} button in the @panel{Tools} panel.  This
causes everything to return to its home position.  You should see
something like Figure 6 at this point: a dodecahedron and a
trefoil knot.

Play around with the trefoil knot and the dodecahedron.  Experiment with
some of the other buttons in the @panel{Tools} panel.  Try coloring the
trefoil knot with the @panel{Appearance} panel.

For a tutorial on how to create your own objects to load into Geomview,
see file @file{doc/oogltour} distributed with Geomview
(@file{/u/gcg/ngrap/doc/oogltour} on the Geometry Center system).  The
things in that file will be incorporated into a future version of this
manual.


@comment ****************************************************************
@node Interaction,Starting Geomview,Tutorial,Top
@chapter Interaction

This chapter describes how you interact with Geomview through the
mouse and keyboard.

@menu
* Starting Geomview::      Starting Geomview.
* Command Line Options::   Command Line Options.
* Basic Interaction::      Basic Interaction: The Main Panel.
* Loading::                Loading Objects Into Geomview.
* Mouse Motions::          Using the Mouse to Manipulate Objects.
* Appearance::             Changing the Way Things Look.
* Cameras::                Cameras.
* Saving::                 Saving your work.
* Commands::               The Commands Panel.
* Keyboard Shortcuts::     Keyboard Shortcuts.
@end menu

@comment ================================================================
@node Starting Geomview,Command Line Options,Interaction,Interaction
@section Starting Geomview

The usual way to start Geomview is to type @kbd{geomview @key{RET}} in a shell
window (RET means hit the "Enter" key).  It may take Geomview a few
seconds to start up; one or more windows will appear and you can begin
interacting with Geomview immediately.

It is also possible to specify actions for Geomview to perform at
startup time by giving arguments in the shell command line.
@xref{Command Line Options}.


@comment ================================================================
@node Command Line Options,Basic Interaction,Starting Geomview,Interaction
@section Command Line Options

Here are the command line options that Geomview allows:

@table @samp
@item -b @var{r} @var{g} @var{b}
Set the window background color to the given @var{r} @var{g} @var{b}
values.

@item -c @var{file}
Interpret the gcl commands in @var{file}, which may be the special
symbol @file{-} for standard input.  For a description of gcl,
@xref{GCL}.

@item -c @var{command}
Commands may also be supplied literally, as in
@example
-c "(ui-panel main off)"
@end example
Since @var{command} includes parentheses, which have special meaning to
the shell, @var{command} must be quoted.  Multiple @var{-c} options are allowed.

@item -wins @var{nwins}
Causes Geomview to initially display @var{nwins} camera windows.

@item -wpos @var{width},@var{height}[@@@var{xmin},@var{ymin}]
Specifies the initial location and size of the first camera window.  The
values for @var{width}, @var{height}, @var{xmin}, and @var{ymin} are in
screen (pixel) coordinates.

@item -M @var{objectname}
Display (possibly dynamically changing) geometry sent from the
programs @code{geomstuff} or @code{togeomview}.  This actually listens to the
named pipe @file{/tmp/geomview/objectname}; you can achieve the same
effect with the shell commands:
@example
mkdir /tmp/geomview
mknod /tmp/geomview/objectname p
@end example
(assuming the directory and named pipe don't already exist), then
executing the gcl command:
@code{(geometry objectname  < /tmp/geomview/objectname)}

@item -Mc @var{pipename}
Like @samp{-M} above, but expects gcl commands, rather than OOGL
geometry data, on the connection.

@item -nopanels
Start up displaying no panels, only graphics windows.  Panels may be
invoked later as usual with the @kbd{Px} keyboard shortcuts or with
the @code{ui-panel} command.

@item -e @var{module}
Start an external module; @var{module} is the name associated with the
module, appearing in the main panel's Applications browser, as defined
by the @code{emodule-define} command.

@item -start @var{module} @var{args} @dots{}
Like -e but allows you to pass arguments to the external module.  "--"
signals the end of the argument list; the "--" may be omitted if it
would be the last argument on the Geomview command line.

@item -run @var{shell-command} @var{args} @dots{}
Like -start but takes the pathname of executable of the external module
instead of the module's name.  The pathnames of all known module directories
are appended to the UNIX search path when invoking @var{shell-command}.

@end table

@comment ================================================================
@node Basic Interaction,Loading,Command Line Options,Interaction
@section Basic Interaction: The Main Panel

Normally when you invoke Geomview, three windows appear: the
@panel{Main} panel, the @panel{Tools} panel, and one camera window.
Geomview has many other windows but most things can be done with these
three and so by default the others do not appear.  This section of the
manual introduces some basic concepts that are used throughout the rest
of the manual and describes the @panel{Main} panel.

@html
<CENTER><IMG SRC="pix/main.gif"><P>The Main Panel</CENTER>
@end html
@tex
\midinsert\vbox{
\centerline{\psfig{file=figs/main.ps}}
\caption{The Main Panel}
}\endinsert
@end tex

Geomview can display an arbitrary number of objects simultaneously.  The
@widget{Targets} browser in the @panel{Main} panel displays a list of all
the objects that Geomview currently knows about.  This browser has a
line for each object that you have loaded, plus some lines for other
objects.  One of the other objects is called @code{World} and corresponds to
the all the currently loaded objects, treated as if they were one
object.  Most of the operations that you can do to one object, such as
applying a motion or changing a color, can also be done to the "World"
object.

The @widget{Targets} browser also has an entry for each camera.  By
default there is only one camera; it is possible to add more of them via
the @widget{New Camera} entry of the @panel{Main} panel's @widget{File} menu.
Geomview treats cameras in much the same way
as it does geometric objects.  For example, you can move cameras around
and add them and delete them just as with geometric objects.  Cameras do
not usually show up in the display as an object that you see.  Each
camera has a separate camera window which displays the view as seen by
that camera.  (It is possible for each camera to display a geometric
representation of other cameras.  @xref{Cameras}.)

Because Geomview treats cameras and geometric objects very similarly,
the term @dfn{object} in this documentation is used to refer to either
one.  When we need to distinguish between the two kinds of objects, we
use the term @dfn{geom} to denote a geometric object and the word
@dfn{camera} to denote a camera.

The object which is selected (highlighted) in the @widget{Targets}
browser is called the @dfn{target} object.  This is the object that
receives any actions that you do with the mouse or keyboard.  You can
change the target object by selecting a different line in the
@widget{Targets} browser.  Another way to change the target object is
to put the mouse cursor directly over a geom in a camera window
and rapidly double-click the right mouse button.  This process is called
@dfn{picking}; the picked object becomes the new target.

Geomview objects are all known by two names, both of which are shown in
the @widget{Targets} browser.  The first name given there, which appears
in square brackets ([ ]), is a short name assigned by Geomview when you
load the object.  It consists of the letter `g' for geoms and `c' for
cameras, followed by a number.  The second name is a longer more
descriptive name; by default this is the name of the file that the
object was loaded from.  The two names are equivalent as far as Geomview
is concerned; at any point where you need to specify a name you can give
either one.

To manipulate an object, make sure you that the object you want to move is the
target object, and put the mouse cursor in a camera window.  Motions are
applied by holding down either the left or middle mouse button and
moving the mouse.  There are several different motion "modes", each for
applying a different kind of motion.  The @widget{MOTION MODE} browser
in the @panel{Main} panel indicates the current motion mode.  The
default is "Rotate".  You can change the current motion mode by
selecting a new one in the @widget{MOTION MODE} browser, or by using the
@panel{Tools} panel.  For more information about motion modes,
@xref{Mouse Motions}.

The @widget{Modules} browser lists Geomview external modules.  An
external module is a separate program that interacts with Geomview to
extend its functionality.  For information on external modules,
@xref{Modules}.

@ifset forms
The @widget{Load} button on the @panel{Main} panel brings up the
@panel{Files} panel for loading a file.  The file can contain either a
geom, a camera, or gcl commands.  For details, @xref{Loading}.

The @widget{Delete} button causes the target
object to be deleted.  Geomview selects another object to be the new
target.  You can delete cameras as well as geoms in this way.  If you
hit the @widget{Delete} button while the target object is "World",
Geomview deletes all geoms.

The three buttons at the bottom of the @panel{Main} panel, labeled
@widget{Euclidean}, @widget{Hyperbolic}, and @widget{Spherical}, allow
you to change the geometry of the space that Geomview displays.  By
default @widget{Euclidean} is selected.  For details about using
@widget{Hyperbolic} and @widget{Spherical} spaces, @xref{Non-Euclidean
Geometry}.
@end ifset

@ifclear forms
The menu bar at the top of the main panel offers menus for common operations.

To create new windows, load new objects, save objects or other information,
or quit from geomview, see the @widget{File} menu.  

To copy or delete objects, see the @widget{Edit} menu.

You can invoke any panel from the @widget{Inspect} menu.

The @widget{Space} menu lets you choose whether geomview operates
in Euclidean, Hyperbolic, or Spherical mode.  Euclidean mode is selected
by default.  For details about using @widget{Hyperbolic} and
@widget{Spherical} spaces, @xref{Non-Euclidean Geometry}.
@end ifclear

Most actions that you can do through Geomview's panels have equivalent
keyboard shortcuts so that you can do the same action by typing a
sequence of keys on the keyboard.  This is useful for advanced users who
are familiar with Geomview's capabilities and want to work quickly
without having to have lots of panels cluttering up the screen.
Keyboard shortcuts are usually indicated in square brackets ([ ]) near
the corresponding item in a panel.  For example, the keyboard shortcut
for @widget{Rotate} mode is 'r'; this is indicated by "[r]" appearing
before the word "Rotate" in the @widget{MOTION MODE} browser.  To
use this keyboard shortcut, just hit the @kbd{r} key while the mouse
cursor is in any Geomview window.  Do not hit the @kbd{@key{RET}} key
afterwards.

Some keyboard shortcuts consist of more than one key.  In these cases
just type the keys one after the other, with no @kbd{@key{RET}}
afterwards.  Keyboard shortcuts are case sensitive.

Many keyboard shortcuts can be preceded by a numeric parameter.
For example, typing @code{ae} toggles the state of drawing edges,
while @code{1ae} always enables edge drawing.

The @widget{keyboard} field in the upper left corner of the @panel{Main}
panel echos the current state of keyboard shortcuts.

@ifset forms
The button labeled @widget{?} near the top right corner of the
@panel{Main} panel causes Geomview to print out a list of all keyboard
shortcuts to standard output.

The @widget{Quit} button on the main panel terminates Geomview.
@end ifset
@ifclear forms
For a list of all keyboard shortcuts, press the @emph{@code{?}} key.
@end ifclear


@comment ================================================================
@node Loading,Mouse Motions,Basic Interaction,Interaction
@section Loading Objects Into Geomview

There are several ways to load an object into Geomview.

@table @asis
@item the @panel{Files} panel
If you click the @widget{Load} button in Geomview's @panel{Main} panel,
the @panel{Files} panel will appear. 

@html
<CENTER><IMG SRC="pix/myfilelist.gif"><P>The Files Panel</CENTER>
@end html
@tex
\midinsert\vbox{
\centerline{\psfig{file=figs/myfilelist.ps}}
\caption{The Files Panel}
}\endinsert
@end tex
This panel lets you select a file from a variety of directories.
The top of the panel is a standard Motif file browser.  Below this is
a list of directories on geomview's standard search path; click on one
of these to browse files in that directory.

To select a file, double-click on its name in the browser at upper right,
or click on its name and press the @kbd{Return} key, or type the file's name
into the text box at the bottom of the browser and press @kbd{Return}.
@refill

If the selected file contains OOGL geometric data, it will be added to the
geomview @widget{Targets} browser.  If it contains GCL commands instead,
the file will be interpreted.  @xref{GCL}.

When the @panel{Files} panel first appears, the directory selected in the
directory browser is the current directory --- the one from which you
invoked Geomview.  The file browser shows @emph{all} the files in this
directory, including ones that are not Geomview files.  If you try to
load a file that doesn't contain either an OOGL object or Geomview
commands, Geomview will print out an error message.

The directory browser also lists a second and third directory in
addition to the current directory.  The second one, which ends in
@file{data/geom}, is the Geomview example data directory.  This contains
a wide variety of sample objects.  It also contains several
subdirectories.  In particular, the @file{hyperbolic} and
@file{spherical} subdirectories have sample hyperbolic and spherical
objects, respectively.  Directory entries in the browser look just like
file entries; to view a subdirectory, click on it.

The third directory shown in the directory browser, which ends in
@file{geom}, contains several subdirectories with other Geomview files
in them.  These are used less frequently than the ones in the
@file{data/geom} directory.

You can change the list of directories shown the @panel{Files}
panel's directory browser by using the @code{set-load-path} command;
@pxref{GCL}.

@item the @kbd{<} keyboard shortcut:
If you type @kbd{<} in any Geomview window, the @panel{Load} panel will
appear.  This is a small version of the @panel{Files} panel; it contains
a text field in which you can enter the name of a file to load (or a
GCL command surrounded by parentheses).  After typing the name of the file
to load, type @kbd{@key{RET}}; Geomview will
load the file as if you had loaded it with the @widget{Add} button in
the @panel{Files} panel.  If, after bringing up the small load panel
with @kbd{<}, you decide you want to use the larger @panel{Files} panel
after all, press the @widget{File Browser} button.
@html
<CENTER><IMG SRC="pix/load.gif"><P>The Load Panel</CENTER>
@end html
@tex
\midinsert\vbox{
\centerline{\psfig{file=figs/load.ps}}
\caption{The Load Panel}
}\endinsert
@end tex

@item geometry loading commands:
The @code{load}, @code{geometry}, @code{new-geometry}, and @code{read}
gcl commands allow you to load an object into Geomview;
@xref{GCL}.@refill

@end table

@comment ================================================================
@node Mouse Motions,Point of Interest,Loading,Interaction
@section Using the Mouse to Manipulate Objects

Geomview lets you manipulate objects with the mouse.  There are six
different mouse motion modes: @widget{Rotate}, @widget{Translate},
@widget{Cam Fly}, @widget{Cam Zoom}, @widget{Geom Scale}, and
@widget{Cam Orbit}.  The tools panel has a button for each of these
modes; to switch modes, click on the corresponding button.  You can also
select these through the @widget{Motion Mode} browser on the
@panel{Main} panel.@refill

This section describes basic mouse interaction.  For details,
@pxref{Commands}.

@html
<CENTER><IMG SRC="pix/tools.gif"><P>The Tools Panel</CENTER>
@end html
@tex
\midinsert
\vbox{
\centerline{\psfig{file=figs/tools.ps}}
\caption{The Tools Panel}
}
\endinsert
@end tex

Each of the motion modes uses a common paradigm for how the motion is
applied.  In particular, each depends on the current @emph{target}
object and the current @emph{center} object.  These are explained in the
following paragraphs.

The current target object is shown in the @widget{Target} field in the
@panel{Tools} panel.  This is the same as the selected object in the
@widget{Targets} browser in the @panel{Main} panel, and you can
change it by either selecting a new object in the browser, by typing
a new entry in the field, or by picking an object in a camera
window by double-clicking the right mouse button with the cursor over
the object.

The current center object is shown in the @widget{Center} field in the
@panel{Tools} panel.  Its default value is the special word "target",
which means that the center object is whatever the target object is.
You can change the center to any object by typing it in the @widget{Center}
field.  The origin of the center object is held fixed in @widget{Rotate} and
@widget{Orbit} modes.  Normally the center object is one of the existing
geoms listed in the @widget{Targets} browser, and the actual center of
rotations is the origin of that object's coordinate system.
It is possible, however, to select an arbitrary point of interest on
an object as the center. For details, @pxref{Point of Interest}.

You apply a mouse motion by holding down either the left or middle mouse
button with the cursor in a camera window and moving the mouse.  Most of
the modes have @emph{inertia}, which means that if you let go of the
button while moving the mouse, the motion will continue.  It may be
helpful to imagine the mouse cursor as being a gripper; when you hold a
mouse button down, it grips the target object and you can move it.  When
you let go of the mouse button, the gripper releases the object.
Letting go of the mouse button while moving the mouse is like throwing
the object --- the object continues moving independent of the mouse.
Inertia can be turned off; see the @panel{Main} panel's @widget{Motion} menu,
described below.

Generally, the left mouse button controls motion in the screen plane,
while the middle mouse controls motion along or around the forward direction.

Pressing the shift key while dragging with left or middle mouse buttons
in most motion modes gives slow-speed motions, useful for fine adjustment.

You can pick any point on an object (not just its origin) as the center of
motion by holding down the shift key while clicking the right mouse button;
this chooses a point of interest.

@table @widget

@item Rotate
In @widget{Rotate} mode, hold the left mouse button down to rotate the
target object about the center object.  Rotation proceeds in the
direction that you move the mouse.  Specifically, the axis of rotation
passes through the origin of the center object, is parallel to the
camera view plane, and is perpendicular to the direction of motion of
the mouse.  When the center is "target", this means that the target
object rotates about its own origin.

The middle mouse button in @widget{Rotate} mode rotates the target
object about an axis perpendicular to the view plane.

@item Translate
In @widget{Translate} mode, hold the left mouse button down to translate
the target object in the direction of mouse motion.  The middle mouse
button translates the target along an axis perpendicular to the view
plane.

In Euclidean space, the center object is essentially irrelevant for
translations.  In hyperbolic and spherical spaces, where translations
have a unique axis, this axis is chosen to go through the origin of the
center object.

@item Cam Fly
@widget{Cam Fly} is a crude flight simulator that lets you fly around
the scene.  It works by moving the camera.
Move the mouse while holding the left mouse button down to
point the camera in a different direction.  To move forward or backward,
hold down the middle button and move the mouse vertically.  Both of
these motions have inertia; typically the easiest way to fly around a
scene is to give the camera a slight forward push by letting go of the
middle button while moving the mouse upward, and then using the left
button to steer.

@widget{Cam Fly} affects the camera window that the mouse is in; it
ignores the target object and the center object.

@item Cam Orbit
@widget{Cam Orbit} mode lets you rotate the current camera around the
current center. The left mouse button does this rotation.  The middle
mouse button in @widget{Cam Orbit} mode acts as in
@widget{Cam Fly} mode: it moves the camera forward or backward.

In general @widget{Cam Orbit} does not move the target object, although
if the current camera is selected as the target and the center is also
the target, it will pivot that camera about itself just as in
@widget{Cam Fly} mode.

@item Cam Zoom
@widget{Cam Zoom} mode lets you change the current camera's field of
view with the mouse; hold the left mouse button down and move the mouse
to change it.  The numeric value of the field of view is shown in the
@widget{FOV} field in the @panel{Camera} panel.

@item Geom Scale
@widget{Geom Scale} mode lets you enlarge or shrink a geom.  It operates
on the target object if that object is a geom.  If the target is a
camera, @widget{Geom Scale} operates on the geom that was most recently
the target object.  Moving the mouse while holding down the left mouse button
scales the object either up or down, depending on the direction of
mouse motion.  The center of the applied scaling transformation is the
center object.

Scaling is meaningful only in Euclidean space; attempts to scale are
ignored in other spaces.

@widget{Geom Scale} mode does not have inertia.

@end table

The @widget{Stop}, @widget{Look At}, @widget{Center}, and @widget{Reset}
buttons on the @panel{Tools} panel perform actions related to motions
but do not change the current motion mode.


@table @widget

@item Stop
The @widget{Stop} button causes all motions to stop.  It affects all
moving objects, not just the target object.  Its keyboard shortcut
is @kbd{H}.

The keyboard command @kbd{h}, which does not correspond to a
panel button, stops the current motion for the target object only.

@item Look At
The @widget{Look At} button causes the current camera to be moved
to a position such that it is looking at the target object, and such
that the target object more or less fills the window.

The Look At command is unreliable in non-Euclidean spaces.

@item Center
The @widget{Center} button undoes the target object's transformation,
moving it back to its home position, which is where it was when you
originally loaded it into Geomview.

@item Reset
The @widget{Reset} button stops all motion and causes all objects to
move back to their home positions.

@end table

The @panel{Tools} panel also sports a @widget{Main} button, to invoke the
main panel in case it was dismissed or buried, and a @widget{Done} button
to close the @panel{Tools} panel.


The @panel{Main} panel's @widget{Motion Style} menu has special controls
affecting how mouse motions are interpreted.

@table @widget

@item [ui] Inertia
Normally, moving objects have inertia: if the mouse is still moving
when the button is released, the selected object continues to move.
When @widget{Inertia} is off, objects cease to move as soon as you release
the mouse.

@item [uc] Constrain Motion
It's sometimes handy to move an object in a direction aligned with a
coordinate axis: exactly horizontally or vertically.  Selecting
@widget{Constrain Motion} changes the interpretation of mouse motions
to allow this; approximately-horizontal or approximately-vertical mouse dragging
becomes exactly horizontal or vertical motion.  Note that the motion is
still along the X or Y axes of the camera in which you move the mouse,
not necessarily the object's own coordinate system.

@item [uo] Own Coordinates
It's sometimes handy to move objects with respect to the coordinate system
where they were defined, rather than with respect to some camera's view.  While
@widget{Own Coordinates} is selected, all motions are interpreted that way:
dragging the mouse rightward in translate mode moves the object in its own +X
direction, and so on.  May be especially useful in conjunction with
the @widget{Constrain Motion} button.

@end table

@comment ================================================================
@node Point of Interest,Appearance,Mouse Motions,Mouse Motions
@subsection Selecting a Point of Interest

It is sometimes useful to specify a particular point on some object in a
geomview window as the center point for mouse motions.  You can do this
by shift-clicking the right mouse button (i.e. click it once
while holding down the shift key on the keyboard) with the cursor over
the desired point.  This point then becomes the @emph{point of
interest}.  The point of interest must be on an existing object.

Selecting a point of interest simplifies examining a small portion of a
larger object.  Shift-right-click on an interesting point, and select
@widget{Orbit} mode.  Use the middle mouse button to approach, and the
left mouse to orbit the point, examining the region from different
directions.

When you have selected a point of interest, the current center object
changes to an object named "CENTER", which is an invisible object
located at the point of interest.  In addition, mouse motions for the
window in which you made the selection are adjusted so that the point of
interest follows the mouse.

You can change the point of interest at any time by selecting a new one
by shift-clicking the right mouse button again.  You can cancel
the point of interest altogether by shift-clicking the right
mouse button with the cursor on the background (i.e. not on any object).
This changes the center object back to its default value, "target".

The object named "CENTER", which serves as the center object for the
point of interest, is a special kind of geom called an "alien".  It does
not appear in the @widget{Targets} browser.  By default it has no
geometry associated with it and hence is invisible.  You can, however,
explicitly give it some geometry using a GCL command, causing it to
appear.  Use the @code{geometry} command for this: @code{(geometry
CENTER @var{geometry})}, where @var{geometry} is any valid geometry.
For example, @code{(geometry CENTER @{ < xyz.vect @})} causes the file
@file{xyz.vect}, which is one of the standard example files distributed
with geomview, to be used at the geometry for CENTER.


What happens internally when you select a point of interest is
that the center is set to the object called CENTER, and that object is
positioned at the point of interest.  In addition, in order for mouse
motions to track the point of interest, the current camera's focal
length is set to be the distance from the camera to the point of
interest.  You can accomplish this via GCL with the following commands:
@example
(if (real-id CENTER) nil (new-alien CENTER {}))
(ui-center CENTER)
(transform-set CENTER universe universe translate @var{x} @var{y} @var{z})
(merge camera @var{cam-id} @{ focus @var{d} @})
@end example
@noindent
where @code{(@var{x},@var{y},@var{z})} are the (universe) coordinates of
the point of interest, and @var{d} is the distance from that point to
the current camera, @var{cam-id}.  The first command above creates the
"alien" CENTER if it does not yet exist.

@comment ================================================================
@node Appearance,Appearance Panel,Point of Interest,Interaction
@section Changing the Way Things Look

Geomview uses a hierarchy of appearances to control the way things look.
An @dfn{appearance} is a specification of information about how
something should be drawn.  This can include many things such things as
color, lighting, material properties, and more.  Appearances work in a
hierarchal manner: if a certain appearance property, for example face
color, is not specified in a particular object's appearance, that object
is drawn using that property from the parent appearance.  If both the
parent and the child appearance specify a property, the child's setting
takes precedence unless the parent appearance is set to override.

Every geom in Geomview has an appearance associated with it.  There is
also an appearance associated with the "World" geom, which serves as the
parent of each individual geom's appearance.  Finally, there is a
global "base" appearance, which is the parent of the World appearance.

The base appearance specifies reasonable values for all appearance
information, and by default none of the other appearances specify
anything, which means they inherit their values from the base
appearance.  This means that by default all objects are drawn using the
base appearance.

If you change a certain appearance property for a geom, that property
is used in drawing that geom.  The parent appearance is used for any
properties that you do not explicitly set.

Geomview has three panels which let you modify appearances.  

@menu
* Appearance Panel::	Color etc.
* Materials Panel::	Surface Material properites.
* Lighting Panel::	Lighting Parameters.
@end menu

@comment ----------------------------------------------------------------
@node Appearance Panel,Materials Panel,Appearance,Appearance
@subsection The Appearance Panel

The @panel{Appearance} panel lets you change most common appearance
properties of the target object.
@html
<CENTER><IMG SRC="pix/ap.gif"><P>The Appearance Panel</CENTER>
@end html
@tex
\midinsert\vbox{
\centerline{\psfig{file=figs/ap.ps}}
\caption{The Appearance Panel}
}\endinsert
@end tex
If the target is an individual geom, then changes you make in the
appearance panel apply to that geom's appearance.  If the target is the
World, then appearance panel changes apply to the World appearance
@emph{and} to all individual geom appearances.  (Users have found that
this is more desirable than having the changes only apply to the World
appearance.)  If the target is a camera, then appearance panel changes
apply to the geom that was most recently the target.

The five buttons near the upper right corner under the word
@widget{Draw} control what parts of the target geom are drawn.

@table @widget

@item Faces
This button specifies whether faces are drawn.

@item Edges
This button specifies whether edges are drawn.

@item BBox
This button specifies whether the bounding box is drawn.

@item Vects
This button specifies whether VECT objects are drawn.  VECTs are a type
of OOGL object that represent points and line segments in 3-space;
they are distinct from edges of other kinds of objects, and it is sometimes
desirable to have separate control over whether they are drawn.

@item Normals
This button specifies whether surface normal vectors are drawn.

@end table

The four buttons under @widget{Color} labeled @widget{Faces}, @widget{Edges},
@widget{Normals}, and @widget{BBox} let you specify the color of
the corresponding aspect of the target geom.  Clicking on one
of them brings up a color chooser panel.
@html
<CENTER><IMG SRC="pix/color.gif"><P>Color Chooser Panel</CENTER>
@end html
@tex
\midinsert\vbox{
\centerline{\psfig{file=figs/color.ps}}
\caption{Color Chooser Panel}
}\endinsert
@end tex
This panel offers two sets of sliders: H(ue) S(aturation) V(alue), or
R(ed) G(reen) B(lue), each in the range 0 through 1.  The square
shows the current color, which is given numerically in both HSV and RGB systems
in the corresponding text boxes.

In the HSV color system, hue H runs from red at 0, green at .333, blue at .667,
and back to red at 1.0.  Saturation gives the fraction of white mixed
into the color, from 0 for pure gray to 1 for pure color.  Value gives the
brightness, from 0 for black to 1 for full brightness.

Pressing the @widget{RGB} or @widget{HSV} button at top center switches
the sliders to the other color system.  You can adjust colors either via
the sliders, or by typing in either the RGB or HSV text boxes.

Click @widget{OK} to accept the color that you have chosen, or
@widget{Cancel} to retain the previous color setting.


The @widget{SHADING} browser lets you specify the shading model that
Geomview uses to paint the target geom.

@table @widget

@item Constant
Every face of the object is drawn with a constant color which does not
depend on the location of the face, the camera, or the light sources.
If the object does not contain per-face or per-vertex colors, the
diffuse color of the object's appearance is used.  If the object
contains per-face colors, they are used.  If the object contains
per-vertex colors, each face is painted using the color of its first
vertex.

@item Flat
Each face of the object is drawn with a color that depends on the
relative location of the face, the camera, and the light sources.
The color is constant across the face but may change as the face,
camera, or lights move.

@item Smooth
Each face of the object is drawn with smoothly interpolated colors based
on the normal vectors at each vertex.  If the object does not contain
per-vertex normals, this has the same effect as flat shading.  If the
object has reasonable per-vertex normals, the effect is to smooth
over the edges between the faces.

@item CSmooth
Each face of the object is drawn with exactly the specified color(s),
independent of lighting, orientation, and material properties.  If the
object is defined with per-vertex colors, the colors are interpolated
smoothly across the face; otherwise the effect is the same as in
Constant shading style.

@end table

The @widget{Facing Normals} button on the @panel{Appearance} panel
indicates whether or not Geomview should arrange that normal vectors
always face the viewer.  If a normal vector points away from the viewer
the color of the corresponding face or vertex usually is darker than is
desired.  Geomview can avoid this by using the opposite normal in
shading calculations.  This is the default.  Using @widget{Facing Normals}
can give strange flickering dark or light shading effects, though, near
the horizon of a fairly smooth facetted object.
Press this button to use the normals given with the object.


The three text fields in the lower left corner of the @panel{Appearance}
panel are:

@table @widget

@item Line Width
The width, in pixels, for lines drawn by Geomview.

@item Normal Length
This is actually a scale factor; when normal vectors are drawn, Geomview
draws them to have a length that is their natural length times this
number.

@item Patch Dicing
Geomview draws Bezier patches by first converting them to meshes.  This
parameter specifies the resolution of the mesh: if @widget{Patch Dicing}
is @var{n}, then an @var{n} by @var{n} mesh is used to draw each Bezier
patch.  if @widget{Patch Dicing} is 1, the resolution reverts to a
built-in default value.

@end table

The @widget{Revert} button on the @panel{Appearance} panel undoes all
settings in the target appearance.  This causes the target geom to
inherit all its appearance properties from its parent.

The @panel{Appearance} panel's @widget{Override} button determines whether
appearance controls should override settings in the objects themselves --
for example, setting the face color will affect all faces of objects with
multi-colored facets.  Otherwise, appearance controls only provide settings
which the objects themselves do not specify.
By default, @widget{Override} is enabled.  This button applies to all objects,
and to all appearance-related panels.

@comment ----------------------------------------------------------------
@node Materials Panel,Lighting Panel,Appearance Panel,Appearance
@subsection The Materials Panel

The @panel{Materials} panel controls material properties of surfaces.
It works with the target object in the same way that the
@panel{Appearance} panel does.
@html
<CENTER><IMG SRC="pix/mat.gif"><P>The Materials Panel</CENTER>
@end html
@tex
\midinsert\vbox{
\centerline{\psfig{file=figs/mat.ps}}
\caption{The Materials Panel}
}\endinsert
@end tex

@table @widget

@item Transparent

This button determines whether transparency is enabled.  Geomview itself
does not fully support transparency yet and on some machines it does not
work at all.  More specifically, the X, NextStep, and some SGI platforms
ignore alpha information entirely, while other SGI platforms use the
alpha information but the picture is guaranteed to be incorrect. Use
RenderMan if you want real transparency: when transparency is enabled, a
RenderMan snapshot will contain the alpha information.

@item Alpha
This slider determines the opacity/transparency when transparency is
enabled.  0 means totally transparent, 1 means totally opaque.

@item Diffuse Reflectance
This slider controls the diffuse reflectance of a surface.  This has
to do with how much the surface scatters light that it reflects.

@item Shininess
This slider controls how shiny a surface is.   This determines the
size of specular highlights on the surface.  Lower values give the
surface a duller appearance.

@item Ambient Reflectance
This slider controls how much of the ambient light a surface reflects.

@item Specular Reflectance
This slider controls the specular reflectance of a surface.  This
has to do with how directly the surface reflects light rays.  Higher
values give brighter specular highlights.

@item Done
This button dismisses the @panel{Materials} panel.

@end table

@comment ----------------------------------------------------------------
@node Lighting Panel,Cameras,Materials Panel,Appearance
@subsection The Lighting Panel

The @panel{Lighting} panel controls the number, position, and color of
the light sources used in shading.
@html
<CENTER><IMG SRC="pix/light.gif"><P>The Lighting Panel</CENTER>
@end html
@tex
\midinsert\vbox{
\centerline{\psfig{file=figs/light.ps}}
\caption{The Lighting Panel}
}\endinsert
@end tex

The @panel{Lighting} panel is different from the @panel{Appearance} and
@panel{Material} panels in that it always works with the base
appearance.  This is because it usually makes sense to use the same set
of lights for drawing all objects in your scene.

@table @widget

@item LIGHTS
The @widget{LIGHTS} browser shows the currently selected light.  Changes
made using the other widgets on this panel apply to this light.  There
is always at least one light, the ambient light.

@item Intensity
This slider controls the intensity of the current light.

@item Color
This button brings up a color chooser which lets you select the color
of the current light.

@item Add
This button adds a light.

@item Delete
This button deletes the current light.

@item Show Lights
This button lets you see and change the positions of the light sources
in a camera window.  Each light is drawn as long cylinder which is
supposed to remind you of a light beam.  When you click on the
@widget{Show Lights} button Geomview goes into "light edit" mode, during
which you can rotate current light by holding down the left mouse button
and moving the mouse.  Lights placed in this way are infinitely distant,
so what you are changing is the angular position.  Click on the
@widget{Show Lights} button again to return to the previous motion mode
and to quit drawing the light beams.

@item Done
This button dismisses the @panel{Lighting} panel.

@end table

Geomview's @panel{Appearance}, @panel{Materials}, and @panel{Lighting}
panels are constructed to allow you to easily do most of the appearance
related things that you might want to do.  The appearance hierarchy that
Geomview supports internally, however, is very complex and there are
certain operations that you cannot do with the panels.  The Geomview
command language (gcl) provides complete support for appearance operations.
In particular, the @code{merge-baseap} command can be used to change the
base appearance (which, except for lighting, cannot be changed by
Geomview's panels).  The @code{merge-ap} command can be used to change
an individual geom's appearance.  Appearances can also be specified in
OOGL files; for details, @pxref{Appearances}.


@comment ================================================================
@node Cameras,Saving,Lighting Panel,Interaction
@section Cameras

A camera in Geomview is the object that corresponds to a camera window.
By default there is only one camera, but it is possible to have as many
as you want.  You can control certain aspects of the way the world is
drawn in each camera window via the @panel{Cameras} panel.
@html
<CENTER><IMG SRC="pix/cam.gif"><P>The Cameras Panel</CENTER>
@end html
@tex
\midinsert\vbox{
\centerline{\psfig{file=figs/cam.ps}}
\caption{The Cameras Panel}
}\endinsert
@end tex
If the target object is a camera, the @panel{Cameras} panel affects that
camera.  If the target object is not a camera, the @panel{Cameras} panel
affects the @dfn{current camera}.  The current camera is the camera of
the window that the mouse cursor is in, or was in most recently if the
cursor is not in a camera window.  Thus, if you use the keyboard
shortcuts for the actions in the @panel{Cameras} panel while the cursor
is in a camera window, the actions apply to that camera, unless you have
explicitly selected another camera.

To create new camera windows, use the @kbd{v+} keyboard shortcut,
or see the @widget{File} menu on the @panel{Main} panel.

@table @widget

@item Single-Buffering
Normally, geomview windows are @emph{double-buffered}: geomview draws the
next picture into a hidden window, then switches buffers to make
it visible all at once.  On many systems, the memory for the hidden buffer
comes from stealing half the bits in each screen pixel, reducing the color
resolution.  When single-buffering is enabled, the window flickers as each
scene is being drawn, but you may get smoother images with reduced grainy
dithering artifacts.  Single-buffering is possible if Geomview is compiled with
GL or OpenGL, but not with plain-X graphics.

@item Dither
Many displays offer less than the 24 bits per pixel (8 bits each of red, green,
and blue) conventionally needed to show smooth gradations of color.  
When trying to show a color not accurately available on the display,
Geomview normally @emph{dithers}, choosing pixel colors sometimes brighter,
sometimes darker than the desired value, so that the average color over an area
is a better approximation to the true color than a single pixel could be.
Effectively this loses spatial resolution to gain color resolution.
This isn't always desirable, though.  Turning @widget{Dither} off
gives less grainy, but less accurately colored, images.

@item Software Shading
This button controls whether Geomview does shading calculations in software.
The default is to let the hardware handle them, and in Euclidean space
this is almost certainly best because it is faster.  In hyperbolic and
spherical space, however, the shading calculations that the hardware
does are incorrect.  Click this button to turn on correct but slower
software shading.

@item Background Color
This button brings up a color chooser which you can use to set the
background color of the camera's window.

@item PROJECTION
This browser lets you pick between perspective and orthogonal projection
for this camera.

@item Near clip
This determines the distance in world coordinates of the near clipping
plane from the eye point.  It must be a positive number.

@item Far clip
This determines the distance in world coordinates of the far clipping
plane from the eye point.  It must be a positive number and in general
should be larger than the @widget{Near clip} value.

@item FOV
This is the camera's field of view, measured in its shorter direction.
In perspective mode, it is an angle in degrees.  In orthographic mode,
it is the linear size of the field of view.  This number can be modified
with the mouse in @widget{Cam Zoom} mode.

@item Focal Length
The focal length is intended to suggest the distance from the camera to
an imaginary plane of interest.  Its value is used when switching
between orthographic and perspective views (and during stereo viewing),
so as to preserve apparent size of objects lying at the focal distance
from the camera.  Focal length also affects interpretation of mouse-based
translational motions.  Speed of forward motion (in translate, fly and
orbit modes) is proportional to focal length; and objects lying at the
focal distance from the camera translate laterally at the same rate as
the mouse cursor.  Finally, in N-D projection mode, cameras are displaced
back by the focal distance from the 3-D projection of the world origin.

@item Lines Closer
This number has to do with the way lines are drawn.  Normally Geomview's
z-buffering algorithm can get confused when drawing lines that lie
exactly on surfaces (such as the edges of an object); due to machine
round-off error, sometimes the lines appear to be in front of the
surface and sometimes they appear behind it.  The @widget{Lines Closer}
value is a fudge factor --- Geomview nudges all the lines that it draws
closer to the camera by this amount.  The number should be a small
integer; try 5 or 10.  0 turns this feature off completely.  Choosing
too large a value will make lines visible even though they should be
hidden.

@item SPACE MODEL
This determines the model used to draw the world.  It is most useful in
hyperbolic and spherical spaces.  You probably don't need to touch this
browser if you stay in Euclidean space.  For more information about
these models, @pxref{Non-Euclidean Geometry}.
@table @widget
@item Virtual
This is the default model and represents the natural view from inside
the space.

@item Projective
The projective model of hyperbolic and spherical space.  Geoms move
under isometries of the space, and cameras move by Euclidean motions.
By default in the projective model, the Euclidean unit sphere is drawn.
In hyperbolic space this is the sphere at infinity.  In Euclidean space
the projective model is the same as the virtual model except that the
sphere is drawn by default.

@item Conformal
The conformal model of hyperbolic and spherical space.  Geoms move under
isometries of the space, and cameras move by Euclidean motions.  In
Euclidean space, the conformal model amounts to inverting everything in
the unit sphere.
@end table

@item Draw Sphere
This controls whether Geomview draws the unit sphere.  By default the
unit sphere appears in the projective and conformal models.  In
hyperbolic space this is the sphere at infinity.  In spherical space it
is the equatorial sphere.

@item Done
This button dismisses the @panel{Cameras} panel.

@end table

@comment ================================================================
@node Saving,Commands,Cameras,Interaction
@section Saving your work

Geomview's @panel{Save} panel lets you store Geomview objects and other
information in files that you can read back into Geomview or other
programs.
@html
<CENTER><IMG SRC="pix/save.gif"><P>The Save Panel</CENTER>
@end html
@tex
\midinsert\vbox{
\centerline{\psfig{file=figs/save.ps}}
\caption{The Save Panel}
}\endinsert
@end tex
To use the @panel{Save} panel you select the desired format in the
browser next to the word @widget{Save}, enter the name of the object you
want to save in the text field next to the word @widget{for}, and enter
the name of the file you wish to save to in the long text field next to
the word @widget{in}.  You can then either hit @kbd{@key{RET}} or click
on the @widget{OK} button.  When the file has been written, the @panel{Save}
panel disappears.  If you want to dismiss the @panel{Save} panel without
writing a file, click the @widget{Cancel} button.

If you specify @file{-} as the file name, Geomview will write the file
to standard output, i.e. in the shell window from which you invoked
Geomview.

The possible formats are given below.  The kind of object that can
be written with each format is given in parentheses.

@table @widget

@item Commands @asis{(any object)}
This write a file of gcl commands containing all information about
the object.  Loading this file later will restore the object as well as
all other information about it, such as appearance, transformations,
etc.

@item Geometry alone @asis{(geom)}
This writes an OOGL file containing just the geometry of the object.

@item Geometry [in world] @asis{(geom)}
This writes an OOGL file containing just the geometry of the object,
transformed under Geomview's current transformation for this object.
Use this if you have moved the object from its initial position and want
to save the new position relative to the world.

@item Geometry [in universe] @asis{(geom)}
This writes an OOGL file containing just the geometry of the geom,
transformed under both the object's transformaton and the world's
transformation.

@item RMan [->tiff] @asis{(camera)}
Writes a RenderMan file which when rendered creates a tiff image.

@item RMan [->frame] @asis{(camera)}
Writes a RenderMan file which when rendered causes an image to appear in
a window on the screen.

@item SGI snapshot @asis{(camera)}
Write an SGI raster file.  A bell rings when the snapshot is complete.
Only available on SGI systems.

@item PPM Screen snapshot @asis{(camera)}
Take a snapshot of the given window and save it as a PPM image.
If you specify a string beginning with a vertical bar (@kbd{|})
as the file name, it's interpreted as a Bourne shell command
to which the PPM data should be piped, as in
@samp{| pnmtotiff > snap.tiff} or @samp{| convert -geometry 50% ppm:- snap.gif}.

PPM screen snapshots are only available with GL and Open GL,
not plain X graphics.  The window should be entirely on the screen.
Geomview will ensure that no other windows cover it while the snapshot
is taken.

@item PPM software snapshot @asis{(camera)}
Writes a snapshot of that window's current view, as a PPM image, to the
given file.  The file name may be a Bourne shell command preceded by a vertical
bar (@kbd{|}), as with the PPM screen snapshot.  The software snapshot, though,
is produced by using a built-in software renderer (related to the X-windows
renderer).  It doesn't matter whether the window is visible or not,
and doesn't depend on GL or OpenGL.  It also doesn't support some features,
such as texture mapping.

@item Postscript snapshot @asis{(camera)}
Writes a Postscript snapshot of the camera's view.  It's made by
breaking up the scene into lines and polygons, sorting by depth, and
generating Postscript lines and polygons for each one.  Advantages over
pixel-based snapshot images: resolution is very high, so edges
look sharp even on high-resolution printers, or comparable-resolution images
are typically much more compact.  Disadvantages: depth-sorting
gives good results on some scenes, but can be wildly wrong as a hidden-surface
removal algorithm for other scenes.  Also, Postscript doesn't offer
smoothly interpolated shading, only flat shading for each facet.

@item Camera @asis{(camera)}
Writes an OOGL file of a camera.

@item Transform [to world] @asis{(any object)}
Writes an OOGL transform file giving Geomview's transform for the object.

@item Transform [to universe] @asis{(any object)}
Writes an OOGL transform file giving a transform which is the
composition of Geomview's transform for the object and the transform for
the world.

@item Window @asis{(camera)}
Writes an OOGL window file for a camera.

@item Panels
Writes a gcl file containing commands which record
the state of all the Geomview panels.  Loading this file later will
restore the positions of all the panels.

@end table

@comment ================================================================
@node Commands,Keyboard Shortcuts,Saving,Interaction
@section The Commands Panel

The @panel{Commands} panel lets you type in a gcl command.  When
you hit @kbd{@key{RET}}, Geomview interprets the command and prints any
resulting output or error messages on standard output.  You can edit the
text and hit @kbd{@key{RET}} as many times as you like, in general,
whenever you hit @kbd{@key{RET}} with the cursor in the @panel{Commands}
panel, Geomview tries to interpret whatever text you have typed in the
text field as a command.
@html
<CENTER><IMG SRC="pix/command.gif"><P>The Commands Panel</CENTER>
@end html
@tex
\midinsert\vbox{
\centerline{\psfig{file=figs/command.ps}}
\caption{The Commands Panel}
}\endinsert
@end tex

@ifset forms
The @panel{Obscure} panel is for relatively obscure things that don't
really belong on any of the other panels.  In the present version of
Geomview, the @panel{Obscure} panel includes the @widget{NORMALIZE GEOMETRY}
browser, which controls the kind of geometry normalization that Geomview does,
and several buttons affecting motion style.
@tex
\midinsert\vbox{
\centerline{\psfig{file=figs/obscure.ps}}
\caption{The Obscure Panel}
}\endinsert
@end tex
@end ifset
[Move this.]
Normalization is a kind of scaling; Geomview can scale an object so that
it fits within a certain region.  The main point of normalization is to
allow you to easily view all of an object without having to worry about
how big it is.  We are gradually replacing Geomview's normalization
feature with more robust camera positioning features.  In general, the
best way to make sure you are seeing all of an object is to use the
@widget{Look At} button on the @panel{Tools} panel.  Normalization may
be completely replaced by this and other features in a future version of
Geomview.

Normalization is a property that applies to each geom separately.  The
@widget{NORMALIZE GEOMETRY} browser affects the normalization property
of target geom.  If the target geom is "World", it affects all geoms.

@table @widget

@item None
Do no normalization.

@item Individual
Normalize this geom to fit within a unit sphere.

@item Sequence
This resembles "Individual", except when an object is changing.  Then,
"Individual" tightly fits the bounding box around the object whenever it
changes and normalizes accordingly, while "Sequence" normalizes the
union of all variants of the object and normalizes accordingly.

@item Keep
This leaves the current normalization transform unchanged when the
object changes.  It may be useful to apply "Individual" or "Sequence"
normalization to the first version of a changing object to bring
it in view, then switch to "Keep".

@end table

@comment ================================================================
@node Keyboard Shortcuts,OOGL File Formats,Commands,Interaction
@section Keyboard Shortcuts

Most actions that you can do through Geomview's panels have equivalent
keyboard shortcuts so that you can do the same action by typing a
sequence of keys on the keyboard.  This is useful for advanced users who
are familiar with Geomview's capabilities and want to work quickly
without having to have lots of panels cluttering up the screen.
Keyboard shortcuts usually are indicated in square brackets ([ ]) near
the corresponding item in a panel.  For example, the keyboard shortcut
for @widget{Rotate} mode is 'r'; this is indicated by "[r]" appearing
before the word "Rotate" in the @widget{MOTION MODE} browser.  To
use this keyboard shortcut just hit the @kbd{r} key while the mouse
cursor is in any Geomview window.  You don't need to press the @kbd{@key{RET}}
or @kbd{@key{SPACE}} keys.

Some keyboard shortcuts consist of more than one key.  In these cases
just type the keys one after the other, with no @kbd{@key{RET}}
afterwards.  Keyboard shortcuts are case sensitive.  You can cancel a
multi-key keyboard shortcut that you have started by typing any invalid
key, for example the space bar.

Keyboard commands apply while the cursor is in any camera window and
most control panels.

Many keyboard shortcuts allow numeric arguments which you type as a
prefix to the command key(s).  For example, the shortcut for
@widget{Near clip} in the camera panel is @kbd{v n}.  To set the near
clip plane to @samp{0.5}, type @kbd{0.5vn}.  Commands that don't take a
numeric prefix toggle or reset the current value.

Most commands allow one of the following selection prefixes.  If none is
provided the command applies to the target object.

@table @kbd
@item g
world geom	
@item g#
#'th geom
@item g*
All geoms
@item c
current camera
@item c#
#'th camera
@item c*
All cameras
@end table

For example, @kbd{g4af} means toggle the face drawing of object
@widget{g4}.

Simply typing a selection prefix, like @kbd{g4}, doesn't yet select an object;
that only happens when a command, like @kbd{ae}, follows the prefix.
To select an object as the target without doing anything else to it,
use the @kbd{p} command.  So @kbd{g3p} selects object g3.

The text field in the upper left corner of the @panel{Main} panel
shows the state of the current keyboard shortcut.

In addition to the keyboard shortcuts for the panel commands, there is
also a shortcut for picking a target object: type the short name of the
object followed by @kbd{p}.  For example, to select object @widget{g3},
type @kbd{g 3 p}.  This only works with the short names --- the ones
that appear in square brackets ([ ]) in the @widget{Targets} browser of
the @panel{Main} panel.

Below is a summary of all keyboard shortcuts.

@table @asis
@item Draw
    @table @kbd
    @item af
    Faces
    @item ae
    Edges
    @item an
    Normals
    @item ab
    Bounding Boxes
    @item aV
    Vectors
    @end table
@item Shading
    @table @kbd
    @item 0as
    Constant
    @item 1as
    Flat
    @item 2as
    Smooth
    @item 3as
    Smooth, non-lighted
    @item aT
    allow transparency
    @item at
    texture mapping
    @end table
@item Other
    @table @kbd
    @item av
    eVert normals: always face viewer
    @item #aw
    Line Width (pixels)
    @item aC
    handle concave polygons
    @item #vc
    edges Closer than faces (try 5-100)
    @end table
@item Color
    @table @kbd
    @item Cf
    faces
    @item Ce
    edges
    @item Cn
    normals
    @item Cb
    bounding boxes
    @item CB
    background
    @end table
@item Motions
    @table @kbd
    @item r
    rotate
    @item t
    translate
    @item z
    zoom FOV
    @item f
    fly
    @item o
    orbit
    @item s
    scale
    @item w
    recenter target
    @item W
    recenter all
    @item h
    halt
    @item H
    halt all
    @item @@
    select center of motion (e.g. @kbd{g 3 @@})
    @item L
    Look At object
    @end table
@item Viewing
    @table @kbd
    @item 0vp
    Orthographic view
    @item 1vp
    Perspective view
    @item  vd
    Draw other views' cameras
    @item #vv
    field of View
    @item #vn
    near clip distance
    @item #vf
    far clip distance
    @item  v+
    add new camera
    @item  vx
    cursor on/off
    @item  vb
    backfacing poly cull on/off
    @item #vl
    focal length
    @item  v~
    Software shading on/off
    @end table
@item Panels
    @table @kbd
    @item Pm
    Main
    @item Pa
    Appearance
    @item Pl
    Lighting
    @item Po
    Obscure
    @item Pt
    Tools
    @item Pc
    Cameras
    @item PC
    Commands
    @item Pf
    Files
    @item Ps
    Save
    @item P-
    read commands from tty
    @item PA
    Credits ("about")
    @end table
@item Lights
    @table @kbd
    @item ls
    show lights
    @item le
    edit lights
    @end table
@item Space
    @table @kbd
    @item me
    Euclidean
    @item mh
    Hyperbolic
    @item ms
    Spherical
    @end table
@item Model
    @table @kbd
    @item mv
    Virtual
    @item mp
    Projective
    @item mc
    Conformal
    @end table
@item Other
    @table @kbd
    @item 0N
    normalizaton: none
    @item 1N
    normalization: each
    @item 2N all
    normalization: all
    @item ui
    motion: Inertia
    @item uc
    motion: Constrain to axis
    @item uo
    motion: object's Own coordinates
    @item <
    @item Pf
    load geometry/command file
    @item dd
    delete target object
    @item >
    @item Ps
    save state to file
    @item TV
    NTSC mode toggle
    @item p
    pick as target object (e.g. @kbd{g 3 p})
    With no prefix, selects the object under the
    mouse cursor (like double-clicking the right mouse)
    @end table
@end table

@comment ****************************************************************
@node OOGL File Formats,Conventions,Keyboard Shortcuts,Top
@chapter OOGL File Formats

The objects that you can load into Geomview are called OOGL objects.
OOGL stands for ``Object Oriented Graphics Library''; it is the library
upon which Geomview is built.

There are many different kinds of OOGL objects.  This chapter gives
syntactic descriptions of file formats for OOGL objects.

Examples of most file types live in Geomview's @file{data/geom}
directory.

@menu
* Conventions::                   Conventions.
* Object File Formats::           Object File Formats.
* Non-geometric objects::         Non-geometric objects.
@end menu

@comment ================================================================
@node Conventions,Common syntax,OOGL File Formats,OOGL File Formats
@section Conventions

@menu
* Common syntax::                  Syntax Common to All OOGL File Formats.
* File names::                     File Names.
* Vertices::                       Vertices.
* Surface normal directions::      Surface normal directions.
* Transformation matrices::        Transformation matrices.
* Binary format::                  Binary format.
* References::                     Embedded objects and external-object references.
* Appearances::                    Appearances.
@end menu

@comment ----------------------------------------------------------------
@node Common syntax,File names,Conventions,Conventions
@subsection Syntax Common to All OOGL File Formats

Most OOGL object file formats are free-format ASCII --- any amount of
white space (blanks, tabs, newlines) may appear between tokens (numbers,
key words, etc.).  Line breaks are almost always insignificant, with a
couple of exceptions as noted.  Comments begin with # and continue to
the end of the line; they're allowed anywhere a newline is.

Binary formats are also defined for several objects; @xref{Binary
format}, and the individual object descriptions.

Typical OOGL objects begin with a key word designating object type,
possibly with modifiers indicating presence of color information etc.
In some formats the key word is optional, for compatibility with file
formats defined elsewhere.  Object type is then determined by
guessing from the file suffix (if any) or from the data itself.

Key words are case sensitive.  Some have optional prefix letters
indicating presence of color or other data; in this case the order of
prefixes is significant, e.g. @code{CNMESH} is meaningful but
@code{NCMESH} is invalid.

@comment ----------------------------------------------------------------
@node File names,Vertices,Common syntax,Conventions
@subsection File Names

When OOGL objects are read from disk files, the OOGL library uses the
file suffix to guess at the file type.

If the suffix is unrecognized, or if no suffix is available (e.g. for an
object being read from a pipe, or embedded in another OOGL object), all
known types of objects are tried in turn until one accepts the data as
valid.

@comment ----------------------------------------------------------------
@node Vertices,Surface normal directions,File names,Conventions
@subsection Vertices

Several objects share a common style of representing vertices with
optional per-vertex surface-normal and color.  All vertices within an
object have the same format, specified by the header key word.

All data for a vertex is grouped together (as opposed to e.g. giving
coordinates for all vertices, then colors for all vertices, and so on).

The syntax is

@table @samp
@item @var{x}  @var{y}  @var{z}
(3-D floating-point vertex coordinates) or
@item @var{x}  @var{y}  @var{z}  @var{w}
(4-D floating-point vertex coordinates)
@end table

optionally followed by

@table @samp
@item @var{nx}  @var{ny}  @var{nz}
(normalized 3-D surface-normal if present)
@end table

optionally followed by

@table @samp
@item @var{r}  @var{g}  @var{b}  @var{a}
(4-component floating-point color if present, each component in range
0..1.  The @var{a} (alpha) component represents opacity: 0 transparent, 1
opaque.)

optionally followed by
@item @var{s} @var{t}
@item or
@item @var{s} @var{t} @var{u}
@end table

(two or three texture-coordinate values).

Values are separated by white space, and line breaks
are immaterial.

Letters in the object's header key word must appear in a specific order;
that's the reverse of the order in which the data is given for each vertex.
So a @samp{CN4OFF} object's vertices contain first the 4-component space
position, then the 3-component normal, finally the 4-component color.
You can't change the data order by changing the header key word; an
@samp{NCOFF} is just not recognized.

@comment ----------------------------------------------------------------
@node Surface normal directions,Transformation matrices,Vertices,Conventions
@subsection Surface normal directions

Geomview uses normal vectors to determine how an object is shaded.
The direction of the normal is significant in this calculation.

When normals are supplied with an object, the direction of the normal
is determined by the data given.

When normals are not supplied with the object, Geomview computes normal
vectors automatically; in this case normals point toward the side from
which the vertices appear in counterclockwise order.

On parametric surfaces (Bezier patches), the normal at point P(u,v)
is in the direction dP/du cross dP/dv.

@comment ----------------------------------------------------------------
@node Transformation matrices,Binary format,Surface normal directions,Conventions
@subsection Transformation matrices

Some objects incorporate 4x4 real matrices for homogeneous object
transformations.  These matrices act by multiplication on the right of
vectors.  Thus, if p is a 4-element row vector representing homogeneous
coordinates of a point in the OOGL object, and A is the 4x4 matrix, then
the transformed point is p' = p A.  This matrix convention is common in
computer graphics; it's the transpose of that often used in mathematics,
where points are column vectors multiplied on the right of matrices.


Thus for Euclidean transformations, the translation components appear in
the fourth row (last four elements) of A.  A's last column (4th, 8th,
12th and 16th elements) are typically 0, 0, 0, and 1 respectively.

@comment ----------------------------------------------------------------
@node Binary format,References,Transformation matrices,Conventions
@subsection Binary format

Many OOGL objects accept binary as well as ASCII file formats.
These files begin with the usual ASCII token (e.g. @code{CQUAD})
followed by the word @code{BINARY}.
Binary data begins at the byte following the first newline after
@code{BINARY}.  White space and a single comment may intervene, e.g.

@example
OFF BINARY	# binary-format "OFF" data follows 
@end example

Binary data comprise 32-bit integers and 32-bit IEEE-format floats, both
in big-endian format (i.e., with most significant byte first).  This is
the native format for 'int's and 'float's on Sun-3's, Sun-4's, and
Irises, among others.

Binary data formats resemble the corresponding ASCII formats, with ints
and floats in just the places you'd expect.  There are some exceptions
though, specifically in the @code{QUAD}, @code{OFF} and @code{COMMENT}
file formats.  Details are given in the individual file format
descriptions.  @xref{QUAD}, @xref{OFF}, and @xref{COMMENT}.

Binary OOGL objects may be freely mixed in ASCII object streams:

@example
LIST
@{ = MESH BINARY
@dots{} binary data for mesh here @dots{}
@}
@{ = QUAD
	1 0 0   0 0 1   0 1 0  0 1 0
@}
@end example

Note that ASCII data resumes immediately following the last byte of
binary data.

Naturally, it's impossible to embed comments inside a binary-format OOGL
object, though comments may appear in the header before the beginning of
binary data.

@comment ----------------------------------------------------------------
@node References,Appearances,Binary format,Conventions
@subsection Embedded objects and external-object references

Some object types (@code{LIST}, @code{INST}) allow references to other
OOGL objects, which may appear literally in the data stream, be loaded
from named disk files, or be communicated from elsewhere via named
objects.  Gcl commands also accept geometry in these forms.

The general syntax is

@example
 <oogl-object>  ::=
	[ "@{" ]
	    [ "define" @code{symbolname} ]
	    [ "appearance" @code{appearance} ]
	    [ ["="] @code{object-keyword} @dots{}
		 | "<" @code{filename}
		 | ":" @code{symbolname} ]
	[ "@}" ]
@end example

where "quoted" items are literal strings (which appear without the
quotes), [bracketed] items are optional, and | denotes alternatives.
Curly braces, when present, must match; the outermost set of curly
braces is generally required when the object is in a larger context,
e.g. when it is part of a larger object or embedded in a Geomview
command stream.

For example, each of the following three lines:
@example
	@{ define fred   QUAD 1 0 0  0 0 1  0 1 0  1 0 0 @}

	@{ appearance @{ +edge @} LIST @{ < "file1" @} @{ : fred @} @}

	VECT 1 2 0   2 0   0 0 0   1 1 2
@end example
@noindent
is a valid OOGL object.  The last example is only valid when it is
delimited unambiguously by residing in its own disk file.

The "<" construct causes a disk file to be read.  Note that this isn't a
general textual "include" mechanism; a complete OOGL object must appear
in the referenced file.

Files read using "<" are sought first in the directory of the file which
referred to them, if any; failing that, the normal search path (set by
Geomview's @code{load-path} command) is used.  The default search looks
first in the current directory, then in the Geomview data directories.

The ":" construct allows references to symbols, created with
@code{define}.  A symbol's initial value is a null object.  When a
symbol is (re)defined, all references to it are automatically changed;
this is a crucial part of the support for interprocess communication.
Some future version of the documentation should explain this better@dots{}

Again, white space and line breaks are insignificant, and "#" comments
may appear anywhere.


@comment ----------------------------------------------------------------
@node Appearances,Texture Mapping,References,Conventions
@subsection Appearances

Geometric objects can have associated "appearance" information,
specifying shading, lighting, color, wireframe vs. shaded-surface
display, and so on.  Appearances are inherited through object
hierarchies, e.g. attaching an appearance to a @code{LIST} means that the
appearance is applied to all the @code{LIST}'s members.

Some appearance-related properties are relegated to "material" and
"lighting" substructures.  Take care to note which properties belong to
which structure.

Here's an example appearance structure including values for all
attributes.  Order of attributes is unimportant.  As usual, white space
is irrelevant.  Boolean attributes may be preceded by "+" or "-" to turn
them on or off; "+" is assumed if only the attribute name appears.
Other attributes expect values.

A "*" prefix on any attribute, e.g. "*+edge" or "*linewidth 2"
or "material { *diffuse 1 1 .25 }", selects "override" status for
that attribute.

@example
appearance @{
  +face               # (Do) draw faces of polygons.  On by default.
  -edge               # (Don't) draw edges of polygons
  +vect               # (Do) draw VECTs.  On by default.
  -transparent        # (Disable) transparency. enabling transparency 
                      # does NOT result in a correct Geomview picture, 
                      # but alpha values are used in RenderMan snapshots.
  -normal             # (Do) draw surface-normal vectors
  normscale 1         # @dots{} with length 1.0 in object coordinates

  +evert              # do evert polygon normals where needed so as
                      #   to always face the camera

  -texturing          # (Disable) texture mapping
  -backcull           # (Don't) discard clockwise-oriented faces
  -concave            # (Don't) expect and handle concave polygons
  -shadelines	      # (Don't) shade lines as if they were lighted cylinders
		      # These four are only effective where the graphics system
		      # supports them, namely on GL and Open GL.

  -keepcolor	      # Normally, when N-D positional coloring is enabled as
		      # with geomview's (ND-color ...) command, all
		      # objects' colors are affected.  But, objects with the
		      # "+keepcolor" attribute are immune to N-D coloring.

  shading smooth      # or ``shading constant'' or ``shading flat'' or
                      # or ``shading csmooth''.
                      # smooth = Gouraud shading, flat = faceted,
                      # csmooth = smoothly interpolated but unlighted.

  linewidth 1         # lines, points, and edges are 1 pixel wide.

  patchdice 10 10     # subdivide Bezier patches this finely in u and v

  material @{         # Here's a material definition;
                      # it could also be read from a file as in
                      #  ``material < file.mat''

      ka  1.0         # ambient reflection coefficient.
      ambient .3 .5 .3 # ambient color (red, green, blue components)
                      # The ambient contribution to the shading is
                      # the product of ka, the ambient color,
                      # and the color of the ambient light.

      kd  0.8         # diffuse-reflection coefficient.
      diffuse .9 1 .4 # diffuse color.
                        # (In ``shading constant'' mode, the surface
                        # is colored with the diffuse color.)

      ks 1.0          # specular reflection coefficient.
      specular 1 1 1  # specular (highlight) color.
      shininess  25   # specular exponent; larger values give
                      # sharper highlights.

      backdiffuse .7 .5 0 # back-face color for two-sided surfaces
                        # If defined, this field determines the diffuse
                        # color for the back side of a surface.
                        # It's implemented by the software shader, and
                        # by hardware shading on GL systems which support
                        # two-sided lighting, and under Open GL.

      alpha   1.0     # opacity; 0 = transparent (invisible), 1 = opaque.
                      # Ignored when transparency is disabled.

      edgecolor   1 1 0  # line & edge color

      normalcolor 0 0 0  # color for surface-normal vectors
  @}

  lighting @{         # Lighting model

      ambient  .3 .3 .3  # ambient light

      replacelights   # ``Use only the following lights to
                      # illuminate the objects under this
                      # appearance.''
                      # Without "replacelights", any lights listed
                      # are added to those already in the scene.

                      # Now a collection of sample lights:
      light @{ 
          color  1 .7 .6      # light color
          position  1 0 .5 0  # light position [distant light]
                              # given in homogeneous coordinates.
                              # With fourth component = 0,
                              # this means a light coming from
                              # direction (1,0,.5).
      @}

      light @{                        # Another light.
          color 1 1 1
          position  0 0 .5 1  # light at finite position @dots{}
          location camera     # specified in camera coordinates.
                              # (Since the camera looks toward -Z,
                              # this example places the light
                              # .5 unit behind the eye.)
          # Possible "location" keywords:
          #  global    light position is in world (well, universe) coordinates
          #             This is the default if no location specified.
          #  camera   position is in the camera's coordinate system
          #  local    position is in the coordinate system where
          #                   the appearance was defined
      @}
  @}                   # end lighting model
  texture @{
        clamp st               # or ``s'' or ``t'' or ``none''
        file lump.tiff         # file supplying texture-map image
        alphafile mask.pgm.Z   # file supplying transparency-mask image
        apply blend            # or ``modulate'' or ``decal''
        transform  1 0 0 0     # surface (s,t,0,1) * tfm -> texture coords
                   0 1 0 0
                   0 0 1 0
                  .5 0 0 1

        background 1 0 0 1     # relevant for ``apply blend''
  @}
@}                     # end appearance
@end example


There are rules for inheritance of appearance attributes when several
are imposed at different levels in the hierarchy.

For example, Geomview installs a backstop appearance which provides
default values for most parameters; its control panels install other
appearances which supply new values for a few attributes; user-supplied
geometry may also contain appearances.

The general rule is that the child's appearance (the one closest to the
geometric primitives) wins.
Further, appearance controls with "override" status
(e.g. *+face or material @{ *diffuse 1 1 0 @})
win over those without it.

Geomview's appearance controls use the "override" feature so as to be
effective even if user-supplied objects contain their own appearance settings.
However, if a user-supplied object contains an appearance field with
override status set, that property will be immune to Geomview's controls.

@comment ----------------------------------------------------------------
@node Texture Mapping,Object File Formats,Appearances,Conventions
@subsection Texture Mapping

Some platforms support texture-mapped objects.
(On those which don't, attempts to use texture mapping are silently
ignored.)  A texture is specified as part of an appearance structure,
as in @xref{Appearances}.  Briefly, one provides a texture image,
which is considered to lie in a square in @code{(s,t)} parameter space in
the range 0 <= s <= 1, 0 <= t <= 1.  Then one provides a geometric primitive,
with each vertex tagged with @code{(s,t)} texture coordinates.  If texturing
is enabled, the appropriate portion of the texture image is pasted onto
each face of the textured object.

There is (currently) no provision for inheritance of part of a texture
structure; if the @code{texture} keyword is mentioned in an appearance,
it supplants any other texture specification.

The appearance attribute @code{texturing} controls whether textures are
used; there's no performance penalty for having texture { ... } fields
defined when texturing is off.

The available fields are:

@example
clamp	none  -or-  s  -or-  t  -or-  st
  Determines the meaning of texture coordinates outside the range 0..1.
  With @code{clamp none}, the default, coordinates are interpreted
  modulo 1, so (s,t) = (1.25,0), (.25,0), and (-.75,0) all refer to
  the same point in texture space.  With @code{s} or @code{t} or
  @code{st}, either or both of s- or t-coordinates less than 0 or
  greater than 1 are clamped to 1 or 0, respectively.

file	filename
alphafile	filename
  Specifies image file(s) containing the texture.
  The @code{file} file's image specifies color or lightness information;
  the @code{alphafile} if present, specifies a transparency ("alpha") mask;
  where the mask is zero, pixels are simply not drawn.
  Several image file formats are available; the file type must be
  indicated by the last few characters of the file name:
    .ppm or .ppm.Z or .ppm.gz  24-bit 3-color image in PPM format
    .pgm or .pgm.Z or .pgm.gz  8-bit grayscale image in PGM format
    .sgi or .sgi.Z or .sgi.gz  8-bit, 24-bit, or 32-bit SGI image
    .tiff 		       8-bit or 24-bit TIFF image
    .gif		       GIF image
  (Though 4-channel TIFF images are possible, and could
  represent both color and transparency information in one image,
  that's not supported in geomview at present.)
  For this feature to work, some programs must be available in
  geomview's search path:
    zcat  for .Z files
    gzip  for .gz files
    tifftopnm for .tiff files
    giftoppm for .gif files

  If an @code{alphafile} image is supplied, it must be the same size
  as the @code{file} image.


apply	modulate  -or-  blend  -or-  decal
  Indicates how the texture image is applied to the surface.
  Here the "surface color" means the color that surface would have
  in the absence of texture mapping.

  With @code{modulate}, the default, the texture color (or lightness,
  if textured by a gray-scale image) is multiplied by the surface color.

  With @code{blend}, texture blends between the @code{background} color
  and the surface color.  The @code{file} parameter must specify a
  gray-scale image.  Where the texture image is 0, the surface color is
  unaffected; where it's 1, the surface is painted in the color given
  by @code{background}; and color is interpolated for intermediate values.

  With @code{decal}, the @code{file} parameter must specify a
  3-color image.  If an @code{alphafile} parameter is present,
  its value interpolates between the surface color (where alpha=0)
  and the texture color (where alpha=1).  Lighting does not affect the
  texture color in @code{decal} mode; effectively the texture is
  constant-shaded.

background  R G B A
  Specifies a 4-component color, with R, G, B, and A floating-point
  numbers normally in the range 0..1, used when @code{apply blend}
  is selected.

transform @code{transformation-matrix}
  Expects a list of 16 numbers, or one of the other ways of representing
  a transformation (@code{: handlename} or @code{< filename}).
  The 4x4 transformation matrix is applied to texture coordinates,
  in the sense of a 4-component row vector (s,t,0,1) multiplied on
  the left of the matrix, to produce new coordinates (s',t')
  which actually index the texture.
@end example

@comment ================================================================
@node Object File Formats,QUAD,Texture Mapping,OOGL File Formats
@section Object File Formats

@menu
* QUAD::		List of quadrilaterals.
* MESH::		Rectangularly-connected mesh.
* BBP and BEZ::		List of Bezier surface patches.
* OFF::			Polyhedra: polygons with shared vertices.
* VECT::		List of points and lines.
* SKEL::		List of points and lines, with shared vertices.
* SPHERE::		Sphere
* INST::		Transformed Instance of another object.
* LIST::		List of other objects.
* TLIST::		Collection of 4x4 transformation matrices.
* GROUP::		Obsolete format for collections of objects.
* DISCGRP::             Discrete Group objects.
* COMMENT::		Comment object, for caching information.
@end menu


@comment ----------------------------------------------------------------
@node QUAD,MESH,Object File Formats,Object File Formats
@subsection QUAD: collection of quadrilaterals

The conventional suffix for a @code{QUAD} file is @file{.quad}.

The file syntax is

@example
   [C][N][4]QUAD  -or-  [C][N][4]POLY		   # Key word
   @var{vertex}  @var{vertex}  @var{vertex}  @var{vertex}  # 4*N vertices for some N
   @var{vertex}  @var{vertex}  @var{vertex}  @var{vertex}
   @dots{}
@end example

The leading key word is @code{[C][N][4]QUAD} or @code{[C][N][4]POLY},
where the optional @code{C} and @code{N} prefixes indicate that each vertex
includes colors and normals respectively.  That is, these files
begin with one of the words

@code{QUAD} @code{CQUAD} @code{NQUAD} @code{CNQUAD} @code{POLY}
@code{CPOLY} @code{NPOLY} @code{CNPOLY}

(but not @code{NCQUAD} or @code{NCPOLY}).  @code{QUAD} and @code{POLY}
are synonymous; both forms are allowed just for compatibility with
ChapReyes.

Following the key word is an arbitrary number of groups of four
vertices, each group describing a quadrilateral.  See the Vertex syntax
above.  The object ends at end-of-file, or with a closebrace if
incorporated into an object reference (see above).

A @code{QUAD BINARY} file format is accepted; @xref{Binary format}.  The
first word of binary data must be a 32-bit integer giving the number of
quads in the object; following that is a series of 32-bit floats,
arranged just as in the ASCII format.

@comment ----------------------------------------------------------------
@node MESH,BBP and BEZ,QUAD,Object File Formats
@subsection MESH: rectangularly-connected mesh

The conventional suffix for a @code{MESH} file is @file{.mesh}.

The file syntax is

@example
[U][C][N][Z][4][u][v][n]MESH # Key word
[@var{Ndim}]                 # Space dimension, present only if nMESH
@var{Nu} @var{Nv}            # Mesh grid dimensions
                             # @var{Nu}*@var{Nv} vertices, in format specified
                             # by initial key word
@var{vertex}(u=0,v=0)  @var{vertex}(1,0)  @dots{} @var{vertex}(@var{Nu}-1,0)
@var{vertex}(0,1) @dots{}    @var{vertex}(@var{Nu}-1,1)
@dots{}
@var{vertex}(0,@var{Nv}-1) @dots{} @var{vertex}(@var{Nu}-1,@var{Nv}-1)
@end example

The key word is  @code{[U][C][N][Z][4][u][v][n]MESH}.
The optional prefix characters mean:

@table @samp
@item U
Each vertex includes a 3-component texture space parameter.
The first two components are the usual @code{S} and @code{T} texture
parameters for that vertex; the third should be specified as zero.
@item C
Each vertex (see Vertices above) includes a 4-component color.
@item N
Each vertex includes a surface normal vector.
@item Z
Of the 3 vertex position values, only the Z component is present; X and
Y are omitted, and assumed to equal the mesh (u,v) coordinate so X
ranges from 0 .. (Nu-1), Y from 0 .. (Nv-1) where Nu and Nv are the mesh
dimensions -- see below.
@item 4
Vertices are 4D, each consists of 4 floating values.  @code{Z} and
@code{4} cannot both be present.
@item u
The mesh is wrapped in the u-direction, so the 
(0,v)'th vertex is connected to the (@var{Nu}-1,v)'th for all v.
@item v
The mesh is wrapped in the v-direction, so the (u,0)'th vertex is
connected to the (u,@var{Nv}-1)'th for all u.  Thus a u-wrapped or
v-wrapped mesh is topologically a cylinder, while a uv-wrapped mesh is a
torus.
@item n
Specifies a mesh whose vertices live in a higher dimensional space.
The dimension follows the "MESH" keyword.  Each vertex then has @var{Ndim}
components.
@end table

Note that the order of prefix characters is significant; a colored,
u-wrapped mesh is a @code{CuMESH} not a @code{uCMESH}.

Following the mesh header are integers @var{Nu} and @var{Nv},
the dimensions of the mesh.

Then follow @var{Nu}*@var{Nv} vertices, each in the form given by the header.
They appear in v-major order, i.e. if we name each vertex by (u,v)
then the vertices appear in the order

@example
(0,0) (1,0) (2,0) (3,0) @dots{}  (@var{Nu}-1,0)
(0,1) (1,1) (2,1) (3,1) @dots{}  (@var{Nu}-1,1)
@dots{}
(0,Nv-1)		@dots{}  (@var{Nu}-1,@var{Nv}-1)
@end example

A @code{MESH BINARY} format is accepted; @xref{Binary format}.  The
values of @var{Nu} and @var{Nv} are 32-bit integers; all other values
are 32-bit floats.

@comment ----------------------------------------------------------------
@node BBP and BEZ,OFF,MESH,Object File Formats
@subsection Bezier Surfaces

The conventional file suffixes for Bezier surface files are @file{.bbp}
or @file{.bez}.  A file with either suffix may contain either type of
patch.

Syntax:

@example
  [ST]BBP -or- [C]BEZ<@var{Nu}><@var{Nv}><@var{Nd}>[_ST]
			# @var{Nu}, @var{Nv} are u- and v-direction 
			# polynomial degrees in range 1..6
			# @var{Nd} = dimension: 3->3-D, 4->4-D (rational)
			# (The '<' and '>' do not appear in the input.)
			# @var{Nu},@var{Nv},@var{Nd} are each a single decimal digit.
			# BBP form implies @var{Nu}=@var{Nv}=@var{Nd}=3 so BBP = BEZ333.

		# Any number of patches follow the header
			# (@var{Nu}+1)*(@var{Nv}+1) patch control points
			# each 3 or 4 floats according to header
  @var{vertex}(u=0,v=0)  @var{vertex}(1,0) @dots{} @var{vertex}(@var{Nu},0)
  @var{vertex}(0,1)			   @dots{} @var{vertex}(@var{Nu},1)
  @dots{}
  @var{vertex}(0,@var{Nv})		   @dots{} @var{vertex}(@var{Nu},@var{Nv})

			# ST texture coordinates if mentioned in header
  @code{S}(u=0,v=0)	@code{T}(0,0)	@code{S}(0,@var{Nv}) @code{T}(0,@var{Nv})
  @code{S}(@var{Nu},0)	@code{T}(@var{Nu},0)	@code{S}(@var{Nu},@var{Nv}) @code{T}(@var{Nu},@var{Nv})

			# 4-component float (0..1) R G B A colors
			# for each patch corner if mentioned in header
  @code{RGBA}(0,0)   @code{RGBA}(0,@var{Nv})
  @code{RGBA}(@var{Nu},0)  @code{RGBA}(@var{Nu},@var{Nv})
@end example

These formats represent collections of Bezier surface patches, of
degrees up to 6, and with 3-D or 4-D (rational) vertices.

The header keyword has the forms @code{[ST]BBP} or
@code{[C]BEZ<@var{Nu}><@var{Nv}><@var{Nd}>[_ST]} (the '<' and '>' are
not part of the keyword.

The @code{ST} prefix on @code{BBP}, or @code{_ST} suffix on
@code{BEZuvn}, indicates that each patch includes four pairs of
floating-point texture-space coordinates, one for each corner of the
patch.

The @code{C} prefix on @code{BEZuvn} indicates a colored patch,
including four sets of four-component floating-point colors (red, green,
blue, and alpha) in the range 0..1, one color for each corner.

@var{Nu} and @var{Nv}, each a single digit in the range 1..6, are the
patch's polynomial degree in the u and v direction respectively. 

@var{Nd} is the number of components in each patch vertex, and must be
either @code{3} for 3-D or @code{4} for homogeneous coordinates, that
is, rational patches.

@code{BBP} patches are bicubic patches with 3-D vertices, so @code{BBP}
= @code{BEZ333} and @code{STBBP} = @code{BEZ333_ST}.

Any number of patches follow the header.  Each patch comprises a series
of patch vertices, followed by optional (s,t) texture coordinates,
followed by optional (r,g,b,a) colors.

Each patch has (@var{Nu}+1)*(@var{Nv}+1) vertices in v-major order, so that if we
designate a vertex by its control point indices (u,v) the order is
@example
     (0,0) (1,0) (2,0) @dots{}  (@var{Nu},0)
     (0,1) (1,1) (2,1) @dots{}  (@var{Nu},1)
     @dots{}
     (0,@var{Nv})            @dots{}  (@var{Nu},@var{Nv})
@end example
@noindent
with each vertex containing either 3 or 4 floating-point numbers
as specified by the header.
   
If the header calls for ST coordinates, four pairs of floating-point
numbers follow: the texture-space coordinates for the (0,0),
(@var{Nu},0), (0,@var{Nv}), and (@var{Nu},@var{Nv}) corners of the
patch, respectively.

If the header calls for colors, four four-component (red, green, blue,
alpha) floating-point colors follow, one for each patch corner.

The series of patches ends at end-of-file, or with a closebrace if
incorporated in an object reference.

@comment ----------------------------------------------------------------
@node OFF,VECT,BBP and BEZ,Object File Formats
@subsection OFF Files

The conventional suffix for @code{OFF} files is @file{.off}.

Syntax:

@example
[ST][C][N][4][n]OFF	# Header keyword
[@var{Ndim}]		# Space dimension of vertices, present only if nOFF
@var{NVertices}  @var{NFaces}  @var{NEdges}   # NEdges not used or checked

@var{x}[0]  @var{y}[0]  @var{z}[0]	# Vertices, possibly with normals,
			# colors, and/or texture coordinates, in that order,
			# if the prefixes @code{N}, @code{C}, @code{ST}
			# are present.
			# If 4OFF, each vertex has 4 components,
			# including a final homogeneous component.
			# If nOFF, each vertex has @var{Ndim} components.
			# If 4nOFF, each vertex has @var{Ndim}+1 components.
@dots{}
@var{x}[@var{NVertices}-1]  @var{y}[@var{NVertices}-1]  @var{z}[@var{NVertices}-1]

    			# Faces
    			# @var{Nv} = # vertices on this face
    			# @var{v}[0] @dots{} @var{v}[@var{Nv}-1]: vertex indices
    			#		in range 0..@var{NVertices}-1
@var{Nv}  @var{v}[0] @var{v}[1] @dots{} @var{v}[@var{Nv}-1]  @var{colorspec}
@dots{}
    			# @var{colorspec} continues past @var{v}[@var{Nv}-1]
    			# to end-of-line; may be 0 to 4 numbers
    			# nothing: default
    			# integer: colormap index
    			# 3 or 4 integers: RGB[A] values 0..255
			# 3 or 4 floats: RGB[A] values 0..1
@end example

@code{OFF} files (name for "object file format") represent collections
of planar polygons with possibly shared vertices, a convenient way to
describe polyhedra.  The polygons may be concave but there's no
provision for polygons containing holes.

An @code{OFF} file may begin with the keyword @code{OFF}; it's
recommended but optional, as many existing files lack this keyword.

Three ASCII integers follow: @var{NVertices}, @var{NFaces}, and
@var{NEdges}.  Thse are the number of vertices, faces, and edges,
respectively.  Current software does not use nor check @var{NEdges}; it
needn't be correct but must be present.

The vertex coordinates follow: dimension * @var{Nvertices}
floating-point values.  They're implicitly numbered 0 through
@var{NVertices}-1.  dimension is either 3 (default) or 4 (specified by
the key character @code{4} directly before @code{OFF} in the keyword).

Following these are the face descriptions, typically written
with one line per face.  Each has the form
@example
@var{N}  @var{Vert1} @var{Vert2} @dots{} @var{VertN}  [@var{color}]
@end example
@noindent
Here @var{N} is the number of vertices on this face,
and @var{Vert1} through @var{VertN} are indices into the list of
vertices (in the range 0..@var{NVertices}-1).

The optional @var{color} may take several forms.  Line breaks are
significant here: the @var{color} description begins after @var{VertN}
and ends with the end of the line (or the next # comment).  A
@var{color} may be:

@table @asis
@item nothing
the default color
@item one integer
index into "the" colormap; see below
@item three or four integers
RGB and possibly alpha values in the range 0..255
@item three or four floating-point numbers
RGB and possibly alpha values in the range 0..1
@end table

For the one-integer case, the colormap is currently read from the file
@file{cmap.fmap} in Geomview's @file{data} directory.  Some better
mechanism for supplying a colormap is likely someday.

The meaning of "default color" varies.  If no face of the object has a
color, all inherit the environment's default material color.  If some
but not all faces have colors, the default is gray (R,G,B,A=.666).

A @code{[ST][C][N][n]OFF BINARY} format is accepted; @xref{Binary format}.  It
resembles the ASCII format in almost the way you'd expect, with 32-bit
integers for all counters and vertex indices and 32-bit floats for
vertex positions (and texture coordinates or vertex colors or normals if
@code{COFF}/@code{NOFF}/@code{CNOFF}/@code{STCNOFF}/etc. format).

Exception: each face's vertex indices are followed by an integer
indicating how many color components accompany it.  Face color
components must be floats, not integer values.  Thus a colorless
triangular face might be represented as

@example
int int int int int
3   17   5   9   0
@end example

while the same face colored red might be

@example
int int int int int float float float float
 3  17   5   9   4   1.0   0.0   0.0   1.0
@end example


@comment ----------------------------------------------------------------
@node VECT,SKEL,OFF,Object File Formats
@subsection VECT Files

The conventional suffix for @code{VECT} files is @file{.vect}.

Syntax:

@example
[4]VECT
@var{NPolylines}  @var{NVertices}  @var{NColors}

@var{Nv[0]} @dots{} @var{Nv[NPolylines-1]}     # number of vertices
                                           # in each polyline

@var{Nc[0]} @dots{} @var{Nc[NPolylines-1]}     # number of colors supplied
                                           # in each polyline

@var{Vert[0]} @dots{} @var{Vert[NVertices-1]}  # All the vertices
                                           # (3*NVertices floats)

@var{Color[0]} @dots{} @var{Color[NColors-1]}  # All the colors
                                           # (4*NColors floats, RGBA)
@end example

@code{VECT} objects represent lists of polylines (strings of connected
line segments, possibly closed).  A degenerate polyline can be used to
represent a point.

A @code{VECT} file begins with the key word @code{VECT} or @code{4VECT}
and three integers: @var{NLines}, @var{NVertices}, and @var{NColors}.
Here @var{NLines} is the number of polylines in the file,
@var{NVertices} the total number of vertices, and @var{NColors} the
number of colors as explained below.

Next come @var{NLines} integers

@center @var{Nv[0]} @var{Nv[1]} @var{Nv[2]} @dots{} @var{Nv[NLines-1]}

giving the number of vertices in each polyline.  A negative number
indicates a closed polyline; 1 denotes a single-pixel point.  The sum
(of absolute values) of the @var{Nv[i]} must equal @var{NVertices}.

Next come @var{NLines} more integers Nc[i]: the number of colors in
each polyline.  Normally one of three values:

@table @asis
@item 0
No color is specified for this polyline.  It's drawn in the same color
as the previous polyline.
@item 1
A single color is specified.  The entire polyline is drawn in that
color.
@item abs(@var{Nv[i]})
Each vertex has a color.  Either each segment is drawn in the
corresponding color, or the colors are smoothly interpolated along the
line segments, depending on the implementation.
@end table

The sum of the @var{Nc[i]} must equal @var{NColors}.

Next come @var{NVertices} groups of 3 or 4 floating-point numbers: the
coordinates of all the vertices.  If the keyword is @var{4VECT} then
there are 4 values per vertex.  The first abs(@var{Nv[0]}) of them form
the first polyline, the next abs(@var{Nv[1]}) form the second and so on.

Finally @var{NColors} groups of 4 floating-point numbers give red,
green, blue and alpha (opacity) values.  The first @var{Nc[0]} of them
apply to the first polyline, and so on.

A @var{VECT BINARY} format is accepted; @xref{Binary format}.  The
binary format exactly follows the ASCII format, with 32-bit ints where
integers appear, and 32-bit floats where real values appear.



@comment ----------------------------------------------------------------
@node SKEL,SPHERE,VECT,Object File Formats
@subsection SKEL Files

@code{SKEL} files represent collections of points and polylines, with
shared vertices.
The conventional suffix for @code{SKEL} files is @file{.skel}.

Syntax:

@example
[4][n]SKEL
[@var{NDim}]                    # Vertex dimension, present only if nSKEL
@var{NVertices}  @var{NPolylines}

@var{x}[0]  @var{y}[0]  @var{z}[0]      # Vertices
				    # (if nSKEL, each vertex has NDim components)
@dots{}
@var{x}[@var{NVertices}-1]  @var{y}[@var{NVertices}-1]  @var{z}[@var{NVertices}-1]

                        # Polylines
                        # @var{Nv} = # vertices on this polyline (1 = point)
                        # @var{v}[0] @dots{} @var{v}[@var{Nv}-1]: vertex indices                        #               in range 0..@var{NVertices}-1
@var{Nv}  @var{v}[0] @var{v}[1] @dots{} @var{v}[@var{Nv}-1]  [@var{colorspec}]
@dots{}
                        # @var{colorspec} continues past @var{v}[@var{Nv}-1]
                        # to end-of-line; may be nothing, or 3 or 4 numbers.
                        # nothing: default color
			# 3 or 4 floats: RGB[A] values 0..1
@end example

The syntax resembles that of @code{OFF} files, with a table of vertices
followed by a sequence of polyline descriptions, each referring to vertices
by index in the table.  Each polyline has an optional color.

For @code{nSKEL} objects, each vertex has @var{NDim} components.
For @code{4nSKEL} objects, each vertex has @var{NDim+1} components;
the final component is the homogeneous divisor.

No @code{BINARY} format is implemented as yet for @code{SKEL} objects.

@comment ----------------------------------------------------------------
@node SPHERE,INST,SKEL,Object File Formats
@subsection SPHERE Files

The conventional suffix for @code{SPHERE} files is @file{.sph}.

@example
SPHERE
@var{Radius}
@var{Xcenter} @var{Ycenter} @var{Zcenter}
@end example

Sphere objects are drawn using rational Bezier patches, which are diced into
meshes; their smoothness, and the time taken to draw them, depends on the
setting of the dicing level, 10x10 by default.
From Geomview, the Appearance panel, the @code{<N>ad} keyboard command, or
a @code{dice nu nv} Appearance attribute sets this.

@comment ----------------------------------------------------------------
@node INST,INST Examples,SPHERE,Object File Formats
@subsection INST Files

The conventional suffix for a @code{INST} file is @file{.inst}.

There is no INST BINARY format.

An @code{INST} applies a 4x4 transformation to another OOGL object.  It
begins with @code{INST} followed by these sections which may appear in
any order:
@example
geom @var{oogl-object}
@end example
@noindent
specifies the OOGL object to be instantiated.  @xref{References}, for
the syntax of an @var{oogl-object}.  The keyword @code{unit} is a
synonym for @code{geom}.
@example
transform   ["@{"] @code{4x4 transform} ["@}"]
@end example
@noindent
specifies a single transformation matrix.  Either the
matrix may appear literally as 16 numbers, or there may be
a reference to a "transform" object, i.e.
@example
    "<" file-containing-4x4-matrix
@end example
or
@example
    ":" symbol-representing-transform-object>
@end example
Another way to specify the transformation is
@example
transforms
    @var{oogl-object}
@end example
The @var{oogl-object} must be a @code{TLIST} object (list of
transformations) object, or a @code{LIST} whose members are ultimately
@code{TLIST} objects.  In effect, the @code{transforms} keyword takes a
collection of 4x4 matrices and replicates the @code{geom} object, making
one copy for each 4x4 matrix.

If no @code{transform} nor @code{transforms} keyword appears, no
transformation is applied (actually the identity is applied).  You could
use this for, e.g., wrapping an appearance around an externally-supplied
object, though a single-membered LIST would do this more efficiently.

@xref{Transformation matrices}, for the matrix format.


Two more INST fields are accepted: @code{location} and @code{origin}.

@example
location [global or camera or ndc or screen or local]
@end example
Normally an INST specifies a position relative to its parent object;
the @code{location} field allows putting an object elsewhere.
@itemize @bullet
@item
@code{location global} attaches the object to the global (a.k.a. universe)
coordinate system -- the same as that in which geomview's World objects,
alien geometry, and cameras are placed.
@item
@code{location camera} places the object relative to the camera.
(Thus if there are multiple views, it may appear in a different 
spatial position in each view.)  The center of the camera's view
is along its negative Z axis; positive X is rightward, positive Y upward.
Normally the units of camera space are the same as global coordinates.
When a camera is reset, the global origin is at (0,0,-3.0).
@item
@code{location ndc} places the object relative to the normalized unit
cube into which the camera's projection (perspective or orthographic)
maps the visible world.  X, Y, and Z are each in the range from -1 to +1,
with Z = -1 the near and Z = +1 the far clipping plane, and X and Y
increasing rightward and upward respectively.
Thus something like
@example
INST  transform  1 0 0 0  0 1 0 0  0 0 1 0  -.9 -.9 -.999 1
      location ndc
      geom < label.vect
@end example
pastes @code{label.vect} onto the lower left corner of each window,
and in front of nearly everything else, assuming @code{label.vect}'s
contents lie in the positive quadrant of the X-Y plane.
It's tempting to use -1 rather than -.999 as the Z component of the
position, but that may put the object just nearer than the near clipping
plane and make it (partially) invisible, due to floating-point error.
@item
@code{location screen} places the object in screen coordinates.
The range of Z is still -1 through +1 as for ndc coordinates;
X and Y are measured in pixels, and range from (0,0) at the @emph{lower left}
corner of the window, increasing rightward and upward.
@end itemize

@code{location local} is the default; the object is positioned relative
to its parent.


@example
origin [global or camera or ndc or screen or local] x y z
@end example
The @code{origin} field translates the contents of the INST to
place the origin at the specified point of the given coordinate system.
Unlike @code{location}, it doesn't change the orientation, only the choice
of origin.  Both @code{location} and @code{origin} can be used together.

So for example
@example
@{ INST
  location screen
  origin ndc 0 0 -.99
  geom @{ < xyz.vect @}
  transform @{ 100 0 0 0  0 100 0 0  0 0 -.009 0   0 0 0 1 @}
@}
@end example

places xyz.vect's origin in the center of the window, just beyond the
near clipping plane.  The unit-length X and Y edges are scaled to be just 100
screen units -- pixels -- long, regardless of the size of the window.

@menu
* INST Examples::	Some example of @code{INST} Files.
@end menu

@comment ................................................................
@node INST Examples,LIST,INST,Object File Formats
@subsubsection INST Examples

Here are some examples of @code{INST} files

@example
INST
     unit < xyz.vect
     transform @{
        1 0 0 0
        0 1 0 0
        0 0 1 0
        1 3 0 1
     @}
@end example

@example
@{ appearance @{ +edge  material @{ edgecolor 1 1 0 @} @}
    INST geom < mysurface.quad @}
@end example

@example
@{INST transform @{: T@} geom @{<dodec.off@}@}
@end example

@example
@{ INST
     transforms
         @{ LIST
     	@{ < some-matrices.prj @}
     	@{ < others.prj @}
     	@{ TLIST <still more of them> @}
     	
         @}
     geom
         @{ # stuff replicated by all the above matrices
     	@dots{}
         @}
@}
@end example

This one resembles the @code{origin} example in the section above,
but makes the X and Y edges be 1/4 the size of the window (1/4, not 1/2,
since the range of ndc X and Y coordinates is -1 to +1).
@example
@{ INST
  location ndc
  geom @{ < xyz.vect @}
  transform @{ .5 0 0 0  0 .5 0 0  0 0 -.009 0   0 0 -.99 1 @}
@}
@end example
@comment ----------------------------------------------------------------
@node LIST,TLIST,INST Examples,Object File Formats
@subsection LIST Files

The conventional suffix for a @code{LIST} file is @file{.list}.

A list of OOGL objects

Syntax:

@example
LIST
    @var{oogl-object}
    @var{oogl-object}
    @dots{}
@end example

Note that there's no explicit separation between the oogl-objects, so
they should be enclosed in curly braces (@{ @}) for sanity.  Likewise
there's no explicit marker for the end of the list; unless appearing
alone in a disk file, the whole construct should also be wrapped in
braces, as in:

@example
   @{ LIST @{ QUAD @dots{} @} @{ < xyz.quad @} @}
@end example

A @code{LIST} with no elements, i.e. @code{@{ LIST @}}, is valid, and is
the easiest way to create an empty object.  For example, to remove a
symbol's definition you might write

@example
   @{ define somesymbol  @{ LIST @} @}
@end example


@comment ----------------------------------------------------------------
@node TLIST,GROUP,LIST,Object File Formats
@subsection TLIST Files


The conventional suffix for a @code{TLIST} file is @file{.grp} ("group")
or or @file{.prj} ("projective" matrices).

Collection of 4x4 matrices, used in the @code{transforms} section of and
@code{INST} object.

Syntax:

@example
TLIST			# key word

<4x4 matrix (16 floats)>
@dots{}				# Any number of 4x4 matrices
@end example

@code{TLIST}s are used only within the @code{transforms} clause of an
@code{INST} object.  They cause the @code{INST}s @code{geom} object to
be instantiated once under each of the transforms in the @code{TLIST}.
The effect is like that of a @code{LIST} of @code{INST}s each with a
single transform, and all referring to the same object, but is more
efficient.

Be aware that a @code{TLIST} is a kind of geometry object, distinct from a 
@code{transform} object.  Some contexts expect one type of object,
some the other.  For example in
@example
INST transform @{ : @var{myT} @} geom @{ @dots{} @}
@end example
@noindent
@var{myT} must be a transform object, which might have been
created with the gcl
@example
(read transform @{ define myT 1 0 0 1 @dots{} @})
@end example
@noindent
while in
@example
    INST transforms @{ : @var{myTs} @} geom @{ @dots{} @}
or  INST transforms @{ LIST @{: @var{myTs}@} @{< more.prj@} @} geom @{ @dots{} @}
@end example
@noindent
@var{myTs} must be a geometry object, defined e.g. with
@example
    (read geometry @{ define @var{myTs} @{ TLIST 1 0 0 1 @dots{} @} @})
@end example

A @code{TLIST BINARY} format is accepted.  Binary data begins with a
32-bit integer giving the number of transformations, followed by that
number of 4x4 matrices in 32-bit floating-point format.  The order of
matrix elements is the same as in the ASCII format.


@comment ----------------------------------------------------------------
@node GROUP,DISCGRP,TLIST,Object File Formats
@subsection GROUP Files

This format is obsolete, but is still accepted.  It combined the
functions of @code{INST} and @code{TLIST}, taking a series of
transformations and a single Geom (@code{unit}) object, and replicating
the object under each transformation.

@example
GROUP @dots{} < matrices > @dots{} unit @{ @var{oogl-object} @}
@end example

is still accepted and effectively translated into

@example
INST
	transforms @{ TLIST @dots{} <matrices> @dots{} @}
	unit @{ @var{oogl-object} @}
@end example

@comment ----------------------------------------------------------------
@node DISCGRP,COMMENT,GROUP,Object File Formats
@subsection DISCGRP Files

This format is for discrete groups, such as appear in the theory of
manifolds or in symmetry patterns.  This format has its own man page.
See discgrp(5).

@comment ----------------------------------------------------------------
@node COMMENT,Non-geometric objects,DISCGRP,Object File Formats
@subsection COMMENT Objects

The COMMENT object is a mechanism for encoding arbitrary data within an
OOGL object. It can be used to keep track of data or pass data back and
forth between external modules. 

Syntax:

@example
COMMENT                 # key word
			
@var{name} @var{type}   # individual name and type specifier
{ @dots{} }             # arbitrary data
@end example

The data, which must be enclosed by curly braces, can include anything
except unbalanced curly braces.  The @var{type} field can be used to
identify data of interest to a particular program through naming
conventions. 

@code{COMMENT} objects are intended to be associated with other objects
through inclusion in a @code{LIST} object. (@xref{LIST}.)  The "#" OOGL
comment syntax does not suffice for data exchange since these comments
are stripped when an OOGL object is read in to Geomview.  The
@code{COMMENT} object is preserved when loaded into Geomview and is
written out intact.

Here is an example associating a WorldWide Web URL with a piece of
geometry:

@example
{ LIST 
 { < Tetrahedron} 
 {COMMENT GCHomepage HREF { http://www.geom.umn.edu/ }}
}
@end example

A binary @code{COMMENT} format is accepted. Its format is not consistent
with the other OOGL binary formats. @xref{Binary format}. The
@code{name} and @code{type} are followed by

@example
@var{N} @var{Byte1} @var{Byte2} @dots{} @var{ByteN}
@end example
 
instead of data enclosed in curly braces. 

@comment ================================================================
@node Non-geometric objects,transform,COMMENT,OOGL File Formats
@section Non-geometric objects


The syntax of these objects is given in the form used in
@xref{References}, where "quoted" items should appear literally but
without quotes, square bracketed ([ ]) items are optional, and | separates
alternative choices.

@menu
* transform::	Transformation matrices.
* camera::	Cameras.
* window::	Windows.
@end menu

@comment ----------------------------------------------------------------
@node transform,camera,Non-geometric objects,Non-geometric objects
@subsection Transform Objects

Where a single 4x4 matrix is expected -- as in the
@code{INST} @code{transform} field, the camera's @code{camtoworld} transform
and the Geomview @code{xform*} commands -- use a transform object.

Note that a transform is distinct from a @code{TLIST}, which is a type
of geometry.  @code{TLIST}s can contain one or more 4x4 transformations;
"transform" objects must have exactly one.

Why have both?  In many places -- e.g. camera positioning -- it's only
meaningful to have a single transform.  Using a separate object type
enforces this.

Syntax for a transform object is

@example
<transform> ::= 
  [ "@{" ]             (curly brace, generally needed to make
                       the end of the object unambiguous.)

   [ "transform" ]    (optional keyword; unnecessary if the type
                       is determined by the context, which it
                       usually is.)
   [ "define" <name> ]
                      (defines a transform named <name>, setting
                       its value from the stuff which follows)

      <sixteen floating-point numbers>
                      (interpreted as a 4x4 homogeneous transform
		       given row by row, intended to apply to a
                       row vector multiplied on its LEFT, so that e.g.
                       Euclidean translations appear in the bottom row)
   | 
      "<" <filename>  (meaning: read transform from that file)
   |
      ":" <name>      (meaning: use variable <name>,
                        defined elsewhere; if undefined the initial
                        value is the identity transform)

 [ "@}" ]              (matching curly brace)
@end example

The whole should be enclosed in @{ braces @}.  Braces are not essential
if exactly one of the above items is present, so e.g. a 4x4 array of
floats standing alone may but needn't have braces.

Some examples, in contexts where they might be used:

@example
# Example 1: A gcl command to define a transform
# called "fred"

(read transform @{ transform  define fred
         1 0 0 0
         0 1 0 0
         0 0 1 0
        -3 0 1 1
    @}
)
@end example

@example
# Example 2:  A camera object using transform
# "fred" for camera positioning
# Given the definition above, this puts the camera at
# (-3, 0, 1), looking toward -Z.

@{ camera
        halfyfield 1
        aspect 1.33
        camtoworld @{ : fred @}
@}
@end example

@comment ----------------------------------------------------------------
@node camera,window,transform,Non-geometric objects
@subsection cameras

A camera object specifies the following properties of a camera:

@table @asis
@item position and orientation
specified by either a camera-to-world or world-to-camera transformation;
this transformation does not include the projection, so it's typically
just a combination of translation and rotation.  Specified as a
transform object, typically a 4x4 matrix.
@item "focus" distance
Intended to suggest a typical distance from the camera to the object of
interest; used for default camera positioning (the camera is placed at
(X,Y,Z) = (0,0,focus) when reset) and for adjusting field-of-view when
switching between perspective and orthographic views.
@item window aspect ratio
True aspect ratio in the sense <Xsize>/<Ysize>.  This normally should
agree with the aspect ratio of the camera's window.  Geomview normally
adjusts the aspect ratio of its cameras to match their associated
windows.
@item near and far clipping plane distances
Note that both must be strictly greater than zero.  Very large
<far>/<near> distance ratios cause Z-buffering to behave badly; part of
an object may be visible even if somewhat more distant than another.
@item field of view
Specified in either of two forms.
@table @samp
  @item fov 
is the field of view -- in degrees if perspective, or linear
distance if orthographic -- in the @emph{shorter} direction.
  @item halfyfield 
is half the projected Y-axis field, in world coordinates (not angle!),
at unit distance from the camera.  For a perspective camera, halfyfield
is related to angular field:

@center halfyfield = tan( Y_axis_angular_field / 2 )

while for an orthographic one it's simply:

@center halfyfield = Y_axis_linear_field / 2

@end table

This odd-seeming definition is (a) easy to calculate with and
(b) well-defined in both orthographic and perspective views.
@end table


The syntax for a camera is:

@example
<camera> ::=

   [ "camera" ]			(optional keyword)
    [ "@{" ]			(opening brace, generally required)
	[ "define" <name> ]

	"<" <filename>
      |
	":" <name>
      |
				(or any number of the following,
				 in any order@dots{})

	"perspective"  @{"0" | "1"@}		(default 1)
					(otherwise orthographic)

	"stereo"       @{"0" | "1"@}		(default 0)
					(otherwise mono)

	"worldtocam" <transform>	(see transform syntax above)

	"camtoworld" <transform>
				(no point in specifying both
				 camtoworld and worldtocam; one is
				 constrained to be the inverse of						 the other)

	"halfyfield" <half-linear-Y-field-at-unit-distance>
				(default tan 40/2 degrees)

	"fov"		(angular field-of-view if perspective,
			 linear field-of-view otherwise.
			 Measured in whichever direction is smaller,
			 given the aspect ratio.  When aspect ratio
			 changes -- e.g. when a window is reshaped --
			 "fov" is preserved.)

	"frameaspect" <aspect-ratio>	(X/Y) (default 1.333)

	"near"  <near-clipping-distance>	(default 0.1)
	
	"far"	<far-clipping-distance>		(default 10.0)

	"focus" <focus-distance>		(default 3.0)

	
     [ "@}" ]				(matching closebrace)
@end example


@comment ----------------------------------------------------------------
@node window,Customization,camera,Non-geometric objects
@subsection window

A window object specifies size, position, and other window-system
related information about a window in a device-independent way.

The syntax for a window object is:

@example
window ::=

	[ "window" ]			(optional keyword)
	  [ "@{" ]			(curly brace, often required)

	    			(any of the following, in any order)

		"size"  <xsize> <ysize>
				(size of the window)

		"position"  <xmin> <xmax> <ymin> <ymax>
				(position & size)


		"noborder"
				(specifies the window should
				 have no window border)

		"pixelaspect"  <aspect>
			    (specifies the true visual aspect ratio
			     of a pixel in this window in the sense
			     xsize/ysize, normally 1.0.
			     For stereo hardware which stretches the
			     display vertically by a factor of 2,
			     ``pixelaspect 0.5'' might do.
			     The value is used when computing the
			     projection of a camera associated with
			     this window.)

	  [ "@}" ]			(matching closebrace)
@end example

Window objects are used in the Geomview @code{window} and
@code{ui-panel} commands to set default properties for future windows or
to change those of an existing window.


@comment ****************************************************************
@node Customization,Modules,window,Top
@chapter Customization: @file{.geomview} files

When Geomview is started, it loads and executes commands in a
system-wide startup file named @file{.geomview}.  This file is in the
@file{data} subdirectory of the Geomview distribution directory
@file{/u/gcg/ngrap/data} on the Geometry Center's computer system) and
contains gcl commands to configure Geomview in a way
common to all users on the system.

Next, Geomview looks for the file @file{~/.geomview} (@file{~}
stands for your home directory).  You can use this to configure
your own default Geomview behavior to suit your tastes.

After reading @file{~/.geomview}, Geomview looks for a file named
@file{.geomview} in the current directory.  If such a file exists
Geomview reads it, unless it is the same as @file{~/.geomview} (which
would be the case if you are running Geomview from your home directory).
You can use the current directory's @file{.geomview} to create a Geomview
customization specific to a certain project.

You can use @file{.geomview} files to control all kinds of things about
Geomview.  They can contain any valid gcl statements.  Especially
useful is the @code{ui-panel} command which controls the initial
placement of Geomview's panels.  For an example see the system-wide
@file{.geomview} file mentioned above.  For details of gcl,
@xref{GCL}.

It is a good idea to enclose all the commands you put in a
@file{.geomview} file in a @code{progn} statement in order to cause
Geomview to execute them all at once.  Otherwise Geomview might execute
them sequentially over the first few refresh cycles after starting up.

@comment ****************************************************************
@node Modules,Interface,Customization,Top
@chapter External Modules

An external module is a program that interacts with Geomview.  A
module communicates with Geomview through gcl and can
control any apsect of Geomview that you can control through Geomview's
user interface.

In many cases an external module is a specialized program that
implements some mathematical algorithm that creates a geometric
object that changes shape as the algorithm progresses.  The module
informs Geomview of the new object shape at each step, so the object
appears to evolve with time in the Geomview window.  In this way
Geomview serves as a @emph{display engine} for the module.

An external module may be interactive.  It can respond to mouse and
keyboard events that take place in a Geomview window, thus extending
the capability of Geomview itself.

@menu
* Interface::               How External Modules Interface with Geomview.
* Example1::                Simple External Module.
* Example2::                Simple External Module with FORMS Control Panel.
* Forms::                   The FORMS Library.
* Example3::                External Module with Bi-Directional Communication.
* Example4::                Simple Tcl/Tk Module Demonstrating Picking.
* Module Installation::     Module Installation.
@end menu

@node Interface,Example1,Modules,Modules
@section How External Modules Interface with Geomview

External modules appear in the @widget{Modules} browser in Geomview's
@panel{Main} panel.  To run a module, click the left mouse button on
the module's entry in the browser.  While the module is running, an
additional line for that module will appear in red in the browser.
This line begins with a number in brackets, which indicates the
@emph{instace} number of the module.  (For some modules it makes sense
to have more than one instance of the module running at the same
time.)  You can kill an external module by clicking on its red
instance entry.

By default when Geomview starts, it displays all the modules that have
been installed on your system. 

For instructions on installing a module on your system so that it will
appear in the @widget{Modules} browser every time Geomview is run by
anyone on your system, @xref{Module Installation}.

When Geomview invokes an external module, it creates pipes connected
to the module's standard input and output. (Pipes are like files
except they are used for communication between programs rather than
for storing things on a disk.)  Geomview interprets anything that the
module writes to its standard output as a gcl command.
Likewise, if the exernal module requests any data from Geomview,
Geomview writes that data to the module's standard input.  Thus all a
module has to do in order to communicate with Geomview is write
commands to standard output and (optionally) receive data on standard
input.  Note that this means that the module cannot use standard input
and output for communicating with the user.  If a module needs to
communicate with the user it can do so either through a control
panel of its own or else by responding to certain events that it finds
out about from Geomview.

@node Example1,Example2,Interface,Modules
@section Example 1: Simple External Module

This section gives a very simple external module which displays an
oscillating mesh.  To try out this example, make a copy of the file
@file{example1.c} (it is distributed with Geomview in the @file{doc}
subdirectory) in your directory and compile it with the command

@example
cc -o example1 example1.c -lm
@end example

Then put the line

@example
(emodule-define "Example 1" "./example1")
@end example

@noindent
in a file called @file{.geomview} in your current directory.  Then invoke
Geomview; it is important that you compile the example program, create
the @file{.geomview} file, and invoke Geomview all in the same
directory.  You should see "Example 1" in the @widget{Modules} browser
of Geomview's @panel{Main} panel; click on this entry in the browser to
start the module.  A surface should appear in your camera window and should
begin oscillating.  You can stop the module by clicking on the red "[1]
Example 1" line in the @widget{Modules} browser.

@example
@comment #include "example1.c"
/*
 * example1.c: oscillating mesh
 *
 * This example module is distributed with the Geomview manual.
 * If you are not reading this in the manual, see the "External
 * Modules" chapter of the manual for more details.
 *
 * This module creates an oscillating mesh.
 */

#include <math.h>
#include <stdio.h>

/* F is the function that we plot
 */
float F(x,y,t)
     float x,y,t;
@{
  float r = sqrt(x*x+y*y);
  return(sin(r + t)*sqrt(r));
@}

main(argc, argv)        
     char **argv;
@{
  int xdim, ydim;
  float xmin, xmax, ymin, ymax, dx, dy, t, dt;

  xmin = ymin = -5;             /* Set x and y            */
  xmax = ymax = 5;              /*    plot ranges         */
  xdim = ydim = 24;             /* Set x and y resolution */
  dt = 0.1;                     /* Time increment is 0.1  */

  /* Geomview setup.  We begin by sending the command
   *            (geometry example @{ : foo@})
   * to Geomview.  This tells Geomview to create a geom called
   * "example" which is an instance of the handle "foo".
   */
  printf("(geometry example @{ : foo @})\n");
  fflush(stdout);

  /* Loop until killed.
   */
  for (t=0; ; t+=dt) @{
    UpdateMesh(xmin, xmax, ymin, ymax, xdim, ydim, t);
  @}
@}

/* UpdateMesh sends one mesh iteration to Geomview.  This consists of
 * a command of the form
 *    (read geometry @{ define foo
 *       MESH
 *       ...
 *    @})
 * where ... is the actual data of the mesh.  This command tells
 * Geomview to make the value of the handle "foo" be the specified
 * mesh.
 */
UpdateMesh(xmin, xmax, ymin, ymax, xdim, ydim, t)
     float xmin, xmax, ymin, ymax, t;
     int xdim, ydim;
@{
  int i,j;
  float x,y, dx,dy;

  dx = (xmax-xmin)/(xdim-1);
  dy = (ymax-ymin)/(ydim-1);

  printf("(read geometry @{ define foo \n");
  printf("MESH\n");
  printf("%1d %1d\n", xdim, ydim);
  for (j=0, y = ymin; j<ydim; ++j, y += dy) @{
    for (i=0, x = xmin; i<xdim; ++i, x += dx) @{
      printf("%f %f %f\t", x, y, F(x,y,t));
    @}
    printf("\n");
  @}
  printf("@})\n");
  fflush(stdout);
@}
@comment #end include
@end example

The module begins by defining a function @code{F(x,y,t)} that
specifies a time-varying surface.  The purpose of the module is to
animate this surface over time.

The main program begins by defining some variables that specify
the parameters with which the function is to be plotted.

The next bit of code in the main program prints the following
line to standard output

@example
(geometry example @{ : foo @})
@end example

This tells Geomview to create a geom called @code{example} which is an
instance of the handle @code{foo}.  @emph{Handles} are a part of the
OOGL file format which allow you to name a piece of geometry whose value
can be specified elsewhere (and in this case updated many times); for
more information on handles, @xref{OOGL File Formats} In this case,
@code{example} is the title by which the user will see the object in
Geomview's object browser, and @code{foo} is the internal name of the
handle that the object is a reference to.

We then do @code{fflush(stdout)} to ensure that Geomview
receives this command immediately.  In general, since pipes may be
buffered, an external module should do this whenever it wants to be
sure Geomview has actually received everything it has printed out.

The last thing in the main program is an infinite loop that cycles
through calls to the procedure @code{UpdateMesh} with increasing
values of @code{t}.  @code{UpdateMesh} sends Geomview a command
of the form

@example
(read geometry @{ define foo 
MESH
24 24
@dots{}
@})
@end example

@noindent
where @code{@dots{}} is a long list of numbers.  This command tells Geomview
to make the value of the handle @code{foo} be the specified mesh.  As
soon as Geomview receives this command, the geom being displayed
changes to reflect the new geometry.

The mesh is given in the format of an OOGL MESH.  This begins with
the keyword @code{MESH}.  Next come two numbers that give the x and y
dimensions of the mesh; in this case they are both 24.  This line is
followed by 24 lines, each containing 24 triples of numbers.  Each of
these triples is a point on the surface.  Then finally there is a line
with "@code{@})}" on it that ends the "@code{@{}" which began the
@code{define} statement and the "@code{(}" that began the command.  For
more details on the format of MESH data, @pxref{MESH}.

This module could be written without the use of handles by having it
write out commands of the form

@example
(geometry example @{
MESH
24 24
@dots{}
@})
@end example

@noindent
This first time Geomview receives a command of this form it would create
a geom called @code{example} with the given @code{MESH} data.
Subsequent @code{(geometry example @dots{})} commands would cause
Geomview to replace the geometry of the geom @code{example} with the new
@code{MESH} data.  If done in this way there would be no need to send
the initial @code{(geometry example @{ : foo @})} command as above.  The
handle technique is useful, however, because it can be used in more
general situations where a handle represents only part of a complex
geom, allowing an external module to replace only that part without
having to retransmit the entire geom.  For more information on handles,
@xref{GCL}.

The module loops through calls to @code{UpdateMesh} which print out
commands of the above form one after the other as fast as possible.
The loop continues indefinitely; the module will terminate when the
user kills it by clicking on its instance line in the @widget{Modules}
browser, or else when Geomview exits.

Sometimes when you terminate this module by clicking on its instance
entry the @widget{Modules} browser, Geomview will kill it while it is in
the middle of sending a command to Geomview.  Geomview will then receive
only a piece of a command and will print out a cryptic but harmless
error message about this.  When a module has a user interface panel
it can use a "Quit" button to provide a more graceful way for the user
to terminate the module.  See the next example.

You can run this module in a shell window without Geomview to see the
commands it prints out.  You will have to kill it with
@kbd{ctrl-C} to get it to stop.

@comment ================================================================
@node Example2,Forms,Example1,Modules
@section Example 2: Simple External Module with FORMS Control Panel

This section gives a new version of the above module --- one that
includes a user interface panel for controlling the velocity of the
oscillation.  We use the FORMS library by Mark Overmars for the control
panel.  The FORMS library is a public domain user interface toolkit for
IRISes; for more information @xref{Forms}.

To try out this example, make a copy of the file
@file{example2.c} (distributed with Geomview in the @file{doc}
subdirectory) in your directory and compile it with the command

@example
cc -I/u/gcg/ngrap/include -o example2 example2.c \
  -L/u/gcg/ngrap/lib/sgi -lforms -lfm_s -lgl_s -lm
@end example

If you are not using the Geometry Center's computer system you should
replace the string @file{/u/gcg/ngrap} above with the pathname of the
Geomview distribution directory on your system.  (The forms library is
distributed with Geomview and the @code{-I} and @code{-L} options above
tell the compiler where to find it.)

Then put the line

@example
(emodule-define "Example 2" "./example2")
@end example

@noindent
in a file called @file{.geomview} in the current directory and invoke
Geomview from that directory.  Click on the "Example 2" entry in the
@widget{Modules} browser to invoke the module.  A small control panel
should appear.  You can then control the velocity of the mesh
oscillation by moving the slider.

@example
@comment #include "example2.c"
/*
 * example2.c: oscillating mesh with FORMS control panel
 *
 * This example module is distributed with the Geomview manual.
 * If you are not reading this in the manual, see the "External
 * Modules" chapter of the manual for an explanation.
 *
 * This module creates an oscillating mesh and has a FORMS control
 * panel that lets you change the speed of the oscillation with a
 * slider.
 */

#include <math.h>
#include <stdio.h>
#include <sys/time.h>           /* for struct timeval below */

#include "forms.h"              /* for FORMS library */

FL@_FORM *OurForm;
FL@_OBJECT *VelocitySlider;
float dt;

/* F is the function that we plot
 */
float F(x,y,t)
     float x,y,t;
@{
  float r = sqrt(x*x+y*y);
  return(sin(r + t)*sqrt(r));
@}

/* SetVelocity is the slider callback procedure; FORMS calls this
 * when the user moves the slider bar.
 */
void SetVelocity(FL@_OBJECT *obj, long val)
@{
  dt = fl@_get@_slider@_value(VelocitySlider);
@}

/* Quit is the "Quit" button callback procedure; FORMS calls this
 * when the user clicks the "Quit" button.
 */
void Quit(FL@_OBJECT *obj, long val)
@{
  exit(0);
@}

/* create@_form@_OurForm() creates the FORMS panel by calling a bunch of
 * procedures in the FORMS library.  This code was generated
 * automatically by the FORMS designer program; normally this code
 * would be in a separate file which you would not edit by hand.  For
 * simplicity of this example, however, we include this code here.
 */
create@_form@_OurForm()
@{
  FL@_OBJECT *obj;
  FL@_FORM *form;
  OurForm = form = fl@_bgn@_form(FL@_NO@_BOX,380.0,120.0);
  obj = fl@_add@_box(FL@_UP@_BOX,0.0,0.0,380.0,120.0,"");
  VelocitySlider = obj = fl@_add@_valslider(FL@_HOR@_SLIDER,20.0,30.0,
                                          340.0,40.0,"Velocity");
    fl@_set@_object@_lsize(obj,FL@_LARGE@_FONT);
    fl@_set@_object@_align(obj,FL@_ALIGN@_TOP);
    fl@_set@_call@_back(obj,SetVelocity,0);
  obj = fl@_add@_button(FL@_NORMAL@_BUTTON,290.0,75.0,70.0,35.0,"Quit");
    fl@_set@_object@_lsize(obj,FL@_LARGE@_FONT);
    fl@_set@_call@_back(obj,Quit,0);
  fl@_end@_form();
@}

main(argc, argv)        
     char **argv;
@{
  int xdim, ydim;
  float xmin, xmax, ymin, ymax, dx, dy, t;
  int fdmask;
  static struct timeval timeout = @{0, 200000@};

  xmin = ymin = -5;             /* Set x and y            */
  xmax = ymax = 5;              /*    plot ranges         */
  xdim = ydim = 24;             /* Set x and y resolution */
  dt = 0.1;                     /* Time increment is 0.1  */

  /* Forms panel setup.
   */
  foreground();
  create@_form@_OurForm();
  fl@_set@_slider@_bounds(VelocitySlider, 0.0, 1.0);
  fl@_set@_slider@_value(VelocitySlider, dt);
  fl@_show@_form(OurForm, FL@_PLACE@_SIZE, TRUE, "Example 2");


  /* Geomview setup.
   */
  printf("(geometry example @{ : foo @})\n");
  fflush(stdout);

  /* Loop until killed.
   */
  for (t=0; ; t+=dt) @{
    fdmask = (1 << fileno(stdin)) | (1 << qgetfd());
    select(qgetfd()+1, &fdmask, NULL, NULL, &timeout);
    fl@_check@_forms();
    UpdateMesh(xmin, xmax, ymin, ymax, xdim, ydim, t);
  @}
@}

/* UpdateMesh sends one mesh iteration to Geomview
 */
UpdateMesh(xmin, xmax, ymin, ymax, xdim, ydim, t)
     float xmin, xmax, ymin, ymax, t;
     int xdim, ydim;
@{
  int i,j;
  float x,y, dx,dy;

  dx = (xmax-xmin)/(xdim-1);
  dy = (ymax-ymin)/(ydim-1);

  printf("(read geometry @{ define foo \n");
  printf("MESH\n");
  printf("%1d %1d\n", xdim, ydim);
  for (j=0, y = ymin; j<ydim; ++j, y += dy) @{
    for (i=0, x = xmin; i<xdim; ++i, x += dx) @{
      printf("%f %f %f\t", x, y, F(x,y,t));
    @}
    printf("\n");
  @}
  printf("@})\n");
  fflush(stdout);
@}
@comment #end include
@end example

The code begins by including some header files needed for the event loop
and the FORMS library.  It then declares global variables for holding a
pointer to the slider FORMS object and the velocity @code{dt}.  These
are global because they are needed in the slider callback procedure
@code{SetVelocity}, which forms calls every time the user moves the
slider bar. @code{SetVelocity} sets @code{dt} to be the new value of the
slider.

@code{Quit} is the callback procedure for the @widget{Quit} button;
it provides a graceful way for the user to terminate the program.

The procedure @code{create_panel} calls a bunch of FORMS library
procedures to set up the control panel with slider and button.  For more
information on using FORMS to create interface panels see the FORMS
documentation.  In particular, FORMS comes with a graphical panel
designer that lets you design your panels interactively and generates
code like that in @code{create_panel}.

This example's main program is similar to the previous example, but
includes extra code to deal with setting up and managing the FORMS
panel.  

To set up the panel we call the GL procedure @code{foreground} to cause
the process to run in the foreground.  By default GL programs run in the
background, and for various reasons external modules that use FORMS
(which is based on GL) need to run in the foreground.  We then call
@code{create_panel} to create the panel and @code{fl_set_slider_value}
to set the initial value of the slider.  The call to @code{fl_show_form}
causes the panel to appear on the screen.

The first three lines of the main loop, starting with 
@example
fdmask = (1 << fileno(stdin)) | (1 << qgetfd());
@end example
@noindent
check for and deal with events in the panel.  The call to @code{select}
imposes a delay on each pass through the main loop.  This call returns
either after a delay of 1/5 second or when the next GL event occurs, or
when data appears on standard input, whichever comes first.  The
@code{timeout} variable specifies the amount of time to wait on this
call; the first member (0 in this example) gives the number of seconds,
and the second member (200000 in this example) gives the number of
microseconds.  Finally, @code{fl_check_forms()} checks for and processes
any FORMS events that have happened; in this case this means calling
@code{SetVelocity} if the user has moved the slider or calling
@code{Quit} if the user has clicked on the @widget{Quit} button.

The purpose of the delay in the loop is to keep the program from using
excessive amounts of CPU time running around its main loop when there
are no events to be processed.  This is not so crucial in this example,
and in fact may actually slow down the animation somewhat, but in
general with external modules that have event loops it is important to
do something like this because otherwise the module will needlessly take
CPU cycles away from other running programs (such as Geomview!)  even
when it isn't doing anything.

The last line of the main loop in this example, the call to
@code{UpdateMesh}, is the same as in the previous example.

@comment ================================================================
@node Forms,Example3,Example2,Modules
@section The FORMS Library

Geomview itself is written using Mark Overmar's public domain FORMS
library.  FORMS is a handy and relatively simple user interface toolkit
for IRISes.  Many Geomview external modules, including the examples in
this manual, use FORMS to create and manage control panels.

We distribute a version of the FORMS library with Geomview because it is
necessary in order to compile Geomview and many of our modules.  If you
use FORMS to write Geomview modules (or anything else, for that matter)
you may use this copy.  The header file @file{forms.h} is in the
@file{include} subdirectory, and the library file @file{libforms.a} is
in the @file{lib/sgi} subdirectory (these are subdirectories of the
Geomview distribution directory, @file{/u/gcg/ngrap} on the Geometry
Center's system).  In particular, you can link the example modules in
this manual using this copy.

FORMS is available via ftp on the Internet from a variety of sites,
including @code{cs.ruu.nl} or @code{glaurung.physics.mcgill.ca}.  It
comes with source code and extensive documentation.

If you wish you may use any other interface toolkit instead of FORMS in
an external module.  We chose FORMS because it is free and relatively
simple.


@comment ================================================================
@node Example3,Example4,Forms,Modules
@section Example 3: External Module with Bi-Directional Communication

The previous two example modules simply send commands to Geomview and do
not receive anything from Geomview.  This section describes a module
that communicates in both directions.  There are two types of
communication that can go from Geomview to an external module.  This
example shows @emph{asynchronous} communication --- the module needs to
be able to respond at any moment to expressions that Geomview may emit
which inform the module of some change of state within Geomview.

(The other type of communication is @emph{synchronous}, where a module
sends a request to Geomview for some piece of information and waits for
a response to come back before doing anything else.  The main gcl
command for requesting information of this type is @code{write}.  This
module does not do any synchronous communication.)

In ansynchronous communication, Geomview sends expressions that are
essentially echoes of gcl commands.  The external module sends
Geomview a command expressing interest in a certain command, and then
every time Geomview executes that command, the module receives a copy of
it.  This happens regardless of who sent the command to Geomview; it can
be the result of the user doing something with a Geomview panel, or
it may have come from another module or from a file that Geomview reads.
This is how a module can find out about and act on things that happen in
Geomview.

This example uses the OOGL lisp library to parse and act on the
expressions that Geomview writes to the module's standard input.  This
library is actually part of Geomview itself --- we wrote the library in
the process of implementing gcl.  It is also convenient to use it in
external modules that must understand a of subset of gcl ---
specifically, those commands that the module has expressed interest in.

This example shows how a module can receive user pick events, i.e.
when the user clicks the right mouse button with the cursor over a geom
in a Geomview camera window.  When this happens Geomview generates an
internal call to a procedure called @code{pick}; the arguments to the
procedure give information about the pick, such as what object was
picked, the coordinates of the picked point, etc.  If an external module
has expressed interest in calls to @code{pick}, then whenever
@code{pick} is called Geomview will echo the call to the module's
standard input.  The module can then do whatever it wants with the pick
information.

This module is the same as the @emph{Nose} module that comes with
Geomview.  Its purpose is to illustrate picking.  Whenever you pick on a
geom by clicking the right mouse button on it, the module draws a little
box at the spot where you clicked.  Usually the box is yellow.  If you
pick a vertex, the box is colored magenta.  If you pick a point on an
edge of an object, the module will also highlight the edge by drawing
cyan boxes at its endpoints and drawing a yellow line along the edge.

Note that in order for this module to actually do anything you must have
a geom loaded into Geomview and you must click the right mouse button
with the cursor over a part of the geom.

@example
@comment #include "example3.c"
/*
 * example3.c: external module with bi-directional communication
 *
 * This example module is distributed with the Geomview manual.
 * If you are not reading this in the manual, see the "External
 * Modules" chapter of the manual for an explanation.
 *
 * This module is the same as the "Nose" program that is distributed
 * with Geomview.  It illustrates how a module can find out about
 * and respond to user pick events in Geomview.  It draws a little box
 * at the point where a pick occurrs.  The box is yellow if it is not
 * at a vertex, and magenta if it is on a vertex.  If it is on an edge,
 * the program also marks the edge.
 *
 * To compile:
 *
 *   cc -I/u/gcg/ngrap/include -g -o example3 example3.c \
 *      -L/u/gcg/ngrap/lib/sgi -loogl -lm
 *
 * If you are not on the Geometry Center's system you should replace
 * "/u/gcg/ngrap" above with the pathname of the Geomview distribution
 * directory on your system.
 */

#include <stdio.h>
#include "lisp.h"               /* We use the OOGL lisp library */
#include "pickfunc.h"           /* for PICKFUNC below */
#include "3d.h"                 /* for 3d geometry library */

/* boxstring gives the OOGL data to define the little box that
 * we draw at the pick point.  NOTE:  It is very important to
 * have a newline at the end of the OFF object in this string.
 */
char boxstring[] = "\
INST\n\
transform\n\
.04 0 0 0\n\
0 .04 0 0\n\
0 0 .04 0\n\
0 0 0 1\n\
geom\n\
OFF\n\
8 6 12\n\
\n\
-.5 -.5 -.5     # 0   \n\
.5 -.5 -.5      # 1   \n\
.5  .5 -.5      # 2   \n\
-.5  .5 -.5     # 3   \n\
-.5 -.5  .5     # 4   \n\
.5 -.5  .5      # 5   \n\
.5  .5  .5      # 6   \n\
-.5  .5  .5     # 7   \n\
\n\
4 0 1 2 3\n\
4 4 5 6 7\n\
4 2 3 7 6\n\
4 0 1 5 4\n\
4 0 4 7 3\n\
4 1 2 6 5\n";

progn()
@{
  printf("(progn\n");
@}

endprogn()
@{
  printf(")\n");
  fflush(stdout);
@}

Initialize()
@{
  extern LObject *Lpick();  /* This is defined by PICKFUNC below but must */
  			    /* be used in the following LDefun() call */
  LInit();
  LDefun("pick", Lpick, NULL);

  progn(); @{
    /* Define handle "littlebox" for use later
     */
    printf("(read geometry @{ define littlebox @{ %s @}@})\n", boxstring);

    /* Express interest in pick events; see Geomview manual for explanation.
     */
    printf("(interest (pick world * * * * nil nil nil nil nil))\n");

    /* Define "pick" object, initially the empty list (= null object).
     * We replace this later upon receiving a pick event.
     */
    printf("(geometry \"pick\" @{ LIST @} )\n");

    /* Make the "pick" object be non-pickable.
     */
    printf("(pickable \"pick\" no)\n");

    /* Turn off normalization, so that our pick object will appear in the
     * right place.
     */
    printf("(normalization \"pick\" none)\n");

    /* Don't draw the pick object's bounding box.
     */
    printf("(bbox-draw \"pick\" off)\n");

  @} endprogn();
@}

/* The following is a macro call that defines a procedure called
 * Lpick().  The reason for doing this in a macro is that that macro
 * encapsulates a lot of necessary stuff that would be the same for
 * this procedure in any program.  If you write a Geomview module that
 * wants to know about user pick events you can just copy this macro
 * call and change the body to suit your needs; the body is the last
 * argument to the macro and is delimited by curly braces.
 *
 * The first argument to the macro is the name of the procedure to
 * be defined, "Lpick".
 *
 * The next two arguments are numbers which specify the sizes that
 * certain arrays inside the body of the procedure should have.
 * These arrays are used for storing the face and path information
 * of the picked object.  In this module we don't care about this
 * information so we declare them to have length 1, the minimum
 * allowed.
 *
 * The last argument is a block of code to be executed when the module
 * receives a pick event.  In this body you can refer to certain local
 * variables that hold information about the pick.  For details see
 * Example 3 in the Extenal Modules chapter of the Geomview manual.
 */
PICKFUNC(Lpick, 1, 1,
@{           
  handle@_pick(pn>0, &point, vn>0, &vertex, en>0, edge);
@})

handle@_pick(picked, p, vert, v, edge, e)
     int picked;                /* was something actually picked?     */
     int vert;                  /* was the pick near a vertex?        */
     int edge;                  /* was the pick near an edge?         */
     HPoint3 *p;                /* coords of pick point               */
     HPoint3 *v;                /* coords of picked vertex            */
     HPoint3 e[2];              /* coords of endpoints of picked edge */
@{
  Normalize(&e[0]);             /* Normalize makes 4th coord 1.0 */
  Normalize(&e[1]);
  Normalize(p);
  progn(); @{
    if (!picked) @{
      printf("(geometry \"pick\" @{ LIST @} )\n");
    @} else @{
      /*
       * Put the box in place, and color it magenta if it's on a vertex,
       * yellow if not.
       */
      printf("(xform-set pick @{ 1 0 0 0  0 1 0 0  0 0 1 0  %g %g %g 1 @})\n",
             p->x, p->y, p->z);
      printf("(geometry \"pick\"\n");
      if (vert) printf("@{ appearance @{ material @{ diffuse 1 0 1 @} @}\n");
      else printf("@{ appearance @{ material @{ diffuse 1 1 0 @} @}\n");
      printf("  @{ LIST @{ :littlebox @}\n");
      
      /*
       * If it's on an edge and not a vertex, mark the edge
       * with cyan boxes at the endpoins and a black line
       * along the edge.
       */
      if (edge && !vert) @{
        e[0].x -= p->x; e[0].y -= p->y; e[0].z -= p->z;
        e[1].x -= p->x; e[1].y -= p->y; e[1].z -= p->z;
        printf("@{ appearance @{ material @{ diffuse 0 1 1 @} @}\n\
  LIST\n\
   @{ INST transform 1 0 0 0 0 1 0 0 0 0 1 0 %f %f %f 1 geom :littlebox @}\n\
   @{ INST transform 1 0 0 0 0 1 0 0 0 0 1 0 %f %f %f 1 geom :littlebox @}\n\
   @{ VECT\n\
          1 2 1\n\
          2\n\
          1\n\
          %f %f %f\n\
          %f %f %f\n\
          1 1 0 1\n\
   @}\n\
  @}\n",
               e[0].x, e[0].y, e[0].z,
               e[1].x, e[1].y, e[1].z,
               e[0].x, e[0].y, e[0].z,
               e[1].x, e[1].y, e[1].z);
      @}
      printf("    @}\n  @}\n)\n");
    @}

  @} endprogn();

@}

Normalize(HPoint3 *p)
@{
  if (p->w != 0) @{
    p->x /= p->w;
    p->y /= p->w;
    p->z /= p->w;
    p->w = 1;
  @}
@}

main()
@{
  Lake *lake;
  LObject *lit, *val;
  extern char *getenv();

  Initialize();

  lake = LakeDefine(stdin, stdout, NULL);
  while (!feof(stdin)) @{

    /* Parse next lisp expression from stdin.
     */
    lit = LSexpr(lake);

    /* Evaluate that expression; this is where Lpick() gets called.
     */
    val = LEval(lit);

    /* Free the two expressions from above.
     */
    LFree(lit);
    LFree(val);
  @}
@}
@comment #end include
@end example

The code begins by defining procedures @code{progn()} and
@code{endprogn()} which begin and end a Geomview @code{progn} group.
The purpose of the Geomview @code{progn} command is to group commands
together and cause Geomview to execute them all at once, without
refreshing any graphics windows until the end.  It is a good idea to
group blocks of commands that a module sends to Geomview like this so
that the user sees their cumulative effect all at once.

Procedure @code{Initialize()} does various things needed at program
startup time.  It initializes the lisp library by calling
@code{LInit()}.  Any program that uses the lisp library should call this
once before calling any other lisp library functions.  It then calls
@code{LDefun} to tell the library about our @code{pick} procedure, which
is defined further down with a call to the @code{DEFPICKFUNC} macro.
Then it sends a bunch of setup commands to Geomview, grouped in a
@code{progn} block.  This includes defining a handle called @code{littlebox}
that stores the geometry of the little box.  Next it sends the command

@example
(interest (pick world * * * * nil nil nil nil nil))
@end example

@noindent
which tells Geomview to notify us when a pick event happens.

The syntax of this @code{interest} statement merits some explanation.
In general @code{interest} takes one argument which is a (parenthesized)
expression representing a Geomview function call.  It specifies a type
of call that the module is interested in knowing about.  The arguments
can be any particular argument values, or the special symbols @code{*}
or @code{nil}.  For example, the first argument in the @code{pick}
expression above is @code{world}.  This means that the module is
interested in calls to @code{pick} where the first argument, which
specifies the coordinate system, is @code{world}.  A @code{*} is like a
wild-card; it means that the module is interested in calls where the
corresponding argument has any value.  The word @code{nil} is like
@code{*}, except that the argument's value is not reported to the
module.  This is useful for cutting down on the amount of data that must
be transmitted in cases where there are arguments that the module
doesn't care about.

The second, third, fourth, and fifth arguments to the @code{pick}
command give the name, pick point coordinates, vertex coordinates, and
edge coordinates of a pick event.  We specify these by @code{*}'s above.
The remaining five arguments to the @code{pick} command give other
information about the pick event that we do not care about in this
module, so we specify these with @code{nil}'s.  For the details of the
arguments to @code{pick}, @xref{GCL}.

The @code{geometry} statement defines a geom called @code{pick} that is
initially an empty list, specified as @code{ @{ LIST @} }; this is the
best way of specifying a null geom.  The module will replace this with
something useful by sending Geomview another @code{geometry} command
when the user picks something.  Next we arrange for the @code{pick}
object to be non-pickable, and turn normalization off for it so that
Geomview will display it in the size and location where we put it,
rather than resizing and relocating it to fit into the unit cube.

The next function in the file, @code{Lpick}, is defined with a strange
looking call to a macro called @code{PICKFUNC}, defined in the header
file @file{pickfunc.h}.  This is the function for handling pick events.
The reason we provide a macro for this is that that macro encapsulates a
lot of necessary stuff that would be the same for the pick-handling
function in any program.  If you write a Geomview module that wants to
know about user pick events you can just copy this macro call and change
it to suit yours needs.

In general the syntax for @code{PICKFUNC} is
@example
PICKFUNC(@var{name}, @var{maxfaceverts}, @var{maxpathlen}, @var{block})
@end example
@noindent
where @var{name} is the name of the procedure to be defined, in this
case @code{Lpick}.  The next two arguments, @var{maxfaceverts} and
@var{maxpathlen}, give the sizes to be used for declaring two local
variable arrays in the body of the procedure.  These arrays are for
storing information about the picked face and the picked primitive's
path.  In this module we don't care about this information (it
corresponds to some of the things masked out by the @code{nil}'s in the
@code{interest} call above) so we specify 1, the minimum allowable, for
both of these.  The last argument, @var{block}, is a block of code to be
executed when a pick event occurs.  The @var{block} should be delimited
by curly braces.  The code in your @var{block} should not include
any @code{return} statements.

@code{PICKFUNC} declares certain local variables in the body of the
procedure.  When the module receives a @code{(pick @dots{})} statement
from Geomview, the procedure assigns values to these variables based on
the information in the @code{pick} call.  (Variables corresponding to
@code{nil}'s in the @code{(interest (pick @dots{}))} are not given
values.)
These variables are:
@table @asis

@item @code{char *coordsys;}
A string specifying the coordinate system in which coordinates are
given.  In this example, this will always be @code{world} because
of the @code{interest} call above.

@item @code{char *id;}
A string specifying the name of the picked geom.

@item @code{HPoint3 point; int pn;}
@code{point} is an @code{HPoint3} structure giving the coordinates of
the picked point.  @code{HPoint3} is a homogeneous point coordinate
representation equivalent to an array of 4 floats.  @code{pn} tells how
many coordinates have been written into this array; it will always be
either 0 or 4.  A value of zero means no point was picked, i.e. the user
clicked the right mouse button while the cursor was not pointing at a
geom.

@item @code{HPoint3 vertex; int vn;}
@code{vertex} is an @code{HPoint3} structure giving the coordinates of
the picked vertex, if the pick point was near a vertex.  @code{vn} tells
how many coordinates have been written into this array; it will always
be either 0 or 4.  A value of zero means the pick point was not near a
vertex.

@item @code{HPoint3 edge[2]; int en;}
@code{edge} is an array of two @code{HPoint3} structures giving the
coordinates of the endpoints of the picked edge, if the pick point was
near an edge.  @code{en} tells how many coordinates have been written
into this array; it will always be either 0 or 8.  A value of zero means
the pick point was not near an edge.

@end table

In this example module, the remaining variables will never be given
values because their values in the @code{interest} statement were
specified as @code{nil}.   

@table @asis

@item @code{HPoint3 face[@var{maxfaceverts}]; int fn;}
@code{face} is an array of @var{maxfaceverts} @code{HPoint3}'s;
@var{maxfaceverts} is the value specified in the @code{PICKFUNC} call.
@code{face} gives the coordinates of the vertices of the picked face.
@code{fn} tells how many coordinates have been written into this array;
it will always be a multiple of 4 and will be at most
4*@var{maxfaceverts}.  A value of zero means the pick point was not near
a face.

@item @code{HPoint3 ppath[@var{maxpathlen}; int ppn;}
@code{ppath} is an array of @var{maxpathlen} @code{int}'s;
@var{maxpathlen} is the value specified in the @code{PICKFUNC} call.
@code{ppath} gives the path through the OOGL heirarchy to the picked
primitive.  @code{pn} tells how many integers have been written into
this array; it will be at most @var{maxpathlen}.  A path of {3,1,2},
for example, means that the picked primitive is "subobject number 2
of subobject number 1 of object 3 in the world".

@item @code{int vi;}
@code{vi} gives the index of the picked vertex in the picked primitive,
if the pick point was near a vertex.

@item @code{int ei[2]; int ein}
The @code{ei} array gives the indices of the endpoints of the picked
edge, if the pick point was near a vertex.  @code{ein} tells how many
integers were written into this array.  It will always be either 0 or 2;
a value of 0 means the pick point was not near an edge.

@item @code{int fi;}
@code{fi} gives the index of the picked face in the picked primitive, if
the pick point was near a face.

@end table

The @code{handle_pick} procedure actually does the work of dealing with
the pick event.  It begins by normalizing the homogeneous coordinates
passed in as arguments so that we can assume the fourth coordinate is 1.
It then sends gcl commands to define the @code{pick} object to be
whatever is appropriate for the kind of pick recieved.  See @pxref{OOGL
File Formats}, and @pxref{GCL}, for an explanation of the
format of the data in these commands.

The main program, at the bottom of the file, first calls
@code{Initialize()}.  Next, the call to @code{LakeDefine} defines the
@code{Lake} that the lisp library will use.  A @code{Lake} is a
structure that the lisp library uses internally as a type of
communiation vehicle.  (It is like a unix stream but more general, hence
the name.)  This call to @code{LakeDefine} defines a @code{Lake}
structure for doing I/O with @code{stdin} and @code{stdout}.  The third
argument to @code{LakeDefine} should be @code{NULL} for external modules
(it is used by Geomview).  Finally, the program enters its main loop
which parses and evaluates expressions from standard input.

@comment ****************************************************************
@node Example4,Module Installation,Example3,Modules
@section Example 4: Simple Tcl/Tk Module Demonstrating Picking

It's not necessary to write a Geomview module in C.  The only requirement
of an external module is that it send GCL commands to its standard output
and expect responses (if any) on its standard input.   An external module
can be written in C, perl, tcl/tk, or pretty much anything.

As an example, assuming you have Tcl/Tk version 4.0 or later,
here's an external module with a simple GUI which demonstrates interaction with
geomview.  This manual doesn't discuss the Tcl/Tk language; see the good book
on the subject by its originator John Ousterhout, published by Addison-Wesley,
titled @emph{Tcl and the Tk Toolkit}.

The @samp{#!} on the script's first line causes the system to interpret
the script using the Tcl/Tk @samp{wish} program; you might have to change its
first line if that's in some location other than /usr/local/bin/wish4.0.
Or, you could define it as a module using
@example
  (emodule-define  "Pick Demo"  "wish pickdemo.tcl")
@end example
in which case @samp{wish} could be anywhere on the UNIX search path.

@example
#! /usr/local/bin/wish4.0

# We use "fileevent" below to have "readsomething" be called whenever
# data is available from standard input, i.e. when geomview has sent us
# something.  It promises to include a trailing newline, so we can use
# "gets" to read the geomview response, then parse its nested parentheses
# into tcl-friendly {} braces.

proc readsomething {} {
  if {[gets stdin line] < 0} {
        puts stderr "EOF on input, exiting..."
        exit
  }
  regsub -all {\(} $line "\{" line
  regsub -all {\)} $line "\}" line
  # Strip outermost set of braces
  set stuff [lindex $line 0]
  # Invoke handler for whichever command we got.  Could add others here,
  # if we asked geomview for other kinds of data as well.
  switch [lindex $stuff 0] {
        pick     {handlepick $stuff}
        rawevent {handlekey $stuff}
  }
}

# Fields of a "pick" response, from geomview manual:
#     (pick COORDSYS GEOMID G V E F P VI EI FI)
#          The pick command is executed internally in response to pick
#          events (right mouse double click).
#
#          COORDSYS = coordinate system in which coordinates of the following
#              arguments are specified.   This can be:
#               world: world coord sys
#               self:  coord sys of the picked geom (GEOMID)
#               primitive: coord sys of the actual primitive within
#                   the picked geom where the pick occurred.
#          GEOMID = id of picked geom
#          G = picked point (actual intersection of pick ray with object)
#          V = picked vertex, if any
#          E = picked edge, if any
#          F = picked face
#          P = path to picked primitive [0 or more]
#          VI = index of picked vertex in primitive
#          EI = list of indices of endpoints of picked edge, if any
#          FI = index of picked face

# Report when user picked something.
# 
proc handlepick {pick} {
  global nameof selvert seledge order
  set obj [lindex $pick 2]
  set xyzw [lindex $pick 3]
  set fv [lindex $pick 6]
  set vi [lindex $pick 8] 
  set ei [lindex $pick 9] 
  set fi [lindex $pick 10]

  # Report result, converting 4-component homogeneous point into 3-space point.
  set w [lindex $xyzw 3]
  set x [expr [lindex $xyzw 0]/$w]
  set y [expr [lindex $xyzw 1]/$w]
  set z [expr [lindex $xyzw 2]/$w]
  set s "$x $y $z "
  if {$vi >= 0} {
        set s "$s  vertex #$vi"
  }
  if {$ei != {}} {
        set s "$s  edge [lindex $ei 0]-[lindex $ei 1]"
  }
  if {$fi != -1} {
        set s "$s  face #$fi ([expr [llength $fv]/3]-gon)"
  }
  msg $s
}


# Having asked for notification of these raw events, we report when
# the user pressed these keys in the geomview graphics windows.

proc handlekey {event} {
  global lastincr
  switch [lindex $event 1] {
    32 {msg "Pressed space bar"}
     8 {msg "Pressed backspace key"}
  }
}


#
# Display a message on the control panel, and on the terminal where geomview
# was started.  We use ``puts stderr ...'' rather than simply ``puts ...'',
# since Geomview interprets anything we send to standard output
# as a GCL command!
#
proc msg {str} {
  global msgtext
  puts stderr $str
  set msgtext $str
  update
}

# Load object from file
proc loadobject {fname} {
  if {$fname != ""} {
        puts "(geometry thing < $fname)"
        # Be sure to flush output to ensure geomview receives this now!
        flush stdout
  }
}


# Build simple "user interface"

# The message area could be a simple label rather than an entry box,
# but we want to be able to use X selection to copy text from it.
# The default mouse bindings do that automatically.

entry .msg -textvariable msgtext -width 45
pack .msg

frame .f

  label .f.l -text "File to load:"
  pack .f.l -side left

  entry .f.ent -textvariable fname
  pack .f.ent -side left -expand true -fill x
  bind .f.ent <Return> { loadobject $fname }

pack .f


# End UI definition.


# Call "readsomething" when data arrives from geomview.

fileevent stdin readable {readsomething}

# Geomview initialization

puts {
        (interest (pick primitive))
        (interest (rawevent 32))	# Be notified when user presses space
        (interest (rawevent 8))		# or backspace keys.
        (geometry thing < hdodec.off)
        (normalization world none)
}
# Flush to ensure geomview receives this.
flush stdout

wm title . {Sample external module}

msg "Click right mouse in graphics window"
@end example

@comment ****************************************************************
@node Module Installation,Private Module Installation,Example4,Modules
@section Module Installation

This section tells how to install an external module so you can invoke
it within Geomview.  There are two ways to install a module: you can
install a @emph{private} module so that the module is available to you
whenever you run Geomview, or you can install a @emph{system} module
so that the module is available to all users on your system whenever they
run Geomview.

@menu
* Private Module Installation::.
* System Module Installation::.
@end menu


@comment ----------------------------------------------------------------
@node Private Module Installation,System Module Installation,Module Installation,Module Installation
@subsection Private Module Installation

The @code{emodule-define} command arranges for a module to appear in
Geomview's @widget{Modules} browser.  @code{emodule-define} takes two
string arguments; the first is the name that will appear in the
@widget{Modules} browser.  The second is the shell command for running
the module; it may include arguments.  Geomview executes this command in
a subshell when you click on the module's entry in the browser.  For
example

@example
(emodule-define "Foo" "/u/home/modules/foo -x")
@end example

@noindent
adds a line labeled "Foo" to the @widget{Modules} browser which
causes the command "/u/home/modules/foo -x" to be executed when selected.

You may put @code{emodule-define} commands in your @file{~/.geomview}
file to arrange for certain modules to be available every time you run
Geomview; @xref{Customization}.  You can also execute
@code{emodule-define} commands from the @widget{Commands} panel
to add a module to an already running copy of Geomview.

There are several other gcl commands for controlling the entries
in the @widget{Modules} browser; for details, @xref{GCL}.

@comment ----------------------------------------------------------------
@node System Module Installation,GCL,Private Module Installation,Module Installation
@subsection System Module Installation

To install a module so that it is available to all Geomview users do
the following

@table @asis

@item 1.
Create a file called @file{.geomview-@var{module}} where
@file{@var{module}} is the name of the module.  This file should contain
a single line which is an @code{emodule-define} command for that module:
@example
(emodule-define "New Module" "newmodule")
@end example
The first argument, @code{"New Module"} above, is the string that will
appear in the @widget{Modules} browser.  The second string,
@code{"newmodule"} above, is the Bourne shell command for invoking the module.
It may include arguments, and you may assume that the module is on the
@$path searched by the shell.

@item 2.
Put a copy of the @file{.geomview-@var{module}} and the module
executable itself in Geomview's @file{modules/sgi} directory.  This is a
subdirectory of the Geomview distribution directory (on the Geometry
Center's system the pathname is @file{/u/gcg/ngrap/modules/sgi}.

@end table

After these steps, the new module should appear, in alphabetical
position, in the @widget{Modules} browser of Geomview's @panel{Main}
panel next time Geomview is run.  The reason this works is that when
Geomview is invoked it processes all the @file{.geomview-*} files in its
@file{modules} directory.  It also remembers the pathname of this
directory and prepends that path to the @$path of the shell in which it
invokes such a module.

@comment ****************************************************************
@node GCL,Argument Conventions,System Module Installation,Top
@chapter gcl: the Geomview Command Language

Gcl has the syntax of lisp -- i.e. an expression of the form (f a b
@dots{}) means pass the values of a, b, @dots{} to the function f.
Gcl is very limited and is by no means an implementation of lisp.  It
is simply a language for expressing commands to be executed in the order
given, rather than a programming language.  It does not support variable
or function definition.

Gcl is the language that Geomview understands for files that it loads
as well as for communication with other programs. 
To execute a gcl command interactively, you can bring up the
@panel{Commands} panel which lets you type in a command; Geomview
executes the command when you hit the return key.  Output from such
commands is printed to standard output.  Alternately, you can invoke
Geomview as @code{geomview -c -} which causes it to read gcl commands
from standard input.

Gcl functions return a value, and you can nest function calls in ways
which use this returned value.  For example
@example
(f (g a b))
@end example
evaluates @code{(g a b)} and then evaluates @code{(f x)} where @code{x}
is the result returned by @code{(g a b)}.  Geomview maintains these
return values internally but does not normally print them out.
To print out a return value pass it to the @code{echo} function.
For example the @code{geomview-version} function returns a string
representing the version of Geomview that is running, and
@example
(echo (geomview-version))
@end example
prints out this string.

Many functions simply return @code{t} for success or @code{nil} for
failure; this is the case if the documentation for the function does not
indicate otherwise.  These are the lisp symbols for true and false,
respectively.  (They correspond to the C variables @code{Lt} and
@code{Lnil} which you are likely to see if you look at the source code
for Geomview or some of the external modules.)

In the descriptions of the commands below several references are made to
"OOGL" formats.  OOGL is the data description language that Geomview
uses for describing geometry, cameras, appearances, and other basic
objects.  For details of the OOGL formats, @xref{OOGL File Formats}.
(Or equivalently, see the oogl(5) manual page, distributed with Geomview
in the file man/cat5/oogl.5.

The gcl commands and argument types are listed below.  Most
of the documentation in this section of the manual is available within
Geomview via the @code{?} and @code{??} commands.  The command @code{(?
@var{command})} causes Geomview to print out a one-line summary of the
syntax of @var{command}, and @code{(?? @var{command})} prints out an
explanation of what @var{command} does.  You can include the wild-card
character @code{*} in @var{command} to print information for a group of
commands matching a pattern.  For example, @code{(?? *emodule*)} will
print all information about all commands containing the string
@code{emodule}.  @code{(? *)} will print a short list of all commands.

@menu
* Argument Conventions::  Conventions used in describing argument types.
* Gcl Reference::	  Documentation for each gcl command.
@end menu

@node Argument Conventions,Gcl Reference,GCL,GCL
@section Conventions Used In Describing Argument Types

The following symbols are used to describe argument types
in the documentation for gcl functions.

@table @code

@item @var{appearance}
is an OOGL appearance specification.

@item @var{cam-id}
is an @var{id} that refers to a camera.

@item @var{camera}
is an OOGL camera specification.

@item @var{geom-id}
is an @var{id} that refers to a geometry.

@item @var{geometry}
is an OOGL geometry specification.

@item @var{id}
is a string which names a geometry or camera.  Besides
those you create, valid ones are:

@table @code

@item @code{World, world, worldgeom, g0}
the collection of all geom's

@item target
selected target object (cam or geom)

@item center
selected center-of-motion object

@item targetcam
last selected target camera

@item targetgeom
last selected target geom

@item focus
camera where cursor is (or most recently was)

@item allgeoms
all geom objects

@item allcams
all cameras

@item @code{default, defaultcam, prototype}
future cameras inherit default's settings

@end table

The following @var{id}s are used to name coordinate systems,
e.g. in @code{pick} and @code{write} commands:

@table @code

@item @code{World, world, worldgeom, g0}
the world, within which all other geoms live.

@item universe 
the universe, in which the World, lights and cameras live.  Cameras'
world2cam transforms might better be called universe2cam, etc.

@item self
"this Geomview object".  Transform from an object to @code{self} is the
identity; writing its geometry gives the object itself with no
enclosing transform; picked points appear in the object's coordinates.

@item primitive
(for @code{pick} only) Picked points appear in the coordinate system of the
lowest-level OOGL primitive.

@end table

A name is also an acceptable id.  Given names are made unique by
appending numbers if necessary (i.e. @code{foo<2>}). Every geom is also
named g[n] and every camera is also named c[n] (@code{g0} is always the
worldgeom): this name is used as a prefix to keyboard commands and can
also be used as a gcl id.  Numbers are reused after an
object is deleted. Both names are shown in the Object browser.

@item @var{statement}
represents a function call.  Function calls have the form @code{(func arg1
arg2 @dots{} )}, where @code{func} is the name of the function and @code{arg1},
@code{arg2}, @dots{} are the arguments.

@item @var{transform}
is an OOGL 4x4 transformation matrix.

@item @var{window}
is an OOGL winddow specification.

@end table

@node Gcl Reference,Non-Euclidean Geometry,Argument Conventions,GCL
@section Gcl Reference Guide

@table @code

@myfindex !
@item ! is a synonym for @code{shell}

@myfindex <
@item (< EXPR1 EXPR2)
Returns t if EXPR1 is less than EXPR2.  EXPR1 and EXPR2 should
be either both integers or floats, or both strings.

@myfindex =
@item (= EXPR1 EXPR2)
Returns t if EXPR1 is equal to EXPR2.  EXPR1 and EXPR2 should
be either both integers or floats, or both strings.

@myfindex >
@item (> EXPR1 EXPR2)
Returns t if EXPR1 is greater than EXPR2.  EXPR1 and EXPR2 should
be either both integers or floats, or both strings.

@myfindex ?
@item (?  [command])
Gives one-line usage summary for @code{command}.
Command may include @code{*}s as wildcards; see also @code{??}
One-line command help; lists names only if multiple commands match.
? is a synonym for @code{help}

@myfindex ??
@item (?? command)  @code{command} may include @code{*} wildcards
Prints more info than @code{(? command)}.  ?? is a synonym
for @code{morehelp}.

@myfindex |
@item | is a synonym for @code{emodule-run}.

@myfindex all
@item (all geometry)  returns a list of names of all geometry objects.
Use e.g. @samp{(echo (all geometry))} to print such a list.
@item (all camera)	returns a list of names of all cameras.
@item (all emodule defined)  returns a list of all defined external modules.
@item (all emodule running)  returns a list of all running external modules.

@myfindex ap-override
@item (ap-override [on|off])
Selects whether appearance controls should override objects' own
settings.  On by default.  With no arguments, returns current setting.

@myfindex backcolor
@item (backcolor      CAM-ID R G B)
Set the background color of CAM-ID; R G B are numbers
between 0 and 1.

@myfindex background-image
@item (background-image CAM-ID [FILENAME])
Use the given image as the background of camera CAM-ID (which must be a
real camera, not @code{default} or @code{allcams}). Centers the image on
the window area.  Works only with GL and OpenGL graphics.
Use "" for filename to remove background.  With no filename argument,
returns name of that window's current background image, or "".  
Any file type acceptable as a texture is allowed, e.g. .ppm.gz, .sgi, etc.

@myfindex bbox-color
@item (bbox-color     GEOM-ID R G B)
Set the bounding-box color of GEOM-ID; R G B are numbers
between 0 and 1.

@myfindex bbox-draw
@item (bbox-draw      GEOM-ID [yes|no])
Say whether GEOM-ID's bounding-box should be drawn; @code{yes} if omitted.

@myfindex camera
@item (camera         CAM-ID [CAMERA])
Specify data for CAM-ID; CAMERA is a string giving an OOGL
camera specification.  If no camera CAM-ID exists,
it is created; in this case, the second argument is optional,
and if omitted, a default camera is used.  See also: new-camera.

@myfindex camera-draw
@item (camera-draw    CAM-ID [yes|no])
Say whether or not cameras should be drawn in CAM-ID; @code{yes} if omitted.

@myfindex camera-prop
@item (camera-prop { geometry object }   [projective])
Specify the object to be shown when drawing other cameras.
By default, this object is drawn with its origin at the camera,
and with the camera looking toward the object's -Z axis.
With the @code{projective} keyword, the camera's viewing projection is
also applied to the object; this places the object's Z=-1 and Z=+1 at
near and far clipping planes, with the viewing area -1<={X,Y}<=+1.
Example:  (camera-prop { < cube } projective)

@myfindex camera-reset
@item (camera-reset   CAM-ID)
Reset CAM-ID to its default value.

@myfindex car
@item (car LIST)
returns the first element of LIST.

@myfindex cdr
@item (cdr LIST)
returns the list obtained by removing the first element of LIST.

@myfindex clock
@item (clock)
Returns the current time, in seconds, as shown by this stream's clock.
See also set-clock and sleep-until.

@myfindex command
@item (command        INFILE [OUTFILE])
Read commands from INFILE; send corresponding responses
(e.g. anything written to filename @code{-}) to OUTFILE, stdout
by default.

@myfindex copy
@item (copy [ID] [name])
Copies an object or camera.  If ID is not specified, it 
is assumed to be targetgeom.  If name is not specified, it 
is assumed to be the same as the name of ID.

@myfindex cursor-still
@item (cursor-still [INT])
Sets the number of microseconds for which the cursor must not
move to register as holding still.  If INT is not specified,
the value will be reset to the default.

@myfindex cursor-twitch
@item (cursor-twitch	[INT])
Sets the distance which the cursor must not move (in x or
y) to register as holding still.  If INT is not specified,
the value will be reset to the default.

@myfindex delete
@item (delete         ID)
Delete object or camera ID.

@myfindex dice
@item (dice           GEOM-ID N)
Dice any Bezier patches within GEOM-ID into NxN meshes; default 10.
See also the appearance attribute @code{dice}, which makes this command
obsolete.

@myfindex dimension
@item (dimension [N])
Sets or reads the space dimension for N-dimensional viewing.
(Since calculations are done using homogeneous coordinates,
this means matrices are (N+1)x(N+1).)
With no arguments, returns the current dimension, or 0 if
N-dimensional viewing has not been enabled.

@myfindex dither
@item (dither  CAM-ID {on|off|toggle})
         Turn dithering on or off in that camera.

@myfindex draw
@item (draw           CAM-ID)
Draw the view in CAM-ID, if it needs redrawing.  See also @code{redraw}.

@myfindex echo
@item (echo          ...)
Write the given data to the special file @code{-}.  Strings are written
literally; lisp expressions are evaluated and their values written.
If received from an external program, @code{echo} sends to the program's
input.  Otherwise writes to geomview's own standard output
(typically the terminal).

@myfindex emodule-clear
@item (emodule-clear)
Clears the geomview application (external module) browser.

@myfindex emodule-define
@item (emodule-define  NAME  SHELL-COMMAND ...)
        Define an external module called NAME, which then appears in the
        external-module browser.  The SHELL-COMMAND string
        is a UNIX shell command which invokes the module.
        See emodule-run for discussion of external modules.

@myfindex emodule-defined
@item (emodule-defined @code{modulename})
If the given external-module name is known, returns the name of
the program invoked when it's run as a quoted string; otherwise
returns nil.  @code{(echo (emodule-defined @code{name}))} prints the string.

@myfindex emodule-isrunning
@item (emodule-isrunning NAME)
Returns Lt if the emodule NAME is running, or Lnil
if it is not running.  NAME is searched for in the
names as they appear in the browser and in the shell commands
used to execute the external modules (not including arguments).

@myfindex emodule-path
@item (emodule-path)
Returns the current search path for external modules.
Note: to actually see the value returned by this function
you should wrap it in a call to echo: (echo (emodule-path)).
        See also set-emodule-path.

@myfindex emodule-run
@item (emodule-run  SHELL-COMMAND ARGS...)
Runs the given SHELL-COMMAND (a string containing a UNIX shell
command) as an external module.  The module's standard output
is taken as geomview commands; responses (written to filename
@code{-}) are sent to the module's standard input.  The shell
command is interpreted by /bin/sh, so e.g. I/O redirection may
be used; a program which prompts the user for input from the
terminal could be run with:
  (emodule-run  yourprogram  <&2)
If not already set, the environment variable $MACHTYPE is set
to the name of the machine type.  Input and output
connections to geomview are dropped when the shell command
terminates.  Clicking on a running program's module-browser entry
sends the signal SIGHUP to the program.  For this to work, programs
should avoid running in the background; those using FORMS or GL
should call foreground() before the first FORMS or winopen() call.
See also emodule-define, emodule-start.

@myfindex emodule-sort
@item (emodule-sort)
        Sorts the modules in the application browser alphabetically.

@myfindex emodule-start
@item (emodule-start  NAME)
        Starts the external module NAME, defined by emodule-define.
        Equivalent to clicking on the corresponding module-browser entry.

@myfindex emodule-transmit
@item (emodule-transmit NAME LIST)
Places LIST into external module NAME's standard input.  NAME is
searched for in the names of the modules as they appear in the
External Modules browser and then in the shell commands used to
execute the external modules.  Does nothing if modname is not
running.

@myfindex escale
@item (escale          GEOM-ID FACTOR)
Same as scale but multiplies by exp(scale).  Obsolete.

@myfindex event-keys
@item (event-keys {on|off})
         Turn keyboard events on or off to enable/disable keyboard shortcuts.

@myfindex event-mode
@item (event-mode     MODESTRING)
Set the mouse event (motion) mode; MODESTRING should be one of
the strings that appears in the motion mode browser (including
the keyboard shortcut, e.g. @code{[r] Rotate}).

@myfindex event-pick
@item (event-pick {on|off})
Turn picking on or off.

@myfindex evert
@item (evert          GEOM-ID [yes|no])
Set the normal eversion state of GEOM-ID.  If the second argument
is omitted, toggle the eversion state.

@myfindex exit
@item (exit)
Terminates geomview.

@myfindex ezoom
@item (ezoom          GEOM-ID FACTOR)
Same as zoom but multiplies by exp(zoom).  Obsolete.

@myfindex freeze
@item (freeze         CAM-ID)
Freeze CAM-ID; drawing in this camera's window is turned off
until it is explicitly redrawn with @code{(redraw CAM-ID)}, after
which time drawing resumes as normal.

@myfindex geometry
@item (geometry       GEOM-ID [GEOMETRY])
Specify the geometry for GEOM-ID.  GEOMETRY is a string
giving an OOGL geometry specification.  If no object
called GEOM-ID exists, it is created; in this case the
GEOMETRY argument is optional, and if omitted, the new
object GEOM-ID is given an empty geometry.

@myfindex geomview-version
@item (geomview-version)
Returns a string representing the version of geomview that is
running.

@myfindex hdefine
@item (hdefine  @code{geometry}|@code{camera}|@code{transform}|@code{window}  name  value)
Sets the value of a handle of a given type.
@example
  (hdefine  <type>  <name>  <value>)
@end example
is generally equivalent to
@example
  (read <type>  { define <name> <value> })
@end example
except that the assignment is done when hdefine is executed,
(possibly not at all if inside a conditional statement),
while the @code{read ... define} performs assignment as soon as the
text is read.


@myfindex help
@item (help		[command])
Command may include @code{*}s as wildcards; see also @code{??}
One-line command help; lists names only if multiple commands match.

@myfindex hmodel
@item (hmodel CAMID {virtual|projective|conformal})
Set the model used to display geometry in
this camera; see also @code{space}.

@myfindex hsphere-draw
@item (hsphere-draw   CAMID [yes|no])
Say whether to draw a unit sphere: the sphere at infinity in
hyperbolic space, and a reference sphere in Euclidean and spherical
spaces.  If the second argument is omitted, @code{yes} is assumed.

@myfindex if
@item (if TEST EXPR1 [EXPR2])
Evaluates TEST; if TEST returns a non-nil value, returns the
value of EXPR1.  If TEST returns nil, returns the value of
EXPR2 if EXPR2 is present, otherwise returns nil.

@myfindex inhibit-warning
@item (inhibit-warning STRING)
Inhibit warning inhbits geomview from displaying a
particular warning message determined by STRING.
At present there are no warning messages that this
applies to, so this command is rather useless.

@myfindex input-translator
@item (input-translator  "#prefix_string"  "Bourne-shell-command")
Defines an external translation program for special input types.
When asked to read a file which begins with the specified string,
geomview invokes that program with standard input coming from the given file.
The program is expected to emit OOGL geometric data to its standard output.
In this implementation, only prefixes beginning with # are recognized.
Useful as in
@example
  (input-translator "#VRML" "vrml2oogl")
@end example

@myfindex interest
@item (interest (COMMAND [args]))

Allows you to express interest in a command.  When geomview
executes that command in the future it will echo it to the
communication pool from which the interest command came.
COMMAND can be any command.  Args specify restrictions on the
values of the arguments; if args are present in the interest
command, geomview will only echo calls to the command in which
the arguments match those given in the interest command.  Two
special argument values may appear in the argument list.  @code{*}
matches any value. @code{nil} matches any value but supresses the
reporting of that value; its value is reported as @code{nil}.

The purpose of the interest command is to allow external
modules to find out about things happening inside geomview.
For example, a module interested in knowing when a geom called
@code{foo} is deleted could say @code{(interest (delete foo))} and would
receive the string @code{(delete foo)} when foo is deleted.

Picking is a special case of this.  For most modules
interested in pick events the command @code{(interest (pick
world))} is sufficient.  This causes geomview to send a string
of the form @code{(pick world ...)} every time a pick event (right
mouse double click).  See the @code{pick} command for details.

@myfindex lines-closer
@item (lines-closer   CAM-ID DIST)
Draw lines (including edges) closer to the camera than polygons
by DIST / 10^5  of the Z-buffer range.  DIST = 3.0 by default.
If DIST is too small, a line lying on a surface may be
dotted or invisible, depending on the viewpoint.
If DIST is too large, lines may appear in front of surfaces
that they actually lie behind.  Good values for DIST vary with
the scene, viewpoint, and distance between near and far clipping
planes.  This feature is a kludge, but can be helpful.

@myfindex load
@item (load  filename  [command|geometry|camera])
Loads the given file into geomview.  The optional second argument
specifies the type of data it contains, which may be @code{command}
(geomview commands), @code{geometry} (OOGL geometric data), or
@code{camera} (OOGL camera definition).  If omitted, attempts to guess
about the file's contents.
Loading geometric data creates a new visible object; loading a camera
opens a new window; loading a command file executes those commands.


@myfindex load-path
@item (load-path)
Returns the current search path for command, geometry, etc. files.
Note: to actually see the value returned by this function
you should wrap it in a call to echo: (echo (load-path)).
See also set-load-path.

@myfindex look
@item (look [objectID] [cameraID])
Rotates the named camera to point toward the center of the 
bounding box of the named object (or the origin in hyperbolic or 
spherical space).  In Euclidean space, moves the camera 
forward or backward until the object appears as large 
as possible while still being entirely visible.  Equivalent to 
progn ( 
	(look-toward [objectID] [cameraID] {center | origin})
	[(look-encompass [objectID] [cameraID])] 
) 
If objectID is not specified, it is assumed to be World.  If 
cameraID is not specified, it is assumed to be targetcam.

@myfindex look-encompass
@item (look-encompass [objectID] [cameraID])
Moves cameraID backwards or forwards until its field of view
surrounds objectID. This routine works only in Euclidean space.  
If objectID is not specified, it is assumed to be the world.  
If cameraID is not specified, it is assumed to be the targetcam.  
See also (look-encompass-size).

@myfindex look-encompass-size
@item (look-encompass-size [view-fraction  clip-ratio  near-margin far-margin])
Sets/returns parameters used by (look-encompass).
view-fraction is the portion of the camera window filled by the object,
clip-ratio is the max allowed ratio of near-to-far clipping planes.
The near clipping plane is 1/near-margin times closer than the near
edge of the object, and the far clipping plane is far-margin times
further away.  Returns the list of current values.
Defaults: .75  100  0.1  4.0


@myfindex look-recenter
@item (look-recenter [objectID] [cameraID])
Translates and rotates the camera so that it is looking in the 
-z direction (in objectID's coordinate system) at the center of 
objectID's bounding box (or the origin of the coordinate system 
in non-Eudlidean space).  In Euclidean space, the camera is also 
moved as close as possible to the object while allowing the 
entire object to be visible.  Also makes sure that the y-axes of 
objectID and cameraID are parallel.

@myfindex look-toward
@item (look-toward [objectID] [cameraID] [origin | center])
Rotates the named camera to point toward the origin of the
object's coordinate system, or the center of the object's
bounding box (in non-Euclidean space, the origin will be used 
automatically).  Default objectID is the world, default camera
is targetcam, default location to point towards is the center
of the bounding box.

@myfindex merge
@item (merge          {window|camera} CAM-ID  { WINDOW or CAMERA ... } )
Modify the given window or camera, changing just those properties
specified in the last argument.  E.g.
	(merge camera @code{Camera} { far 20 })
sets Camera's far clipping plane to 20 while leaving
other attributes untouched.

@myfindex merge-ap
@item (merge-ap       GEOM-ID APPEARANCE)
Merge in some appearance characteristics to GEOM-ID.
Appearance parameters include surface and line color, shading
style, line width, and lighting.

@myfindex merge-base-ap
@item merge-base-ap is a synonym for merge-baseap.

@myfindex merge-baseap
@item (merge-baseap   APPEARANCE)
Merge in some appearance characteristics to the base default
appearance (applied to every geom before its own apperance).
Lighting is typically included in the base appearance.

@myfindex morehelp
@item (morehelp    command)
@code{command} may include @code{*} wildcards.
Prints more info than @code{(help command)}.

@myfindex name-object
@item (name-object    ID NAME)
Assign a new NAME (a string) to ID.  A number is appended if
that name is in use (for example, @code{foo} -> @code{foo<2>}).  The new
name, possibly with number appended, may be used as object's
id thereafter.

@myfindex ND-axes
@item (ND-axes CAMID [CLUSTERNAME [Xindex Yindex Zindex]])
In our model for N-D viewing (enabled by (dimension)), objects in
N-space are viewed by N-dimensional @emph{camera clusters}.
Each real camera window belongs to some cluster, and shows &
manipulates a 3-D axis-aligned projected subspace of the N-space seen
by its cluster.  Moving one camera in a cluster affects its siblings.

The ND-axes command configures all this.  It specifies a camera's
cluster membership, and the set of N-space axes which become the
3-D camera's X, Y, and Z axes.  Axes are specified by their indices,
from 0 to N-1 for an N-dimensional space.  Cluster CLUSTERNAME is
implicitly created if not previously known.
To read a camera's configuration, use @code{(echo (ND-axes CAMID))}.


@myfindex ND-color
@item (ND-color CAMID
	[ (( [ID] (x0 x1 x2 ... xn) v r g b a   v r g b a  ... )
	   ((x0 ... xn)  v r g b a  v r g b a ...) ...)] )
Specifies a function, applied to each N-D vertex, which determines the
colors of N-dimensional objects as shown in camera CAMID.
Each coloring function is defined by a vector (in ID's coordinate system)
[x0 x1 ... xn] and by a sequence of value (v)/color(r g b a) tuples,
ordered by increasing v.  The inner product v = P.[x] is linearly
interpolated in this table to give a color.
If ID is omitted, the (xi) vector is assumed in universe coordinates.
The ND-color command specifies a list of such functions; each vertex
is colored by their sum (so e.g. green intensity could indicate
projection along one axis while red indicated another.
An empty list, as in (ND-color CAMID ()), suppresses coloring.
With no second argument, (ND-color CAMID) returns that camera's
color-function list.
Even when coloring is enabled, objects tagged with the @code{keepcolor}
appearance attribute are shown in their natural colors.


@myfindex ND-xform
@item (ND-xform OBJID [ntransform { idim odim  ... }])
Sets or returns the N-D transform of the given object.
In dimension N, this is an (N+1)x(N+1) matrix.
Note that all cameras in a camera-cluster have the same N-D transform.


@myfindex ND-xform-get
@item (ND-xform-get ID [from-ID])
Returns the N-D transform of the given object in the coordinate system
of from-ID (default @code{universe}), in the sense
  <point-in-ID-coords> * Transform = <point-in-from-ID-coords>


@myfindex new-alien
@item (new-alien      name [GEOMETRY])
Create a new alien (geom not in the world) with the given name
(a string).  GEOMETRY is a string giving an OOGL geometry
specification.  If GEOMETRY is omitted, the new alien
is given an empty geometry.  If an object with that name
already exists, the new alien is given a unique name.  The
light beams that are used to move around the lights are an
example of aliens. They're drawn but are not controllable the
way ordinary objects are: they don't appear in the object
browser and the user can't move them with the normal motion
modes.

@myfindex new-camera
@item (new-camera     name [CAMERA])
Create a new camera with the given name (a string).  If a
camera with that name already exists, the new object is given
a unique name.  If CAMERA is omitted a default camera is used.

@myfindex new-center
@item (new-center [id])
Stop id, then set id's transform to the identity.  Default id 
is target.  Also, if the id is a camera, calls 
(look-recenter World id).  The main function of the call to 
(look-recenter) is to place the camera so that it is pointing 
parallel to the z axis toward the center of the world.

@myfindex new-geometry
@item (new-geometry   name [GEOMETRY])
Create a new geom with the given name (a string).  GEOMETRY is
a string giving an OOGL geometry specification.  If
GEOMETRY is omitted, the new object is given an empty geometry.
If an object with that name already exists, the new object is
given a unique name.

@myfindex new-reset
@item (new-reset)
Equivalent to (progn (new-center ALLGEOMS)(new-center ALLCAMS))

@myfindex NeXT
@item (NeXT)
Returns t if running on a NeXT, nil if not

@myfindex normalization
@item (normalization  GEOM-ID {each|none|all|keep})
Set the normalization status of GEOM-ID.
@table @code
@item none
suppresses all normalization.
@item each
normalizes the object's bounding box to fit into the unit
sphere, with the center of its bounding box translated
to the origin.  The box is scaled such that its long diagonal,
sqrt((xmax-xmin)^2 + (ymax-ymin)^2 + (zmax-zmin)^2), is 2.
@item all
resembles @code{each}, except when an object is changing
(e.g. when its geometry is being changed by an external program).
Then, @code{each} tightly fits the bounding box around the
object whenever it changes and normalizes accordingly,
while @code{all} normalizes the union of all variants of the object
and normalizes accordingly.
@item keep
leaves the current normalization transform unchanged
when the object changes.  It may be useful to apply @code{each} or
@code{all} normalization apply to the first version of a changing
object to bring it in view, then switch to @code{keep}.
@end table

@myfindex pick
@item (pick COORDSYS GEOMID G V E F P VI EI FI)
The pick command is executed internally in response to pick
events (right mouse double click).

COORDSYS = coordinate system in which coordinates of the following
    arguments are specified.   This can be:
	world: world coord sys
	self:  coord sys of the picked geom (GEOMID)
	primitive: coord sys of the actual primitive within
	    the picked geom where the pick occurred.
GEOMID = id of picked geom
G = picked point (actual intersection of pick ray with object)
V = picked vertex, if any
E = picked edge, if any
F = picked face
P = path to picked primitive [0 or more]
VI = index of picked vertex in primitive
EI = list of indices of endpoints of picked edge, if any
FI = index of picked face

External modules can find out about pick events by registering
interest in calls to @code{pick} via the @code{interest} command.

@myfindex pick-invisible
@item (pick-invisible [yes|no])
Selects whether picks should be sensitive to objects whose appearance
makes them invisible; default yes.
With no arguments, returns current status.

@myfindex pickable
@item (pickable       GEOM-ID {yes|no})
Say whether or not GEOM-ID is included in the pool of objects
that could be returned from the pick command.

@myfindex position
@item (position       objectID otherID)
Set the transform of objectID to that of otherID.

@myfindex position-at
@item (position-at    objectID otherID [center | origin])
Translate objectID to the center of the bounding box or the 
origin of the coordinate system of otherID (parallel translation).
Default is center.

@myfindex position-toward
@item (position-toward objectID otherID [center | origin])
Rotate objectID so that the center of the bounding box
or the origin of the coordinate system of the otherID
lies on the positive z-axis of the first object.  Default is
the center of the bounding box.

@myfindex progn
@item (progn STATEMENT [ ... ])
evaluates each STATEMENT in order and returns the value of the
last one.  Use progn to group a collection of commands together,
forcing them to be treated as a single command.

@myfindex quit
@item quit is a synonym for @code{exit}

@myfindex quote
@item (quote EXPR)
returns the symbolic lisp expression EXPR without evaluating it.

@myfindex rawevent
@item (rawevent       dev val x y t)
Enter the specified raw event into the event queue.  The
arguments directly specify the members of the event structure
used internally by geomview.  This is the lowest level event
handler and is not intended for general use.

@myfindex rawpick
@item (rawpick CAMID X Y)
Process a pick event in camera CAMID at location (X,Y) given in
integer pixel coordinates.  This is a low-level procedure not
intended for external use.

@myfindex read
@item (read {geometry|camera|transform|command} {GEOMETRY or CAMERA or ...})
Read and interpret the text in ... as containing the
given type of data.  Useful for defining objects using OOGL
reference syntax, e.g.

  (geometry  thing { INST  transform : T    geom : fred })
  (read  geometry  { define fred QUAD 1 0 0  0 1 0  0 0 1  1 0 0 })
  (read  transform { define T <myfile})

@myfindex real-id
@item (real-id ID)
Returns a string canonically identifying the given ID,
or @code{nil} if the object does not exist.  Examples:
 (if (real-id fred) (delete fred))
deletes @code{fred} if it exists but reports no error if it doesn't, and
 (if (= (real-id targetgeom) (real-id World)) () (delete targetgeom))
deletes @code{targetgeom} if it is different from the World.


@myfindex redraw
@item (redraw         CAM-ID)
States that the view in CAM-ID should be redrawn on the
next pass through the main loop or the next invocation of @code{draw}.

@myfindex regtable
@item (regtable) --- shows the registry table

@myfindex rehash-emodule-path
@item (rehash-emodule-path)
Rebuilds the application (external module) browser by reading
all .geomview-* files in all directories on the emodule-path.
Primarily intended for internal use; any applications defined
by (emodule-define ...) commands outside of the .geomview-*
files on the emodule-path will be lost.  Does not sort the
entries in the brower; see (emodule-sort) for that.

@myfindex replace-geometry
@item (replace-geometry GEOM-ID PART-SPECIFICATION GEOMETRY)
Replace a part of the geometry for GEOM-ID.

@myfindex rib-display
@item (rib-display    [frame|tiff] FILEPREFIX)
Set Renderman display to framebuffer (popup screen window) or a
TIFF format disk file. FILEPREFIX is used to construct
names of the form @code{prefixNNNN.suffix}. (i.e. foo0000.rib)
The number is incremented on every call to @code{rib-snapshot} and
reset to 0000 when @code{rib-display} is called. TIFF files are given
the same prefix and number as the RIB file (i.e. foo0004.rib
generates foo0004.tiff). The default FILEPREFIX is @code{geom} and
the default format is TIFF. (Note that geomview just generates a
RIB file, which must then be rendered.)

@myfindex rib-snapshot
@item (rib-snapshot   CAM-ID  [filename])
Write Renderman snapshot (in RIB format) of CAM-ID to <filename>.
If no filename specified, see @code{rib-display} for explanation of
the filename used.

@myfindex scale
@item (scale          GEOM-ID FACTOR [FACTORY FACTORZ])
Scale GEOM-ID, multiplying its size by FACTOR.  The factors 
should be positive numbers.  If FACTORY and FACTORZ are 
present and non-zero, the object is scaled by FACTOR in x, by 
FACTORY in y, and by FACTORZ in z.  If only FACTOR is present, 
the object is scaled by FACTOR in x, y, and z.  Scaling only 
really makes sense in Euclidean space.  Mouse-driven scaling in 
other spaces is not allowed;  the scale command may be issued 
in other spaces but should be used with caution because it may 
cause the data to extend beyond the limits of the space.

@myfindex scene
@item (scene          CAM-ID [GEOMETRY])
Make CAM-ID look at GEOMETRY instead of at the universe.

@myfindex set-clock
@item (set-clock TIME)
Adjusts the clock for this command stream to read TIME (in seconds)
as of the moment the command is received.  See also sleep-until, clock.

@myfindex set-conformal-refine
@item (set-conformal-refine CMX [N [SHOWEDGES]])
Sets the parameters for the refinement algorithm used in drawing
in the conformal model.  CMX is the cosine of the maximum angle
an edge can bend before it is refined.  Its value should be between
-1 and 1; the default is 0.95; decreasing its value will cause less
refinement.  N is the maximum number of iterations of refining;
the default is 6.  SHOWEDGES, which should be @code{no} or @code{yes},
determines whether interior edges in the refinement are drawn.

@myfindex set-emodule-path
@item (set-emodule-path      (PATH1 ... PATHN))
Sets the search path for external modules.  The PATHi should
be pathnames of directories containing, for each module, the
module's executable file and a .geomview-<modulename> file
which contains an (emodule-define ...) command for that
module.  This command implicitly calls (rehash-emodule-path)
to rebuild the application brower from the new path setting.
The special directory name @code{+} is replaced by the existing path,
so e.g. (set-emodule-path (mydir +)) prepends mydir to the path.

@myfindex set-load-path
@item (set-load-path      (PATH1 ... PATHN))
Sets search path for command, geometry, etc. files.  The PATHi
are strings giving the pathnames of directories to be searched.
The special directory name @code{+} is replaced by the existing path,
so e.g. (set-load-path (mydir +)) prepends mydir to the path.

@myfindex set-motionscale
@item (set-motionscale X)
Set the motion scale factor to X (default value 0.5).  These
commands scale their motion by an amount which depends on the
distance from the frame to the center and on the size of the
frame.  Specifically, they scale by
        dist + scaleof(frame) * motionscale
where dist is the distance from the center to the frame and
motionscale is the motion scale factor set by this function.
Scaleof(frame) measures the size of the frame object.

@myfindex setenv
@item (setenv  name string)  sets the environment variable @code{name} to the value

@var{string};
the name is visible to geomview (as in pathnames containing @code{$name})
and to processes it creates, e.g. external modules.

@myfindex sgi
@item (sgi)
Returns t if running on an sgi machine, nil if not

@myfindex shell
@item (shell         SHELL-COMMAND)
Execute the given UNIX SHELL-COMMAND using /bin/sh.  Geomview
waits for it to complete and will be unresponsive until it does.
A synonym is @code{!}.

@myfindex sleep-for
@item (sleep-for  TIME)
Suspend reading commands from this stream for TIME seconds.
Commands already read will still be executed; @code{sleep-for} inside
@code{progn} won't delay execution of the rest of the progn's contents.

@myfindex sleep-until
@item (sleep-until TIME)
Suspend reading commands from this stream until TIME (in seconds).
Commands already read will still be executed; @code{sleep-until} inside
@code{progn} won't delay execution of the rest of the progn's contents.
Time is measured according to this stream's clock, as set by
@code{set-clock}; if never set, the first sleep-until sets it to 0
(so initially (sleep-until TIME) is the same as (sleep-for TIME)).
Returns the number of seconds until TIME.

@myfindex snapshot
@item (snapshot       CAM-ID     FILENAME [FORMAT [XSIZE [YSIZE]]])
Save a snapshot of CAM-ID in the FILENAME (a string).  The
FORMAT argument is optional; it may be @code{ppmscreen},
@code{sgi}, @code{ps}, or @code{ppm}.  A @code{ppmscreen} snapshot is created by reading
the image directly from the given window; the window is popped above
other windows and redrawn first, then its contents are written as a
PPM format image.  With @code{ps}, dumps a Postscript picture representing
the view from that window; hidden-surface removal might be incorrect.
With @code{ppm}, dumps a PPM-format image produced by geomview's internal
software renderer; this may be of arbitrary size.  If the FILENAME
argument begins with the vertical bar @code{|}, it's interpreted as a
/bin/sh command to which the PPM or PS data should be piped.
Optional XSIZE and YSIZE values are relevant only for @code{ppm} format,
and render to a window of that size (or scaled to that size,
with aspect fixed, if only XSIZE is given)

@myfindex soft-shader
@item (soft-shader  CAM-ID  {on|off|toggle})
Select whether to use software or hardware shading in that camera.

@myfindex space
@item (space {euclidean|hyperbolic|spherical})
Set the space associated with the world.

@myfindex stereowin
@item (stereowin CAM-ID  [no|horizontal|vertical|colored] [gapsize])
Configure CAM-ID as a stereo window.
no: entire window is a single pane, stereo disabled@*
horizontal: split left/right: left is stereo eye#0, right is #1.@*
vertical: split top/bottom: bottom is eye#0, top is #1.@*
colored: panes overlap, red is stereo eye#0, cyan is #1.

A gap of @code{gapsize} pixels is left between subwindows;
if omitted, subwindows are adjacent.
If both layout and gapsize are omitted, e.g. (stereowin CAM-ID),
returns current settings as a @code{(stereowin ...)} command list.
This command doesn't set stereo projection; use @code{merge camera} or
@code{camera} to set the stereyes transforms, and @code{merge window} or
@code{window} to set the pixel aspect ratio & window position if needed.

@myfindex time-interests
@item (time-interests deltatime initial prefix [suffix])
Indicates that all interest-related messages, when separated by at
least @code{deltatime} seconds of real time, should be preceded by
the string @code{prefix} and followed by @code{suffix}; the first message
is preceded by @code{initial}.  All three are printf format strings,
whose argument is the current clock time (in seconds) on that stream.
A @code{deltatime} of zero timestamps every message.  Typical usage:@*
(time-interests .1 @code{(set-clock %g)} @code{(sleep-until %g)})  or@*
(time-interests .1 @code{(set-clock %g)}
	"(sleep-until %g) (progn (set-clock %g)" ")")    or@*
(time-interests .1 "(set-clock %g)"
		   "(if (> 0 (sleep-until %g)) (" "))".

@myfindex transform
@item (transform      objectID centerID frameID [rotate|translate|translate-scaled|scale] x y z [dt] [@code{smooth}])
Apply a motion (rotation, translation, scaling) to object @code{objectID};
that is, construct and concatenate a transformation matrix with
objectID's transform  The 3 IDs involved are the object
that moves, the center of motion, and the frame of reference
in which to apply the motion.  The center is easiest understood
for rotations: if centerID is the same as objectID then it will
spin around its own axes; otherwise the moving object will orbit
the center object.  Normally frameID, in whose coordinate system
the (mouse) motions are interpreted, is @code{focus}, the current camera.
Translations can be scaled proportional to the
distance between the target and the center. Support for
spherical and hyperbolic as well as Euclidean space is
built-in: use the @code{space} command to change spaces.  With type
@code{rotate} x, y, and z are floats specifying angles in RADIANS.
For types @code{translate} and @code{translate-scaled} x, y, and z are
floats specifying distances in the coordinate system of the
center object.  The optional @code{dt} field allows a simple form of
animation; if present, the object moves by just that amount during
approximately @code{dt} seconds, then stops.  If present and followed by
the @code{smooth} keyword, the motion is animated with a 3t^2-2t^3
function, so as to start and stop smoothly.  If absent, the motion is
applied immediately.

@myfindex transform-incr
@item (transform-incr  objectID centerID frameID [rotate|translate|translate-scaled|scale] x y z [dt])
Apply continuing motion: construct a transformation matrix and
concatenate it with the current transform of objectID every
refresh (sets objectID's incremental transform). Same syntax
as transform.  If optional @code{dt} argument is present,
the object is moved at each time step such that its average motion
equals one instance of the motion per @code{dt} seconds.  E.g.
  (transform-incr  World World World  rotate  6.28318 0 0  10.0)
rotates the World about its X axis at 1 turn (2pi radians) per 10 seconds.


@myfindex transform-set
@item (transform-set objectID centerID frameID [rotate|translate|translate-scaled|scale] x y z)
Set objectID's transform to the constructed transform.
Same syntax as transform.

@myfindex ui-center
@item (ui-center      ID)
        Set the center for user interface (i.e. mouse) controlled
        motions to object ID.

@myfindex ui-emotion-program
@item ui-emotion-program is an obsolete command.
Use its new eqivalent @code{emodule-define} instead.

@myfindex ui-emotion-run
@item ui-emotion-run is an obsolete command.
Use its new eqivalent @code{emodule_start} instead.

@myfindex ui-freeze
@item (ui-freeze [on|off])
        Toggle updating user interface panels. Off by default.

@myfindex ui-panel
@item (ui-panel       PANELNAME  {on|off} [ WINDOW ] )
        Do or don't display the given user-interface panel.
        Case is ignored in panel names.  Current PANELNAMEs are:
                geomview        main panel
                tools           motion controls
                appearance      appearance controls
                cameras         camera controls
                lighting        lighting controls
                obscure         obscure controls
                materials       material properties controls
                command         command entry box
                credits         geomview credits
        By default, the @code{geomview} and @code{tools} panels appear when
        geomview starts.  If the optional Window is supplied, a
        @code{position} clause (e.g. (ui-panel obscure on { position xmin
        xmax ymin ymax }) sets the panel's default position.  (Only
        xmin and ymin values are actually used.)  A present but empty
        Window, e.g.  @code{(ui-panel obscure on {})} causes interactive
        positioning.

@myfindex ui-target
@item (ui-target      ID [yes|no])
        Set the target of user actions (the selected line of the
        target object browser) to ID.  The second argument specifies
        whether to make ID the current object regardless of its type.
        If @code{no}, then ID becomes the current object of its type
        (geom or camera).  The default is @code{yes}.  This command may
        result in a change of motion modes based on target choice.

@myfindex uninterest
@item (uninterest (COMMAND [args]))
Undoes the effect of an @code{interest} command.  (COMMAND [args]) must
be identical to those used in the @code{interest} command.

@myfindex update
@item (update [timestep_in_seconds])
Apply each incremental motion once.  Uses timestep if it's present and
nonzero; otherwise motions are proportional to elapsed real time.

@myfindex update-draw
@item (update-draw    CAM-ID  [timestep_in_seconds])
Apply each incremental motion once and then draw CAM-ID.
Applies @code{timestep} seconds' worth of motion, or uses elapsed real
time if @code{timestep} is absent or zero.

@myfindex window
@item (window         CAM-ID  WINDOW)
Specify attributes for the window of CAM-ID, e.g. its size
or initial position, in the OOGL Window syntax.
The special CAM-ID @code{default} specifies
properties of future windows (created by @code{camera} or
@code{new-camera}).

@myfindex winenter
@item (winenter       CAM-ID)
Tell geomview that the mouse cursor is in the window
of CAM-ID.  This function is for development purposes
and is not intended for general use.

@myfindex write
@item (write {command,geometry,camera,transform,window} FILENAME [ID|(ID ...)] [self|world|universe|otherID])
write description of ID in given format to FILENAME.  Last
parameter chooses coordinate system for geometry & transform:
self: just the object, no transformation or appearance (geometry only)
world: the object as positioned within the World.
universe: object's position in universal coordinates;
includes Worldtransform
other ID: the object transformed to otherID's coordinate system.

A filename of @code{-} is a special case: data are written to the
stream from which the 'write' command was read.  For external
modules, the data are sent to the module's standard input.
For commands not read from an external program, @code{-} means
geomview's standard output.  (See also the @code{command}
command.)

The ID can either be a single id or a parenthesized list of
ids, like @code{g0} or @code{(g2 g1 dodec.off)}.

@myfindex write-comments
@item (write-comments FILENAME GEOMID PICKPATH)
write OOGL COMMENT objects in the GEOMID hierarchy at the
 	level of the pick path to FILENAME. Specifically, COMMENTS
 	at level (a b c ... f g) will match pick paths of the form
 	(a b c ... f *) where * includes any value of g, and also
 	any values of possible further indices h,i,j, etc. The pick
 	path (returned in the @code{pick} command) is a list of
 	integer counters specifying a subpart of a hierarchical
 	OOGL object. Descent into a complex object (LIST or INST)
 	adds a new integer to the path. Traversal of simple objects
 	increments the counter at the current level.
 	Individual COMMENTS are enclosed by curly braces, and the
 	entire string of zero, one, or more COMMENTS (written in
 	the order in which they are encountered during hierarchy
 	traversal) is enclosed by parentheses.
        
        Note that arbitrary data can only be passed through the OOGL
 	libraries as full-fledged OOGL COMMENT objects, which can be
 	attached to other OOGL objects via the LIST type as described
 	above. Ordinary comments in OOGL files (i.e. everything after
 	'#' on a line) are ignored at when the file is loaded and
 	cannot be returned.

@myfindex write-sexpr
@item (write-sexpr     FILENAME LISPOBJECT)
Writes the given LISPOBJECT to FILENAME. This function is intended
for internal debugging use only.

@myfindex xform
@item (xform          ID TRANSFORM)
Concatenate TRANSFORM with the current transform of the object
(apply TRANSFORM to object ID).

@myfindex xform-incr
@item (xform-incr     ID TRANSFORM)
Apply continual motion: concatenate TRANSFORM with the current
transform of the object every refresh (set object ID's
incremental transform to TRANSFORM).

@myfindex xform-set
@item (xform-set      ID TRANSFORM)
Overwrite the current object transform with TRANSFORM (set
object ID's transform to TRANSFORM).

@myfindex zoom
@item (zoom           CAM-ID FACTOR)
Zoom CAM-ID, multiplying its field of view by FACTOR.
FACTOR should be a positive number.

@end table


@comment ****************************************************************
@node Non-Euclidean Geometry,Mathematica,Gcl Reference,Top
@chapter Non-Euclidean Geometry

Geomview supports hyperbolic and spherical geometry as well as
Euclidean geometry.  The three buttons at the bottom of the @panel{Main}
panel are for setting the current geometry type.

In each of the three geometries, three models are supported:
@widget{Virtual}, @widget{Projective}, and @widget{Conformal}.  You can
change the current model with the @widget{Model} browser on the
@panel{Camera} panel.  Each Geomview camera has its own model setting.

The default model is all three spaces is @widget{Virtual}.  This
corresponds to the camera being in the same space as, and moving under
the same set of transformations as, the geometry itself.

In Euclidean space @widget{Virtual} is the most useful model.
The other models were implemented for hyperbolic and spherical
spaces and just happen to work in Eucldiean space as well:
@widget{Projective} is the same as @widget{Virtual} but by default
displays the unit sphere, and @widget{Conformal} displays everything
inverted in the unit sphere.

In hyperbolic space, the @widget{Projective} model setting gives a view
of the projective ball model of hyperbolic 3-space imbedded in Euclidean
space.  The camera is initially outside the unit ball.  In this model,
the camera moves by Euclidean motions and geometry moves by hyperbolic
motions.  @widget{Conformal} model is similar but shows the conformal
ball model instead. 

In spherical space, the @widget{Projective} model gives a view of half
of the 3-sphere imbedded in Euclidean 3-space.  Spherical motions give
rise to projective transformations in the @widget{Projective} model, and
to
@tex
Mo\"bius
@end tex
@ifinfo
Moebius
@end ifinfo
transformations in the @widget{Conformal} model.  In both of these
models the camera moves by Euclidean motions.

In @widget{Projective} and @widget{Conformal} models, the unit sphere is
drawn by default.  You can turn it off and on at will using the
@widget{Draw Sphere} button in the @panel{Camera} panel.  In the
@widget{Conformal} model, polygons and edges are subdivided as necessary
to make them look curved.  The parameters which determine this
subdivision can be set with the @code{set-conformal-refine} gcl command.

There are several sample hyperbolic space objects in the
@file{data/geom/hyperbolic} subdirectory of the Geomview directory
(@file{/u/gcg/ngrap/data/geom/hyperbolic} on the Geometry Center's
system).  Likewise, the subdirectory @file{data/geom/spherical}
contains several sample spherical space objects.

@comment ****************************************************************
@node Mathematica,OOGL.m,Non-Euclidean Geometry,Top
@chapter Mathematica Graphics in Geomview or RenderMan

Geomview comes with some Mathematica packages that let you use use
Geomview to display Mathematica graphics.  Mathematica is a commercial
mathematical software system available from Wolfram Research, Inc.

There are two ways to do this.
@enumerate
@item
Use Mathematica to write a graphics object to a file in OOGL format
or in RIB format.
@item
Use Geomview as the default display for all 3D graphics output in
Mathematica.
@end enumerate
You can also use these packages to save Mathematica graphics in
RenderMan (RIB) format.

Since the format of Mathematica graphics objects is different from the
OOGL formats, both of these methods involve translating Mathematica
graphics to OOGL format.  Geomview is distributed with a Mathematica
package which does this translation.  Before doing either of the
above you must install this package.

@menu
* OOGL.m::		Generating OOGL files in Mathematica.
* Geomview.m::		Geomview as Mathematica's Default 3D Display.
* RenderMan::		Generating RenderMan files in Mathematica.
* Remote Display::	Using Geomview and Mathematica on different computers.
* Package Details::	Some details about the packages.
* Package Installation::  Installing the Mathematica->Geomview package.
@end menu

@comment ================================================================
@node OOGL.m,Geomview.m,Mathematica,Mathematica
@section Using Mathematica to generate OOGL files

The package @file{OOGL.m} allows Mathematica to write graphics objects
in OOGL format.  To use it, give the command @code{<< OOGL.m} to
Mathematica to load the package.  The
@code{WriteOOGL[@var{file},@var{graphics}]} command writes an OOGL
description of the 3D graphics object @var{graphics} to the file named
@var{file}.@refill

This package also provides the @code{Geomview} command which sends a
3D graphics object to Geomview.  The first time you use this command
it starts up a copy of Geomview.  Later calls send the graphics to the
same Geomview.  There are two ways to use the @code{Geomview} command.

@table @code
@item Geomview[@var{graphics}]
Sends the 3D graphics object @var{graphics} to Geomview as a geom named
@code{Mathematica}.  Subsequent usage of @code{Geomview[@var{graphics}]}
replaces the @code{Mathematica} object in Geomview with the new
@var{graphics}.

@item @code{Geomview[@var{name},@var{graphics}]}
Sends the 3D graphics object @var{graphics} to Geomview as a geom named
@var{name}.  You can use multiple calls of this form with different
names to cause Geomview to display several Mathematica objects at once
and allow independent control over them.
@end table
@example
% math
Mathematica 2.0 for SGI Iris
Copyright 1988-91 Wolfram Research, Inc.
 -- GL graphics initialized --

In[1] := <<OOGL.m
 
In[2] := Plot3D[Sin[x + Sin[y]], @{x,-2,2@},@{y,-2,2@}]

Out[2] := -Graphics3D-
@end example
@noindent
This displays graphics in the usual Mathematica way here.
@example
In[3] := WriteOOGL["math.oogl", %2]

Out[3] := -Graphics3D-
@end example
@noindent
This displays nothing new but writes the file @file{math.oogl}.
You can now load that file into Geomview on any computer.  Alternately,
you can use the @code{Geomview} command to start up a copy of Geomview
from within Mathematica.
@example
In[5] := Geomview[%2]

Out[5] := -Graphics3D-
@end example


@comment ================================================================
@node Geomview.m,RenderMan,OOGL.m,Mathematica
@section Using Geomview as Mathematica's Default 3D Display

The package @file{Geomview.m} arranges for Geomview to be the
default display program for 3D graphics in Mathematica.  To
load it, give the command @code{<< Geomview.m} to Mathematica.
Thereafter, whenever you display 3D graphics with @code{Plot3D}
or @code{Show}, Mathematica will send the graphics to Geomview.

Loading @file{Geomview.m} implicitly loads @file{OOGL.m} as well, so you
can use the @code{Geomview} and @code{WriteOOGL} as described above
after loading @file{Geomview.m}.  You do not have to separately load
@file{OOGL.m}.
@example
% math
Mathematica 2.0 for SGI Iris
Copyright 1988-91 Wolfram Research, Inc.
 -- GL graphics initialized --

In[1] := <<Geomview.m

In[2] := Plot3D[x^2 + y^2, @{x, -2, 2@}, @{y, -2, 2@}]

Out[2] := -SurfaceGraphics-
@end example
@noindent
This invokes geomivew and loads the graphics object into it.
@example
In[3] := Plot3D[@{x*y + 6, RGBColor[0,x,y]@}, @{x,0,1@}, @{y,0,1@}]

Out[3] := -SurfaceGraphics-
@end example
@noindent
This replaces the previous Geomview object by the new object. 
@example
In[4] := Geomview[@{%2,%3@}]

Out[4] := @{-SurfaceGraphics-, -SurfaceGraphics-@}
@end example
@noindent
This displays both objects at once.  You also can have more than one
Mathematica object at a time on display in Geomview, and have separate
control over them, by using the @code{Geomview} command with a name,
@xref{OOGL.m}.
@example
In[5] := Graphics3D[ @{RGBColor[1,0,0], Line[@{ @{2,2,2@},@{1,1,1@} @}] @}]

Out[5] := -Graphics3D-

In[6] := Geomview["myline", %5]
@end example
@noindent
This addes the @code{Line} specified in @code{In[5]} to the existing
Geomview display.  It can be controlled independently of the
"Mathematica" object, which is currently the list of two plots.
@example
In[7] := <<GL.m
@end example
@noindent
If you're on an SGI, loading @code{GL.m} returns Mathematica to its
usual 3D graphics display.  To do this on a NeXT you should load
@code{PSDirect.m} if you are using Mathematica in a notebook, or
@code{NeXT.m} if you invoked Mathematica from a shell.  The following
plot will appear in a normal static Mathematica window.
@example
In[8] := ParametricPlot3D[@{Sin[x],Sin[y],Sin[x]*Cos[y]@}, @{x,0,Pi@},@{y,0,Pi@}]

Out[8] := -Graphics3D-
@end example
@noindent
We can return to Geomview graphics at any time by reloading @file{Geomview.m}.
@example
In[9] := <<Geomview.m

In[10] := Show[%8]

Out[10] := -Graphics3D-

In[11] := ParametricPlot3D[
	   @{(2*(Cos[u] + u*Sin[u])*Sin[v])/(1 + u^2*Sin[v]^2),
	   (2*(Sin[u] - u*Cos[u])*Sin[v])/(1 + u^2*Sin[v]^2),
	   Log[Tan[v/2]] + (2*Cos[v])/(1 + u^2*Sin[v]^2)@},
	  @{u,-4,4@},@{v,.01,Pi-.01@}]

Out[11] := -Graphics3D-
@end example
This last plot is Kuen's surface, a surface of constant negative
curvature.  Parametrization from Alfred Gray's @emph{Modern Differential
Geometry of Curves and Surfaces} textbook.

@comment ================================================================
@node RenderMan,Remote Display,Geomview.m,Mathematica
@section Using Mathematica to generate RenderMan files

In addition to the @code{WriteOOGL} and @code{Geomview} commands
described above, the package @file{OOGL.m} also defines the command
@code{WriteRIB} which writes a 3D graphics object to a RenderMan RIB
file:  @code{WriteRIB[@var{file}, @var{graphics}]} writes @var{graphics}
to file @var{file}.  RenderMan is a commercial rendering system available
from Pixar, Inc., which can produce extremely high quality images.
@example
In[1] := <<OOGL.m

In[2] := <<Graphics/Polyhedra.m

In[3] := Graphics3D[Cube[]]

Out[3] := -Graphics3D-

In[4] := WriteRIB["cube.rib", %3]

Out[4] := -Graphics3D-
@end example
@noindent
This generates the file @file{math.rib}.  This is a ready-to-render RIB
file of the given geometry, using a default camera position, lighting,
and the ``plastic'' shader. In a shell window, type @code{render
cube.rib} to generate the image file @file{mma.tiff}. Of course, you
need to have RenderMan installed for this to work. A shortcut to render
from inside Mathematica is @code{WriteRIB["!render", foo]}.@refill

@code{WriteRIB} works by first converting the Mathematica graphics
object to OOGL format using @code{WriteOOGL} and then calls an external
program @file{oogl2rib} to convert OOGL to RIB format.  The
oogl2rib program takes several options which you can specify in a
string as an optional third argument to @code{WriteRIB}.  The default
option string is @code{" -n mma.tiff "}, which indicates that the RIB
file should generate a rendered TIFF file named @file{mma.tiff}.  A
particularly useful option is @code{-g}, which tells oogl2rib to
convert only the geometry into a RIB fragment. You can insert that
fragment into a full RIB file of your own making with camera positions
and shaders of your choice, to harness the full power of RenderMan.

The full usage of oogl2rib is:
@example
oogl2rib [-n @var{name}] [-B @var{r},@var{g},@var{b}] [-w @var{width}] [-h @var{height}] [-fgb] [@var{infile}] [@var{outfile}]
@end example
@noindent
By default it reads from stdin and writes to stdout.
Either @var{infile} or @var{outfile} may be @file{-}, which means
use stdin/stdout.  The options are:
@table @code

@item -n @var{name}
Use @var{name} for the name of the rendered TIFF file (default
"geom.tiff") or framebuffer window (default "geom.rib").

@item -B @var{r},@var{g},@var{b}
Use background color (@var{r},@var{g},@var{b}).  Each component ranges
from 0 to 1. Default: none.

@item -w @var{width} -h @var{height}
Rendered frame will be @var{width} by @var{height} pixels.

@item -f
RIB file renders to on-screen framebuffer instead of TIFF file.

@item -g
Output only the geometry in RIB format.

@item -b
Output only a Quick Renderman clip object.  Ignores -nBwhf.

@end table


@comment ================================================================
@node Remote Display,Networked Geomview,RenderMan,Mathematica
@section Using Geomview and Mathematica on Different Computers

It is possible to use Geomview to display graphics generated by
Mathematica running on a different computer.  If each computer is either
an SGI or a NeXT and they are networked together, you can tell
Mathematica to use a remote host for Geomview graphics.  If you want to
use Mathematica on a computer that is not networked with your Geomview
computer, or on any kind of computer other than an SGI or a NeXT (for
example a PC or a Mac), you can write out @emph{chunk} files in
Mathematica which you transfer to the Geomview computer and then
translate to OOGL format.

@menu
* Networked Geomview::	Using a networked Geomview host.
* Chunks::		Transporting Mathematica files to Geomview by Hand.
@end menu

@comment ----------------------------------------------------------------
@node Networked Geomview,Chunks,Remote Display,Remote Display
@subsection Using a Networked Geomview Host

The @code{Geomview} command looks at the @code{DISPLAY} or
@code{REMOTEHOST} environment variables to try to determine if you are
logged in from another computer.  If either of these indicates that you
are, @code{Geomview} will attempt to run Geomview on that
computer.  In order for this to work, your network must be configured
such that the Mathematica computer can successfully @code{rsh} to the
Geomview computer without giving a password.

You can also explicitly set the @code{DisplayHost} option to the
@code{Geomview} command to a string which is the desired hostname, for
example:
@example
In[1] := << OOGL.m

In[2] := Plot3D[Sin[x + Sin[y]], @{x,-2,2@},@{y,-2,2@}]

Out[2] := -Graphics3D-

In[3] := Geomview[%3, DisplayHost->"riemann"]
@end example
@noindent
This displays the graphics @code{%3} on the remote host named
@code{riemann}.@refill

@code{Geomview} recognizes the string @code{"local"} as a value for
@code{@$DisplayHost}; it forces the graphics to be displayed on the local
machine.@refill

In addition to knowing the name of the machine you want to run Geomview
on, the @code{Geomview} needs to know the type of that machine (SGI or
NeXT).  By default, @code{Geomview} assumes that it is the same kind of
computer as the one you are running Mathematica on.  The @code{MachType}
option lets you explicitly specify the type of the @code{DisplayHost}
computer; it should be one of the strings @code{"sgi"} or
@code{"next"}.@refill

You can use @code{SetOptions} to change the default @code{DisplayHost}
and @code{MachType}.  For example,
@example
In[4] := SetOptions[Geomview, DisplayHost->"riemann", MachType->"sgi"]
@end example
@noindent
arranges for @code{Geomview} to run Geomview on an SGI workstation named
@code{riemann}.@refill

@comment ----------------------------------------------------------------
@node Chunks,Package Details,Networked Geomview,Remote Display
@subsection Transporting Mathematica Files to Geomview by Hand

The auxilliary function @code{WriteChunk} is for those who can only use
Mathematica on a non-Unix machine (Mac, PC) or a Unix machine that is
not on a network with an SGI or NeXT.  @code{WriteChunk[@var{file},
@var{graphics}]} generates a file named @var{file} which contains the
graphics object @var{graphics} in the format accepted by
@file{math2oogl}.@refill

You can transfer that file to a computer that has Geomview installed on
it and then use the programs @file{math2oogl}, @file{oogl2rib}, and
@file{geomview} directly from the shell.  These programs are distributed
in the @file{bin/sgi} (on SGIs) or @file{bin/next} (on NeXTs)
subdirectory of the Geomview directory, and may have been installed so
that they are on your @code{path}. 

@example
In[1]:= <<OOGL.m

In[2]:= Plot3D[ Sin[x + Sin[y]], {x,-2,2}, {y,-2,2} ]

Out[2]= -SurfaceGraphics-

In[3]:= WriteChunk["mychunk",%2]
@end example
@noindent
This writes the file @file{mychunk} which contains a description
of the graphics object.  You can then transfer this file to an SGI or
NeXT and type
@example
math2oogl < mychunk > mma.oogl
@end example
@noindent
to convert it to the OOGL file @file{mma.oogl} which you can then view
using Geomview. This is the equivalent of the @code{WriteOOGL} command. 

For a result equivalent to the @code{Geomview} or @code{Show}
commands, type
@example
math2oogl -togeomview Mathematica geomview < mychunk
@end example
@noindent

The @code{WriteRIB} command can be emulated from the shell as
@example
math2oogl < mychunk | oogl2rib -n mma.tiff
@end example
@noindent




@comment ================================================================
@node Package Details,Package Installation,Chunks,Mathematica
@section Details of the Mathematica->Geomview Package

The @file{OOGL.m} package uses the external program @file{math2oogl} to
convert @code{Graphics3D} objects to OOGL format, because a compiled
external program is able to do this conversion many times faster than
Mathematica.

The converter will sometimes handle colored SurfaceGraphics objects
correctly that Mathematica does not handle correctly, which means that
Geomview[object] sometimes works where Show[object] will give errors.

The converter supports the @code{Polygon}, @code{Line}, and @code{Point}
graphics primitives, @code{RGBColor Graphics3D} directives, and
@code{SurfaceGraphics} objects with or without @code{RGBColor}
directives, and lists of any combination of these. It silently ignores
all other directives.

The Mathematica to RenderMan conversion is actually a two-step process:
Mathematica->OOGL (math2oogl), and OOGL->RenderMan (oogl2rib). The
math2oogl program has only been tested on SGIs and NeXTs, but could
theoretically compile on any machine. The oogl2rib program depends on
the OOGL (Object Oriented Graphics Language) libraries, which now only
exist on SGI and NeXT machines.

In the @code{WriteOOGL} and @code{WriteRIB} commands, filename can
either be a string containing a filename, an @code{OutputStream} object,
or a string starting with a @code{!} to send the output to a command.
Object can be a @code{Graphics3D} object, a @code{SurfaceGraphics}
object, or a list of these.@refill

The packages work best with Mathematica 2.0 or better.  With version 1.2,
the Geomview display is always on the local host. 

@comment ================================================================
@node Package Installation,Installation,Package Details,Mathematica
@section Installing the Mathematica Packages

If Geomview is properly installed on your system according to the
instructions in @xref{Installation}, then the Mathematica-to-Geomview
packages should work as described here; there should be no need for
additional installation procedures.  In practice, however, it is
sometimes necessary to taylor the installation of the Mathematica
packages and/or of Geomview itself to suit the needs of a particular
system.  This section contains details about how the installation works;
if the Mathematica-to-Geomview connection does not seem to work for you
after following the Geomview installation procedure, consult this
section to see what might need to be fixed.

In this section, the phrase @emph{Geomview installation} refers any of
the procedures in @xref{Installation}.  The way the Mathematica packages
work and are installed is the same regardless of whether you have
one of the binary distributions or the source distribution.

@enumerate

@item
The relevant mathematica files are @file{OOGL.m}, @file{Geomview.m}, and
@file{BezierPlot.m}; Mathematica must be able to find these files.  They
are distributed in the @file{@$GEOMROOT/mathematica} subdirectory of the
binary distributions, and in the
@file{@$GEOMROOT/src/bin/geomutil/math2oogl} subdirectory of the source
distribution.  These files need to be in a directory that is on
Mathematica's search path.  You can look at the value of the
@code{@$Path} variable in a Mathematica session on your system to see a
list of the directories on Mathematica's search path.

The Geomview installation procedure puts copies of the Mathematica
packages into a directory that you specify (@code{MMAPACKAGEDIR}).  This
should ensure that Mathematica can find them.  Alternately, you could
arrange to append the pathname of the Mathmematica package subdirectory
of the Geomview distribution to the @code{@$Path} variable each time you
run Mathematica.

@item
The package @file{OOGL.m} needs to be able to invoke the programs
@file{geomview}, @file{math2oogl}, and @file{oogl2rib}.  The Geomview
installation procedure installs these programs into a directory that you
specify for executables (@code{BINDIR}).  Ideally, this directory should
be on your shell's @code{@$path}.  More specifically, it should be on
the @code{@$path} of the shell in which Mathematica runs; the directory
@file{/usr/local/bin} is usually a good choice.  You can see the list of
directories on this path by giving the command @code{!echo @$path} in
Mathematica.

If for some reason you can't arrange for @file{geomview},
@file{math2oogl}, and @file{oogl2rib} to be in a directory on the
shell's @code{@$path}, you can modify @file{OOGL.m} to cause it to look
for them using absolute pathnames.  To do this, change the definitions
of the variables @code{@$GeomviewPath} and @code{@$GeomRoot}, which are
defined near the top of the file.  Change @code{@$GeomviewPath} to the
absolute pathname of the @file{geomview} shell script on your system.
Change @code{@$GeomRoot} to the absolute pathname of the
@file{@$GEOMROOT} directory on your system.  If you do this, you should
also make sure there are copies of @file{geomview}, @file{math2oogl},
and @file{oogl2rib} in the @file{@$GEOMROOT/bin/sgi} (on an SGI) or
@file{@$GEOMROOT/bin/next} (on a NeXT) directory.

@item
The @file{geomview} shell script, which @file{OOGL.m} uses to invoke
Geomview, needs to be able to find the geomview executable file (which
is called @file{gvx} on the SGI and @file{Geomview.app/Geomview} on the
NeXT).  The Geomview installation procedure should have been taken care
of this, but if your Mathematica session doesn't seem to be able to
invoke Geomview, it's worth double-checking that the settings in the
@file{geomview} script are correct.

@end enumerate

@comment ****************************************************************
@node Installation,SGI Binary Installation,Package Installation,Top
@chapter Installation

What you do to install Geomview depends on which kind of computer you
have (SGI or NeXT) and on whether you have the source distribution or
the binary distribution.

In general, if you don't care about looking at Geomview's source code,
you should get the binary distribution.  Its installation is much easier
and quicker than that for the source code.

@menu
* SGI Binary Installation::   Installing the SGI Binary Distribution.
* NeXT Binary Installation::  Installing the NeXT Binary Distribution.
* Source Code Installation::  Compiling and Installing the Source Code Distribution.
* Obtaining::		Obtaining Geomview.
@end menu

@comment ================================================================
@node SGI Binary Installation,SGI Binary Detail,Installation,Installation
@section Installing the SGI Binary Distribution

If you have just obtained a copy of the SGI binary distribution (file
@file{geomview-sgi.tar.Z}), you should be able to run Geomview and make
use of most of its features immediately after unpacking it by
@code{cd}'ing to the directory that it is in and typing @code{geomview}.

In order to fully install Geomview so that you can run it from any
directory and use all of its features, follow the steps in this section.
In particular, you must go through this installation procedure in order
to use Geomview to display Mathematica graphics.

Geomview is distributed in a directory that contains various files and
subdirectories that Geomview needs at run-time, such as data files and
external modules.  It also contains other things distributed with
Geomview, such as documentation and (in the soure-code distribution)
source-code.  We refer to the root directory of this tree as the
@file{@$GEOMROOT} directory.  This is the directory called @file{Geomview}
that is created when you unpack the distribution file.

To install Geomview on your system, arrange for the @file{@$GEOMROOT}
directory to be in a permanent place.  Then, in a shell window,
@code{cd} to that directory and type @code{install}.  This runs a shell
script which does the installation after asking you several questions
about where you want to install the various components of Geomview.

After running the @code{install} script you should now be able to run
Geomview from any directory on your system.  (You may need to give the
@code{rehash} command in any shells on your computer that were started
up before you did the installation.)


The @file{install} script puts copies of the files in
@file{@$GEOMROOT/bin/sgi} and @file{@$GEOMROOT/man} into the directories
you specified for executables and man pages, respectively.  Once you
have done the installation you can cut down one the disk space required
by Geomview by removing some files from these directories, since copies
have been installed elsewhere.  You should first test that your
installed Geomview works properly because once you remove these files
from their distribution directories you will not be able to do the
installation again.

In particular, the files you can remove are

@table @asis

@item @file{@$GEOMROOT/bin/sgi}:
Remove all files from here except @file{gvx}, which is the geomview
executable file.  DO NOT REMOVE @file{gvx}.  It is not installed
elsewhere.

@item @file{@$GEOMROOT/man}:
You can remove all the files in this directory.

@end table


@comment ================================================================
@node SGI Binary Detail,NeXT Binary Installation,SGI Binary Installation,SGI Binary Installation
@subsection Details of the SGI Binary Installation

The @code{install} script should be self-explanatory; just run it and
answer the questions.  This section gives some details for system
administrators and other users who may want to know more about the
installation. 

The installation is actually done by @code{make}; the @code{install}
script queries the user for the settings of the following @code{make}
variables and then invokes @code{make install}.

@table @asis

@item @code{GEOMROOT}:
the absolute pathname of the Geomview root directory.  The
@code{geomview} shell script, which is what users invoke to run
Geomview, uses this to set various environment variables that Geomview
needs.  It is very important that this be an @emph{absolute} pathname
--- i.e. it should start with a '/'.

@item @code{BINDIR}:
a directory where executable files are installed.  The @code{geomview}
shell script goes here, as well as various other auxiliary programs that
can be used in conjunction with @code{geomview}.  This should be a
directory that is on users' @file{@$path}.  These auxiliary programs are
distributed in the @file{@$GEOMROOT/bin/sgi} directory; if you specify
this directory for @code{BINDIR}, they are left in that directory.

@item @code{MANDIR}:
a directory where Unix manual pages are installed.  These are
distributed in the @file{@$GEOMROOT/man} subdirectory; if you specify
this directory for @code{MANDIR}, they are left in that directory.

@item @code{MMAPACKAGEDIR}:
a directory where Mathematica packages are installed.  This should be a
directory that Mathematica searches for packages that it loads; you can
see what directories your Mathematica searches by looking at the value
of the @code{@$Path} variable in a Mathematica session.  The
installation process will install some packages there which allow you to
use Geomview to display Mathematica graphics.  These packages are
distributed in the @file{@$GEOMROOT/mathematica} subdirectory; if you
specify this directory for @code{MMAPACKAGEDIR}, or if you specify the
empty string for @code{MMAPACKAGEDIR}, the packages are left in that
directory.  For more details about the way these Mathematica packages
connect to Geomview, @pxref{Package Installation}.

@end table

@comment ================================================================
@node NeXT Binary Installation,NeXTStep Binary Detail,SGI Binary Detail,Installation
@section Installing the NeXT Binary Distribution

@enumerate

@item
If you have just obtained a copy of the NeXTStep binary distribution
(file @file{geomview-next.tar}), you can unpack it by double-clicking on
it in the Workspace.  This will open up a File Viewer panel showing,
among other things, a NeXT Installer package called @file{Geomview.pkg}.


@item
The first thing you should do is double-click on @file{Geomview.pkg} to
invoke the NeXT Installer.  You will be asked where you want to install
it; typically it should go in @file{/LocalApps} or in @file{~/Apps} in
your home directory.  You should now be able to run Geomview and make
use of most of its features by double-clicking on the installed
@file{Geomview.app} icon.

@item
There are some aspects of the installation, however, that the NeXT
Installer can't handle.  In order to fully install Geomview so that you
can use all of its features, you should run the @file{install} script in
the @file{Geomview.app} directory. In particular, you must go through
this installation procedure in order to use Geomview to display
Mathematica graphics.

To run the @file{install} script you can open @file{Geomview.app} in the
Workspace by selecting it and picking @code{File->Open as Folder} from
the Workspace menu.  This will pop up a File Viewer panel showing the
contents of @file{Geomview.app}.  Scroll down to the file named
@file{install}, and double-click on it.  This will open a terminal
window and run the script in that window.  Alternately, you can open a
terminal window yourself, cd to @file{Geomview.app}, and run
@file{install} there.

The @file{install} script does the installation after asking you several
questions about where you want to install the various components of
Geomview.  After running the @code{install} script, Geomview is
completely installed.  If in the future you move @file{Geomview.app} to
some other location you should run @file{install} again.

@item
This step is optional.  Geomview's example data files are in the
@file{Geomview.app/data} directory.  If you are on a network with both
SGI workstations and NeXTStep workstations, and you want to install
Geomview to run on both, you can save disk space by having the two
installations share a common data directory.  To do this, decide on a
location for the data directory and copy it there if it isn't there
already (a good choice would be to leave it in the @file{@$GEOMROOT}
directory in your SGI Geomview installation).  Then edit the file
@file{Geomview.app/CONFIG.gv} to change the setting of the variable
@code{GEOMVIEW_DATA} to point to this directory (there are comments in
the file telling you what to do).  You can then remove the data
directory from @file{Geomview.app}.

@end enumerate

To run geomview, double-click on @file{Geomview.app} from the workspace,
or type @code{open Geomview.app} from the appropriate directory, or type
@code{geomview} from a shell window.

More Geomview documentation is in the @file{Geomview.app/doc}
subdirectory.  In particular, a copy of the manual is there.

The @file{install} script puts copies of the files in
@file{Geomview.app/bin/next} and @file{Geomview.app/man} into the
directories you specified for executables and man pages, respectively.
Once you have done the installation you can cut down one the disk space
required by Geomview by removing all the files in these directories,
since copies have been installed elsewhere.  You should first test that
your installed Geomview works properly because once you remove these
files from their distribution directories you will not be able to do the
installation again.

@comment ================================================================
@node NeXTStep Binary Detail,Source Code Installation,NeXT Binary Installation,NeXT Binary Installation
@subsection Details of the NeXTStep Binary Installation

Other than the installation of the @file{Geomview.app} directory, the
installation details of the NeXTStep binary distribution are the same as
for the SGI distribution, @pxref{SGI Binary Detail}.  Note that the
directory referred to in the SGI distribution as @file{@$GEOMROOT}
is the @file{Geomview.app} directory in the NeXTStep distribution.

@comment ================================================================
@node Source Code Installation,Obtaining,NeXTStep Binary Detail,Installation
@section Compiling and Installing the Source Code Distribution

The main reason to get the source code distribution is to look at and/or
work with the source code.  If you are only concered with @emph{using}
Geomview it is better to get the binary distribution.  It takes anywhere
from 15 minutes to 1.5 hours to compile the entire source distribution,
depending on what kind of computer you have.

Let @file{@$GEOMROOT} denote the full pathname of the Geomview source
code directory; this is the directory called @file{Geomview} that is
created when you unpack the distribution.  This directory contains the
Geomview source code as well as various other files and subdirectories
that Geomview needs when it runs.

Before doing any compilation you should edit the file
@file{@$GEOMROOT/makefiles/mk.site.default}.  This file defines some
@code{make} variables which specify your local configuration.  This
includes the pathnames of the directories into which Geomview will be
installed, and possibly some other settings as well.  There are comments
in the file telling you what to do.  This file is included by every
Makefile in the source tree, so the settings you specify here are used
throughout the source.

If you will be compiling for both SGI and NeXT, you can do both in the
same directory tree.  By default the Makefiles are set up to put the
objects files, libraries, and executables in directories which depend on
the type of computer, so the two architectures will not interfere with
each other.  The Makefiles use a variable called @code{CPU} to determine
the type of machine. Before doing any compilation you must arrange for
this variable to have a value.  There are two ways you can do this.

@enumerate

@item
If you will always be compiling Geomview on the same type of computer
(SGI or NeXT), edit the file @file{@$GEOMROOT/makefiles/Makedefs.global}
to set the @code{CPU} variable to either @code{iris4} or @code{NeXT}.
The comments near the top of that file will tell you where to do this.

@item
If you will be compiling on both types of computers you can set a shell
environment variable named @code{CPU} to either @code{iris4} or
@code{NeXT}, and the Makefiles will inherit the value from the
environment.  The script @file{@$GEOMROOT/config} determines which kind
of computer you are on and sets this variable accordingly.  To use this
script, type @code{source config} in the (assuming a C-shell type shell)
in the @file{@$GEOMROOT} directory shell in which you plan to do the
compilation.  Or you can set the variable directly; it should be either
@code{NeXT} or @code{iris4}.  You will need to do this in every shell in
which you plan to do compilation.

Alternately, you could modify your shell initialization file
(@file{.cshrc} or whatever) to set @code{CPU} appropriately.

@end enumerate

@noindent
Note that many of the Makefiles refer to a variable called @code{MACHTYPE}
to determine the type of machine.  This is set to either @code{sgi} or
@code{next}, depending on the value of @code{CPU}.

Once you have configured your source tree by editing the files as
described above and setting the @code{CPU} variable, you can compile and
install Geomview by typing @code{make install} in the @file{@$GEOMROOT}
directory.  You can also type @code{make all}, or equivalently just
@code{make}, to compile without installing, and then type @code{make
install} later to install.

You can use these same @code{make} comands in any subdirectory in the
tree to recompile and/or install a part of Geomview or a module.

If you want to compile fat binaries under NeXTStep 3.1, before doing any
compilation edit the file @file{@$GEOMROOT/makefiles/mk.next} to
uncomment a particular line there.  There are comments in the file
telling you which line to uncomment.

If you want to modify the complier flags used during compilation, edit
the file @file{@$GEOMROOT/makefiles/Makedefs.global}; the @code{COPTS}
variable specifies the flags passed to the C compiler (cc).

@comment =============================================================
@node Obtaining,Function Index,Source Code Installation,Installation
@section Obtaining Geomview

Geomview is available free via anonymous ftp from Internet host
@file{geom.umn.edu}, IP address 128.101.25.35.  The Geomview
distribution files are in the @file{pub/software/geomview} subdirectory.
They are all tar archive files (@file{.tar} or @file{.tar.Z} files), so
you should use binary mode in ftp for transferring them to your site.

The main files are

@table @asis

@item @file{geomview-sgi.tar.Z}
The SGI binary distribution. Contains executables for running
on any Silcon Graphics IRIS workstation, plus documentation
and example files.

@item @file{geomview-next.tar}
The NeXTStep binary distribution.  This contains fat binaries which will
run on either a NeXT workstation running NeXTStep 3.0 or 3.1, or a 486
PC running NeXTStep 3.1.  Also contains documentation and example files.
This {.tar} file is not compressed because it contains the distribution
compressed into a NeXT Installer package, and further compression
actually increases the size of the file.  To unpack
@file{geomview-next.tar} on a NeXT, simple double-click on it in the
Workspace.@refill

@item @file{geomview-src.tar.Z}
The source code distribution; contains source code so you can compile
Geomview and the distributed external modules on either an SGI or on a
NeXT workstation running NeXTStep 3.0 or 3.1, or a 486 PC running
NeXTStep 3.1.  Also contains documentaion and examples files.

@end table

Each of the above archive files contains the entire distribution:
executables or source for Geomview itself, plus all distributed external
modules, example data files, and documentation.  These archive files are
therefore rather large.  If you do not have enough disk space on your
workstation for the entire distribution, various pieces of the
distribution are available separately in the
@file{pub/software/geomview/pieces} subdirectory.  See the file
@file{README} in that directory for details.

After retrieving any of the distribution archive files, you can
unpack it with a command like the following
@example
% uncompress < geomview-sgi.tar.Z | tar xvopBf -
@end example
@noindent
This will unpack the contents of the archive file into
a subdirectory named @file{Geomview}.  Once unpacked, you
can delete the archive file.

The following is a sample ftp session for retreiving and unpacking the
SGI binary distribution.  After unpacking, see the file @file{README}
for more information.

@example
artin% ftp geom.umn.edu
Connected to geom.umn.edu.
220 cameron FTP server (Version 5.88 Thu Jun 25 16:41:41 CDT 1992) ready.
Name (geom.umn.edu:mbp): anonymous
331 For password please enter your e-mail address or name and institution.
Password:mbp@@geom.umn.edu

230 Guest login ok, access restrictions apply.
ftp> cd pub/software/geomview
250 CWD command successful.
ftp> binary
200 Type set to I.
ftp> get geomview-sgi.tar.Z
200 PORT command successful.
150 Opening BINARY mode data connection for geomview-sgi.tar.Z (5815980 bytes).
226 Transfer complete.
local: geomview-sgi.tar.Z remote: geomview-sgi.tar.Z
5815980 bytes received in 28.67 seconds (1.98e+02 Kbytes/s)
ftp> quit
221 Goodbye.
artin% ls -l
total 5680
-rw-rw-r--  1 mbp      5815980 Aug 19 16:38 geomview-sgi.tar.Z
artin% uncompress < geomview-sgi.tar.Z | tar xvopf -
x ./CHANGES, 16910 bytes, 34 tape blocks
@dots{}
artin% rm geomview-sgi.tar.Z
@end example

@comment @comment ****************************************************************
@comment @node General Index,Function Index,Installation,Top
@comment @unnumbered General Index
@comment 
@comment @printindex cp

@comment ****************************************************************
@node Function Index, ,Obtaining,Top
@unnumbered Function Index

@printindex fn

@comment ****************************************************************

@contents

@bye
