%%% -*-texinfo-*-
\tolerance=2000
\input texinfo
@c @letterpaper
@setfilename geomview
@settitle Geomview Manual

@include version.texi

@dircategory Graphics Applications
@direntry
* Geomview: (geomview).         The interactive 3D viewing program.
@end direntry

@c
@titlepage
@sp 1
@center @titlefont{Geomview Manual}
@sp 4
@center Geomview Version @value{VERSION}
@sp 1
@center for Unix
@sp 1
@center @value{UPDATED-MONTH}
@comment November 19, 2000
@sp 2
@center Mark Phillips et al.
@sp 4
@vskip 0pt plus 1filll
@center Copyright @copyright{} 1992-1998 The Geometry Center
@center Copyright @copyright{} 1998-2006 Stuart Levy, Tamara Munzner, Mark Phillips
@center Copyright @copyright{} 2006-2007 Claus-Justus Heine

@end titlepage
@page

@node Top, Intro, (dir), (dir)

Geomview, the interactive 3D viewing program.

@menu
* Intro::                       Introduction to Geomview.
* Distrib::                     How to get the latest Geomview distribution.
* Copying::                     The GNU Lesser Public License.
* History::                     History of Geomview's Development.
* Platforms::                   Supported Platforms.
* Pronunciation::               How to Pronounce ``Geomview''.
* 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.
* Non-Euclidean Geometry::      Non-Euclidean Geometry.
* Mathematica::                 Mathematica Graphics in Geomview or RenderMan.
* Installation::                Installing Geomview on your computer.
* Support::                     Getting Technical Support for Geomview.

* Contributing::                How to contribute to Geomview.
* Function Index::              A node for each GCL function.
* List of Figures::             List of Figures.
@end menu

@node Intro, Distrib, Top, Top
@unnumbered Introduction to Geomview

Geomview is an interactive program for viewing and manipulating
geometric objects, originally written by staff members of the Geometry
Center at the University of Minnesota, starting in 1991.  It can be used
as a stand-alone viewer for static objects or as a display engine for
other programs which produce dynamically changing geometry.  It runs on
many kinds of Unix computers, including Linux, SGI, Sun, and HP. It also
runs with Cygwin. This manual describes Geomview version 1.9. @refill

Geomview is free software, available under the terms of the GNU Lesser
Public License; @pxref{Copying} for details.

Geomview and this manual are available for download from
@uref{http://www.geomview.org}.

Permission is granted to make copies of this manual.

If you have questions or comments about Geomview or this manual,
consider joining in the @file{geomview-users} mailing list, which is a
forum in which users of Geomview communicate to answer
each others' questions and to share news about what they are doing with
Geomview.  The Geomview authors participate in this list and sometimes
post answers to questions there.  To join the list, visit the list web page
at @uref{http://lists.sourceforge.net/mailman/listinfo/geomview-users}.

@node Distrib, Copying, Intro, Top
@unnumbered Distribution

Geomview is @dfn{free software}; this means that everyone is free to
use it and free to redistribute it on certain conditions.  
Geomview is
not in the public domain; it is copyrighted and there are restrictions
on its distribution, but these restrictions are designed to permit
everything that a good cooperating citizen would want to do.  What is
not allowed is to try to prevent others from further sharing any version
of Geomview that they might get from you.  The precise conditions are
found in the GNU Lesser Public License that comes with Geomview and also
appears following this section.

One way to get a copy of Geomview is from someone else who has it.  You
need not ask for our permission to do so, or tell any one else; just
copy it.  If you have access to the Internet, you can get the latest
distribution version of Geomview at @uref{http://www.geomview.org}.

You may also receive Geomview when you buy a computer.  Computer
manufacturers are free to distribute copies on the same terms that apply to
everyone else.  These terms require them to give you the full sources,
including whatever changes they may have made, and to permit you to
redistribute the Geomview received from them under the usual terms of the
General Public License.  In other words, the program must be free for you
when you get it, not just free for the manufacturer.

@node Copying, History, Distrib, Top
@unnumbered Copying

@c cH: in my opinion the following paragraph is complete nonsense; programs
@c which simply communicate with other programs by means of streams
@c cannot inherit the restriction imposed by the GPL

@smallexample
NOTE: Geomview is distributed under the GNU LESSER GENERAL PUBLIC
LICENSE.  For the purposes of this license we think of Geomview as if it
were a "library", and of Geomview external modules as "programs that
link with the library".  We do this because we specifically want to
allow proprietary programs and modules to use Geomview.
@end smallexample

@unnumbered GNU LESSER PUBLIC LICENSE
@center Version 2.1, February 1999

@display
Copyright @copyright{} 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

[This is the first released version of the Lesser GPL.  It also counts
 as the successor of the GNU Library Public License, version 2, hence
 the version number 2.1.]
@end display

@unnumberedsec Preamble

The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.

This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it.  You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations
below.

When we speak of free software, we are referring to freedom of use,
not price.  Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.

To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights.  These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.

For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you.  You must make sure that they, too, receive or can get the source
code.  If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it.  And you must show them these terms so they know their rights.

We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.

To protect each distributor, we want to make it very clear that
there is no warranty for the free library.  Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.

Finally, software patents pose a constant threat to the existence of
any free program.  We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder.  Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.

Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License.  This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License.  We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.

When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library.  The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom.  The Lesser General
Public License permits more lax criteria for linking other code with
the library.

We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License.  It also provides other free software developers Less
of an advantage over competing non-free programs.  These disadvantages
are the reason we use the ordinary General Public License for many
libraries.  However, the Lesser license provides advantages in certain
special circumstances.

For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it
becomes a de-facto standard.  To achieve this, non-free programs must
be allowed to use the library.  A more frequent case is that a free
library does the same job as widely used non-free libraries.  In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.

In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software.  For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.

Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.

The precise terms and conditions for copying, distribution and
modification follow.  Pay close attention to the difference between a
"work based on the library" and a "work that uses the library".  The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.

@unnumberedsec TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

@enumerate 0
@item
This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".

A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.

The "Library", below, refers to any such software library or work
which has been distributed under these terms.  A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language.  (Hereinafter, translation is
included without limitation in the term "modification".)

"Source code" for a work means the preferred form of the work for
making modifications to it.  For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control
compilation
and installation of the library.

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it).  Whether that is true depends on what the Library does
and what the program that uses the Library does.

@item
You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.

You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.

@item
You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

@enumerate a
@item
The modified work must itself be a software library.

@item
You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.

@item
You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.

@item
If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.

(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application.  Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
@end enumerate

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.

In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

@item
You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library.  To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License.  (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.)  Do not make any other change in
these notices.
^L
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.

This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.

@item
You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.

If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.

@item
A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library".  Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.

However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library".  The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.

When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library.  The
threshold for this to be true is not precisely defined by law.

If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work.  (Executables containing this object code plus portions of the
Library will still fall under Section 6.)

Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.

@item
As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.

You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License.  You must supply a copy of this License.  If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License.  Also, you must do one
of these things:

@enumerate a
@item
Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library.  (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)

@item
Use a suitable shared library mechanism for linking with the
Library.  A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.

@item
Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.

@item
If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.

@item
Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
@end enumerate

For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it.  However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.

It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system.  Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.

@item
You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:

@enumerate a
@item
Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities.  This must be distributed under the terms of the
Sections above.

@item
Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
@end enumerate

@item
You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License.  Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License.  However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.

@item
You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Library or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.

@item
Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.

@item
If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all.  For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply, and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

@item
If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License
may add an explicit geographical distribution limitation excluding those
countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

@item
The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.

Each version is given a distinguishing version number.  If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation.  If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.

@item
If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission.  For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this.  Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.

@b{NO WARRANTY}

@item
BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

@item
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
@end enumerate

@b{END OF TERMS AND CONDITIONS}

@page
@unnumberedsec How to Apply These Terms to Your New Programs

If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change.  You can do so by permitting
redistribution under these terms (or, alternatively, under the terms
of the ordinary General Public License).

To apply these terms, attach the following notices to the library.
It is safest to attach them to the start of each source file to most
effectively convey the exclusion of warranty; and each file should
have at least the "copyright" line and a pointer to where the full
notice is found.


@smallexample
@var{one line to give the library's name and a brief idea of what it does.}
Copyright (C) <year>  @var{name of author}

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
@end smallexample

Also add information on how to contact you by electronic and paper
mail.

You should also get your employer (if you work as a programmer) or
your school, if any, to sign a "copyright disclaimer" for the library, if
necessary.  Here is a sample; alter the names:

@smallexample
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James
Random Hacker.

<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
@end smallexample

That's all there is to it!

@node History, Platforms, Copying, Top
@unnumbered History of Geomview's Development

Geomview was originally written at the Geometry Center at the University
of Minnesota in Minneapolis.
The Geometry Center was a research and education center
funded by the National Science Foundation, with a mission to promote
research and communication of mathematics.  Much of the work there
involved the use of computers to help visualize mathematical concepts.

The project that eventually led to Geomview
began in the summer of 1988 with the work of Pat
Hanrahan on a viewing program called MinneView.  Shortly
thereafter Charlie Gunn begin developing OOGL
(Object Oriented Graphics Language) in conjunction with
MinneView.  Many people contributed to OOGL and MinneView,
including Stuart Levy, Mark Meuer, Tamara Munzner, Steve
Anderson, Mario Lopez, Todd Kaplan.

In 1991 the staff of the Geometry Center began work on a new improved
version of OOGL, and a new and improved viewing program, which they
called Geomview.  At that time essentially the only game in town for
interactive 3D graphics was Silicon Graphics (SGI), so Geomview was
developed initially on SGI workstations, using IRIS GL.  The first
version was finished in January of 1992.  It immediately became very
popular among visitors to the Geometry Center, and through the Center's
ftp archive (this was before the web) people at other institutions began
using it too.

In addition to SGI workstations the Geometry Center had
quite a few NeXT stations, so soon after Geomview was running
on SGIs the staff developed a version for NeXTStep as well.
By this time there were several thousand people using it
around the world.

A few years later the staff ported Geomview to X windows and OpenGL, and
eventually, with the demise of NeXT, the NeXT version fell by the
wayside.

In its mission to foster communication among researchers and educators,
the Geometry Center developed a web site, www.geom.umn.edu, in late
1993.  It was one of the first 300 web sites in existence.  A part of
the web site was of course devoted to Geomview, and helped to spread the
word about its existence.

The Geometry Center closed its "brick and mortar" facilities in August
of 1998 (NSF cut its funding), but the web site continued to exist, and
Geomview continued to be very popular around the world.  In December of
1999 some of the former Geometry Center staff set up
@uref{http://www.geomview.org} as a permanent home on the web for
Geomview.

Geomview's original authors, as well as a number of other volunteers
around the world, are still actively involved in using and developing
Geomview.

@menu
* Authors::                     Authors.
@end menu

@node Authors,  , History, History
@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.  Many other Geometry Center staff members, as well
as several people elsewhere, also contributed.

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 Platforms, Pronunciation, History, Top
@unnumbered Supported Platforms

Geomview 1.9 should -- in principle -- compile and run on any fairly
recent Unix-like operating system. Specifically, it runs on Linux and on
Cygwin (Cygwin emulates a SystemV Unix-like environment under Microsoft
Windows). Unluckily Geomview compiles with MacOS X (Darwin), but
seemingly communicating with Geomview by means of pipes and sockets
cause segmentation faults. Feel free to fix that! @xref{Contributing},
for details.

@c Geomview runs on a wide variety of Unix systems. It has been tested on
@c each of the following systems: Linux, FreeBSD, SGI, Sun either (Sun-OS
@c 4.1.x and Solaris), HP RISC, Dec Alpha, RS/6000, and NeXT.  Precompiled
@c distributions are available for all of these systems.  Using either
@c OpenGL or the generic X11 renderer it can probably be compiled on other
@c Unix systems as well.

@c There is not a version of Geomview for Microsoft Windows.  The main
@c reason for this is that at the time when Geomview was written, personal
@c computers were not fast enough to make interactive 3D graphics feasible,
@c and by the time fast-enough PCs came around, the Geometry Center,
@c where Geomview was developed, was in the process of being closed.  The
@c staff started work on a port to Windows but was not able to finish it
@c before the Center shut down.

@c If you would like to see a version of Geomview for Windows, 
@c you can contribute to its development in several ways.
@c @xref{Contributing}, for details.

@c There is also no version of Geomview for Macintosh.

@node Pronunciation, Overview, Platforms, Top
@unnumbered How to Pronounce ``Geomview``

The word 'Geomview' is a combination of the first syllable of the word
'geometry', and the word 'view'. The authors pronounce it with the
accent on the first syllable

@display
  GE-om-view
@end display

Some people put the accent on the second syllable, where it
falls in the word 'geometry', but the original authors, who
invented the name, prefer the accent-on-first-syllable
pronunciation.


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

@comment ****************************************************************
@node Overview, Tutorial, Pronunciation, 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 stand-alone 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 is the product of an 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 computer 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{Enter}} here
means hit the "Enter" key):

@example
geomview tetra dodec @key{Enter}
@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; @pxref{figinitial, Figure}.

@float Figure,figinitial
@image{figs/initial}
@caption{Initial Geomview display.}
@end float

The panel on the left is Geomview's main control panel; it's called
the @emph{Main} panel.  The skinny panel in the middle is the
@emph{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 wire-frame
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 @emph{Targets} browser in
the @emph{Main} panel.  Click (any button) on the word @emph{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 @emph{Tools}
panel.  To translate instead, click on the @emph{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
@emph{Center} button in the @emph{Tools} panel.  This causes it to
come back to its initial position.

Click on the @emph{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 @emph{Targets}
browser in the @emph{Main} panel and click on "World" to select the
whole world again.  Now click on the @emph{Look At} button in the
@emph{Tools} panel. You should see the dodecahedron and the tetrahedron
in the middle of the window next to each other (@pxref{figlookatworld,
Figure}).  The @emph{Look At} button positions the camera in such a way
that the target object is centered in the window.
@float Figure,figlookatworld
@image{figs/fig2}
@caption{Looking at the world.}
@end float
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 @emph{Targets} browser in the
@emph{Main} panel.  Double-clicking the right mouse button on an object
is another way to make it the target object.

@float Figure,figappearance
@image{figs/ap}
@caption{The Appearance Panel.}
@end float
Go to the @emph{Inspect} menu at the top of the @emph{Main} panel and select
@emph{Appearance}.  This brings up the @emph{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.

The @emph{Appearance} panel lets you control various things about the
way Geomview draws objects.  Note the buttons labeled @emph{[af] Faces} and
@emph{[ae] Edges}.  Click on the @emph{[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 @emph{[af] Faces} button.  This toggles the faces
on and off.  Click the button again to turn them back on.

Now click on the @emph{[Cf] Faces} button under the word @emph{COLOR}. A
color chooser panel should appear (@pxref{figcolorchooser, Figure}).
@float Figure,figcolorchooser
@image{figs/color}
@caption{Color Chooser Panel.}
@end float

@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, @emph{H}, @emph{S}, and @emph{V},
controlling the color's hue, saturation, and value (lightness).
Clicking the @emph{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 @emph{Intensity} slider.  When you find a color that
you like, click the @emph{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 @emph{Look At} button to look at the world again.

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

Click on the @emph{[ab] BBox} button under the word @emph{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 @emph{Targets} browser.
Then click on the @emph{Delete} button in the @emph{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 @emph{File}
menu in the @emph{Main} panel and choose @emph{Open}.
The @emph{Files} panel will appear.
@c
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; @pxref{figfilespanel, Figure}. Scroll down in
the list of files until you see @file{tref.off}.  Click on that line,
and then click on the @emph{OK} button.  A large trefoil-shaped tube
will appear in your window.  Click the @emph{Hide} button in the
@emph{Files} panel to dismiss the panel.

@float Figure,figfilespanel
@image{figs/secondlinelist}
@caption{The Files Panel.}
@end float

Now click on the @emph{Reset} button in the @emph{Tools} panel.  This
causes everything to return to its home position.  You should see a
dodecahedron and a trefoil knot (@pxref{figtrefdodec, Figure}).

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

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

@float Figure,figtrefdodec
@image{figs/trefdodecinter}
@caption{Trefoil and Dodecahedron.}
@end float

@comment ****************************************************************
@node Interaction, OOGL File Formats, 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{Enter}} in a shell
window (@key{Enter} 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[cg][ps[un|in|in6]] @var{PIPENAME}|@var{TCPPORT}
The @samp{-M} option accepts modifiers: a @samp{g} suffix expects
geometry data (the default), while a @samp{c} suffix expects GCL
commands. A @samp{p} implies the connection should use a named pipe (the
default on everything except on the NeXT), while @samp{s} implies using
a UNIX-domain socket (the default on the NeXT). Since version 1.9 of
Geomview Internet domain sockets are also supported; use @samp{sin} to
make Geomview listen on the IPv4 port given by @var{TCPPORT}, or use
@samp{sin6} to make Geomview listen on an IPv6 port (also as specified
by @var{TCPPORT}). @samp{sun} is a synonym for @samp{s}, i.e. use the
Unix domain socket with the name @var{PIPENAME}. If @var{PIPENAME}
starts with a slash ('/'), then it is assumed to be an absolute
pathname, otherwise the named pipe or socket is created below
@file{$@{TMPDIR@}/geomview/}.

@b{Listening to command streams on TCP ports can be a security risk,
as Geomview itself does not take any security precautions, it simply
executes all commands fed to it through the network socket. This also
implies that disk-io can be initiated remotely.}

Examples:
@table @code
@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:
@example
(geometry objectname  < /tmp/geomview/objectname)
@end example
(@pxref{geometry,@code{(geometry @dots{})}})

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

@item -Mcs fred
Read commands from the UNIX-domain socket named.
@file{/tmp/geomview/fred}

@item -Mcsin 40000
Read commands from the IPv4 port @samp{40000}. Geomview itself does not
take any security precautions, so this can be a security risk.
@end table

@item -noopengl
Disable the use of OpenGL for (possibly) hardware accelerated rendering,
even if the Geomview binary has support for OpenGL compiled in. This
also disables the support for transparency and textures in the
camera windows. RenderMan snapshots still will have correct transparency
and some limited texture support.

@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. @xref{ui-panel, @code{(ui-panel @dots{})}}.

@item -noinit
Read no initialization files. By default, geomview reads the system-wide
@file{.geomview} file, followed by those in @file{$@{HOME@}/.geomview} and
@file{./.geomview}.

@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. @xref{emodule-define,
@code{(emodule-define @dots{})}}.

@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
@emph{Main} panel, the @emph{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 @emph{Main} panel.
@c
@float Figure,figmainpanel
@image{figs/main}
@caption{The Main Panel}
@end float
@c
Geomview can display an arbitrary number of objects simultaneously.  The
@emph{Targets} browser in the @emph{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 @emph{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 @emph{New Camera} entry of the @emph{Main} panel's @emph{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 @emph{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
@emph{Targets} browser.  Another way to change the target object is
to put the mouse cursor directly over a geometry 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 @emph{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 geometries 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 @emph{MOTION MODE} browser
in the @emph{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 @emph{MOTION MODE} browser, or by using the
@emph{Tools} panel.  For more information about motion modes,
@xref{Mouse Motions}.

The @emph{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 @emph{Load} button on the @emph{Main} panel brings up the
@emph{Files} panel for loading a file.  The file can contain either a
geom, a camera, or GCL commands.  For details, @xref{Loading}.

The @emph{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 geometries in this way.  If you
hit the @emph{Delete} button while the target object is "World",
Geomview deletes all geometries.

The three buttons at the bottom of the @emph{Main} panel, labeled
@emph{Euclidean}, @emph{Hyperbolic}, and @emph{Spherical}, allow
you to change the geometry of the space that Geomview displays.  By
default @emph{Euclidean} is selected.  For details about using
@emph{Hyperbolic} and @emph{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 @emph{File} menu.  

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

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

The @emph{Space} menu lets you choose whether geomview operates
in Euclidean, Hyperbolic, or Spherical mode.  Euclidean mode is selected
by default.  For details about using @emph{Hyperbolic} and
@emph{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 @emph{Rotate} mode is 'r'; this is indicated by "[r]" appearing
before the word "Rotate" in the @emph{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{Enter}} 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{Enter}}
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 @emph{keyboard} field in the upper left corner of the @emph{Main}
panel echos the current state of keyboard shortcuts.

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

The @emph{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 @emph{Files} panel
If you click the @emph{Load} button in Geomview's @emph{Main} panel,
the @emph{Files} panel will appear. 

@float Figure,figmyfilelist
@image{figs/myfilelist}
@caption{The Files Panel.}
@end float
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 @key{Enter} key, or type the file's name
into the text box at the bottom of the browser and press @key{Enter}.
@refill

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

When the @emph{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 @emph{Files}
panel's directory browser by using the @code{set-load-path} command;
@pxref{set-load-path, @code{(set-load-path @dots{})}}.

@item the @kbd{<} keyboard shortcut:
If you type @kbd{<} in any Geomview window, the @emph{Load} panel will
appear.  This is a small version of the @emph{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{Enter}}; Geomview will
load the file as if you had loaded it with the @emph{Add} button in
the @emph{Files} panel.  If, after bringing up the small load panel
with @kbd{<}, you decide you want to use the larger @emph{Files} panel
after all, press the @emph{File Browser} button.
@float Figure,figloadpanel
@image{figs/load}
@caption{The Load Panel.}
@end float

@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}. @xref{load, @code{(load @dots{})}}. @xref{new-geometry,
@code{(new-geometry @dots{})}}. @xref{read, @code{(read @dots{})}}.
@refill

@end table

@comment ================================================================
@node Mouse Motions, Appearance, Loading, Interaction
@section Using the Mouse to Manipulate Objects

Geomview lets you manipulate objects with the mouse.  There are six
different mouse motion modes: @emph{Rotate}, @emph{Translate},
@emph{Cam Fly}, @emph{Cam Zoom}, @emph{Geom Scale}, and
@emph{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 @emph{Motion Mode} browser on the
@emph{Main} panel.@refill

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

@float Figure,figtools
@image{figs/tools}
@caption{The Tools Panel.}
@end float

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 @emph{Target} field in the
@emph{Tools} panel.  This is the same as the selected object in the
@emph{Targets} browser in the @emph{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 @emph{Center} field in the
@emph{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 @emph{Center}
field.  The origin of the center object is held fixed in @emph{Rotate} and
@emph{Orbit} modes.  Normally the center object is one of the existing
geoms listed in the @emph{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}.

It is also possible to toggle the button @emph{BBox Center} to set the
center of motion to the center of the current object's bounding
box. Once toggled, the active geometry's bounding box center will become
the center of motion. If you select another object, then the center of
motion will become the center of that object's bounding box. Nothing
changes when a camera or the @emph{World} is selected; you have to
type in the word @code{target} in the @emph{Center} field to reset to
the default.

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 @emph{Main} panel's @emph{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 @emph

@item Rotate
In @emph{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 @emph{Rotate} mode rotates the target
object about an axis perpendicular to the view plane.

@item Translate
In @emph{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
@emph{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.

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

@item Cam Orbit
@emph{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 @emph{Cam Orbit} mode acts as in
@emph{Cam Fly} mode: it moves the camera forward or backward.

In general @emph{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
@emph{Cam Fly} mode.

@item Cam Zoom
@emph{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
@emph{FOV} field in the @emph{Camera} panel.

@item Geom Scale
@emph{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, @emph{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.

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

@end table

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


@table @emph

@item Stop
The @emph{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 @emph{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 @emph{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 @emph{Reset} button stops all motion and causes all objects to
move back to their home positions.

@end table

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

The @emph{Main} panel's @emph{Motion} menu has special controls
affecting how mouse motions are interpreted; the toggles are also
accessible through a GCL command. @xref{ui-motion, @code{(ui-motion
@dots{})}}.

@table @emph

@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 @emph{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
@emph{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
@emph{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 @emph{Constrain Motion} button.

@end table

@comment ================================================================
@menu
* Point of Interest::           Point of Interest.
@end menu

@node Point of Interest,  , 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
@emph{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 @emph{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. @xref{geometry,
@code{(geometry @dots{})}}.


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, Cameras, Mouse Motions, 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 properties.
* Lighting Panel::              Lighting Parameters.
@end menu

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

The @emph{Appearance} panel lets you change most common appearance
properties of the target object.
@float Figure,figap
@image{figs/ap}
@caption{The Appearance Panel.}
@end float
If the target is an individual geom, then changes you make in the
appearance panel apply to that geometry'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 left corner under the word
@emph{Show} control what parts of the target geom are drawn.

@table @emph

@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 @emph{Color} labeled @emph{Faces}, @emph{Edges},
@emph{Normals}, and @emph{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.
@float Figure,figcolorchooserpanel
@image{figs/color}
@caption{Color Chooser Panel.}
@end float
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 @emph{RGB} or @emph{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 @emph{OK} to accept the color that you have chosen, or
@emph{Cancel} to retain the previous color setting.


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

@table @code

@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.

@item VCflat
A combination of @code{CSmooth} and @code{Flat} shading. So the shading
is constant on each face, depending on the relative orientation of the
light sources, the camera and the surface normal of the face.

@end table

The @emph{Facing Normals} button on the @emph{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 @emph{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 @emph{Appearance}
panel are:

@table @emph

@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 @emph{Patch Dicing}
is @var{n}, then an @var{n} by @var{n} mesh is used to draw each Bezier
patch.  if @emph{Patch Dicing} is 1, the resolution reverts to a
built-in default value.

@end table

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

The @emph{Appearance} panel's @emph{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, @emph{Override} is enabled.  This button applies to all objects,
and to all appearance-related panels.

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
@emph{Look At} button on the @emph{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
@emph{NORMALIZE GEOMETRY} browser affects the normalization property
of target geom.  If the target geom is "World", it affects all geoms.

@table @emph

@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 Materials Panel, Lighting Panel, Appearance Panel, Appearance
@subsection The Materials Panel

The @emph{Materials} panel controls material properties of surfaces.
It works with the target object in the same way that the
@emph{Appearance} panel does.
@float Figure,figmatpanel
@image{figs/mat}
@caption{The Materials Panel.}
@end float

@table @emph

@item Translucent

This button determines whether translucency is enabled. Geomview
supports three different flavours of translucency:

@table @emph
@item Alpha-blending with BSP-tree depth-sorting
This is the most accurate flavour for online viewing, but consumes vast
amounts of computation time and memory. In this mode single translucent
objects are displayed correctly with respect to themselves; however
multiple translucent objects may appear in the wrong order on the
screen. The notion @emph{object} means here: top-level geometries as
displayed in the geometry target browser.

@item Screen Door Translucency
If the machine support OpenGL then there is support for kind-of
translucency by masking out (completely) transparent pixels by means of
a stipple mask. This is currently very experimental, and the result is
somewhat ugly, but fast.

@item Alphe-blending without depth-sorting
This is the old naive way of doing quick and dirty translucency. It is
fast, but the results are completely incorrect.
@end table

When transparency is enabled, a RenderMan snapshot will contain the
alpha information, a RenderMan compliant renderer can then generate
high-quality pictures, including correct translucency.

@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 @emph{Materials} panel.

@end table

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

The @emph{Lights} panel controls the number, position, and color of
the light sources used in shading.
@float
@image{figs/light}
@caption{The Lighting Panel.}
@end float

The @emph{Lighting} panel is different from the @emph{Appearance} and
@emph{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 @emph

@item LIGHTS
The @emph{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
@emph{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
@emph{Show Lights} button again to return to the previous motion mode
and to quit drawing the light beams.

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

@end table

Geomview's @emph{Appearance}, @emph{Materials}, and @emph{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}. @xref{merge-baseap,@code{(merge-baseap
@dots{})}}. @xref{merge-ap,@code{(merge-ap @dots{})}}.


@comment ================================================================
@node Cameras, Saving, Appearance, 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 @emph{Cameras} panel.
@float Figure,figcamerapanel
@image{figs/cam}
@caption{The Cameras Panel.}
@end float
If the target object is a camera, the @emph{Cameras} panel affects that
camera.  If the target object is not a camera, the @emph{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 @emph{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 @emph{File} menu on the @emph{Main} panel.

@table @emph

@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 @emph{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 @emph{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 @emph{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 @emph{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 @emph
@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 @emph{Cameras} panel.

@end table

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

Geomview's @emph{Save} panel lets you store Geomview objects and other
information in files that you can read back into Geomview or other
programs.
@float Figure,figsavepanel
@image{figs/save}
@caption{The Save Panel.}
@end float
To use the @emph{Save} panel you select the desired format in the
browser next to the word @emph{Save}, enter the name of the object you
want to save in the text field next to the word @emph{for}, and enter
the name of the file you wish to save to in the long text field next to
the word @emph{in}.  You can then either hit @kbd{@key{Enter}} or click
on the @emph{OK} button.  When the file has been written, the @emph{Save}
panel disappears.  If you want to dismiss the @emph{Save} panel without
writing a file, click the @emph{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 @emph

@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 transformation and the world's
transformation.

@item RMan [->tiff] @asis{(camera)}
Writes a RenderMan file which when rendered creates a tiff
image. Transparency and texturing (the latter only to some extent) will
be available.

@item RMan [->frame] @asis{(camera)}
Writes a RenderMan file which when rendered causes an image to appear in
a window on the screen. Transparency and texturing (the latter only to
some extent) will be available.

@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 GLX-offscreen snapshot @asis{(camera)}
Render the complete scene anew into off-screen memory; GLX provides the
means to use a Pixmap as rendering area. The advantage of rendering into
@emph{off}-screen memory over taking screen snapshot is that the camera
windows need not be mapped and even raised at the time the snapshot is
taken. So with off-screen snapshot one can safely iconify the camera
window (but do not close it!), activate the screen-saver and go to bed
while some script advances the scenes and takes snapshots.

@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. It is
probably a better idea to use GLX-@emph{off-screen} snapshots, as
explained above.

@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 @emph{Commands} panel lets you type in a GCL command.  When
you hit @kbd{@key{Enter}}, Geomview interprets the command and prints any
resulting output or error messages on standard output.  You can edit the
text and hit @kbd{@key{Enter}} as many times as you like, in general,
whenever you hit @kbd{@key{Enter}} with the cursor in the @emph{Commands}
panel, Geomview tries to interpret whatever text you have typed in the
text field as a command.
@float Figure,figcommandpanel
@image{figs/command}
@caption{The Commands Panel.}
@end float

@ifset forms
The @emph{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 @emph{Obscure} panel includes the @emph{NORMALIZE GEOMETRY}
browser, which controls the kind of geometry normalization that Geomview does,
and several buttons affecting motion style.
@float Figure,figobscurepanel
@image{figs/obscure}
@caption{The Obscure Panel.}
@end float
@end ifset

@comment ================================================================
@node Keyboard Shortcuts,  , 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 @emph{Rotate} mode is 'r'; this is indicated by "[r]" appearing
before the word "Rotate" in the @emph{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{Enter}}
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{Enter}}
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
@emph{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
@emph{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 @emph{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 @emph{g3},
type @kbd{g 3 p}.  This only works with the short names --- the ones
that appear in square brackets ([ ]) in the @emph{Targets} browser of
the @emph{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
    normalization: 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, Customization, Interaction, 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 and general remarks.
* Object File Formats::         Object File Formats.
* Non-geometric objects::       Non-geometric objects.
@end menu

@comment ================================================================
@node Conventions, Object File Formats, OOGL File Formats, OOGL File Formats
@section Conventions

@menu
* Common syntax::               Syntax Common to All OOGL File Formats.
* File names::                  File Names.
* Vertices::                    Vertices.
* ND-Vertices::                 @var{N}-dimensional Vertices.
* Surface normal directions::   Surface normal directions.
* Transformation matrices::     Transformation matrices.
* ND Transformation matrices::  @var{N}-dimensional transformation matrices.
* Binary format::               Binary format.
* References::                  Embedded objects and external-object references.
* Appearances::                 Appearances.
* Texture Mapping::             Texture mapping.
@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, ND-Vertices, 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 ND-Vertices, Surface normal directions, Vertices, Conventions
@subsection @var{N}-dimensional 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 for @var{N}-dimensional vertices (@var{N} > 3) is

@table @samp
@item @var{x[1]}  @var{x[2]}  @var{x[3]} @var{x[4]} @dots{}
(@var{N} floating-point vertex coordinates) or
@item @var{x[0]} @var{x[1]}  @var{x[2]}  @var{x[3]} @var{x[4]} @dots{}
(@var{(N+1)} floating-point vertex coordinates, if the @code{4} modifier
has been specified in the object's header line)
@end table

Note, however, that @var{N}-dimensional objects internally always have
@var{(N+1)}-dimensional points; the first component @var{x[0]} -- if
present in the object file -- is used as homogeneous divisor. This is
different from the ordinary 3D case where the @code{4} modifier
generates a 4D object where the homogeneous component implicitly is set
to 1.

Color components usually can be specified like for 3D vertices,
@pxref{Vertices}, while specifying normals does not make sense.

@comment ----------------------------------------------------------------
@node Surface normal directions, Transformation matrices, ND-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, ND Transformation matrices, 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 ND Transformation matrices, Binary format, Transformation matrices, Conventions
@subsection ND Transformation matrices

In the context of @var{N}-dimensional space (@var{N} > 3) some objects
incorporate @var{(N+1)}x@var{(N+1)} real matrices for homogeneous object
transformations.  These matrices act by multiplication on the right of
vectors.  Thus, if p is an @var{(N+1)}-element row vector representing
homogeneous coordinates of a point in the OOGL object, and A
@var{(N+1)}x@var{(N+1)} is the matrix, then the transformed point is p'
= p A.

Note that (unlike for the 4x4 transformation matrices,
@pxref{Transformation matrices}) the homogeneous component is located at
index @b{zero}, so the translation components for Euclidean
transformations appear in the @b{zero}-th row (first @var{(N+1)}
elements). A's first column (at column index zero) is typically 1, 0,
@dots{}, 0.

@comment ----------------------------------------------------------------
@node Binary format, References, ND 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} ]
            [ ["="] @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 @}

        @{ 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 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.

The "@code{define} NAME" construct allows to define a global symbol for
the given object. If "NAME" already references an object, then the old
object is discarded and replaced by the new
definition. @xref{read,@code{(read @dots{})}}. @xref{hdefine,@code{(hdefine
@dots{})}}.

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
(@pxref{load-path, @code{(load-path @dots{})}}) is used.  The default search
looks first in the current directory, then in the Geomview data
directories.

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, wire-frame 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",
"lighting" and "texture" substructures. Take care to note which
properties belong to which structure. Any geometric object can be
preceded by an appearance definition like in the following example:

@example
@{ 
   appearance @{ +edge @}
   LIST @{ < "file1" @} @{ QUAD 1 0 0  0 0 1  0 1 0  1 0 0 @}
@}
@end example

Appearances are also OOGL objects in their own right and can be given
symbolic names and referenced by them
(@pxref{References}). @xref{appearance objects, Appearance objects}.

@table @b
@item Texture Mapping
There is a separate section concerning the definition of textures
(@pxref{Texture Mapping}).

@item Transparency
Rendering translucent objects is not supported by all drawing back
ends. The OpenGL renderer has limited support for it: top-level objects
(i.e. those which appear in the object browser of the main panel
(@pxref{Basic Interaction, The Main Panel}) are rendered correctly by
means of alpha-blending). Also, the RenderMan snapshots will include
opacity values.
@end table

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 screendoor
                      # (Enable) transparency. Enabling transparency 
                      # does not (necessarily) result in a correct Geomview
                      # pictures, but alpha values are used in RenderMan
                      # snapshots.
                      # The allowed keywords are ``screendoor'' (masking out
                      # out pixels by means of a stipple pattern),
                      # ``blending'' for alpha-blending with BSP-tree
                      # space paritioning and depth-sorting (slow) and
                      # ``naive'' for alpha-blending without even
                      # depth-sorting, not to talk about space
                      # partioning. Omitting the keyword will default to
                      # alpha-blending with BSP-tree space-partioning
                      # and depth-sorting.
  -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          # (Enable) texture mapping
  +linear             # (Enable) linear average of closest texture elements
  +mipmap             # (Enable) texture mip-mapping
  +mipinterp          # (Enable) linear mip-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'' or ``shading vcflat''.
                      # smooth = Gouraud shading, flat = faceted,
                      # csmooth = smoothly interpolated but unlighted,
                      # vcflat = flat shading, but smoothly interpolated colors.

  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. @code{*+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,  , Appearances, Conventions
@subsection Texture Mapping

Some rendering back-ends support texture-mapped objects, actually only
the OpenGL and the RenderMan interface at the time of this
writing. There are also some issues with the RMan interface when using
an alpha-channel in the texture image. Those rendering back-ends which
don't support texturing silently ignore attempts to use texture
mapping. A texture is specified as part of an appearance structure
(@pxref{Appearances}).  Briefly, one provides a texture image
(@pxref{image, Image objects}), 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 @{ @dots{} @} 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.

image @{ <image specification> (@pxref{image, Image objects}) @}
  Specify the actual texture image. Images can have 1, 2, 3 or 4 channels:
    1 channel:  luminance
    2 channels: luminance and alpha
    3 channels: RGB data
    4 channels: RGBA data

  @xref{image, Image objects}, for the actual definition of image
  objects. The alpha-channel is only interpreted as mask: where the mask
  is zero, pixels are simply not drawn. An exception is the case where
  @emph{apply} is equal to @emph{modulate} and translucency is enabled:
  in this case the resulting alpha value is the result of the
  multiplication of the surface color with the alpha value of the
  texture's alpha channel.

file      filename
alphafile filename
  @emph{This is considered obsolete, and only kept for compatibility,
  the modern way is to use the new OOGL image object. @xref{image, Image objects}.
  The stuff documented here should still work, though}

  Specifies image file(s) containing the texture.
       
  The @emph{file} keyword specifies a file with color or lightness information;
  @emph{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
  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.

  @emph{Image objects provide a more flexible way to specify texture
  data. @xref{image, Image objects}.}

apply   modulate  -or-  blend  -or-  decal
  Indicates how the texture image is applied to the surface.
  Here the "surface color" means the color the 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, Non-geometric objects, Conventions, OOGL File Formats
@section Object File Formats

@menu
* QUAD::                        List of quadrilaterals.
* MESH::                        Rectangularly-connected mesh.
* BBOX::                        Simple bounding-boxes.
* 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 close-brace 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, BBOX, 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 BBOX, BBP and BEZ, MESH, Object File Formats
@subsection BBOX: simple bounding boxes

This is a very simple toy-object: it takes 2 vertices and draws a
(hyper-) cube which is the bounding box of the two vertices.

Syntax:

@example
  BBOX
  @var{x}[0] @var{y}[0] @var{z}[0]
  @var{x}[1] @var{y}[1] @var{z}[1]
@end example

or

@example
  4BBOX
  @var{x}[0] @var{y}[0] @var{z}[0] @var{w}[0]
  @var{x}[1] @var{y}[1] @var{z}[1] @var{w}[1]
@end example

or

@example
  nBBOX
  @var{Ndim} # > 3
  @var{x}[0] @var{y}[0] @var{z}[0] @var{w}[0] @dots{}
  @var{x}[1] @var{y}[1] @var{z}[1] @var{w}[1] @dots{}
@end example

or

@example
  4nBBOX
  @var{Ndim} # > 3
  @var{d}[0] @var{x}[0] @var{y}[0] @var{z}[0] @var{w}[0] @dots{}
  @var{d}[0] @var{x}[1] @var{y}[1] @var{z}[1] @var{w}[1] @dots{}
@end example

There is no BBOX binary format. The @code{4} modifyer has different
meanings depending on the dimension of the bounding box: @code{4BBOX}
means that the 4 components of the vertices make up a 4-dimensional
bounding-box. Using @code{4} in conjunction with @code{n} --
@code{4nBBOX @var{NDim}} -- means that the vertices specified in the
file have @var{NDim+1} components, but the component at index 0 is the
homogeneous divisor (in contrast to the ordinary 3d case where the
homogeneous divisor would be the @code{w} -- the third -- component).

@comment ----------------------------------------------------------------
@node BBP and BEZ, OFF, BBOX, 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}.  These 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} @b{16-bit} 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 @b{16-bit} integers @var{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

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; @pxref{Binary format}.  The
binary format exactly follows the ASCII format, with 32-bit Big-Endian
integers where ordinary integer numbers appear, and with @b{16-bit}
Big-Endian integers where 16-bit integers appear; 32-bit Big-Endian
floats where real values appear.  @b{BIG FAT NOTE:} The vertex counts
@var{Nv[i]} and the color counts @var{Nc[i]} are @b{16-bit} Big-Endian
integers.

@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
[C][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 4SKEL, each vertex has 4 components
                                    # if nSKEL, each vertex has NDim components
                                    # if C[4][n]SKEL vertex coordinates are
                                    # followed by an RGBA color specification
@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.

A @var{[4][n]SKEL 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.

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

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

while the same polyline 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 SPHERE, INST, SKEL, Object File Formats
@subsection SPHERE Files

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

@example
[ST][E|H|S]SPHERE # Keyword
# auto-generated texture co-ordinates, only allowed with @emph{ST}SPHERE objects
[SINUSOIDAL|CYLINDRICAL|RECTANGULAR|STEREOGRAPHIC|ONEFACE]
# next four fields are required
@var{Radius}
@var{Xcenter} @var{Ycenter} @var{Zcenter}
@end example

The key word is  @code{[ST][E|H|S]SPHERE}.
The optional prefix characters mean:

@table @samp
@item ST
The sphere carries automatically generated texture co-ordinates. See below.
@item E
The sphere lives in Euclidean space.
@item H
The sphere lives in Hyperbolic space. @xref{Non-Euclidean Geometry}.
@item S
The sphere lives in spherical space. @xref{Non-Euclidean Geometry}.
@end table

Sphere objects are drawn using meshes which are rectangular in a polar
co-ordinate system, with the equatorial plane parallel to the
@code{x,y}-plane. 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.

Texture co-ordinates are generated for @code{STSPHERE} objects; the
keyword following the initial @code{STSPHERE} keyword defines the way
this is done. It follows the conventions of the @command{mktxmesh}
Perl-script which comes with the @emph{Orrery}.

@table @var
@item SINUSOIDAL
sinusoidal equal-area projection
@item CYLINDRICAL
cylindrical proj: @var{s} is the longitude, @var{t} is the latitude
@item RECTANGULAR
rectangular proj: @var{s} is the longitude, @var{t} is @code{sin(latitude)}
(i.e. @code{z} co-ordinate in the sphere's co-ordinate system)
@item STEREOGRAPHIC
stereographic projection from the south (@code{z=-1}) pole
@item ONEFACE
stretch orthographic view of @code{+y} hemisphere over both, mirroring
@end table

@comment ----------------------------------------------------------------
@node INST, LIST, 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 (or @var{(N+1)}x@var{(N+1)} in the context of
ND-viewing) 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.

When replicating a single geometry by means of a @code{TLIST} object
(see @samp{transforms} above) it may be useful to transform texture
co-ordinates by another list of transformations; that list can be
specified by
@example
txtransforms
    @var{TLIST-object}
@end example
The number of texture transformations must match the number of geometry
transformations. The @code{SPHERE} object (@pxref{SPHERE, Sphere
Objects}) uses this technique to generate an entire textured sphere out
of some fraction of a sphere (usually one octant).

A single @var{(N+1)}-dimensional transformation can be specified by

@example
ntransform ["@{"] @var{N+1} @var{N+1} @code{(N+1)x(N+1) floats} ["@}"]
@end example
@noindent
This gives a single @var{N+1}-dimensional transformation matrix.  Either
the matrix may appear literally as @var{(N+1)}x@var{(N+1)} numbers, or
there may be a reference to an @samp{ntransform} object, i.e.
@example
    "<" file-containing-@var{(N+1)}x@var{(N+1)}-matrix
@end example
or
@example
    ":" symbol-representing-ntransform-object
@end example

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

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

Note that @code{location} as well as @code{origin} are ignored if this
@code{INST} object carries an @code{ntransform}. Also, if ND-viewing is
active (@code{ND-axes} command, @pxref{GCL}) then @code{INST} objects
with @code{origin} unequal to @code{local} will not be drawn, though the
@code{location} stuff may work (or not).

@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,  , INST, INST
@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, 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 @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
transform @{             # reference to a transform object
<transform object (can be a handle)>
@}
tlist @{                 # nested TLIST
<TLIST OOGL object (can be a handle)>
@}
@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.

@code{TLIST}s can be nested: effectively this means that all
transformations in each nested @code{TLIST} object are multiplied (from
the left) by the transformations in the outer @code{TLIST} object.

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,  , 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.geomview.org/ @}@}
@}
@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,  , Object File Formats, 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
* appearance objects::          Appearance objects.
* image objects::               Image objects.
* transform objects::           Transformation matrices.
* ntransform objects::          N-dimensional transformation matrices.
* camera objects::              Cameras.
* window objects::              Windows.
@end menu

@comment ----------------------------------------------------------------
@node appearance objects, image objects, Non-geometric objects, Non-geometric objects
@subsection Appearance Objects
Appearances are OOGL objects of their own right, which simply means that
it is possible to give them symbolic names (@pxref{References}). There
are other sections dealing with appearance
details. @xref{Appearances}.

@node image objects, transform objects, appearance objects, Non-geometric objects
@subsection Image Objects

Image objects are used to specify pixmap data for either textures
(@pxref{Texture Mapping}), or for background images of cameras
(@pxref{camera, Camera objects}).

At the time of this writing images are comprised of 1 to 4 channels, a
channel provides a single number in the range from 0 to @code{maxval}
for each pixel; and @code{maxval} is tied to 255. The interpretation of the image data depending on the number of channels is like follows:

@multitable @columnfractions 0.2 0.2 0.6
@headitem #Channels @tab Channel No. @tab Interpretation
@item 1
@tab 1
@tab greyscale or luminance data
@item 2
@tab 1
@tab greyscale or luminance data
@item @code{ }
@tab 2
@tab alpha channel (0: transparent, @code{maxval}: opaque)
@item 3
@tab 1
@tab red channel
@item @code{}
@tab 2
@tab green channel
@item @code{}
@tab 3
@tab blue channel
@item 4
@tab 1
@tab red channel
@item @code{}
@tab 2
@tab green channel
@item @code{}
@tab 3
@tab blue channel
@item @code{}
@tab 4
@tab alpha channel (0: transparent, @code{maxval}: opaque)
@end multitable

Image data can be specified inline (embedded into the current data stream)
or via file references; in both cases the data is read in and
interpreted at the time the image object is parsed. @emph{This is
different from the old (and deprecated) texture image specification,
where the the image data on-disk would eventually be re-read by
Geomview}.

The general syntax of image objects is like follows:
@example
<image> ::= 
  [ "@{" ]             (curly brace, generally needed to make
                       the end of the object unambiguous.)
  [ "image" ]          (optional keyword; unnecessary if the type
                       is determined by the context, which it
                       usually is.)
  [ "define" <name> ]
                       (defines an image named <name>, setting
                       its value from the stuff which follows)
  | 
      "<" <filename>   (meaning: read image from that file)
  |
      ":" <name>       (meaning: use variable @var{name},
                       defined elsewhere; if undefined the image
                       carries no data)
  |
                       (actual stuff defining the image; image data
                       must come last, after defining the width and
                       height and number of channels)

      "width"          (width of the image, auto-detected from image data
                       if possible)

      "height"         (height of the image, auto-detected from image data
                       if possible)

      "channels"       (number of channels, auto-detected from image data
                       and @code{data} specifications, if possible)

      "maxval"         (unsupported, must be @code{255} if specified)

      "data DESTMASK [FILTER] [@{] < FILENAME [@}]"
      "data DESTMASK [FILTER] DATASIZE [@{][\n]LITERAL_IMAGE_DATA[@}]"
                       (either external or embedded image data, see below
                       for a detailed description of the meaning of
                       @emph{MASK} and @emph{FILTER}. An image can (and
                       has, in general) multiple data sections.)

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

@b{Details concerning the image data specification:}

@table @samp
@item DESTMASK
This is a bit-field describing where the specified image data should be
placed in the destination pixmap. The bit-field is specified by an
integer in one of the known formats (decimal, octal, hexadecimal). The
channels of the source data are always enumbered consecutively. If,
e.g. @samp{FILENAME} or @samp{LITERAL_IMAGE_DATA} specify a
three-channel (probably RGB @dots{}) image and @samp{DESTMASK} equals
@code{0xD} (i.e. bit 1 is 0), then the 3rd channel of the source pixmap
would be placed in the 4th channel of the destination image object (the
alpha channel), the 2nd source channel would determine the @samp{blue}
destination value and the 1st source channel the @samp{red} destination
value.

The number of channels of the source data always has to match the number
of bits set in @samp{DESTMASK}. @b{Exception:} if the source pixmap has
only one channel, then it can be used to fill any number of destination
channels; all channels specified in @samp{DESTMASK} are filled with the
data of the single channel source pixmap.

Geomview knows the following symbolic constants, which can be used
instead of specifying the @samp{DESTMASK} bit-field numerically:
@table @code
@item LUMINANCE
same as @samp{1}, @samp{0x1}, @samp{\01}
@item LUMINANCE_ALPHA
same as @samp{3}, @samp{0x3}, @samp{\03}
@item RGB
same as @samp{7}, @samp{0x7}, @samp{\07}
@item RGBA
same as @samp{15}, @samp{0xf}, @samp{\017}
@item ALPHA
depends on the context: the absolute number of channels must be known;
i.e. @samp{data ALPHA @dots{}} must be prepended by something determining
the number of channels of the image, e.g.
@example
...
data RGB ...
data ALPHA
...
@end example
is valid, but
@example
<no other channel or image data specification>
data ALPHA ...
<whatever else ...>
@end example
is not valid, because Geomview has not means to determine the
destination channel from the context.
@item AUTO
PGM image data is interpreted as single grey-scale channel, RGB PNM data
as RGB image data. @code{AUTO} cannot work with @samp{raw} image data.
@end table

@item FILTER
The @samp{FILTER} specification is optional. If it is missing, then
Geomview tries to determine the image type from the @samp{FILENAME}
suffix. If there is no suffix or the suffix is unknown, or for embedded
image data, Geomview is able to auto-detectc SGI image file formats (for
historical reasons @dots{}) and NetPBM image formats (for practical
reasons). The auto-detection of NetPBM formats includes the new
@dfn{PAM} image format which allows (among other things) to store an
alpha channel together with the luminance or RGB data. Likewise, the
final output of any of the specified filters must either be in SGI image
file format, or specify a PAM, PNM or PGM image.  If the image file
format cannot be determined by either the filenmae suffix or the filter
specification or by auto-deteciong of SGI or NetPBM data, then Geomview
assume that it is raw-data. See below.

The decompression filters may be prepended to either one of the know
image formats or an explicitly specified filter, e.g. the following is
valid:
@example
data LUMINANCE raw.gzip @{ < gzippedgreymapfile @}
@end example
The above should be equivalent to
@example
data LUMINANCE raw @{ < greymapfile @},
@end example
provided that the decompressed data carries single channel data, with
the first pixel corresponding to the lower-left corner (because of the
@samp{raw} image format, see below).

Geomview has builtin knowledge for the following filters/suffixes:
@table @b
@item Data Decompression
@table @samp
@item z
@item gz
@item gzip
data is piped through @samp{gzip -dc}
@item bz2
@item bzip2
data is piped through @samp{bzip2 -dc}
@end table

@item Image Formats
@table @samp
@item tiff
@item tif
@code{TIFF} image file format. Only supported if the @code{tifftopnm}
executable can be fond in the current excution path.
@item png
@code{PNG} image file format. Only supported if the @code{pngtopnm}
executable can be fond in the current excution path.
@item jpg
@item jpeg
@code{JPEG} image file format. Only supported if the @code{jpegtopnm}
executable can be fond in the current excution path.
@item gif
@code{GIF} image file format. Only supported if the @code{giftoppm}
executable can be fond in the current excution path.
@item raw
Raw image data; the number of channels must match the number of bits set
in @samp{DESTMASK}. Pixels are specified with 1 byte per channel. The
pixels are organized in rows as @samp{liminance[-alpha]} or
@samp{RGB[A]} samples. The left-most pixel is the first pixel in each
data-row, the top-most image row must come first (this is just the same
as the NetPBM convention, the image co-ordinate systems has its origin
in the left/top corner, as usual).
@end table
@item Explicitly Specified Filters
If none of the suffixes specified above should match, then the
suffix/filter is interpreted as an external filter program; the filter
program must read from @code{STDIN} and write to @code{STDOUT}. The
output must either be in SGI image format, or in PNM or PGM
format. Otherwise the output data is interpreted as raw image data (see
above).

Something like the following should work, provided that the program
@file{$@{HOME@}/bin/bububfilter} exists, is executable and does
something useful:
@example
...
data RGB "$@{HOME@}/bin/bububfilter.bzip2" 7 @{ # binary data follows
bububub
@}
...
@end example

Note that -- prior to feeding the data to the @samp{bububfilter} --
Geomview will try to decompress the stuff with @samp{bzip2 -dc}.

@end table

@end table

@b{Missing image data:} Normally, the number of image channels is
determined automatically from the image @code{data} specifications; if
the image specification carries an explicit number of channels via the
@code{channels} keyword which exceeds the number of channels found in
the image @code{data} specifications, or if the union of all
@samp{DESTMASK} specfications has holes, then missing luminance and RGB
channels are initialized to 0, and a missing alpha-channel is
initialized to @code{maxval}, i.e. omitting the alpha channel data for
an RGBA image is just the same as defining an RGB image.

@node transform objects, ntransform objects, image 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 ntransform objects, camera objects, transform objects, Non-geometric objects
@subsection ND-Transform Objects

Where -- in the context of ND-viewing -- a single (N+1)x(N+1) matrix is
expected -- as in the @code{INST} @code{ntransform} field, or the
@code{ND-xform*} (@pxref{GCL}) commands -- use an @code{ntransform} object.

@code{ntransform} are @var{NRows} x @var{NCols} transformation matrix
where usually @var{NRows} = @var{N+1} in the context of
@var{N}-dimensional objects and viewing. The homogeneous component of an
@code{ntransform} sits at column zero (in contrast to ordinary
@code{transform} objects where it is located at column
three). @code{ntransform} objects operate on points of any dimension: if
a point is to be transformed by an @code{ntransform} object and the
dimension of the point does not match the number of rows of the
@code{ntransform} object, then either the point is implicitly padded
with zeros to match @var{NRows} or the matrix is implicitly padded with
ones down its diagonal (and zeros everywhere else) such that it will
operate as identity on the excess dimensions of the input point.

Syntax for an @code{ntransform} object is

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

   [ "ntransform" ]    (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)

     @var{NRows} @var{NCols}
                       (number of rows and columns of the matrix,
                       typically @var{N+1} @var{N+1}, but any dimensions
                       are possible)
     <@var{NRows} x @var{NCols} floating-point numbers>
                       (interpreted as a @var{NRows} x @var{NCols}
                       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
                       @b{top} row -- in contrast to the ordinary
                       transform objects where the 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
necessarily essential, so e.g. two integers -- @var{NRows} @var{NCols}
-- followed by a @var{NRows} x @var{NCols} 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 @code{6x6} transform called
# "fred", a mere translation by the vector @code{-3 0 1 1 0}. This
# transform is meant for a five dimensional space, with an homogeneous
# component a index zero.

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

@example
# Example 2: Set the ND-xform of an object -- a geometry or a camera
# cluster. Given the definition above, this puts the object at (-3 0 1 1
# 0) in the five dimensional space.

(ND-xform-set focus : fred)

# or

(ND-xform-set g1 : fred)
@end example

@comment ----------------------------------------------------------------
@node camera objects, window objects, ntransform objects, 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.

@item background color
Arguably not a property of a camera, but of the scene. Nevertheless, as
there is no "background" OOGL object, and the background color should
not be a property of the drawing device, it can be specified here. At
the time of this writing, however, the GUI always overrides the
background color with its own settings.

@item background image
Same reasoning as above, only that the GUI does not override this
setting. The image is centered at NDC co-ordinates @code{(0,0,-1)}; it
is not resized, just painted behind everything else as is. @xref{image,
Image objects}.

@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)

        "bgcolor" <float RGB(A) color>          (default 1/3 1/3 1/3 1)

        "bgimage" @{ <image specification> @}     (default no background image)

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


@comment ----------------------------------------------------------------
@node window objects,  , camera objects, 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. @xref{window, @code{(window
@dots{})}}. @xref{ui-panel, @code{(ui-panel @dots{})}}.


@comment ****************************************************************
@node Customization, Modules, OOGL File Formats, 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
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.  @xref{GCL}. @xref{ui-panel, @code{(ui-panel
@dots{})}}.

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.

To change, e.g. the focus policy of the camera window such that they
pick up the focus policy of the window manager (instead of being
activated when the mouse cursor crosses the window), you could put the
following in your @file{~/.geomview} file:

@example
(progn
  (ui-cam-focus focus-change)
  @dots{} # other stuff
)
@end example

You can put any valid @code{GCL} command into your @file{.geomview}
files,@pxref{GCL}. @xref{progn,@code{(progn
@dots{})}}. @xref{ui-cam-focus,@code{(ui-cam-focus @dots{})}}.

@comment ****************************************************************
@node Modules, GCL, 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.
* XForms::                      The XForms 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 @emph{Modules} browser in Geomview's
@emph{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 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
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 @emph{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 external 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 @emph{Modules} browser
of Geomview's @emph{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 "[1]
Example 1" line in the @emph{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,
@pxref{GCL}. @xref{References}. @xref{hdefine,@code{(hdefine
@dots{})}}. @xref{read,@code{(read @dots{})}}.

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 @emph{Modules}
browser, or else when Geomview exits.

Sometimes when you terminate this module by clicking on its instance
entry the @emph{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, XForms, 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. @c 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

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
@emph{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 @emph{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 @emph{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 XForms, Example3, Example2, Modules
@section The XForms Library

XForms is a handy and relatively simple user interface toolkit for X11.
Many Geomview external modules, including the examples in this manual,
use XForms to create and manage control panels. XForms is available from
@uref{http://www.nongnu.org/xforms/}. XForms is free-ware.  If you wish
you may use any other interface toolkit instead of XForms in an external
module.  We chose FORMS because it is free and relatively simple.

There is a complete autoconf'ed package @samp{gvemod-xforms-example}
available from Geomview's
@uref{http://geomview.sourceforge.net, Sourceforge.NET}
page.

@comment ================================================================
@node Example3, Example4, XForms, 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
@ref{write,@code{(write @dots{})}}.  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
 *
 * 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);
@},
/* version for picking Nd-objects (not documented here) */)

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{PICKFUNC} 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{block}, @var{NDblock})
@end example
@noindent
where @var{name} is the name of the procedure to be defined, in this
case @code{Lpick}. The next argument, @var{block}, is a block of code to
be executed when a pick event occurs.  If @var{block} contains a return
statement, then the returned value must be a pointer to a Lisp-object,
that is of type @code{LObject *}. The last argument has the same
functionality as the @var{block} argument, but is only invoked when
picking objects in a higher dimensional world.

@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). 

There is also a second variant of the @code{PICKFUNC} macro with a
slightly different syntax:
@example
DEFPICKFUNC(@var{helpstr}, @var{coordsys}, @var{id},
  @var{point}, @var{pn}, @var{vertex}, @var{vn}, @var{edge}, @var{en}, @var{face}, @var{fn}, @var{ppath}, @var{ppn},
  @var{vi}, @var{ei}, @var{ein}, @var{fi},
  @var{body}, @var{NDbody})
@end example
@code{DEFPICKFUNC} can be used as well as @code{PICKFUNC}, there is no
functional difference with the exception that the name of the C-function
is tied to @code{Lpick} when using @code{DEFPICKFUNC} and that the
@code{(help pick)} GCL-command (@pxref{help, @code{(help @dots{})}})
would respond with echoing @var{helpstr}.

The table below lists all variables defined in @code{PICKFUNC} In the
context of ND-viewing @code{float} variants of the arguments apply: the
@var{body} execution block sees the @code{HPoint3} variables, and the
@var{NDbody} block sees only flat one-dimensional arrays of
@code{float}-type.

In the ND-viewing context the co-ordinates passed to the pick function
are still the 3-dimensional co-ordinates of the camera view-port where
the pick occurred, but padded with zeroes on transformed back to the
co-ordinate system specified by the second argument of the @code{pick}
command.

@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;}

@item @code{float *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 @code{0}, @code{4} or greater than @code{4}. If it is greater
than @code{4}, then the @var{NDbody} instruction block is invoked and in
this case @code{point} is a flat array of @code{pn} many @code{float}s.
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. In this
case the ordinary @var{block} 3d instruction block is executed.

@item @code{HPoint3 vertex; int vn;}

@item @code{float *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 @code{0} or greater equal @code{4}. A value of zero means the
pick point was not near a vertex. In the context of ND-viewing
@code{vertex} will be an array of @code{vn} @code{float}s and @code{vn}
will be equal to @code{pn}.

@item @code{HPoint3 edge[2]; int en;}

@item @code{float *edge; 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 @code{0} or greater equal @code{8}.
A value of zero means the pick point was not near an edge. In the
context of ND-viewing @code{edge} will be a flat one-dimensional array
of @code{en} many @code{float}s: the first @code{pn} @code{float}s
define the first vertex, and the second @code{pn} many @code{float}s
define the second vertex; @code{en} will be two times @code{pn}.

@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[]; int fn;}

@item @code{float *face; int fn;}
@code{face} is a variable length array of @var{fn} @code{HPoint3}'s.
@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 either @code{0} or a multiple of @code{pn}. A value of
zero means the pick point was not near a face. In the context of
ND-viewing @code{face} is a flat one-dimensional array of @code{fn} many
floats of which each vertex occupies @code{pn} many components.

@item @code{int ppath[]; int ppn;}
@code{ppath} is an array of @var{maxpathlen} @code{int}'s.  @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 @dots{}'' rather than simply ``puts @dots{}'',
# 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,  , 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::  Per-user modules.
* System Module Installation::  System-wide modules.
@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 @emph{Modules} browser. The command takes two string
arguments; the first is the name that will appear in the @emph{Modules}
browser.  The second is the shell command for running the module; it may
include arguments (@pxref{emodule-define,@code{(emodule-define @dots{})}}).
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 @emph{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 @emph{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 @emph{Modules} browser; for details, @xref{GCL}.

@comment ----------------------------------------------------------------
@node System Module Installation,  , 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 @emph{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 @file{/usr/local/libexec/geomview} directory.

@end table

After these steps, the new module should appear, in alphabetical
position, in the @emph{Modules} browser of Geomview's @emph{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, Non-Euclidean Geometry, Modules, 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
@emph{Commands} panel which lets you type in a command; Geomview
executes the command when you hit the @key{Enter} 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 /share/man/man5/oogl.5gv.

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{ntransform}
is an OOGL (N+1)x(N+1) transformation matrix.

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

@end table

@node GCL Reference,  , Argument Conventions, GCL
@section GCL Reference Guide

@c @table @code

@menu
* shell-shortcut::              @code{(! SHELLCOMMAND)}
* lt::                          @code{(< EXPR1 EXPR2)}
* eq::                          @code{(= EXPR1 EXPR2)}
* gt::                          @code{(> EXPR1 EXPR2)}
* mul::                         @code{(* EXPR1 EXPR2)}
* div::                         @code{(/ EXPR1 EXPR2)}
* add::                         @code{(+ EXPR1 EXPR2)}
* sub::                         @code{(- EXPR1 EXOR2)}
* help-shortcut::               @code{(? COMMAND)}
* morehelp-shortcut::           @code{(?? COMMAND)}
* emodule-run-shortcut::        @code{(| NAME)}
* all::                         @code{(all geometry|camera|emodule)}
* and::                         @code{(and EXPR1 EXPR2)}
* ap-override::                 @code{(ap-override [on|off])}
* backcolor::                   @code{(backcolor      CAM-ID R G B)}
* background-image::            @code{(background-image CAM-ID [FILENAME])}
* bbox-color::                  @code{(bbox-color GEOM-ID R G B)}
* bbox-draw::                   @code{(bbox-draw GEOM-ID [yes|no])}
* camera::                      @code{(camera CAM-ID [CAMERA])}
* camera-draw::                 @code{(camera-draw CAM-ID [yes|no])}
* camera-prop::                 @code{(camera-prop @{ geometry object @} [projective])}
* camera-reset::                @code{(camera-reset CAM-ID)}
* car::                         @code{(car LIST)}
* cdr::                         @code{(cdr LIST)}
* clock::                       @code{(clock)}
* command::                     @code{(command INFILE [OUTFILE])}
* cons::                        @code{(cons EXPR LIST)}
* copy::                        @code{(copy [ID] [name])}
* cursor-still::                @code{(cursor-still [INT])}
* cursor-twitch::               @code{(cursor-twitch [INT])}
* defun::                       @code{(defun NAME ARGS [DOC] BODY)}
* delete::                      @code{(delete ID)}
* dice::                        @code{(dice GEOM-ID N)}
* dimension::                   @code{(dimension [N])}
* dither::                      @code{(dither CAM-ID @{on|off|toggle@})}
* draw::                        @code{(draw CAM-ID)}
* dump-handles::                @code{(dump-handles)}
* echo::                        @code{(echo @dots{})}
* emodule-clear::               @code{(emodule-clear)}
* emodule-define::              @code{(emodule-define NAME SHELL-COMMAND @dots{})}
* emodule-defined::             @code{(emodule-defined @code{modulename})}
* emodule-isrunning::           @code{(emodule-isrunning NAME)}
* emodule-path::                @code{(emodule-path)}
* emodule-run::                 @code{(| NAME)}
* emodule-sort::                @code{(emodule-sort)}
* emodule-start::               @code{(emodule-start  NAME)}
* emodule-transmit::            @code{(emodule-transmit NAME LIST)}
* escale::                      @code{(escale GEOM-ID FACTOR)}
* eval::                        @code{(eval EXPR)}
* event-keys::                  @code{(event-keys @{on|off@})}
* event-mode::                  @code{(event-mode MODESTRING)}
* event-pick::                  @code{(event-pick @{on|off@})}
* evert::                       @code{(evert GEOM-ID [yes|no])}
* exit::                        @code{(exit)}
* ezoom::                       @code{(ezoom GEOM-ID FACTOR)}
* freeze::                      @code{(freeze CAM-ID)}
* geometry::                    @code{(geometry GEOM-ID [GEOMETRY])}
* geomview-version::            @code{(geomview-version)}
* hdefine::                     @code{(hdefine geometry|camera|@dots{} NAME VALUE)}
* hdelete::                     @code{(hdelete [geometry|camera|@dots{}] name)}
* help::                        @code{(? COMMAND)}
* hmodel::                      @code{(hmodel CAMID @{virtual|projective|conformal@})}
* hsphere-draw::                @code{(hsphere-draw CAMID [yes|no])}
* if::                          @code{(if TEST EXPR1 [EXPR2])}
* inhibit-warning::             @code{(inhibit-warning STRING)}
* input-translator::            @code{(input-translator "#pfx" "sh-command")}
* interest::                    @code{(interest (COMMAND [args]))}
* lambda::                      @code{(lambda ARGS BODY)}
* let::                         @code{(let (ARGS) BODY)}
* lines-closer::                @code{(lines-closer CAM-ID DIST)}
* load::                        @code{(load filename [command|geometry|camera])}
* load-path::                   @code{(load-path)}
* look::                        @code{(look [objectID] [camID])}
* look-encompass::              @code{(look-encompass [objID] [camID])}
* look-encompass-size::         @code{(look-encompass-size [view clip near far])}
* look-recenter::               @code{(look-recenter [objID] [camID])}
* look-toward::                 @code{(look-toward [objID] [camID] [origin|center])}
* merge::                       @code{(merge @{window|camera@} CAM-ID @{ WIN or CAM @dots{} @})}
* merge-ap::                    @code{(merge-ap GEOM-ID APPEARANCE)}
* merge-base-ap::               @code{(merge-base-ap APPEARANCE)}
* merge-baseap::                @code{(merge-baseap APPEARANCE)}
* mod::                         @code{(mod NUMERATOR DENOMINATOR)}
* morehelp::                    @code{(?? COMMAND)}
* name-object::                 @code{(name-object ID NAME)}
* ND-axes::                     @code{(ND-axes CAMID [CLUSTER [Xidx Yidx Zidx [Widx]]])}
* ND-color::                    @code{(ND-color CAMID @dots{}}
* ND-xform::                    @code{(ND-xform OBJID [ntransform @{ @dots{} @}])}
* ND-xform-get::                @code{(ND-xform-get ID [from-ID])}
* ND-xform-set::                @code{(ND-xform-set OBJID [ntransform @{ @dots{} @}])}
* new-alien::                   @code{(new-alien name [GEOMETRY])}
* new-camera::                  @code{(new-camera name [CAMERA])}
* new-center::                  @code{(new-center [id])}
* new-geometry::                @code{(new-geometry name [GEOMETRY])}
* new-reset::                   @code{(new-reset)}
* NeXT::                        @code{(NeXT)}
* normalization::               @code{(normalization GEOM-ID @{each|none|all|keep@})}
* not::                         @code{(not EXPR)}
* or::                          @code{(or EXPR1 EXPR2)}
* pick::                        @code{(pick COORDSYS GEOMID G V E F P VI EI FI)}
* pick-invisible::              @code{(pick-invisible [yes|no])}
* pickable::                    @code{(pickable GEOM-ID @{yes|no@})}
* position::                    @code{(position objectID otherID)}
* position-at::                 @code{(position-at objectID otherID [center | origin])}
* position-toward::             @code{(position-toward objID othID [center|origin])}
* process-events::              @code{(process-events)}
* progn::                       @code{(progn STATEMENT [ @dots{} ])}
* quit::                        @code{(quit)}
* quote::                       @code{(quote EXPR)}
* rawevent::                    @code{(rawevent dev val x y t)}
* rawpick::                     @code{(rawpick CAMID X Y)}
* read::                        @code{(read geometry|camera|@dots{} @{GEOM or CAM or @dots{}@})}
* real-id::                     @code{(real-id ID)}
* redraw::                      @code{(redraw CAM-ID)}
* regtable::                    @code{(regtable)}
* rehash-emodule-path::         @code{(rehash-emodule-path)}
* replace-geometry::            @code{(replace-geometry GEOM-ID PART GEOMETRY)}
* rib-display::                 @code{(rib-display [frame|tiff] FILEPREFIX)}
* rib-snapshot::                @code{(rib-snapshot CAM-ID [filename])}
* scale::                       @code{(scale GEOM-ID FACTOR [FACTORY FACTORZ])}
* scene::                       @code{(scene CAM-ID [GEOMETRY])}
* set-clock::                   @code{(set-clock TIME)}
* set-conformal-refine::        @code{(set-conformal-refine CMX [N [EDGES]])}
* set-emodule-path::            @code{(set-emodule-path (PATH1 @dots{} PATHN))}
* set-load-path::               @code{(set-load-path (PATH1 @dots{} PATHN))}
* set-motionscale::             @code{(set-motionscale X)}
* setenv::                      @code{(setenv name string)}
* setq::                        @code{(setq SYM EXPR)}
* sgi::                         @code{(sgi)}
* shell::                       @code{(! SHELLCOMMAND)}
* sleep-for::                   @code{(sleep-for TIME)}
* sleep-until::                 @code{(sleep-until TIME)}
* snapshot::                    @code{(snapshot CAM-ID FILENAME [FORMAT [XSIZE [YSIZE]]])}
* soft-shader::                 @code{(soft-shader CAM-ID @{on|off|toggle@})}
* space::                       @code{(space @{euclidean|hyperbolic|spherical@})}
* stereowin::                   @code{(stereowin CAM-ID [no|horizontal|@dots{}] [gap])}
* time-interests::              @code{(time-interests delta initial prefix [suffix])}
* transform::                   @code{(transform objectID centerID frameID [rotate|@dots{}] @dots{})}
* transform-incr::              @code{(transform-incr objectID centerID frameID @dots{})}
* transform-set::               @code{(transform-set objectID centerID frameID @dots{})}
* truncate::                    @code{(truncate NUMBER)}
* ui-cam-focus::                @code{(ui-cam-focus @{focus-change|mouse-cross@})}
* ui-center::                   @code{(ui-center ID)}
* ui-center-origin::            @code{(ui-center-origin @{origin|bbox-center@})}
* ui-emotion-program::          @code{(ui-emotion-program PROGRAM)}
* ui-emotion-run::              @code{(ui-emotion-run EMODULE)}
* ui-freeze::                   @code{(ui-freeze @{on|off@})}
* ui-html-browser::             @code{(ui-html-browser BROWSER)}
* ui-motion::                   @code{(ui-motion @{inertia|@dots{}@} @{on|off@})}
* ui-panel::                    @code{(ui-panel PANELNAME @{on|off@} [WINDOW])}
* ui-pdf-viewer::               @code{(ui-pdf-viewer VIEWER)}
* ui-target::                   @code{(ui-target ID [yes|no])}
* uninterest::                  @code{(uninterest (COMMAND [args]))}
* update::                      @code{(update [timestep_in_seconds])}
* update-draw::                 @code{(update-draw CAM-ID  [timestep_in_seconds])}
* while::                       @code{(while TEST BODY)}
* window::                      @code{(window CAM-ID WINDOW)}
* winenter::                    @code{(winenter CAM-ID)}
* write::                       @code{(write command|geometry|@dots{} FILENAME @dots{})}
* write-comments::              @code{(write-comments FILENAME GEOMID PICKPATH)}
* write-handle::                @code{(write-handle PREFIX FILENAME HANDLE)}
* write-sexpr::                 @code{(write-sexpr FILENAME LISPOBJECT)}
* xform::                       @code{(xform ID TRANSFORM)}
* xform-incr::                  @code{(xform-incr ID TRANSFORM)}
* xform-set::                   @code{(xform-set ID TRANSFORM)}
* zoom::                        @code{(zoom CAM-ID FACTOR)}
@end menu

@node shell-shortcut, lt, GCL Reference, GCL Reference
@subsection !
@findex !, shell
@findex shell, !
@table @code
@item !
is a synonym for @code{shell}. @xref{shell}.
@end table

@node lt, eq, shell-shortcut, GCL Reference
@subsection <
@findex <
@table @code
@item (< EXPR1 EXPR2)
Returns t if EXPR1 is less than EXPR2.  EXPR1 and EXPR2 should
be either both integers or floats, or both strings.
@end table

@node eq, gt, lt, GCL Reference
@subsection =
@findex =
@table @code
@item (= EXPR1 EXPR2)
Returns t if EXPR1 is equal to EXPR2.  EXPR1 and EXPR2 should
be either both integers or floats, or both strings.
@end table

@node gt, mul, eq, GCL Reference
@subsection >
@findex >
@table @code
@item (> EXPR1 EXPR2)
Returns t if EXPR1 is greater than EXPR2.  EXPR1 and EXPR2 should
be either both integers or floats, or both strings.
@end table

@node mul, div, gt, GCL Reference
@subsection *
@findex *
@table @code
@item (* EXPR1 EXPR2)
Multiplies @var{EXPR1} and @var{EXPR2} and returns the result.
@end table

@node div, add, mul, GCL Reference
@subsection /
@findex /
@table @code
@item (/ EXPR1 EXPR2)
Divides @var{EXPR1} by @var{EXPR2} and returns the result.
@end table

@node add, sub, div, GCL Reference
@subsection +
@findex +
@table @code
@item (+ EXPR1 EXPR2)
Adds @var{EXPR1} and @var{EXPR2} and returns the result.
@end table

@node sub, help-shortcut, add, GCL Reference
@subsection -
@findex -
@table @code
@item (- EXPR1 EXPR2)
Substracts @var{EXPR2} from @var{EXPR1} and returns the result.
@end table

@node help-shortcut, morehelp-shortcut, sub, GCL Reference
@subsection ?
@findex ?
@table @code
@item (?  [command])
Gives one-line usage summary for @code{command}.  Command may include
@code{*}s as wildcards; see also @ref{morehelp, @code{(?? @dots{})}}.
One-line command help; lists names only if multiple commands match.
@code{?} is a synonym for @ref{help, @code{(help @dots{})}}
@end table

@node morehelp-shortcut, emodule-run-shortcut, help-shortcut, GCL Reference
@subsection ??
@findex ??
@table @code
@item (?? command)
@code{command} may include @code{*} wildcards.
Prints more info than @code{(? command)}. @code{??} is a synonym
for @ref{morehelp, @code{morehelp}}.
@end table

@node emodule-run-shortcut, all, morehelp-shortcut, GCL Reference
@subsection |
@findex |, emodule-run
@findex emodule-run, |
@table @code
@item |
@code{|} is a synonym for @code{emodule-run}.
@end table

@node all, and, emodule-run-shortcut, GCL Reference
@subsection all
@findex all
@table @code
@findex all geometry
@item (all geometry)
returns a list of names of all geometry objects. Use e.g.
@samp{(echo (all geometry))} to print such a list.
@findex all camera
@item (all camera)
returns a list of names of all cameras.
@findex all emodule defined
@item (all emodule defined)
returns a list of all defined external modules.
@findex all emodule running
@item (all emodule running)
returns a list of all running external modules.
@end table

@node and, ap-override, all, GCL Reference
@subsection and
@findex and
@table @code
@item (and EXPR1 EXPR2)
Evaluate @code{EXPR1} and @code{EXPR2} and return @code{t} if both
return non-@code{nil}, otherwise return @code{nil}.
@end table

@node ap-override, backcolor, and, GCL Reference
@subsection ap-override
@findex ap-override
@table @code
@item (ap-override [on|off])
Selects whether appearance controls should override objects' own
settings.  On by default.  With no arguments, returns current setting.
@end table

@node backcolor, background-image, ap-override, GCL Reference
@subsection backcolor
@findex backcolor
@table @code
@item (backcolor CAM-ID R G B)
Set the background color of CAM-ID; R G B are numbers
between 0 and 1.
@end table

@node background-image, bbox-color, backcolor, GCL Reference
@subsection background-image
@findex background-image
@table @code
@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.
@end table

@node bbox-color, bbox-draw, background-image, GCL Reference
@subsection bbox-color
@findex bbox-color
@table @code
@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.
@end table

@node bbox-draw, camera, bbox-color, GCL Reference
@subsection bbox-draw
@findex bbox-draw
@table @code
@item (bbox-draw GEOM-ID [yes|no])
Say whether GEOM-ID's bounding-box should be drawn; defaults to
@code{yes} if second argument is omitted.
@end table

@node camera, camera-draw, bbox-draw, GCL Reference
@subsection camera
@findex camera
@table @code
@item (camera CAM-ID [CAMERA])
Specify data for @var{CAM-ID}; @var{CAMERA} is a string giving an OOGL
camera specification.  If no camera @var{CAM-ID} exists, it is created;
in this case, the second argument is optional, and if omitted, a default
camera is used.  @xref{new-camera, @code{(new-camera @dots{})}}.
@end table

@node camera-draw, camera-prop, camera, GCL Reference
@subsection camera-draw
@findex camera-draw
@table @code
@item (camera-draw CAM-ID [yes|no])
Say whether or not cameras should be drawn in CAM-ID; @code{yes} if omitted.
@end table

@node camera-prop, camera-reset, camera-draw, GCL Reference
@subsection camera-prop
@findex camera-prop
@table @code
@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)
@end table

@node camera-reset, car, camera-prop, GCL Reference
@subsection camera-reset
@findex camera-reset
@table @code
@item (camera-reset CAM-ID)
Reset CAM-ID to its default value.
@end table

@node car, cdr, camera-reset, GCL Reference
@subsection car
@findex car
@table @code
@item (car LIST)
returns the first element of LIST.
@end table

@node cdr, clock, car, GCL Reference
@subsection cdr
@findex cdr
@table @code
@item (cdr LIST)
returns the list obtained by removing the first element of LIST.
@end table

@node clock, command, cdr, GCL Reference
@subsection clock
@findex clock
@table @code
@item (clock)
Returns the current time, in seconds, as shown by this stream's clock.
@xref{set-clock, @code{(set-clock @dots{})}}. @xref{sleep-until,
@code{(sleep-until @dots{})}}.
@end table

@node command, cons, clock, GCL Reference
@subsection command
@findex command
@table @code
@item (command INFILE [OUTFILE])
Read commands from INFILE; send corresponding responses
(e.g. anything written to filename @code{-}) to OUTFILE, stdout
by default.
@end table

@node cons, copy, command, GCL Reference
@subsection cons
@findex cons
@table @code
@item (cons EXPR LIST)
Returns the list obtained by adding @var{EXPR} as first element of
@var{LIST}. Note that the second argument has to be a list.
@end table

@node copy, cursor-still, cons, GCL Reference
@subsection copy
@findex copy
@table @code
@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.
@end table

@node cursor-still, cursor-twitch, copy, GCL Reference
@subsection cursor-still
@findex cursor-still
@table @code
@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.
@end table

@node cursor-twitch, defun, cursor-still, GCL Reference
@subsection cursor-twitch
@findex cursor-twitch
@table @code
@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.
@end table

@node defun, delete, cursor-twitch, GCL Reference
@subsection defun
@findex defun
@table @code
@item (defun NAME (ARG1 @dots{}) [DOCSTRING] EXPR1 @dots{})
Define a named lambda-expression, that is: define @var{NAME} to evaluate
to the lambda-expression @code{(lambda (ARG1 @dots{}) (EXPR1 @dots{}))}
when called as a function. Also, install @var{DOCSTRING} as response to
the commands @code{(help NAME)} and @code{(morehelp NAME)}.  Note that
@var{DOCSTRING} need not contain the command-synopsis, it is generated
automatically.  @var{EXPR1} cannot be a string if @code{DOCSTRING} is
omitted; it would be interpreted as the doc-string. The return value of
@code{(defun @dots{})} is the function name. Functions can be recursive
and self-modifying. It is possible to redefine builtin-functions, in
this case the old definition is still available under the name
@code{-builtin-OLDNAME-}. Argument values may be altered by @code{setq};
the new binding is discarded after evaluation of the surrounding
@code{defun}-body. The special keywords @code{&optional} and
@code{&rest} have the same meaning as for anonymous lambda-expression,
see there. @xref{lambda, @code{(lambda @dots{})}}.  @xref{setq,
@code{(setq @dots{})}}.  @xref{let, @code{(let @dots{})}}.
@end table

@node delete, dice, defun, GCL Reference
@subsection delete
@findex delete
@table @code
@item (delete ID)
Delete object or camera ID.
@end table

@node dice, dimension, delete, GCL Reference
@subsection dice
@findex dice
@table @code
@item (dice GEOM-ID N)
Dice any Bezier patches within @var{GEOM-ID} into NxN meshes; default
10. See also the appearance attribute @ref{Appearances, @code{patchdice}},
which makes this command obsolete.
@end table

@node dimension, dither, dice, GCL Reference
@subsection dimension
@findex dimension
@table @code
@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.
@end table

@node dither, draw, dimension, GCL Reference
@subsection dither
@findex dither
@table @code
@item (dither CAM-ID @{on|off|toggle@})
Turn dithering on or off in that camera.
@end table

@node draw, dump-handles, dither, GCL Reference
@subsection draw
@findex draw
@table @code
@item (draw CAM-ID)
Draw the view in CAM-ID, if it needs redrawing. @xref{redraw,
@code{(redraw @dots{})}}.
@end table

@node dump-handles, echo, draw, GCL Reference
@subsection dump-handles
@findex dump-handles
@table @code
@item (dump-handles)
Dump the list of currently active handles to stdout. This function is
intended for internal debugging use only.
@end table

@node echo, emodule-clear, dump-handles, GCL Reference
@subsection echo
@findex echo
@table @code
@item (echo @dots{})
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).
@end table

@node emodule-clear, emodule-define, echo, GCL Reference
@subsection emodule-clear
@findex emodule-clear
@table @code
@item (emodule-clear)
Clears the geomview application (external module) browser.
@end table

@node emodule-define, emodule-defined, emodule-clear, GCL Reference
@subsection emodule-define
@findex emodule-define
@table @code
@item (emodule-define NAME SHELL-COMMAND @dots{})
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 @ref{emodule-run,
@code{(emodule-run @dots{})}} for discussion of external modules.
@end table

@node emodule-defined, emodule-isrunning, emodule-define, GCL Reference
@subsection emodule-defined
@findex emodule-defined
@table @code
@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.
@end table

@node emodule-isrunning, emodule-path, emodule-defined, GCL Reference
@subsection emodule-isrunning
@findex emodule-isrunning
@table @code
@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).
@end table

@node emodule-path, emodule-run, emodule-isrunning, GCL Reference
@subsection emodule-path
@findex emodule-path
@table @code
@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: @code{(echo (emodule-path))}.
@xref{set-emodule-path, @code{(set-emodule-path @dots{})}}.
@end table

@node emodule-run, emodule-sort, emodule-path, GCL Reference
@subsection emodule-run
@findex emodule-run, |
@findex |, emodule-run
@table @code
@item (emodule-run SHELL-COMMAND ARGS@dots{})
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:
@example
  (emodule-run  yourprogram  <&2)
@end example
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.  @xref{emodule-define, @code{(emodule-define
@dots{})}}. @xref{emodule-start, @code{(emodule-start @dots{})}}.
@end table

@node emodule-sort, emodule-start, emodule-run, GCL Reference
@subsection emodule-sort
@findex emodule-sort
@table @code
@item (emodule-sort)
Sorts the modules in the application browser alphabetically.
@end table

@node emodule-start, emodule-transmit, emodule-sort, GCL Reference
@subsection emodule-start
@findex emodule-start
@table @code
@item (emodule-start  NAME)
Starts the external module NAME, defined by emodule-define. Equivalent
to clicking on the corresponding module-browser entry.
@end table

@node emodule-transmit, escale, emodule-start, GCL Reference
@subsection emodule-transmit
@findex emodule-transmit
@table @code
@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 the module NAME is not
running.
@end table

@node escale, eval, emodule-transmit, GCL Reference
@subsection escale
@findex escale
@table @code
@item (escale GEOM-ID FACTOR)
Same as scale but multiplies by exp(scale).  Obsolete.
@end table

@node eval, event-keys, escale, GCL Reference
@subsection eval
@findex eval
@table @code
@item (eval EXPR)
Evaluate a lisp expression. If @var{EXPR} is an unevaluated S-expression
as returned by the @code{(quote @dots{})} command then the effect will
be as if calling the un-quoted expression directly. It is also possible
to evaluate S-expression constructed via @code{car}, @code{cdr} and
@code{cons}. @xref{car, @code{(car @dots{})}}.  @xref{cdr, @code{(cdr
@dots{})}}. @xref{cons, @code{(cons @dots{})}}.
@end table

@node event-keys, event-mode, eval, GCL Reference
@subsection event-keys
@findex event-keys
@table @code
@item (event-keys @{on|off@})
Turn keyboard events on or off to enable/disable keyboard shortcuts.
@end table

@node event-mode, event-pick, event-keys, GCL Reference
@subsection event-mode
@findex event-mode
@table @code
@item (event-mode MODESTRING)
Set the mouse event (motion) mode; MODESTRING should be one of
the following strings:
@enumerate
@item
@code{"[r] Rotate"}
@item
@code{"[t] Translate"}
@item
@code{"[z] Cam Zoom"}
@item
@code{"[s] Geom Scale"}
@item
@code{"[f] Cam Fly"}
@item
@code{"[o] Cam Orbit"}
@item
@code{"[le] Edit Lights"}
@end enumerate
@end table

@node event-pick, evert, event-mode, GCL Reference
@subsection event-pick
@findex event-pick
@table @code
@item (event-pick @{on|off@})
Turn picking on or off.
@end table

@node evert, exit, event-pick, GCL Reference
@subsection evert
@findex evert
@table @code
@item (evert GEOM-ID [yes|no])
Set the normal eversion state of GEOM-ID.  If the second argument
is omitted, toggle the eversion state.
@end table

@node exit, ezoom, evert, GCL Reference
@subsection exit
@findex exit
@table @code
@item (exit)
Terminates geomview.
@end table

@node ezoom, freeze, exit, GCL Reference
@subsection ezoom
@findex ezoom
@table @code
@item (ezoom GEOM-ID FACTOR)
Same as zoom but multiplies by exp(zoom).  Obsolete.
@end table

@node freeze, geometry, ezoom, GCL Reference
@subsection freeze
@findex freeze
@table @code
@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.
@end table

@node geometry, geomview-version, freeze, GCL Reference
@subsection geometry
@findex geometry
@table @code
@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.
@end table

@node geomview-version, hdefine, geometry, GCL Reference
@subsection geomview-version
@findex geomview-version
@table @code
@item (geomview-version)
Returns a string representing the version of geomview that is
running.
@end table

@node hdefine, hdelete, geomview-version, GCL Reference
@subsection hdefine
@findex hdefine
@table @code
@item (hdefine @code{geometry}|@code{camera}|@code{window}|@code{appearance}|@code{image}|@code{transform}|@code{ntransform} 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
@dots{} define} performs assignment as soon as the text is
read. @xref{References}. @xref{read, @code{(read @dots{})}}. @xref{hdelete,
@code{(hdelete @dots{})}}.
@end table

@node hdelete, help, hdefine, GCL Reference
@subsection hdelete
@findex hdelete
@table @code
@item (hdelete [@code{geometry}|@code{camera}|@code{window}|@code{appearance}|@code{image}|@code{transform}|@code{ntransform}] name)
Deletes the given handle. Note that the handle will not actually be
deleted in case there are still other objects referring to the handle,
but once those objects are gone, the handle will also automatically go
away. The object the handle referes to (if any) will only be deleted if
there are no other references to that object.

If the optional first argument is omitted, then the first handle
matching @var{name} will be deleted, regardless of the type of the
object it is attached to. It is not an error to call this function with
a non-existent handle, but it is an error to call this funcion with the
name of a non-global handle, i.e. one that was not created by
@code{(hdefine @dots{})} or @code{(read @dots{} @{ define
@dots{}@})}. @xref{References}.  @xref{read,@code{(read
@dots{})}}. @xref{hdefine,@code{(hdefine @dots{})}}.
@end table

@node help, hmodel, hdelete, GCL Reference
@subsection help
@findex help
@table @code
@item (help [command])
Command may include @code{*}s as wildcards; see also @ref{help,
@code{(?? @dots{})}}  One-line command help; lists names only if multiple
commands match.
@end table

@node hmodel, hsphere-draw, help, GCL Reference
@subsection hmodel
@findex hmodel
@table @code
@item (hmodel CAMID @{virtual|projective|conformal@})
Set the model used to display geometry in
this camera. @xref{space, @code{(space @dots{})}}.
@end table

@node hsphere-draw, if, hmodel, GCL Reference
@subsection hsphere-draw
@findex hsphere-draw
@table @code
@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.
@end table

@node if, inhibit-warning, hsphere-draw, GCL Reference
@subsection if
@findex if
@table @code
@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.
@end table

@node inhibit-warning, input-translator, if, GCL Reference
@subsection inhibit-warning
@findex inhibit-warning
@table @code
@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.
@end table

@node input-translator, interest, inhibit-warning, GCL Reference
@subsection input-translator
@findex input-translator
@table @code
@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
@end table

@node interest, lambda, input-translator, GCL Reference
@subsection interest
@findex interest
@table @code
@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. @var{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 @dots{})} 
every time a pick event (right mouse double click).  See the @ref{pick,
@code{(pick @dots{})}} command for details.
@end table

@node lambda, let, interest, GCL Reference
@subsection lambda
@findex lambda
@table @code
@item (lambda (ARG1 @dots{}) EXPR1 @dots{} EXPRN)
A lambda expression is like a function. To ``call'' a lambda expression,
it has to be evoked like a function: @code{((lambda (arg) (+ 1 arg))
2)}. In this example, the value of the entire expression would be 3.  In
general, the value of the call will be the value of @var{EXPRN}. The
first list serves to define formal parameters. The lambda expression
itself is just a list, starting with the key-word lambda, followed by
several quoted lists.  @xref{defun, @code{(defun @dots{})}}.
@xref{setq, @code{(setq @dots{})}}.  @xref{let, @code{(let @dots{})}}.
Note the argument list may contain the special keywords
@table @code
@item &optional
giving values to the following identifiers is optional,
their default value will be @code{nil}
@item &rest
all excess arguments will be collected in a list, and that list will be
assigned to the following argument, like so:
@example
((lambda (&rest rest) (echo rest)) a b c d)
@end example
The output would be @code{(a b c d)}.
@end table
@end table

@node let, lines-closer, lambda, GCL Reference
@subsection let
@findex let
@table @code
@item (let ARGUMENTS EXPR1 @dots{} EXPRN)
Generate a lambda expression from @var{EXRP1} @dots{} @var{EXPRN}, with
the argument bindings described by @var{ARGUMENTS}. @var{ARGUMENTS} is a
list of symbols (bound to @code{nil} by default) or lists of the form
@code{(ARG VALUE)} where @var{ARG} is a symbol and not evaluated and
@var{VALUE} is an S-expression which is first evaluated, then its value
is bound to @var{ARG}. The entire expression evaluates to the value of
@var{EXPRN}, the last expression in the body of the statement. The
argument list must be present, but can be empty; in the latter case the
@code{(let () @dots{})} statement is equivalent to a @code{(progn
@dots{})}. @xref{lambda, @code{(lambda @dots{})}}.
@xref{defun, @code{(defun @dots{})}}.
@xref{setq, @code{(setq @dots{})}}.
@end table

@node lines-closer, load, let, GCL Reference
@subsection lines-closer
@findex lines-closer
@table @code
@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.
@end table

@node load, load-path, lines-closer, GCL Reference
@subsection load
@findex load
@table @code
@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.
@end table

@node load-path, look, load, GCL Reference
@subsection load-path
@findex load-path
@table @code
@item (load-path)
Returns the current search path for command, geometry, files, etc.
Note: to actually see the value returned by this function
you should wrap it in a call to echo: @code{(echo (load-path))}.
@xref{set-load-path, @code{(set-load-path @dots{})}}.
@end table

@node look, look-encompass, load-path, GCL Reference
@subsection look
@findex look
@table @code
@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 
@example
progn ( 
        (look-toward [objectID] [cameraID] @{center | origin@})
        [(look-encompass [objectID] [cameraID])] 
) 
@end example
If objectID is not specified, it is assumed to be World.  If 
cameraID is not specified, it is assumed to be targetcam.
@end table

@node look-encompass, look-encompass-size, look, GCL Reference
@subsection look-encompass
@findex look-encompass
@table @code
@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.  
@xref{look-encompass-size, @code{(look-encompass-size @dots{})}}.
@end table

@node look-encompass-size, look-recenter, look-encompass, GCL Reference
@subsection look-encompass-size
@findex look-encompass-size
@table @code
@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
@end table

@node look-recenter, look-toward, look-encompass-size, GCL Reference
@subsection look-recenter
@findex look-recenter
@table @code
@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.
@end table

@node look-toward, merge, look-recenter, GCL Reference
@subsection look-toward
@findex look-toward
@table @code
@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.
@end table

@node merge, merge-ap, look-toward, GCL Reference
@subsection merge
@findex merge
@table @code
@item (merge @{window|camera@} CAM-ID  @{ WINDOW or CAMERA @dots{} @})
Modify the given window or camera, changing just those properties
specified in the last argument.  E.g.
@example
        (merge camera @code{Camera} @{ far 20 @})
@end example
sets Camera's far clipping plane to 20 while leaving
other attributes untouched.
@end table

@node merge-ap, merge-base-ap, merge, GCL Reference
@subsection merge-ap
@findex merge-ap
@table @code
@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.
@end table

@node merge-base-ap, merge-baseap, merge-ap, GCL Reference
@subsection merge-base-ap
@findex merge-base-ap
@table @code
@item (merge-base-ap APPEARANCE)
@code{merge-base-ap} is a synonym for @ref{merge-baseap, @code{merge-baseap}}.
@end table

@node merge-baseap, mod, merge-base-ap, GCL Reference
@subsection merge-baseap
@findex merge-baseap
@table @code
@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.
@end table

@node mod, morehelp, merge-baseap, GCL Reference
@subsection mod
@findex mod
@table @code
@item (mod EXPR1 EXPR2)
Divides @var{EXPR1} by @var{EXPR2} and returns the remainder.
@end table

@node morehelp, name-object, mod, GCL Reference
@subsection morehelp
@findex morehelp
@table @code
@item (morehelp command)
@code{command} may include @code{*} wildcards.
Prints more info than @ref{help, @code{(help command)}}.
@end table

@node name-object, ND-axes, morehelp, GCL Reference
@subsection name-object
@findex name-object
@table @code
@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.
@end table

@node ND-axes, ND-color, name-object, GCL Reference
@subsection ND-axes
@findex ND-axes
@table @code
@item (ND-axes CAMID [CLUSTERNAME [Xindex Yindex Zindex [Windex]]])
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 1
to N for an N-dimensional space.  Cluster CLUSTERNAME is implicitly
created if not previously known. 

In principle it is possible to map the homogeneous component of a
conformal 4 point to some other index; this would be done by specifying
0 for one of @code{Xindex}, @code{Yindex} or @code{Zindex} and giving
@code{Windex} some positive value. This is probably not useful because
Geomview does not support non-Euclidean geometries for in higher
dimensions.

To read a camera's configuration, use @code{(echo (ND-axes CAMID))}.
The return value is an array of 4 integers, the last one should 0.
@end table

@node ND-color, ND-xform, ND-axes, GCL Reference
@subsection ND-color
@findex ND-color
@table @code
@item (ND-color CAMID
        [ (( [ID] (x1 x2 @dots{} xN) v r g b a   v r g b a  @dots{} )
           ((x1 @dots{} xN)  v r g b a  v r g b a @dots{}) @dots{})] )
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)
[x1 @dots{} 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.
@end table

@node ND-xform, ND-xform-get, ND-color, GCL Reference
@subsection ND-xform
@findex ND-xform
@table @code
@item (ND-xform OBJID [ntransform @{ idim odim  @dots{} @}])
Concatenate the given ND-transform with the current ND-transform of the
object (apply the ND-transform to object ID, as opposed to simply
setting its ND-transform). Note that ND-transforms have their
homogeneous coordinate at index 0, while 3D transform have it at index
3.
@end table

@node ND-xform-get, ND-xform-set, ND-xform, GCL Reference
@subsection ND-xform-get
@findex ND-xform-get
@table @code
@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>.
Note that ND-transforms have their
homogeneous coordinate at index 0, while 3D transform have it at index
3.
@end table

@node ND-xform-set, new-alien, ND-xform-get, GCL Reference
@subsection ND-xform-set
@findex ND-xform-set
@table @code
@item (ND-xform-set OBJID [ntransform @{ idim odim  @dots{} @}])
Sets the N-D transform of the given object.
In dimension N, this is an (N+1)x(N+1) matrix, so in that case
idim and odim are expected to be both equal to (N+1). Note that
all cameras in a camera-cluster have the same N-D transform.
Note that ND-transforms have their
homogeneous coordinate at index 0, while 3D transform have it at index
3.
@end table

@node new-alien, new-camera, ND-xform-set, GCL Reference
@subsection new-alien
@findex new-alien
@table @code
@item (new-alien name [GEOMETRY])
Create a new alien (geom not in the world) with the given name (a
string). @var{GEOMETRY} is a string giving an OOGL geometry
specification. If @var{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.
@end table

@node new-camera, new-center, new-alien, GCL Reference
@subsection new-camera
@findex new-camera
@table @code
@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
@var{CAMERA} is omitted a default camera is used.
@end table

@node new-center, new-geometry, new-camera, GCL Reference
@subsection new-center
@findex new-center
@table @code
@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.
@end table

@node new-geometry, new-reset, new-center, GCL Reference
@subsection new-geometry
@findex new-geometry
@table @code
@item (new-geometry name [GEOMETRY])
Create a new geom with the given name (a string). @var{GEOMETRY} is a
string giving an OOGL geometry specification.  If @var{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.
@end table

@node new-reset, NeXT, new-geometry, GCL Reference
@subsection new-reset
@findex new-reset
@table @code
@item (new-reset)
Equivalent to @code{(progn (new-center ALLGEOMS)(new-center ALLCAMS))}.
@end table

@node NeXT, normalization, new-reset, GCL Reference
@subsection NeXT
@findex NeXT
@table @code
@item (NeXT)
Returns @code{t} if running on a NeXT, @code{nil} if not. A relict from
ancient work-station year.
@end table

@node normalization, not, NeXT, GCL Reference
@subsection normalization
@findex normalization
@table @code
@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
@end table

@node not, or, normalization, GCL Reference
@subsection not
@findex not
@table @code
@item (not EXPR)
Evaluates @code{EXPR}; if @code{EXPR} returns a non-@code{nil} value,
returns nil, if @code{EXPR} returns @code{nil}, return @code{t}.
@end table

@node or, pick, not, GCL Reference
@subsection or
@findex or
@table @code
@item (or EXPR1 EXPR2)
Evaluates @code{EXPR1}; if @code{EXPR1} returns non-@code{nil}, return
its value, if @code{EXPR1} returns @code{nil}, evaluate @code{EXPR2} and
return its value.
@end table

@node pick, pick-invisible, or, GCL Reference
@subsection pick
@findex pick
@table @code
@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).

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

External modules can find out about pick events by registering
interest in calls to @code{pick} via the @code{interest} command.

In the ND-viewing context the co-ordinates are actually ND-points. They
correspond to the 3D points of the pick relative to the sub-space
defined by the viewport of the camera where the pick occurred. The
co-ordinates are then padded with zeroes and transformed back to the
co-ordinate system defined by @var{COORDSYS}.
@end table

@node pick-invisible, pickable, pick, GCL Reference
@subsection pick-invisible
@findex pick-invisible
@table @code
@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.
@end table

@node pickable, position, pick-invisible, GCL Reference
@subsection pickable
@findex pickable
@table @code
@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.
@end table

@node position, position-at, pickable, GCL Reference
@subsection position
@findex position
@table @code
@item (position objectID otherID)
Set the transform of objectID to that of otherID.
@end table

@node position-at, position-toward, position, GCL Reference
@subsection position-at
@findex position-at
@table @code
@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.
@end table

@node position-toward, process-events, position-at, GCL Reference
@subsection position-toward
@findex position-toward
@table @code
@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.
@end table

@node process-events, progn, position-toward, GCL Reference
@subsection process-events
@findex process-events
@table @code
@item (process-events)
Pass control back to the event loop of Geomview, then continue
evaluating the current command-script. If the current input stream has
been put to sleep by one of the @code{(sleep-@dots{})} commands, then
the control remains by the main-loop until the current input streams
``sleep'' is over.
@xref{sleep-until, @code{(sleep-until @dots{})}}.
@xref{sleep-for, @code{(sleep-for @dots{})}}.
@end table

@node progn, quit, process-events, GCL Reference
@subsection progn
@findex progn
@table @code
@item (progn STATEMENT [ @dots{} ])
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.
@end table

@node quit, quote, progn, GCL Reference
@subsection quit
@findex quit
@table @code
@item (quit)
@code{quit} is a synonym for @ref{exit, @code{exit}}.
@end table

@node quote, rawevent, quit, GCL Reference
@subsection quote
@findex quote
@table @code
@item (quote EXPR)
returns the symbolic lisp expression @var{EXPR} without evaluating
it. Note, however, that @code{quote} parses @var{EXPR} as if it should
be evaluated. @xref{eval, @code{(eval @dots{})}}. 
@end table

@node rawevent, rawpick, quote, GCL Reference
@subsection rawevent
@findex rawevent
@table @code
@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.
@end table

@node rawpick, read, rawevent, GCL Reference
@subsection rawpick
@findex rawpick
@table @code
@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.
@end table

@node read, real-id, rawpick, GCL Reference
@subsection read
@findex read
@table @code
@item (read @{geometry|camera|appearance|image|ntransform|transform|command@} @{GEOMETRY or CAMERA or @dots{}@})
Read and interpret the text in @dots{} as containing the
given type of data.  Useful for defining objects using OOGL
reference syntax, e.g.
@example
(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@})
@end example
@xref{References}. @xref{hdefine, @code{(hdefine @dots{})}}. @xref{hdelete,
@code{(hdelete @dots{})}}.
@end table

@node real-id, redraw, read, GCL Reference
@subsection real-id
@findex real-id
@table @code
@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.
@end table

@node redraw, regtable, real-id, GCL Reference
@subsection redraw
@findex redraw
@table @code
@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}.
@end table

@node regtable, rehash-emodule-path, redraw, GCL Reference
@subsection regtable
@findex regtable
@table @code
@item (regtable)
shows the registry table
@end table

@node rehash-emodule-path, replace-geometry, regtable, GCL Reference
@subsection rehash-emodule-path
@findex rehash-emodule-path
@table @code
@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
@code{(emodule-define @dots{})} commands outside of the .geomview-* files on
the emodule-path will be lost.  Does not sort the entries in the
brower. @xref{emodule-sort, @code{(emodule-sort)}}.
@xref{emodule-define, @code{(emodule-define @dots{})}}.
@end table

@node replace-geometry, rib-display, rehash-emodule-path, GCL Reference
@subsection replace-geometry
@findex replace-geometry
@table @code
@item (replace-geometry GEOM-ID PART-SPECIFICATION GEOMETRY)
Replace a part of the geometry for GEOM-ID.
@end table

@node rib-display, rib-snapshot, replace-geometry, GCL Reference
@subsection rib-display
@findex rib-display
@table @code
@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.)
@end table

@node rib-snapshot, scale, rib-display, GCL Reference
@subsection rib-snapshot
@findex rib-snapshot
@table @code
@item (rib-snapshot CAM-ID [filename])
Write Renderman snapshot (in RIB format) of CAM-ID to <filename>.  If no
filename specified, see @ref{rib-display, @code{(rib-display @dots{}}} for an
explanation of the filename used.
@end table

@node scale, scene, rib-snapshot, GCL Reference
@subsection scale
@findex scale
@table @code
@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.
@end table

@node scene, set-clock, scale, GCL Reference
@subsection scene
@findex scene
@table @code
@item (scene CAM-ID [GEOMETRY])
Make CAM-ID look at GEOMETRY instead of at the universe.
@end table

@node set-clock, set-conformal-refine, scene, GCL Reference
@subsection set-clock
@findex set-clock
@table @code
@item (set-clock TIME)
Adjusts the clock for this command stream to read @var{TIME} (in
seconds) as of the moment the command is received. @xref{sleep-until,
@code{(sleep-until @dots{})}}. @xref{clock, @code{(clock @dots{})}}.
@end table

@node set-conformal-refine, set-emodule-path, set-clock, GCL Reference
@subsection set-conformal-refine
@findex set-conformal-refine
@table @code
@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.
@end table

@node set-emodule-path, set-load-path, set-conformal-refine, GCL Reference
@subsection set-emodule-path
@findex set-emodule-path
@table @code
@item (set-emodule-path (PATH1 @dots{} 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 @dots{}) command for that
module.  This command implicitly calls (rehash-emodule-path)
to rebuild the application browser 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.
@end table

@node set-load-path, set-motionscale, set-emodule-path, GCL Reference
@subsection set-load-path
@findex set-load-path
@table @code
@item (set-load-path (PATH1 @dots{} PATHN))
Sets search path for command, geometry, files, etc.  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.
@end table

@node set-motionscale, setenv, set-load-path, GCL Reference
@subsection set-motionscale
@findex set-motionscale
@table @code
@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.
@end table

@node setenv, setq, set-motionscale, GCL Reference
@subsection setenv
@findex setenv
@table @code
@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.
@end table

@node setq, sgi, setenv, GCL Reference
@subsection setq
@findex setq
@table @code
@item (setq SYM EXPR)
Bind the symbol @var{SYM} to the value of @var{EXPR}. @var{SYM} must be
an unqualified symbol, i.e. not quoted, and literal: @code{(setq "foo"
bar)} will not work. Likewise @code{(setq (bar STUFF) foo)} will also
not work, even if @code{(bar @dots{})} would evaluate to an unqualified
symbol: varible names must be literals.  Note that calling @code{(setq
SYM @dots{})} will alter the value of @var{SYM} within the current
name-space: if @var{SYM}, e.g., is bound as local variable by a lambda,
let or defun expression, then @code{(setq SYM @dots{})} will change the
value of the local variable, the global binding will remain unchanged.
It is NOT possible to un-bind a symbol. However, subsequent @code{(setq
SYM @dots{})} invocations will re-bind @var{SYM} to another value and free
the lisp-object previously bound to @var{SYM}.
@xref{lambda, @code{(lambda @dots{})}}.
@xref{defun, @code{(defun @dots{})}}.
@xref{let, @code{(let @dots{})}}.
@end table

@node sgi, shell, setq, GCL Reference
@subsection sgi
@findex sgi
@table @code
@item (sgi)
Returns @code{t} if running on an sgi machine, @code{nil} if not. A
relict from the old work-station years.
@end table

@node shell, sleep-for, sgi, GCL Reference
@subsection shell
@findex !, shell
@findex shell, !
@table @code
@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{!}.
@end table

@node sleep-for, sleep-until, shell, GCL Reference
@subsection sleep-for
@findex sleep-for
@table @code
@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.
@end table

@node sleep-until, snapshot, sleep-for, GCL Reference
@subsection sleep-until
@findex sleep-until
@table @code
@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.
@end table

@node snapshot, soft-shader, sleep-until, GCL Reference
@subsection snapshot
@findex snapshot
@table @code
@item (snapshot CAM-ID FILENAME [FORMAT [XSIZE [YSIZE]]])
Save a snapshot of @var{CAM-ID} in the @var{FILENAME} (a string). The
@var{FORMAT} argument is optional; it may be "ppmscreen" (the default),
"ps", "ppm", "sgi" (on SGI machines), "ppmosmesa" (if built with
libOSMesa) or "ppmosglx". A "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. A "ppmosmesa" snapshot is drawn by Mesa's software
renderer into a memory buffer in RAM. A "ppmosglx" snapshot is rendered
into a GLX Pixmap buffer, which is also off-screen but may or may not
reside in video RAM.  Rendering may or may not be accelerated. The
problem with on-screen snapshots is that the window must be mapped and
not obscured by other windows. So on-screen snapshots will not work in
the background, or when a screen saver is active. With "ps", dumps a
Postscript picture representing the view from that window;
hidden-surface removal might be incorrect. With "ppm", dumps a
PPM-format image produced by geomview's internal software renderer; this
may be of arbitrary size. If the @var{FILENAME} argument begins with
"|", it's interpreted as a @code{/bin/sh} command to which the PPM or PS
data should be piped. Optional @var{XSIZE} and @var{YSIZE} values are
relevant only for "ppm" formats, and render to a window of that size (or
scaled to that size, with aspect fixed, if only @var{XSIZE} is given)
@end table

@node soft-shader, space, snapshot, GCL Reference
@subsection soft-shader
@findex soft-shader
@table @code
@item (soft-shader CAM-ID @{on|off|toggle@})
Select whether to use software or hardware shading in that camera.
@end table

@node space, stereowin, soft-shader, GCL Reference
@subsection space
@findex space
@table @code
@item (space @{euclidean|hyperbolic|spherical@})
Set the space associated with the world.
@end table

@node stereowin, time-interests, space, GCL Reference
@subsection stereowin
@findex stereowin
@table @code
@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 @dots{})} 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.
@end table

@node time-interests, transform, stereowin, GCL Reference
@subsection time-interests
@findex time-interests
@table @code
@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)) (" "))".
@end table

@node transform, transform-incr, time-interests, GCL Reference
@subsection transform
@findex transform
@table @code
@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. There is the
special keyword @code{bbox-center} which may be used for
@code{centerID}. As a result the motion will be relative to the center
of the bounding box of @code{objectID}. 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.
@end table

@node transform-incr, transform-set, transform, GCL Reference
@subsection transform-incr
@findex transform-incr
@table @code
@item (transform-incr objectID centerID frameID [rotate|translate|translate-scaled|scale] x y z [origin|bbox-center] [dt [smooth]])
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.
@end table

@node transform-set, truncate, transform-incr, GCL Reference
@subsection transform-set
@findex transform-set
@table @code
@item (transform-set objectID centerID frameID [rotate|translate|translate-scaled|scale] x y z [origin|bbox-center])
Set objectID's transform to the constructed transform.
Same syntax as transform.
@end table

@node truncate, ui-cam-focus, transform-set, GCL Reference
@subsection truncate
@findex truncate
@table @code
@item (truncate EXPR)
Rounds @var{EXPR} towards zero.
@end table

@node ui-cam-focus, ui-center, truncate, GCL Reference
@subsection ui-cam-focus
@findex ui-cam-focus
@table @code
@item (ui-cam-focus [focus-change|mouse-cross])
Set the focus policy for the camera windows. The default is
@code{mouse-cross}: a camera is made the active camera (for interactive
mouse events) when the mouse cursor crosses the window. Because this
means it can become complicated to activate a specific camera (in the
context of multiple camera windows) there is also the option to only
change the camera focus when the window-manager decides to give it the
focus for input events. So, after specifying @code{focus-change} it
depends on the focus-change configuration of your window-manager when a
camera becomes the active camera for mouse-interaction. To change this
behaviour permanently you could, e.g., place the following line in your
@file{$@{HOME@}/.geomview} file (@pxref{Customization}):

@example
(progn
  (ui-cam-focus focus-change)
  @dots{} # other stuff
)
@end example
@end table

@node ui-center, ui-center-origin, ui-cam-focus, GCL Reference
@subsection ui-center
@findex ui-center
@table @code
@item (ui-center ID)
Set the center for user interface (i.e. mouse) controlled
motions to object ID.
@end table

@node ui-center-origin, ui-emotion-program, ui-center, GCL Reference
@subsection ui-center-origin
@findex ui-center-origin
@table @code
@item (ui-center-origin [origin|bbox-center])
Set the origin of the coordinate system of the @code{CENTER} object for
user interface (i.e. mouse) controlled motions.  The keyword
@code{origin} means to use the origin of the coordinate system of the
currently selected object, while @code{bbox-center} means to use the
center of the bounding box of the current object.  The keyword
@code{bbox-center} makes no sense if the geometry is
non-Euclidean. Using either @code{bbox-center} or @code{origin} does not
make a difference if the center object is not a @emph{geometry}, e.g. if
it is a camera. Same holds if the World is the currently selected
object.
@end table

@node ui-emotion-program, ui-emotion-run, ui-center-origin, GCL Reference
@subsection ui-emotion-program
@findex ui-emotion-program
@table @code
@item (ui-emotion-program PROGRAM)
This is an obsolete command.  Use its new eqivalent @ref{emodule-define,
@code{emodule-define}} instead.
@end table

@node ui-emotion-run, ui-freeze, ui-emotion-program, GCL Reference
@subsection ui-emotion-run
@findex ui-emotion-run
@table @code
@item (ui-emotion-run EMODULE)
This is an obsolete command.  Use its new eqivalent @ref{emodule-start,
@code{emodule_start}} instead.
@end table

@node ui-freeze, ui-html-browser, ui-emotion-run, GCL Reference
@subsection ui-freeze
@findex ui-freeze
@table @code
@item (ui-freeze @{on|off@})
Toggle updating user interface panels. Off by default.
@end table

@node ui-html-browser, ui-motion, ui-freeze, GCL Reference
@subsection ui-html-browser
@findex ui-html-browser
@table @code
@item (ui-html-browser BROWSER)
Use @var{BROWSER} for viewing the @var{HTML}-version of the manual when
the @samp{Manual (HTML)} menu item is selected in the @samp{Help}-menu.
If the @code{(ui-html-browser @dots{})} command was never executed, then the
default is to use the browser stored in the @code{WEBBROWSER}
environment variable. If the environment variable is unset then the
default is compile-time dependent.
@end table

@node ui-motion, ui-panel, ui-html-browser, GCL Reference
@subsection ui-motion
@findex ui-motion
@table @code
@item (ui-motion @{inertia|constrain|own-coordinates@} @{on|off@})
Enable or disable certain properties of mouse-controlled motion. The
purpose of this command is to give access to the respective toggles of
the @emph{Main} panel's @emph{Motion} menu through GCL
commands. @xref{Mouse Motions}.

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

@item constrain
It's sometimes handy to move an object in a direction aligned with a
coordinate axis: exactly horizontally or vertically. Calling
@code{(ui-motion constrain on)} 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 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. When @code{(ui-motion own-coordinates on)} has been
called, all motions are interpreted that way: dragging the mouse
rightward in translate mode moves the object in its own @var{+X}
direction, and so on. May be especially useful in conjunction with the
@code{(ui-motion constrain on)} command.
@end table

@end table

@node ui-panel, ui-pdf-viewer, ui-motion, GCL Reference
@subsection ui-panel
@findex ui-panel
@table @code
@item (ui-panel PANELNAME @{on|off@} [WINDOW])
Do or don't display the given user-interface panel.
Case is ignored in panel names. Current @var{PANELNAMEs} are:
@table @asis
@item geomview
main panel
@item tools
motion controls
@item appearance
appearance controls
@item cameras
camera controls
@item lighting
lighting controls
@item obscure
obscure controls (doesn't seem to exist any more)
@item materials
material properties controls
@item command
command entry box
@item credits
geomview credits
@end table
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.
@end table

@node ui-pdf-viewer, ui-target, ui-panel, GCL Reference
@subsection ui-pdf-viewer
@findex ui-pdf-viewer
@table @code
@item (ui-pdf-viewer VIEWER)
Use the executable @var{VIEWER} for viewing the @var{PDF}-version of the
manual when the @samp{Manual (PDF)} menu-item is selected in the
@samp{Help}-menu.  If the @code{(ui-pdf-viewer @dots{})} command was
never executed, then the default is to use the browser stored in the
@code{PDFVIEWER} environment variable. If the environment variable is
unset then the default is compile-time dependent.
@end table

@node ui-target, uninterest, ui-pdf-viewer, GCL Reference
@subsection ui-target
@findex ui-target
@table @code
@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.
@end table

@node uninterest, update, ui-target, GCL Reference
@subsection uninterest
@findex uninterest
@table @code
@item (uninterest (COMMAND [args]))
Undoes the effect of an @code{interest} command.  (COMMAND [args]) must
be identical to those used in the @ref{interest, @code{interest}}
command.
@end table

@node update, update-draw, uninterest, GCL Reference
@subsection update
@findex update
@table @code
@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.
@end table

@node update-draw, while, update, GCL Reference
@subsection update-draw
@findex update-draw
@table @code
@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.
@end table

@node while, window, update-draw, GCL Reference
@subsection while
@findex while
@table @code
@item (while TEST BODY)
Iterate: @emph{evaluate @var{TEST}, if non nil, evaluate @var{BODY}}.
@end table

@node window, winenter, while, GCL Reference
@subsection window
@findex window
@table @code
@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 @ref{camera,
@code{camera}} or @ref{new-camera, @code{new-camera}}).
@end table

@node winenter, write, window, GCL Reference
@subsection winenter
@findex winenter
@table @code
@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.
@end table

@node write, write-comments, winenter, GCL Reference
@subsection write
@findex write
@table @code
@item (write @{command|geometry|camera|transform|ntransform|window|bbox@} FILENAME [ID|(ID @dots{})] [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
(@pxref{command, @code{(command @dots{})}}).

The ID can either be a single id or a parenthesized list of
ids, like @code{g0} or @code{(g2 g1 dodec.off)}.
@end table

@node write-comments, write-handle, write, GCL Reference
@subsection write-comments
@findex write-comments
@table @code
@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 @dots{} f g)
will match pick paths of the form (a b c @dots{} 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.
@end table

@node write-handle, write-sexpr, write-comments, GCL Reference
@subsection write-handle
@findex write-handle
@table @code
@item (write-handle PREFIX FILENAME HANDLE)
Writes the object underlying the given handle to @var{FILENAME}. This
function is intended for internal debugging use only.
@end table

@node write-sexpr, xform, write-handle, GCL Reference
@subsection write-sexpr
@findex write-sexpr
@table @code
@item (write-sexpr FILENAME LISPOBJECT)
Writes the given LISPOBJECT to FILENAME. This function is intended
for internal debugging use only.
@end table

@node xform, xform-incr, write-sexpr, GCL Reference
@subsection xform
@findex xform
@table @code
@item (xform ID TRANSFORM)
Concatenate TRANSFORM with the current transform of the object
(apply TRANSFORM to object ID).
@end table

@node xform-incr, xform-set, xform, GCL Reference
@subsection xform-incr
@findex xform-incr
@table @code
@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).
@end table

@node xform-set, zoom, xform-incr, GCL Reference
@subsection xform-set
@findex xform-set
@table @code
@item (xform-set ID TRANSFORM)
Overwrite the current object transform with TRANSFORM (set
object ID's transform to TRANSFORM).
@end table

@node zoom,  , xform-set, GCL Reference
@subsection zoom
@findex zoom
@table @code
@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, Top
@chapter Non-Euclidean Geometry

Geomview supports hyperbolic and spherical geometry as well as
Euclidean geometry.  The three buttons at the bottom of the @emph{Main}
panel are for setting the current geometry type.

In each of the three geometries, three models are supported:
@emph{Virtual}, @emph{Projective}, and @emph{Conformal}.  You can
change the current model with the @emph{Model} browser on the
@emph{Camera} panel.  Each Geomview camera has its own model setting.

The default model is all three spaces is @emph{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 @emph{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:
@emph{Projective} is the same as @emph{Virtual} but by default
displays the unit sphere, and @emph{Conformal} displays everything
inverted in the unit sphere.

In hyperbolic space, the @emph{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.  @emph{Conformal} model is similar but shows the conformal
ball model instead. 

In spherical space, the @emph{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 @emph{Projective} model, and
to
@tex
M\"{o}bius
@end tex
@ifnottex
Moebius
@end ifnottex
transformations in the @emph{Conformal} model.  In both of these
models the camera moves by Euclidean motions.

In @emph{Projective} and @emph{Conformal} models, the unit sphere is
drawn by default.  You can turn it off and on at will using the
@emph{Draw Sphere} button in the @emph{Camera} panel.  In the
@emph{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. @xref{set-conformal-refine,@code{(set-conformal-refine @dots{})}}.

There are several sample hyperbolic space objects in the
@file{data/geom/hyperbolic} subdirectory of the Geomview directory.
Likewise, the subdirectory @file{data/geom/spherical}
contains several sample spherical space objects.

@comment ****************************************************************
@node Mathematica, Installation, 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.  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{WriteRI}b 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.ri}b.  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.ri}b 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{WriteRI}b works by first converting the Mathematica graphics
object to OOGL format using @code{WriteOOGL} and then calls an external
program @file{oogl2ri}b 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{WriteRI}b.  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, Package Details, 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 you want to
use Mathematica on a computer that is not networked with your Geomview
computer, you can write out @emph{chunk} files in
Mathematica which you transfer to the Geomview computer and then
translate to OOGL format for displaying in Geomview.

@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, @code{Geomview} needs to know the type of that machine (the setting
of the CPU variable that corresponds to the machine;
@pxref{Source Code Installation}).
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"} or @code{"x11"}.@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,  , 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 computer that Geomview isn't installed on.
@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{oogl2ri}b, and
@file{geomview} directly from the shell.  These programs are distributed
in the @file{bin/<CPU>}
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 a system
with Geomview 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{WriteRI}b command can be emulated from the shell as
@example
math2oogl < mychunk | oogl2rib -n mma.tiff
@end example
@noindent




@comment ================================================================
@node Package Details, Package Installation, Remote Display, 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).

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,  , Package Details, Mathematica
@section Installing the Mathematica Packages

@quotation @b{BUG}
This section is out of date. @code{Geomview} follows the
GNU-installation habits, data goes to @file{PREFIX/share/geomview/},
user executables to @file{PREFIX/bin/}, private executables to
@file{PREFIX/libexec/geomview/}, libraries to @file{PREFIX/lib/} where
@code{PREFIX} denotes the installation prefiex specified for the
@file{TOPSRCDIR/configure} script. Please have a look at the files
@file{TOPSRCDIR/INSTALL} and @file{TOPSRCDIR/INSTALL.Geomview} for
installation instructions.

The installed Mathematica data-files can be found in
@file{PREFIX/share/geomview/Mathematica/}.
@end quotation

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{PREFIX/share/geomview/Mathematica}
subdirectory of the binary distributions, and in the
@file{TOPSRCDIR/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{oogl2ri}b in the @file{$GEOMROOT/bin/<CPU>}.

@item
The @file{geomview} shell script, which @file{OOGL.m} uses to invoke
Geomview, needs to be able to find the geomview executable file (
called @file{gvx}).
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, Support, Mathematica, Top
@chapter Installation

@quotation @b{BUG}
This section is out of date. @code{Geomview} follows the
GNU-installation habits, data goes to @file{PREFIX/share/geomview/},
user executables to @file{PREFIX/bin/}, private executables to
@file{PREFIX/libexec/geomview/}, libraries to @file{PREFIX/lib/} where
@code{PREFIX} denotes the installation prefiex specified for the
@file{TOPSRCDIR/configure} script. Please have a look at the files
@file{TOPSRCDIR/INSTALL} and @file{TOPSRCDIR/INSTALL.Geomview} for
installation instructions.
@end quotation

What you do to install Geomview depends on which kind of computer you
have 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 one of the binary distribution.  The binary
installation is much easier and quicker than compiling and
installing the source code.

@menu
* Unix Binary Installation::    Installing the Unix Binary Distribution
* Source Code Installation::    Compiling and Installing the Source Code Distribution.
@end menu

@comment ================================================================
@node Unix Binary Installation, Source Code Installation, Installation, Installation
@section Installing the Unix Binary Distribution

@quotation @b{BUG}
This section is out of date. @code{Geomview} follows the
GNU-installation habits, data goes to @file{PREFIX/share/geomview/},
user executables to @file{PREFIX/bin/}, private executables to
@file{PREFIX/libexec/geomview/}, libraries to @file{PREFIX/lib/} where
@code{PREFIX} denotes the installation prefiex specified for the
@file{TOPSRCDIR/configure} script. Please have a look at the files
@file{TOPSRCDIR/INSTALL} and @file{TOPSRCDIR/INSTALL.Geomview} for
installation instructions.
@end quotation

If you have just obtained a copy of the binary distribution 
for a Unix system (Linux, SGI, Solaris, HP, etc),
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/<CPU>} 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/<MACHTYPE>}:
(where @file{<MACHTYPE>} is the type of system you are on, e.g.
@file{linux}, @file{sgi}, @file{hpux}, etc).
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 ================================================================
@menu
* Unix Binary Detail::          
@end menu

@node Unix Binary Detail,  , Unix Binary Installation, Unix Binary Installation
@subsection Details of the Unix Binary Installation

@quotation @b{BUG}
This section is out of date. @code{Geomview} follows the
GNU-installation habits, data goes to @file{PREFIX/share/geomview/},
user executables to @file{PREFIX/bin/}, private executables to
@file{PREFIX/libexec/geomview/}, libraries to @file{PREFIX/lib/} where
@code{PREFIX} denotes the installation prefiex specified for the
@file{TOPSRCDIR/configure} script. Please have a look at the files
@file{TOPSRCDIR/INSTALL} and @file{TOPSRCDIR/INSTALL.Geomview} for
installation instructions.
@end quotation

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/<MACHTYPE>} 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 Source Code Installation,  , Unix Binary Installation, Installation
@section Compiling and Installing the Source Code Distribution

@quotation @b{BUG}
This section is out of date. @code{Geomview} follows the
GNU-installation habits, data goes to @file{PREFIX/share/geomview/},
user executables to @file{PREFIX/bin/}, private executables to
@file{PREFIX/libexec/geomview/}, libraries to @file{PREFIX/lib/} where
@code{PREFIX} denotes the installation prefiex specified for the
@file{TOPSRCDIR/configure} script. Please have a look at the files
@file{TOPSRCDIR/INSTALL} and @file{TOPSRCDIR/INSTALL.Geomview} for
installation instructions.
@end quotation

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 a few minutes to an hour or more 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 multiple systems, you can do them all 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
edit the file @file{$GEOMROOT/makefiles/Makedefs.global} to set the
@code{CPU} variable to one of the values @file{linux}, @file{FreeBSD},
@file{sgi}, @file{hpux}, @file{hpux-gcc}, @file{solaris}, @file{sun4os4}
(for Suns with SunOS 4, not Solaris), @file{rs6000},
or @file{alpha}.  If you're using a type of system not in this
list, make up a new value for CPU, and write a @file{mk.<CPU>} file 
for it patterned
after the other @file{mk.*} in the @file{makefiles} subdirectory.

@item
If you will be compiling on more than one type of computer you can set a
shell environment variable named @code{CPU} to one of the values above
and the Makefiles will inherit the value from the environment.

@end enumerate

@noindent
Note that many of the Makefiles refer to a variable called
@code{MACHTYPE}; this variable tells which type of graphics
system to compile Geomview for.  The @file{mk.<CPU>} files
set this variable for you; in most cases its value is @file{x11},
which specifies that Geomview should be compiled for X windows.

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 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 Support, Contributing, Installation, Top
@unnumbered Getting Technical Support for Geomview

There are several ways to get support for Geomview.

@enumerate

@item 
Visit the Geomview web site, @uref{http://www.geomview.org}.  It
contains the latest documentation, news about development, and FAQ
(Frequently Asked Questions) list.

@item
Send email to the geomview-users@@lists.sourceforge.net mailing list.
This is a mailing list for discussing any issues related to using
Geomview.  To join the list, send an empty note with 'subscribe' in the
subject line to
@uref{mailto:geomview-users-request@@lists.sourceforge.net,geomview-users-request@@lists.sourceforge.net}, or visit
the list web page at
@uref{http://lists.sourceforge.net/mailman/listinfo/geomview-users}.


@item
Contract with Geometry Technologies for support.  Geometry Technologies
is a contract support and programming company that emerged from the
Geometry Center, where Geomview was written.  For more information visit
the Geometry Technologies web site at @uref{http://www.geomtech.com}.

@end enumerate

@comment ############################################################
@node Contributing, Function Index, Support, Top
@unnumbered Contributing to Geomview's Development

If you are interested in contributing to the development of Geomview,
there are several things you can do:

@enumerate

@item @strong{Volunteer programming work}.

If you are a programmer and make an improvement to Geomview, contact
the other geomview authors by sending a note to the
@file{geomview-users} mailing list (see
@uref{http://lists.sourceforge.net/mailman/listinfo/geomview-users}).

@item @strong{Contract with Geometry Technologies}.

Geometry Technologies, Inc. is a consulting firm that provides contract
technical support and custom programming services in the area of 3D
graphics.  This includes a wide range of services related to 3D
graphics, included but not limited to applications involving Geomview.
To the extent that resources allow, Geometry Technologies supports the
developement of Geomview; in particular it hosts the
@uref{http://www.geomview.org} web site, and its staff make ongoing
improvements to Geomview itself.  If you are in a position to pay for
technical support or custom programming work, contracting with Geometry
Technologies indirectly supports Geomview.  You can also contract with
with Geometry Technologies to have particular features that you want
added to Geomview, or to port Geomview to a new platform.  For more
information see Geometry Technologies web site at
@uref{http://www.geomtech.com}.

@end enumerate

Thank you.



@comment ****************************************************************
@node Function Index, List of Figures, Contributing, Top
@unnumbered Function Index

@printindex fn

@comment ****************************************************************

@contents

@node List of Figures,  , Function Index, Top
@unnumbered List of Figures
@listoffloats Figure

@bye

@c  LocalWords:  Geomview RenderMan texinfo letterpaper setfilename geomview sp
@c  LocalWords:  settitle texi dircategory direntry titlepage titlefont vskip
@c  LocalWords:  Munzner uref Hanrahan MinneView OOGL Meuer Kaplan SGI NeXT GPL
@c  LocalWords:  SGIs NeXTStep OpenGL Geomview's unnumberedsec Gunn Krech MacOS
@c  LocalWords:  Daeron Cygwin SystemV FreeBSD Solaris Precompiled emph Heine
@c  LocalWords:  Renderman Mathematica pxref smallexample Yoyodyne Thurston GCL
@c  LocalWords:  xref Bezier var emodule iconify PPM NCMESH NCOFF RGBA
