<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.0/docbookx.dtd">
<book>
<bookinfo>
<title><application>PyOpenGL</application> Manual</title>
<authorgroup>
<author>
<firstname>Tarn</firstname> 
<othername>Weisner</othername>
<surname>Burton</surname>
</author>
<author>
<firstname>Mike</firstname>
<othername>C.</othername>
<surname>Fletcher</surname>
</author>
</authorgroup>
<abstract>
<para>
<ulink url="http://pyopengl.sourceforge.net"><application>PyOpenGL</application></ulink> is a cross-platform open source Python binding to
<ulink url="http://www.opengl.org">OpenGL</ulink> which provides a standard 2D and 3D graphics API.
<application>PyOpenGL</application> also supports GLU, <ulink url="http://linas.org/gle">GLE</ulink>, <ulink url="http://reality.sgi.com/mjk/glut3">GLUT</ulink>, WGL, and Togl.
</para>
</abstract>
</bookinfo>
<chapter id="intro">
<title>Introduction</title>
<para>
<application>PyOpenGL</application> is a cross-platform open source Python binding to the
standard OpenGL API providing 2-D and 3-D graphic drawing. <application>PyOpenGL</application>
supports the GL, GLU, GLE, and GLUT libraries. The library can be used with almost any Python windowing library which can provide an OpenGL context.
Currently supported libraries include:
</para>
<itemizedlist>
<listitem><ulink url="http://fxpy.sourceforge.net">FXPy</ulink></listitem>
<listitem><ulink url="http://pygame.seul.org">pygame</ulink></listitem>
<listitem>Tkinter</listitem>
<listitem>win32gui</listitem>
<listitem><ulink url="http://www.wxpython.org">wxPython</ulink></listitem>
</itemizedlist>
<para>
All <application>PyOpenGL</application> modules are contained in the package <classname>OpenGL</classname>. For the sake
of brevity, the top level package name is omitted when referring to
modules, variables and functions in this document. For example, instead
of <classname>OpenGL.GL</classname> this document uses the label <classname>GL</classname>.
</para>
<section id="intro-interfaces">
<title>Interfaces To Other Libraries</title>
<para>
<application>PyOpenGL</application> currently requires either Python 1.5.2 or greater because of
the use of the Distutils setup mechanisms. For versions of Python
earlier than 1.5.2, the <application>PyOpenGL 1.5.5</application> release (available from the
<application>PyOpenGL</application> project download page) may be usable.
</para>
<para>
<application>PyOpenGL</application> includes support for the Tkinter widget, <ulink url="http://togl.sourceforge.net">Togl</ulink>.
Togl 1.5 is currently shipped with <application>PyOpenGL</application>.
</para>
<para>
<application>PyOpenGL</application>'s setup will attempt to enable certain functionality
(primarily array support) if it can import the Python Numeric
Extensions available at: <ulink url="http://numpy.sourceforge.net">http://numpy.sourceforge.net</ulink>. Most people
interested in using <application>PyOpenGL</application> for nontrivial purposes will want to
install this package before installing <application>PyOpenGL</application>.
</para>
<para>
<application>PyOpenGL</application> does not directly interface with the Python Imaging Library,
or <ulink url="http://www.pythonware.com/products/pil/index.htm">PIL</ulink>, but PIL images can be used within <application>PyOpenGL</application> easily.
Demonstrations of this are available within the <application>PyOpenGL</application> package.
</para>
</section>
<section id="intro-installation">
<title>Installation</title>
<para>
Before installing PyOpenGL be sure to uninstall or remove any previous versions.
Failure to do this may result in irratic behavior of Python scripts which use PyOpenGL.
</para>
<para>
There are two main methods of installing PyOpenGL.  On Win32 systems executable installers are available, for other
platforms you will have to build <application>PyOpenGL</application> from the source.
To do so you will need Distutils 1.0.2pre or higher. Python 2.1 users
should already have this installed. To get the latest version of
see the <ulink url="http://www.python.org/sigs/distutils-sig">distutils-sig</ulink> page.
</para>
<para>
You will also need the GLUT library.  On UNIX systems this will probably already be present, for other systems
see the <ulink url="http://reality.sgi.com/mjk/glut3/glut3.html">GLUT homepage</ulink>.
</para>
<para>
As discussed in the <link linkend="intro-interfaces">previous section</link> PyOpenGL can interface to the <ulink url="http://numpy.sourceforge.net">Numeric library</ulink>.
To enable this support Numeric and its associated headers must be installed at build time.
</para>
<para>
To build <application>PyOpenGL</application> type
</para>
<programlisting>$ python setup.py build</programlisting>
<para>
at the shell prompt.
</para>
<note>
<para>
<ulink url="http://swig.sourceforge.net">SWIG</ulink> is not needed to build <application>PyOpenGL</application>, but if SWIG is present on your
system then the <command>build_w</command> setup command can be used to rebuild the generated
wrappers. Currently only SWIG 1.3a5 is supported.
</para>
</note>
<para>
After building, to install type
</para>
<programlisting>$ python setup.py install</programlisting>
<para>
This will also execute the build command if required.  To find out what various options are accepted
by the setup script one can also
</para>
<programlisting>$ python setup.py build --help</programlisting>
<para>
or
</para>
<programlisting>$ python setup.py install --help</programlisting>
<important>
<para>
The setup script will try to build Togl if the <classname>Tkinter</classname> module can be
imported.  Togl version 1.5 is shipped with this version of
<application>PyOpenGL</application>.  The building of Togl can be bypassed by changing a
setting in a platform specific configuration file.  The name of this file is based on
<constant>sys.platform</constant>.  For instance, on Linux platforms it will be called
<filename>config/linux.cfg</filename>.  For more information on this file see the
<link linkend="internals-porting">Porting Section</link>.
</para>
</important>
</section>
<section id="intro-bug_reporting">
<title>Bug Reporting</title>
<para>
Please submit bug reports using the bug tracker at the
<ulink url="http://sourceforge.net/projects/pyopengl"><application>PyOpenGL</application> project page</ulink>. 
There are also support and feature request trackers at this page.
</para>
<note>
<para>
<application>PyOpenGL</application> development, usage and bugs are discussed on the
<ulink url="http://groups.yahoo.com/group/PyOpenGL"><application>PyOpenGL</application> mailing list</ulink>.
</para>
</note>
<para>
Before you send any bug reports, try the demos and if they show the
same problem. When submitting a bug report always include:
</para>
<orderedlist>
<listitem>complete traceback</listitem>
<listitem>the HTML output of the script <filename>OpenGL/scripts/info.py</filename></listitem>
</orderedlist>
<para>
If you have problems compiling <application>PyOpenGL</application>, also include:
</para>
<orderedlist>
<listitem>description of your system and your compiler</listitem>
<listitem>
output of following python statements
<para>
<programlisting>import sys, distutils
print sys.platform
print sys.version
print distutils.__version__</programlisting>
</para>
</listitem>
</orderedlist>
</section>
</chapter>
<chapter id="upgrading">
<title>Upgrading From <application>PyOpenGL 1.5</application></title>
<para>
This section presents various notes regarding upgrading from <application>PyOpenGL 1.5</application>
to the newer <application>PyOpenGL 2</application> binding. This complete rewrite of the
<application>PyOpenGL</application> system has a slightly different API from the original
<application>PyOpenGL</application> binding. Most of these changes are minor, with the obvious
exception of the error handling mechanism (which is always strict in
<application>PyOpenGL 2</application>, while only optionally strict in <application>PyOpenGL 1.5</application>).
</para>
<para>
These upgrading notes are by no means a complete discussion of the
<application>PyOpenGL 2</application> binding and are only meant as a guide to the most likely
issues when upgrading.
</para>
<section id="upgrading-error_handling">
<title>Error Handling</title>
<para>
<application>PyOpenGL 2</application> always uses "strict" OpenGL operation, which is closer to
the operation of Python itself, i.e. errors are raised as exceptions,
rather than silently being passed back to the user. <function>glGetError</function> is not
available as it would never return anything save <constant>GL_NO_ERROR</constant>.
</para>
<para>
To convert, you will want to search for each instance of <function>glGetError</function>
and introduce the appropriate exception handling mechanisms. The
exceptions raised are:
</para>
<itemizedlist>
<listitem>
<exceptionname>GL.GLerror</exceptionname> by all modules except <classname>WGL</classname>
</listitem>
<listitem>
<exceptionname>GLU.GLUerror</exceptionname> by some <classname>GLU</classname> functions.
Note that <classname>GLU</classname> can also throw <exceptionname>GL.GLerror</exceptionname>
</listitem>
<listitem>
<exceptionname>WindowsError</exceptionname>/<exceptionname>SystemError</exceptionname> by
<classname>WGL</classname>
</listitem>
</itemizedlist>
</section>
<section id="upgrading-GL">
<title><classname>GL</classname></title>
<formalpara>
<title><function>glCleanRotMat</function> &ndash; Not Available</title>
<para>
This utility function attempted to
recover from precision errors encountered with multiple matrix
rotations. This seems like an inelegant approach to the situation.
Consider using quaternion addition (see <filename>OpenGL/quaternion.py</filename>) or single rotation calls.
</para>
</formalpara>
<formalpara>
<title><function>glSaveTIFF</function>, <function>glSaveJPEG</function>, <function>glSavePPM</function> &ndash; Not Available</title>
<para>
These
functions attempted to save a file in a particular format directly
from the OpenGL context. They largely duplicated effort both from
the Python Imaging Library (PIL) (image handling) and python
itself (file handling). Since <function>glReadPixels</function> is fully functional
under <application>PyOpenGL</application>, these functions were not provided.
See <filename>OpenGLContext/tests/saveimage.py</filename> for demonstration code
showing how to save an image using PIL
</para>
</formalpara>
<formalpara>
<title><function>glTetrahedra</function> &ndash; Not Available</title>
<para>
This does not seem like something
that needs to be in the core library.
</para>
</formalpara>
<formalpara>
<title>
<function>glTriangleNormals</function>, <function>glIndexedGeomDSPL</function>, <function>glTrianglesWithNormals</function>,
<function>glLines</function>, <function>glPoints</function> &ndash; Not Available
</title>
<para>
These functions provide
somewhat higher level rendering mechanisms for a small subset of
geometry types. They do not really seem to be something that
belongs in the core library. Although they may be implemented in
a utility library at a later date for legacy purposes, at the present time
they are not supported.
</para>
</formalpara>
<formalpara>
<title><function>glGetError</function></title>
<para>
See Error Handling above for rationale. You will need
to either define a nop function <function>glGetError</function>, or remove all
instances of <function>glGetError</function>.
</para>
</formalpara>
<formalpara>
<title><function>glGetBooleanv</function>, <function>glGetFloatv</function>, <function>glGetDoublev</function>, <function>glGetIntegerv</function> &ndash; Changed Behavior</title>
<para>
The <function>glGetX</function> family of functions no longer chooses a single default
type for each argument, instead, it returns the type appropriate
to the explicitly named function. For instance,
<programlisting>&gt;&gt;&gt; glGetInteger( GL_MODELVIEW_MATRIX )
[[1 0 0 0]
 [0 1 0 0]
 [0 0 1 0]
 [0 0 0 1]]</programlisting>
You will need to search for each <function>glGetX</function> call and determine if the
call really intended to use the function named, or whether it was
relying on the looser semantics of the original functions.
</para></formalpara>
<formalpara>
<title><function>gl<emphasis role="bold">X</emphasis>Pointer</function> Family &ndash; Changed Behavior</title>
<para>
There are now two major
variants of these functions. The first variant, spelled with the
appropriate type decoration <function>{d|f|i|b|ub}</function> takes a two- dimensional
python (or Numeric) array as its single argument:
</para>
</formalpara>
<programlisting>glVertexPointerd([[0.0, 0.0, 0.0], # note need for 2-d array!
                  [5.0, 0.0, 0.0], # Changed with PyOpenGL 2
                  [5.0, 5.0, 0.0],
                  [0.0, 5.0, 0.0]])</programlisting>
<para>
The second variant allows you to specify a string argument, as
well as the stride argument, and matches the semantics of the
underlying OpenGL function.
</para>
<programlisting>glVertexPointer(3, GL_DOUBLE, 0, vertices.tostring())</programlisting>
<note>
<para>
<function>glInterleavedArrays</function> is not part of this family and requires
a string, not an array argument
</para>
</note>
<formalpara>
<title><function>glVertex</function> - Changed Behavior</title>
<para>
<function>glVertex</function> no longer supports passing
in arrays of points, you will need to convert your code to using
<function>glVertexPointer{d|f}</function>.
</para>
</formalpara>
<formalpara>
<title><function>glColor2Vertexd</function>, <function>glColor2Vertex</function> &ndash; Not Available</title>
<para>
Like <function>glVertex</function>
this functionally should be replaced using <function>glVertexPointer</function> and
<function>glColorPointer</function>.
</para>
</formalpara>
<formalpara>
<title>Function Aliases</title>
<para>
<application>PyOpenGL 1.5</application> provided a number of convenience
names which were aliases for decorated function names. To preserve
code compatibility, many of these functions are now available
within <application>PyOpenGL 2</application>.

<variablelist>
<title>Function Aliases</title>
<varlistentry>
<term><function>glGetBooleanv</function> aliases</term>
<listitem><function>glGetBoolean</function></listitem>
</varlistentry>

<varlistentry>
<term><function>glGetDoublev</function> aliases</term>
<listitem><function>glGetDouble</function></listitem>
</varlistentry>

<varlistentry>
<term><function>glGetIntegerv</function> aliases</term>
<listitem><function>glGetInteger</function></listitem>
</varlistentry>

<varlistentry>
<term><function>glColord</function> aliases</term>
<listitem><simplelist>
<member><function>glColor</function></member>
<member><function>glColor3</function></member>
<member><function>glColor4</function></member>
</simplelist></listitem>
</varlistentry>

<varlistentry>
<term><function>glEvalCoordd</function> aliases</term>
<listitem><simplelist>
<member><function>glEvalCoord</function></member>
<member><function>glEvalCoord1</function></member>
<member><function>glEvalCoord2</function></member>
</simplelist></listitem>
</varlistentry>

<varlistentry>
<term><function>glFogfv</function> aliases</term>
<listitem><function>glFog</function></listitem>
</varlistentry>

<varlistentry>
<term><function>glIndexd</function> aliases</term>
<listitem><function>glIndex</function></listitem>
</varlistentry>

<varlistentry>
<term><function>glLightfv</function> aliases</term>
<listitem><function>glLight</function></listitem>
</varlistentry>

<varlistentry>
<term><function>glLightModelfv</function> aliases</term>
<listitem><function>glLightModel</function></listitem>
</varlistentry>

<varlistentry>
<term><function>glMaterialfv</function> aliases</term>
<listitem><function>glMaterial</function></listitem>
</varlistentry>

<varlistentry>
<term><function>glNormald</function> aliases</term>
<listitem><simplelist>
<member><function>glNormal</function></member>
<member><function>glNormal3</function></member>
<member><function>glNormal4</function></member>
</simplelist></listitem>
</varlistentry>

<varlistentry>
<term><function>glRasterPosd</function> aliases</term>
<listitem><simplelist>
<member><function>glRasterPos</function></member>
<member><function>glRasterPos2</function></member>
<member><function>glRasterPos3</function></member>
<member><function>glRasterPos4</function></member>
</simplelist></listitem>
</varlistentry>

<varlistentry>
<term><function>glRotated</function> aliases</term>
<listitem><function>glRotate</function></listitem>
</varlistentry>

<varlistentry>
<term><function>glScaled</function> aliases</term>
<listitem><function>glScale</function></listitem>
</varlistentry>

<varlistentry>
<term><function>glTexCoordd</function> aliases</term>
<listitem><simplelist>
<member><function>glTexCoord</function></member>
<member><function>glTexCoord1</function></member>
<member><function>glTexCoord2</function></member>
<member><function>glTexCoord3</function></member>
<member><function>glTexCoord4</function></member>
</simplelist></listitem>
</varlistentry>

<varlistentry>
<term><function>glTexGendv</function> aliases</term>
<listitem><function>glTexGen</function></listitem>
</varlistentry>

<varlistentry>
<term><function>glTexParameterfv</function> aliases</term>
<listitem><function>glTexParameter</function></listitem>
</varlistentry>


<varlistentry>
<term><function>glTranslated</function> aliases</term>
<listitem><function>glTranslate</function></listitem>
</varlistentry>

<varlistentry>
<term><function>glVertexd</function> aliases</term>
<listitem><function>glVertex</function></listitem>
</varlistentry>
</variablelist>

</para>
</formalpara>
</section>
<section id="upgrading-GLUT">
<title><classname>GLUT</classname></title>
<formalpara>
<title>Callback Registration &ndash; Changed Behavior.</title>
<para>
The method for registering
callbacks in <classname>GLUT</classname> has changed. Instead of calling:
</para>
</formalpara>
<programlisting>glutSetReshapeFuncCallback(OnResize)
glutReshapeFunc()</programlisting>
<para>
You will call:
<para>
<programlisting>glutReshapeFunc(OnResize)</programlisting>
</para>
</para>
<para>
If you need to unbind the callback then just use <constant>None</constant> instead of a
callback function in the callback registration function, i.e.
</para>
<programlisting>glutReshapeFunc(None)</programlisting>
<para>
If you need your code to run under both versions, you can catch a
raised <exceptionname>NameError</exceptionname> on <function>glutSetReshapeFuncCallback</function> and call
<function>glutReshapeFunc</function>. See <classname>OpenGLContext.GLUTContext</classname> for a
demonstration.
</para>
<formalpara>
<title><function>glutInit</function> &ndash; Changed Behavior</title>
<para>
This method initializes the GLUT
windowing system taking a non-string sequence of strings such as
available in sys.argv. <application>PyOpenGL</application> would allow you to use a single
string as the argument. <function>glutInit</function> returns the arguments not used by
GLUT as a list of strings.
</para>
</formalpara>
</section>
</chapter>
<!--<section>
<title>Nonstandard Interfaces</title>
<para>
This document attempts to provide a reference for <application>PyOpenGL 2</application>'s
non-standard APIs. Most of the functions are altered to return
arguments rather than using argument pointers. Some are altered to
take advantage of already known information (such as array
dimensions).
</para>
<para>
glDrawElements
</para>
<para>
void glDrawElements (GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices);
</para>
<para>
glDrawElements(mode, type, indices[]) -> None
</para>
<para>
* glDrawPixels
</para>
<para>
void glDrawPixels (GLsizei width, GLsizei height, GLenum format,
GLenum type, const GLvoid *pixels);
</para>
<para>
glDrawPixels(width, height, format, type, pixels) -> None
</para>
<para>
* glFeedbackBuffer
</para>
<para>
void glFeedbackBuffer (GLsizei size, GLenum type, GLfloat
*buffer);
</para>
<para>
glFeedbackBuffer(size, type) -> None
</para>
<para>
The buffer is returned by glRenderMode when the mode changed to a
mode other than GL_FEEDBACK. If the buffer is overflown then
glRenderMode will return None. Each item in the buffer returned by
glRenderMode is a 2-tuple of the form (token, vertices)
</para>
<para>
* glGenTextures
</para>
<para>
void glGenTextures (GLsizei n, GLuint *textures);
</para>
<para>
glGenTextures(n) -> textures
</para>
<para>
* glGetInteger glGetDouble glGetBoolean
</para>
<para>
glGetBooleanv(GLenum pname, GLboolean *params);
</para>
<para>
glGetDoublev(GLenum pname,GLdouble *params);
</para>
<para>
glGetFloatv(GLenum pname,GLfloat *params);
</para>
<para>
glGetIntegerv(GLenum pname,GLint *params);
</para>
<para>
glGetBooleanv( pname ) -> value
</para>
<para>
* glGetMapdv
</para>
<para>
void glGetMapdv (GLenum target, GLenum query, GLdouble *v);
</para>
<para>
glGetMapdv(target, query) -> values
</para>
<para>
* glGetMapfv
</para>
<para>
void glGetMapfv (GLenum target, GLenum query, GLfloat *v);
</para>
<para>
glGetMapfv(target, query) -> values
</para>
<para>
* glGetMapiv
</para>
<para>
void glGetMapiv (GLenum target, GLenum query, GLint *v);
</para>
<para>
glGetMapiv(target, query) -> values
</para>
<para>
* glGetPixelMapfv
</para>
<para>
void glGetPixelMapfv (GLenum map, GLfloat *values);
</para>
<para>
glGetPixelMapfv(map) -> values
</para>
<para>
* glGetPixelMapuiv
</para>
<para>
void glGetPixelMapuiv (GLenum map, GLuint *values);
</para>
<para>
glGetPixelMapuiv(map) -> values
</para>
<para>
* glGetPixelMapusv
</para>
<para>
void glGetPixelMapusv (GLenum map, GLushort *values);
</para>
<para>
glGetPixelMapusv(map) -> values
</para>
<para>
* glGetPolygonStipple
</para>
<para>
void glGetPolygonStipple (GLubyte* mask);
</para>
<para>
glGetPolygonStipple() -> packed stipple
</para>
<para>
* glGetTexImage
</para>
<para>
void glGetTexImage (GLenum target, GLint level, GLenum format,
GLenum type, GLvoid *pixels);
</para>
<para>
glGetTexImage(target, level, format, type) -> pixels
</para>
<para>
* glMap1d
</para>
<para>
void glMap1d (GLenum target, GLdouble u1, GLdouble u2, GLint
stride, GLint order, const GLdouble *points);
</para>
<para>
glMap1d(target, u1, u2, points[][]) -> None
</para>
<para>
* glMap1f
</para>
<para>
void glMap1f (GLenum target, GLfloat u1, GLfloat u2, GLint stride,
GLint order, const GLfloat *points);
</para>
<para>
glMap1f(target, u1, u2, points[][]) -> None
</para>
<para>
* glMap2d
</para>
<para>
void glMap2d (GLenum target, GLdouble u1, GLdouble u2, GLint
ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride,
GLint vorder, const GLdouble *points);
</para>
<para>
glMap2d(target, u1, u2, v1, v2, points[][][]) -> None
</para>
<para>
* glMap2f
</para>
<para>
void glMap2f (GLenum target, GLfloat u1, GLfloat u2, GLint
ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride,
GLint vorder, const GLfloat *points);
</para>
<para>
glMap2f(target, u1, u2, v1, v2, points[][][]) -> None
</para>
<para>
* glReadPixels
</para>
<para>
void glReadPixels (GLint x, GLint y, GLsizei width, GLsizei
height, GLenum format, GLenum type, GLvoid *pixels);
</para>
<para>
glReadPixels(x, y, width, height, format, type) -> pixels
</para>
<para>
* glRenderMode
</para>
<para>
GLint glRenderMode (GLenum mode);
</para>
<para>
glRenderMode(mode) -> None | FeedbackBuffer | SelectBuffer
</para>
<para>
See glSelectBuffer and glFeedbackBuffer for the format of
SelectBuffer and FeedbackBuffer.
</para>
<para>
* glSelectBuffer
</para>
<para>
void glSelectBuffer (GLsizei size, GLuint *buffer);
</para>
<para>
glSelectBuffer(size) -> None
</para>
<para>
The buffer is returned by glRenderMode when the mode changed to a
mode other than GL_SELECT. If the buffer is overflown then
glRenderMode will return None. Each item in the buffer returned by
glRenderMode is a 3-tuple of the form (min_depth, max_depth,
names)
</para>
<para>
* glTexImage1D
</para>
<para>
void glTexImage1D (GLenum target, GLint level, GLint
internalFormat, GLsizei width, GLint border, GLenum format, GLenum
type, const GLvoid *pixels);
</para>
<para>
glTexImage1D(target, level, internalFormat, width, border, format,
type, pixels) -> None
</para>
<para>
* glTexImage2D
</para>
<para>
void glTexImage2D (GLenum target, GLint level, GLint
internalFormat, GLsizei width, GLsizei height, GLint border,
GLenum format, GLenum type, const GLvoid *pixels);
</para>
<para>
glTexImage2D(target, level, internalFormat, width, height, border,
format, type, pixels) -> None
</para>
<para>
* glTexSubImage1D
</para>
<para>
void glTexSubImage1D (GLenum target, GLint level, GLint xoffset,
GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
</para>
<para>
glTexSubImage1D(target, level, xoffset, width, format, type,
pixels) -> None
</para>
<para>
* glTexSubImage2D
</para>
<para>
void glTexSubImage2D (GLenum target, GLint level, GLint xoffset,
GLint yoffset, GLsizei width, GLsizei height, GLenum format,
GLenum type, const GLvoid *pixels);
</para>
<para>
glTexSubImage2D(target, level, xoffset, yoffset, width, height,
format, type, pixels) -> None
</para>
<para>
* glNormalPointer
</para>
<para>
void glNormalPointer (GLenum type, GLsizei stride, const GLvoid
*pointer);
</para>
<para>
glNormalPointer(size, type, stride, pointer) -> None
</para>
<para>
See glPushClientAttrib() or glPopClientAttrib() for notes about
pointer reference counting.
</para>
<para>
* glVertexPointer
</para>
<para>
void glVertexPointer (GLint size, GLenum type, GLsizei stride,
const GLvoid *pointer);
</para>
<para>
glVertexPointer(size, type, stride, pointer) -> None
</para>
<para>
See glPushClientAttrib() or glPopClientAttrib() for notes about
pointer reference counting. Note that glVertexPointerd|f|b
functions are also available with the signatures glVertexPointerd(
2DArray )
</para>
<para>
* glIndexPointer
</para>
<para>
void glIndexPointer (GLenum type, GLsizei stride, const GLvoid
*pointer);
</para>
<para>
glIndexPointer(type, stride, pointer) -> None
</para>
<para>
See glPushClientAttrib() or glPopClientAttrib() for notes about
pointer reference counting.
</para>
<para>
* glTexCoordPointer
</para>
<para>
void glTexCoordPointer (GLint size, GLenum type, GLsizei stride,
const GLvoid *pointer);
</para>
<para>
glTexCoordPointer(size, type, stride, pointer) -> None
</para>
<para>
See glPushClientAttrib() or glPopClientAttrib() for notes about
pointer reference counting.
</para>
<para>
* glEdgeFlagPointer
</para>
<para>
void glEdgeFlagPointer (GLsizei stride, const GLvoid *pointer);
</para>
<para>
glEdgeFlagPointer(stride, pointer) -> None
</para>
<para>
See glPushClientAttrib() or glPopClientAttrib() for notes about
pointer reference counting.
</para>
<para>
* glPopClientAttrib - Although the following APIs are source code
compatible with their official API, there are semantic differences
which should be noted.
</para>
<para>
void glPopClientAttrib (void);
</para>
<para>
glPopClientAttrib() -> None
</para>
<para>
Because reference counting is done in glPopClientAttrib() every
call to glPopClientAttrib() from Python must be preceded by a call
to glPushClientAttrib() from within Python. Also every call to
glColorPointer, glIndexPointer, etc. from within an extension
module must be surrounded by calls from the extension module to
glPushClientAttrib and glPopClientAttrib.
</para>
<para>
* glPushClientAttrib - Although the following APIs are source code
compatible with their official API, there are semantic differences
which should be noted.
</para>
<para>
void glPushClientAttrib (GLbitfield mask);
</para>
<para>
glPushClientAttrib(mask) -> None
</para>
<para>
Because reference counting is done in glPushClientAttrib() every
call to glPushClientAttrib() from Python must be accompanied by a
call to glPopClientAttrib() from within Python. Also every call to
glColorPointer, glIndexPointer, etc. from within an extension
module must be surrounded by calls from the extension module to
glPushClientAttrib and glPopClientAttrib.
</para>
</section>-->
<chapter id="users_guide">
<title>User's Guide</title>
<para>
Most of the functions which appear in <application>PyOpenGL 2</application> are identical in
calling method and functionality to that of the appropriate specification.
There are a few exceptions because of the differences between C and
Python. Most of these exceptions are due to the difference between C and Python 
in the way that they access arrays.  For example, a C function like this:</para>
<programlisting>void foo(int count, const int *args);</programlisting>
<para>
will have the Python binding:
</para>
<programlisting>foo(args) -> None</programlisting>
<para>
Also C functions which write array data to a function argument like:
</para>
<programlisting>void bar(int args[4]);</programlisting>
<para>
will have the Python binding:
</para>
<programlisting>bar() -> args[]</programlisting>
<para>
The following sections will document changes other than simple changes like
the above examples.  When in doubt about
the Python binding for a specific function one can always check the docstring
explicitly. For instance, to check the Python binding of the C function <function>glDeleteTextures</function>
which has the C binding
</para>
<programlisting>void glDeleteTextures(GLsizei n, const GLuint *textures);</programlisting>
<para>
one could do the following from the Python prompt
</para>
<programlisting>
&gt;&gt;&gt; from OpenGL.GL import *
&gt;&gt;&gt; glDeleteTextures.__doc__
'glDeleteTextures(textures[]) -> None'</programlisting>
<para>
Notice that the parameter <parameter>n</parameter> is missing from the Python prototype since this
can automatically be determined from the parameter <parameter>textures</parameter>.  Also note that the
notation <parameter>textures[]</parameter> is used in docstrings to indicate that the <parameter>textures</parameter> parameter
should be a Python sequence.  If the <parameter>textures</parameter> parameter was required to be a two dimensional
array than this would be indicated by <parameter>textures[][]</parameter>.  If one of the array dimensions
is expected to have a fixed size than this will be indicated by a number enclosed in the brackets.
For instance, <function>glePolyCone</function> of the GLE module has the prototype
</para>
<programlisting>glePolyCone(point_array[][3], color_array[][3], radius_array[]) -> None</programlisting>
<para>
Of course in many Python IDEs the first line of the function docstring will be displayed
in a tool-tip when you type the function name in a Python script.  Another way to see all the functions, attributes,
or docstrings of a specific module is to use the pydoc utility.  Python 2.1 includes this utility.  For other versions
of Python see Ka-Ping Lee's <ulink url="http://web.lfw.org/python">Python Things</ulink>.
</para>
<section id="users_guide-GL">
<title><classname>GL</classname></title>
<subtitle>OpenGL Library; API versions 1.0 and 1.1</subtitle>
<section id="users_guide-selection_feedback">
<title>Selection and Feedback buffers</title>
<para>
Normally in OpenGL to use a selection buffer one would do the
following:
</para>
<programlisting>GLuint buffer[SIZE];
glSelectBuffer(SIZE, buffer);
glRenderMode(GL_SELECT);
/* draw some stuff */
GLint count = glRenderMode(GL_RENDER);
/* parse the selection buffer */</programlisting>
<para>
In Python this accomplished like this:
</para>
<programlisting>glSelectBuffer(SIZE) # allocate a selection buffer of SIZE elements
glRenderMode(GL_SELECT)
# draw some stuff
buffer = glRenderMode(GL_RENDER)
for hit_record in buffer:
    min_depth, max_depth, names = hit_record
    # do something with the record</programlisting>
<para>
Feedback buffers are used in the same way except that each item in the
buffer is tuple <function>(token, value)</function>, where value is either a passthrough
token or a list of vertices. Note that if <function>glRenderMode</function> returns a
buffer than it also resets <application>OpenGL</application>'s pointer for the corresponding
buffer. This means that the buffer returned by <function>glRenderMode</function> is
independent of future calls to <function>glRenderMode</function>, i.e. it will not be
overwritten by any such future calls. This makes the returned buffer somewhat
thread-safe. It also means that every call to <function>glRenderMode(GL_SELECT |
GL_FEEDBACK)</function> needs to preceded by a call to <function>glSelectBuffer</function> or <function>glFeedbackBuffer</function> first,
i.e. the following code will not work
</para>
<programlisting>glSelectBuffer(SIZE) # allocate a selection buffer of SIZE elements
glRenderMode(GL_SELECT)
# draw some stuff
buffer = glRenderMode(GL_RENDER)
# do another selection
glRenderMode(GL_SELECT)
# draw some stuff
buffer = glRenderMode(GL_RENDER)</programlisting>
<para>
Instead one must
</para>
<programlisting>glSelectBuffer(SIZE) # allocate a selection buffer of SIZE elements
glRenderMode(GL_SELECT)
# draw some stuff
buffer = glRenderMode(GL_RENDER)
# do another selection
glSelectBuffer(SIZE) allocate a new selection buffer
glRenderMode(GL_SELECT)
# draw some stuff
buffer = glRenderMode(GL_RENDER)</programlisting>
<para>
In previous versions of <application>PyOpenGL</application> in order to perform selection one
would use the <function>glSelectWithCallback</function> function. This function is still
available, but the only thing that it does in addition to the method
described above is setup the projection matrix using <function>gluPickMatrix</function>.
</para>
</section>
<section id="users_guide-array">
<title>Array Routines</title>
<para>
Each call which sets an array pointer, such as <function>glVertexPointer</function>, will
have many variants. First there will a function which is identical
that of the specification. For the <parameter>pointer</parameter> argument one should pass a string. Also
note that the stride values are used.
</para>
<para>
Next there will a set of functions named
</para>
<programlisting>gl<emphasis role="bold">X</emphasis>Pointer{ub|b|us|s|ui|i|f|d}</programlisting>
<para>
These will usually take as a single argument a multidimensional array
of values. The type argument is controlled by the suffix of the
function (<function>ub</function> is unsigned byte, etc.) All other arguments are derived
from the dimensions of the array.
</para>
<para>
So for <function>glColorPointer</function> we have:
</para>
<programlisting>glColorPointer(size, type, stride, pointer) -> None
glColorPointerub(pointer[][]) -> None
glColorPointerb(pointer[][]) -> None
glColorPointerus(pointer[][]) -> None
glColorPointers(pointer[][]) -> None
glColorPointerui(pointer[][]) -> None
glColorPointeri(pointer[][]) -> None
glColorPointerf(pointer[][]) -> None
glColorPointerd(pointer[][]) -> None</programlisting>
<para>
This same decoration strategy is used for other array functions besides <function>gl<emphasis role="bold">X</emphasis>Pointer</function>.
For instance, <function>glDrawElements</function> has the Python binding:
</para>
<programlisting>glDrawElements(mode, count, type, indices) -> None</programlisting>
<para>
where <parameter>indices</parameter> is expected to be a string.  There are also the decorated bindings
</para>
<programlisting>glDrawElementsub(mode, indices[]) -> None
glDrawElementsus(mode, indices[]) -> None
glDrawElementsui(mode, indices[]) -> None</programlisting>
<para>
where "indices" is now a single dimensional array.
</para>
<para>
When calling a <function>glColorPointer</function>, <function>glVertexPointer</function>, etc. Python needs
to allocate memory to store the values that OpenGL needs. This memory
is reference counted and takes into account function calls like
<function>glPushClientAttrib</function> and <function>glPopClientAttrib</function>. To force this memory to be
released one just need to make a call <function>glColorPointerub(None)</function>.
</para>
<para>
Currently <function>glPushClientAttrib</function> will always set the
<constant>GL_CLIENT_VERTEX_ARRAY_BIT</constant> flag as <function>glPopClientAttrib</function> has no way of
knowing that flag was set and the state of the flag is needed to know
whether or not to decrement the pointer locks on the allocated memory.
This may change in the future. That said, surrounding array use
<function>glPushClientAttrib</function>/<function>glPopClientAttrib</function> is a good way to force the
release of any allocated memory, but make sure that all calls to
<function>gl<emphasis role="bold">X</emphasis>Pointer</function>, etc. are within the <function>ClientAttrib</function> block if you chose to
use this scheme.
</para>
<note>
<para>
Since all the memory allocation is automatic there is no need for
<function>glGetPointerv</function> function, so it is excluded.
</para>
</note>
<note>
<para>
The function <function>glInterleavedArrays</function> is also present, but it does not have
the variants that the others do (i.e., no <function>glInterleavedArraysf</function>)
</para>
</note>
<warning>
<para>
If you write an extension module which makes calls to
the pointer functions and expects to interact with <application>PyOpenGL</application> safely
it should push the client state (from within the extension) before and
after array use.
</para>
</warning>
</section>
<section id="users_guide-image">
<title>Image Routines</title>
<para>
<function>glDrawPixels</function> and the other image/texturing functions have much the
same decoration scheme as the array functions. For <function>glDrawPixels</function> there is the
standard function which expects a string as the pixel data:
</para>
<programlisting>glDrawPixels(width, height, format, type, pixels) -> None</programlisting>
<para>
This function will respect the parameters set by <function>glPixelStore{i|f}</function>.
There is also a collection of variants which take a multidimensional
array as the data source and set <function>glPixelStore{i|f}</function> automatically. For
example:
</para>
<programlisting>glDrawPixelsub(format, pixels) -> None</programlisting>
<para>
Notice that <parameter>width</parameter> and <parameter>height</parameter> are inferred from the pixel data and the
type is GLubyte.
</para>
</section>
<section id="users_guide-errors">
<title>Error Handling</title>
<para>
In OpenGL the current error status is retrieved with the function <function>glGetError</function>.
This function returns an error code and clears the current error status at the same time. On some
distributed systems multiple errors may be generated at a time. In that case it is necessary to call
<function>glGetError</function> multiple times.
</para>
<para>
PyOpenGL does not expose the <function>glGetError</function>. Instead it automatically checks
the error status and throws an instance of <exceptionname>GL.GLerror</exceptionname> on an error.
This is a more "Pythonic" approach. <exceptionname>GL.GLerror</exceptionname> is a subclass of
<exceptionname>EnvironmentError</exceptionname> and has a <varname>errno</varname> and
<varname>msg</varname> like <exceptionname>EnvironmentError</exceptionname>. In the case of
multiple errors the <varname>errno</varname> attribute will be set to a tuple of error numbers and <varname>msg</varname>
will be a concatenation of the error messages for each error.
</para>
</section>
</section>
<!--<section>
<title>Tk Module</title>
<para>
Some Togl applications used the functions glTranslateScene,
glRotateScene, and glDistFromLine. Previously these were implemented
in the GL extension module. They are now implemented using Python in
the Tk module.
</para>
</section>-->
<section id="users_guide-GLU">
<title><classname>GLU</classname></title>
<subtitle>GL Utility Library; API versions 1.0, 1.1, 1.2 and 1.3</subtitle>
<para>
For the most part the Python bindings of the GLU module are identical to that
of the GLU specification. The first main difference is in the callback implementation of
<classname>GLUnurbs</classname>, <classname>GLUquadric</classname> and <classname>GLUtesselator</classname>.
Callbacks can be set with the appropriate function, for instance
</para>
<programlisting>def begin(type):
    print 'begin', type

tess = gluNewTess()
gluTessCallback(tess, GLU_TESS_BEGIN, begin)</programlisting>
<para>except that the error callbacks <constant>GLU_TESS_ERROR</constant>, <constant>GLU_TESS_ERROR_DATA</constant>, or 
<constant>GLU_ERROR</constant> cannot be set.  Instead a <exceptionname>GLU.GLUerror</exceptionname> exception
is thrown on an error.  The value of the exception will be a 2-tuple except when the error is a tessellation error,
in which case the value will be set to <function>(error_code, error_string, polygon_data)</function>.
</para>
<para>
Some other GLU functions can also throw a <exceptionname>GLUerror</exceptionname>.  These are primarily functions which
would normally return an error code.  For instance, <function>gluScaleImage</function>
</para>
<programlisting>
try:
    dataout = gluScaleImage(format, widthin, heightin, typein,
                            datain, widthout, heightout, typeout)
except GLUerror:
    pass</programlisting>
<para>
The last major difference between the <classname>GLU</classname> module and the <classname>GLU</classname> specification is that it also implements the variant decoration
scheme as discussed previously for the GL module.  This is implemented for the image functions:
<function>gluScaleImage</function>, <function>gluBuild1DMipmaps</function>, <function>gluBuild2DMipmaps</function>,
<function>gluBuild3DMipmaps</function>, <function>gluBuild1DMipmapLevels</function>,
<function>gluBuild2DMipmapLevels</function>, and <function>gluBuild3DMipmapLevels</function>.
</para>
</section>
<section id="users_guide-GLUT">
<title><classname>GLUT</classname></title>
<subtitle>GL Utility Toolkit; API versions 1.0, 2.0, 3.0, 3.4, 3.6, and 3.7</subtitle>
<para>
PyOpenGL provides coverage of all GLUT API versions and the calling convention for
the exposed functions are identical to that of the C binding, with a few minor exceptions.
</para>
<para>
First, the <function>glutInit</function> function takes a list of arguments (usually
<varname>sys.argv</varname>, but not <varname>sys.argv[1:]</varname>) and returns all non GLUT arguments.  For example
</para>
<programlisting>import sys

my_argv = glutInit(sys.argv)</programlisting>
<para>
Secondly, setting callbacks in Python is done in the same way as done in C, but Python has no <constant>NULL</constant>
pointer so <constant>None</constant> is used to clear a callback instead, i.e.</para>
<programlisting>def on_display():
    pass

glutDisplayFunc(on_display) # set the callback
glutDisplayFunc(None)       # clear the callback</programlisting>
<para>
For more information about GLUT see the <ulink url="http://pyopengl.sourceforge.net/documentation/ref/glut.html">Man Pages</ulink>,
the <ulink url="http://reality.sgi.com/mjk/glut3/glut3.html">GLUT homepage</ulink>, or OpenGL.org's
<ulink url="http://www.opengl.org/developers/documentation/glut.html">GLUT documentation</ulink>.
</para>
</section>
<section id="users_guide-WGL">
<title><classname>WGL</classname></title>
<subtitle>Win32 OpenGL Library; API version 4</subtitle>
<para>
PyOpenGL has complete coverage of the WGL API, with the exception that the <function>GetEnhMetaFilePixelFormat</function>
function is currently not supported.
</para>
<para>
Like the rest of PyOpenGL, the WGL module has a strict error mechanism.  If a Windows error occurs
during a WGL call then a <exceptionname>WindowsError</exceptionname> exception error is thrown. For
Python versions less than 2.1, an <exceptionname>OSError</exceptionname> will be thrown instead.
</para>
<para>
For more information about WGL see the <ulink url="http://msdn.microsoft.com/library/?url=/library/en-us/opengl/hh/opengl/ntopnglo_0e0o.asp?frame=true">MSDN Library</ulink>.
</para>
</section>
<section id="users_guide-GLE">
<title><classname>GLE</classname></title>
<subtitle>Tubing and Extrusion Library; API version 3</subtitle>
<para>
<application>PyOpenGL</application> supports version 3 of the GLE (Tubing and Extrusion)
library. The function prototype exposed by the Python binding are identical to that of
the GLE C binding, except that passing array lengths explicitly is not needed.  For more
information consult the docstring of each function or the <ulink url="http://pyopengl.sourceforge.net/documentation/ref/gle.html">Man Pages</ulink>.
For information regarding GLE itself see the <ulink url="http://linas.org/gle">GLE homepage</ulink>.
</para>
</section>
<section id="users_guide-extensions">
<title>Extensions</title>
<para>
<application>PyOpenGL</application> includes support for many GL, GLU and WGL extensions. These extensions
are implemented as sub-modules of the <classname>GL</classname>, <classname>GLU</classname> or <classname>WGL</classname> package. For example, the
<constant>GL_ARB_multitexture</constant> extension would be implemented in the module
<classname>GL.ARB.multitexture</classname>. For every extension that <application>PyOpenGL</application> supports the
corresponding module will exist regardless of whether or not that
extension is implemented by the user's OpenGL library. A placeholder
module will also exist even if the extension defines no new tokens or
functions. If the extension is not supported by the current context
than any attempt to use that extension will throw a <exceptionname>GLerror</exceptionname> exception
with a code of <constant>GL_INVALID_OPERATION</constant>.
</para>
<para>
Each OpenGL implementation has its' own method for linking to OpenGL extensions.  These methods vary from dynamic
linking to static linking and even some dynamic/static combinations.  Regardless of which case applies to a specific
implementation of OpenGL, one still needs to verify that a particular extension is supported before attempting to use
any functions or tokens that it declares.  This is usually done by calling <function>glGetString(GL_EXTENSIONS)</function>
and looking for extension name in the returned string.
</para>
<para>
Extensions are potentially context dependent, which means that an extension supported by one OpenGL context
may not be supported by another.  This means that verification that extension is supported and loading of the extension
procedure addresses (if the OpenGL extension mechanism is dynamic) needs to be done for each context that intends to
use a particular extension.  PyOpenGL simplifies this somewhat by providing a single initialization function for each
extension which does the following:
</para>
<orderedlist>
<listitem>verify the extension is supported by the current context</listitem>
<listitem>load all procedure addresses for extension if needed</listitem>
<listitem>return a boolean indicating success of the previous steps</listitem>
</orderedlist>
<para>
The naming scheme of the this initialization is designed to
be consistent with the naming scheme used with OpenGL extensions. For instance, here is a function which takes an
extension name and returns the initialization function name:
</para>
<programlisting>def init_name(extension_name):
    parts = string.split(extension_name, '_')
    return string.join([string.lower(parts[0]), 'Init'] +
                       map(string.capitalize, parts[2:]) +
                       [parts[1]], '')

&gt;&gt;&gt; init_name('GL_ARB_multitexture')
'glInitMultitextureARB'

&gt;&gt;&gt; init_name('GLU_SGI_filter4_parameters')
'gluInitFilter4ParametersSGI'</programlisting>
<para>
As an example of extension usage, here is a GLUT program that needs the GL_ARB_multitexture extension:
</para>
<programlisting>from OpenGL.GLUT import *
from OpenGL.GL.ARB.multitexture import *
import sys

# initialize GLUT
argv = glutInit(sys.argv)

# create a window, needs to be done before glInitMultitextureARB
glutCreateWindow('foo')

# see if GL_ARB_multitexture is supported
if not glInitMultitextureARB():
    # it's not supported...panic!
    print "Help, I'm lost without GL_ARB_multitexture!"
    sys.exit(1)
    
# do something with it...</programlisting>
<para>
It is important to note that the initialization function for an extension <emphasis role="bold">must</emphasis> be
called by each context that intends to use that extension.  Failure to do so will result in a
<exceptionname>GL.GLerror</exceptionname> with a code of <constant>GL_INVALID_OPERATION</constant>
even if the extension is actually supported by that context.
</para>
</section>
<section id="users_guide-portable_code">
<title>Writing Portable Code</title>
<para>
For many modules <application>PyOpenGL</application> is designed to support multiple versions
of the API exposed by that particular module. For instance, the <classname>GLU</classname>
module supports GLU API versions 1.0, 1.1, 1.2 and 1.3. In many cases
different versions of an API have different functions and constants.
There are several ways for Python code to determine at runtime which
API is exposed.
</para>
<para>
All <application>PyOpenGL</application> modules have an attribute named <constant>__api_version__</constant> which
is set to an integer which defines the current version. Usually this a
combination of the major version number in the high word and the minor
in the low word. So <classname>GLU</classname> has
</para>
<programlisting>__api_version__ = 0x100 | 0x101 | 0x102 | 0x103</programlisting>
<para>Currently the only exception to this is the <classname>GLUT</classname> module which
only uses the low word to store the Xlib implementation number (see
your GLUT header for information about this.)
</para>
<para>
Often times a C header which defines an API has some macro or macros
which define the version number. <application>PyOpenGL</application> includes the same macros
as module attributes to make porting C code easier. For the <classname>GLU</classname> module
these macros are <constant>GLU_VERSION_1_1</constant>, <constant>GLU_VERSION_1_2</constant>, and
<constant>GLU_VERSION_1_3</constant>. So if your Python code needs GLU 1.2 to run then you
could test for this at runtime by doing the following:
</para>
<programlisting>from OpenGL.GLU import *

try:
    GLU_VERSION_1_2
except:
    print "Help! I'm lost without GLU 1.2!"
    sys.exit(1)</programlisting>
</section>

</chapter>
<!--<chapter>
<title>Reference</title>
<section>
<title>GL</title>
<refentry id="glAccum">

<refmeta>
<refentrytitle>glAccum</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>

<refnamediv>
<refname>glAccum</refname>
<refpurpose>Perform an operation on the accumulation buffer.</refpurpose>
<indexterm zone="glAccum"><primary>glAccum</primary></indexterm>
</refnamediv>

<refsynopsisdiv>

<variablelist>
<varlistentry>
<term>Python Prototype</term>
<listitem><function>glAccum</function>(<parameter>op</parameter>, <parameter>value</parameter>) -> <constant>None</constant></listitem>
</varlistentry>

<varlistentry>
<term>C Prototype</term>
<listitem><type>void</type> <function>glAccum</function>(<type>GLenum</type> <parameter>op</parameter>, <type>GLfloat</type> <parameter>value</parameter>)</listitem>
</varlistentry>

</variablelist>

</refsynopsisdiv>

<refsect1><title>Description</title>
<para>
</para>
</refsect1>
</refentry>

</section>

</chapter>-->
<chapter id="internals">
<title>Internals</title>
<section id="internals-porting">
<title>Porting</title>
<para>
There are three main files which contain platform specific information.  The first is the configuration file
used by the setup script.  The following code illustrates how this file is selected
</para>
<programlisting>name = sys.platform
config_name = os.path.join('config', name + '.cfg')

while len(name) and not os.path.exists(config_name):
    name = name[:-1]
    config_name = os.path.join('config', name + '.cfg')</programlisting>
<para>
The net effect of this method is to allow the names of configuration files to proceed from fine to 
coarse in granularity.  For instance, suppose that the "linux-alpha" platform required a special configuration
file but all other Linux platforms (linux, linux1, linux2, linux-i386, etc.) used the same configuration file.  
To cover both of these cases one would create two configuration files: <filename>config/linux.cfg</filename>
and <filename>config/linux-alpha.cfg</filename>.
</para>
<para>
This configuration file controls various build options, such as include directories or lib directories.
For example, here is a verbatim copy of this file for the "linux" platform:
</para>
<programlisting>
; General config options
;
; Setting build_togl to zero will avoid trying to build Togl
;
; gl_platform is the name of the platform specific OpenGL module
; For X-windows this GLX, Windows has WGL, etc.
;
; include_dirs and library_dirs are a sys.pathsep separated list of
; additional directories for headers and libraries.  No quotes
; are needed
[General]
build_togl=1
gl_platform=GLX
include_dirs=/usr/include:/usr/local/include:/usr/X11/include
library_dirs=/usr/lib:/usr/local/lib:/usr/X11/lib

; a sys.pathsep separated list of the libs needed when linking GL
[GL]
libs=GL:X11:Xext

; a sys.pathsep separated list of the libs needed when linking GLU
; the GL libraries are included automatically
[GLU]
libs=GLU

; a sys.pathsep separated list of the libs needed when linking GLUT
; the GL and GLU libraries are included automatically
[GLUT]
libs=glut:Xi:Xmu

; a comma separated list of the libs needed when linking Togl
; the GL and GLU libraries are included automatically
[Togl]
libs=Xmu:Xt:m
</programlisting>
<para>
Most of the entries are explained by the embedded comments, but one is worth commenting on further.
This is the "gl_platform" entry.  This entry is used tell the setup script the name of the platform
specific GL platform.  This name is used in the <filename>src/config.h</filename> and the <filename>src/interface_util/platform.c</filename>
files to include the right code for that platform.  For instance in <filename>src/config.h</filename>
</para>
<programlisting>#if defined(WGL_PLATFORM)

#include &lt;windows.h&gt;

/* Do extension definitions define the C prototype
   or just the enumerants? */
#define EXT_DEFINES_PROTO 0

/* A function which returns true if the current
   context is valid */
#define CurrentContextIsValid() wglGetCurrentContext()

/* Get a hash code (long) corresponding to the
   current context */
#define GetCurrentContext() ((long)wglGetCurrentContext())

/* Does the platform have a dynamic extension loading
   mechanism? */
#define HAS_DYNAMIC_EXT 1

#elif defined(AGL_PLATFORM)

.
.
.
</programlisting>
<para>
The last platform specific file is the <filename>src/interface_util/platform.c</filename> file.  This file defines
functions to retrieve platform specific extension addresses and extension strings.  For more information see the 
source code.
</para>
</section>
<section id="internals-contributing">
<title>Contributing</title>
<para>
<application>PyOpenGL</application> uses the wrapper generator SWIG to convert wrapper
descriptions (interfaces) into Python extension modules. In order to
add to <application>PyOpenGL</application> you need SWIG 1.3a5 which available at the
<ulink url="http://swig.sourceforge.net">SWIG homepage</ulink>. If you haven't used SWIG before then you
might consider playing with it a bit before you contemplate trying to
contribute to <application>PyOpenGL</application>.
</para>
<para>
<application>PyOpenGL</application> makes extensive use of the SWIG typemap feature. Chances
are that you won't have to write any complex typemaps yourself as most
these have probably already been created to support the <classname>GL</classname> module,
etc. You may have to write some simple scalar typemaps.
</para>
<section id="internals-build_system">
<title>The Build System</title>
<para>
You probably won't have to modify the build system to add a
module unless the module needs some external library or such. To add a
module just put the interface file (.i extension) in the interface
directory. For example, <classname>GL.ARB.multitexture</classname> goes into
<filename>interface/GL/ARB/multitexture.i</filename>.
</para>
</section>
<section id="internals-interface_files">
<title>Interface Files</title>
<para>
Here are some lines common to every interface file (using the GLUT
module as an example)
</para>
<programlisting>/*
# BUILD api_versions [1, 2, 5, 7, 9, 11, 13]
# BUILD macro_template 'GLUT_XLIB_IMPLEMENTATION >= %(api_version)d'
# BUILD headers ['GL/glut.h']
# BUILD libs ['GLUT']
*/

%module GLUT

#define __version__ "$Revision: 1.23 $"
#define __api_version__ API_VERSION
#define __doc__ "http:\057\057reality.sgi.com/mjk/glut3/glut3.html"

%include util.inc</programlisting>
<para>
First off notice that the <constant>__doc__</constant> define uses "\057\057" and not "//".
This is because the preprocessor of SWIG is a bit buggy and sometimes won't handle double slashes.
</para>
<para>
Second, notice the inclusion of the <filename>util.inc</filename> file.  It defines a lot of the typemaps and such needed by
<application>PyOpenGL</application> modules, chances are you'll need it.
</para>
<para><application>PyOpenGL</application> has the ability to support multiple versions of an API.
This is accomplished by this line
</para>
<programlisting># BUILD api_versions [1, 2, 5, 7, 9, 11, 13]</programlisting>
<para>
For each number listed in this list the build system will run SWIG
with the macro API_VERSION defined to be the API version to be generated. So
suppose that I want to put in a feature that is only supported in
version 11 of the API. Then the function prototype in the interface would
look like this:
</para>
<programlisting>#if API_VERSION >= 11
void foo(int bar);
#endif</programlisting>
<para>
Note that the SWIG preprocessor also doesn't like comparisons between
hexadecimal numbers so don't use this
</para>
<programlisting>#ifdef API_VERSION >= 0xb</programlisting>
<para>
When the generated C code for the interface is compiled it needs to
pick out the right code for API version that is supported. Usually the
API version is defined by some macro in the header file which defines
the API. For instance, GLUT has the macro GLUT_XLIB_IMPLEMENTATION.
In order to test this macro first the build system needs to know what
header the macro is located in. This is accomplished by the 
</para>
<programlisting># BUILD headers ['GL/glut.h']</programlisting>
<para>line. The build system also needs to know how to make a
comparison on the macro. This is accomplished by the
</para>
<programlisting># BUILD macro_template 'GLUT_XLIB_IMPLEMENTATION >= %(api_version)d'</programlisting>
<para>
line. The string defined by the macro template line
should be a Python format string. The substitution names allowed are
<varname>api_version_underscore</varname> which splits the API_VERSION into high word and
low word separated by an underscore, and <varname>api_version</varname> which is just
API_VERSION as an integer.  <varname>api_version_underscore</varname> is useful for macros
like <constant>GL_VERSION_1_1</constant>.
</para>
<para>
If the API that you are wrapping defines structures or classes which
need to be exposed than you need to use the "shadow" feature of SWIG.
I won't go into all the details of how this feature works here. To see
an example of its use look at the WGL module. To turn on shadowing use
this line:
</para>
<programlisting># BUILD shadow 1</programlisting>
<para>
There are other "BUILD" headers allowed by <application>PyOpenGL</application>. Here are some
examples:
</para>
<itemizedlist>
<listitem>
<para>
To only build the module on GLX platforms:
</para>
<programlisting># BUILD gl_platforms ['GLX']</programlisting>
</listitem>
<listitem>
<para>
To specify what libraries the module needs:
</para>
<programlisting># BUILD libs = ['GLUT']</programlisting>
<para>
Note that the names in the in the libs header are platform independent
names. The setup script transforms these into a platform specific
name or names. For example on Win32, GLUT = glut32.
</para>
</listitem>
</itemizedlist>
<section id="internals-docstrings">
<title>Docstrings</title>
<para>
One nice feature of Python is the docstring feature. SWIG does not
support this natively, but <application>PyOpenGL</application> has a workaround to enable their use.
To add a docstring to a function call "foo" just include in the
interface the line:
</para>
<programlisting>DOC(foo, "foo() -> bar")</programlisting>
</section>
<section id="internals-exception_handlers">
<title>Exception Handlers</title>
<para>
<application>PyOpenGL</application> doesn't expose the <function>glGetError</function> function, instead it throws a
<exceptionname>GL.GLerror</exceptionname> exception. To turn on the GL exception handler you need a line
like this:
</para>
<programlisting>GL_EXCEPTION_HANDLER()</programlisting>
<para>
Some GL commands are designed to run between a <function>glBegin</function> and a <function>glEnd</function>.
For these it is not possible to call <function>glGetError</function>, so before these
functions you need this:
</para>
<programlisting>EXCEPTION_HANDLER()</programlisting>
<para>
To restore the ordinary exception handler just call
<function>GL_EXCEPTION_HANDLER</function> again.
</para>
<para>
WGL, AGL, etc. need their own OS specific exception handler, so you'll
need use the SWIG <command>%except</command> command. Look at the <classname>WGL</classname> module for an
example.
</para>
</section>
</section>
</section>
</chapter>
<appendix id="changes">
<title>Changes</title>
<orderedlist id="changes-2.0.0.44">
<title>2.0.0.44</title>
<listitem>Fixed PyMem_Del -> PyObject_Del bug; Patch #455646.</listitem>
<listitem>Made <function>glDrawRangeElementsEXT</function> more like other array functions including adding decoration variants</listitem>
<listitem>Added some aliases for various extension initialization functions.</listitem>
<listitem>Added the GL_OML_subsample, GL_OML_resample, and GL_OML_interlace extensions</listitem>
<listitem>Fixed Numeric import bug in the interface_util library.</listitem>
<listitem>Added quaternion class.</listitem>
<listitem>Changed comments over to C style.</listitem>
<listitem>Fixed install bug which prevented installation of demos.</listitem>
</orderedlist>
<orderedlist id="changes-2.0.0.42beta">
<title>2.0.0.42beta</title>
<listitem>Added GL 1.0 compatibility.</listitem>
<listitem>Moved <filename>info.py</filename> into the new scripts directory</listitem>
<listitem>Added a "__build__" attribute to <filename>OpenGL/__init__.py</filename></listitem>
<listitem>Added the GL_EXT_texture_object, GL_EXT_polygon_offset, and the GL_EXT_vertex_array extensions</listitem>
<listitem>Made <function>glDrawElements</function> more like other array functions including adding decoration variants</listitem>
</orderedlist>
<orderedlist id="changes-2.0.0.40beta">
<title>2.0.0.40beta</title>
<listitem>
Fixed the export name of <function>gluPwlCurve</function> and <function>gluNurbsCurve</function>
</listitem>
<listitem>
Fixed mishandling of count parameter in <function>gluPwlCurve</function> and changed
the prototype to <function>gluPwlCurve(nobj, points, type)</function>.
</listitem>
<listitem>
Changed proto of <function>gluNurbsCurve</function> to <function>gluNurbsCurve(nobj, knot, ctlarray, type) -> None</function>
</listitem>
<listitem>
Changed prototype of <function>gluNurbsSurface</function> to <function>gluNurbsSurface(nobj, sknot, tknot, ctlarray, type) -> None</function>
</listitem>
<listitem>
Added initialization functions to extension modules.
</listitem>
<listitem>
Added the platform specific source <filename>platform.c</filename>
</listitem>
<listitem>
Killed the <classname>OpenGL.extensions</classname> module, no longer needed.
</listitem>
<listitem>
Added a <classname>trackball</classname> module.
</listitem>
</orderedlist>
<orderedlist id="changes-2.0.0.34b3">
<title>2.0.0.34b3</title>
<listitem>
Fixed the export name of <function>gluTessVertex</function>, was <function>_gluTessVertex</function>.
</listitem>
<listitem>
Fixed misuse of <function>PyObject_CallFunction</function> which resulted in wrong
number of arguments passed when only one argument was being passed
to a callback. Affected several functions in the GLU and GLUT
modules.
</listitem>
<listitem>
Added locking mechanism to <classname>GLUtesselator</classname> and <classname>GLUnurbs</classname> to prevent
user data from being collected by the garbage collector.
</listitem>
<listitem>
Fixed prototype of <function>gluUnProject4</function>, was missing <parameter>clipW</parameter> argument.
</listitem>
<listitem>
Fixed prototypes of <function>gluBuild1DMipmapLevels</function>, was missing some
arguments.
</listitem>
<listitem>
Fixed <function>gluNurbsCallbackData wrapper</function>, wrong object pointer cast.
</listitem>
<listitem>
Changed list separator in config files to <constant>os.pathsep</constant> instead of a
comma.
</listitem>
<listitem>
Fixed bug in <function>PyObject_Dimension</function> on non-Numeric arrays.
</listitem>
<listitem>
Fixed docstrings of <function>glTexImage2D</function>
</listitem>
<listitem>
<filename>setup.py</filename> now adds the current directory to the search path. Needed
since <command>build_py</command> has to execute various configure programs.
</listitem>
</orderedlist>
<orderedlist id="changes-2.0.0.27b2">
<title>2.0.0.27b2</title>
<listitem>
When testing for a <exceptionname>GLerror</exceptionname> an attempt is now made to verify that
the current context is valid. This avoids strange behavior like
<function>glutDestroyWindow</function> throwing <exceptionname>GLerror</exceptionname> when it is used to destroy the
current window. Also in 2.0b1 a maximum limit of 16 errors could
be return by <exceptionname>GLerror</exceptionname>. This was done to avoid infinite loop result
resulting from calls to <function>glGetError</function> without a valid context. This
is not needed anymore, so the hard-coded limit has been removed.
</listitem>
<listitem>
Fixed <varname>sys.argv</varname> bugs in knot and molehill demos.
</listitem>
<listitem>
Added short name aliases like <function>glTranslate</function> = <function>glTranslated</function>.
</listitem>
<listitem>
Fixed <function>glGetBooleanv</function>, now needs only one argument.
</listitem>
<listitem>
Added build number to setup.
</listitem>
<listitem>
The current version number of the entire <application>PyOpenGL</application> system is now
stored in <constant>__version__</constant>.
</listitem>
<listitem>
Fixed various Python 1.5/1.6 incompatibilities.
</listitem>
<listitem>
Fixed image routines which return packed images like
<function>glGetPolygonStipple</function>.
</listitem>
<listitem>
Added <function>glGetPolgonStippleub</function> and <function>glPolygonStippleub</function> to use arrays
instead of packed strings.
</listitem>
<listitem>
Fixed bugs in <function>glMap{1|2}{f|d}</function> in the automatic selection of
<parameter>ustride</parameter> and <parameter>vstride</parameter> arguments.
</listitem>
<listitem>
Fixed <function>glRenderMode</function> and <function>glSelectBuffer</function> to avoid the strange
behavior of <function>glSelectBuffer(0, NULL)</function> on some systems.
</listitem>
<listitem>
<function>glutInit</function> now raises TypeError if its single argument is not a
non-string sequence.
</listitem>
<listitem>
Removed the GL_EXT_polygon_offset extension since it is a standard
part of OpenGL 1.1 and some systems seem to define
GL_EXT_polygon_offset yet don't export <function>glPolygonOffsetEXT</function>.
</listitem>
<listitem>
Fixed bug in <function>glGetBooleanv</function> which caused it to return the wrong
number of values, i.e. not parameter specific.
</listitem>
<listitem>
Fixed a bug in WGL routines in which the previous error wasn't
cleared.
</listitem>
<listitem>
Added support for GLU 1.0 and 1.1 to support Mesa.
</listitem>
<listitem>
Added the <classname>info</classname> script.
</listitem>
<listitem>
Added new platform specific config files.
</listitem>
<listitem>
Fixed broken prototypes in <classname>GL.EXT.coordinate_frame</classname>,
<classname>GL.EXT.cull_vertex</classname>, <classname>GL.EXT.multi_draw_arrays</classname> and <classname>GL.EXT.fog_coord</classname>.
</listitem>
<listitem>
Changed the generation of shadow wrappers a bit and turned the <classname>GL</classname>
and <classname>GLU</classname> modules into shadow wrappers.
</listitem>
</orderedlist>
<orderedlist id="changes-2.0b1">
<title>2.0b1</title>
<listitem>
<classname>WGL</classname> modules now throw <exceptionname>WindowsError</exceptionname> (<exceptionname>OSError</exceptionname> for Python 2.0) on a
windows error.
</listitem>
<listitem>
Added <exceptionname>GLerror</exceptionname> to <classname>GL</classname> and <exceptionname>GLUerror</exceptionname> to <classname>GLU</classname>. <function>"except GLerror, e:"</function> now
works.
</listitem>
<listitem>
<exceptionname>GLerror</exceptionname> now handles multiple errors resulting from distributed
systems.
</listitem>
</orderedlist>
<orderedlist id="changes-2.0a4">
<title>2.0a4</title>
<listitem>
Made the viewport argument to <function>gluPickMatrix</function> a keyword.
</listitem>
<listitem>
Added a <function>glSelectWithCallback</function> function. This function is pretty
trivial since <function>glRenderMode</function> already returns a selection buffer. See
the release notes.
</listitem>
<listitem>
Made the order arguments to <function>glMap{1|2}{f|v}v</function> automatic and removed the
stride arguments.
</listitem>
<listitem>
Changed <exceptionname>GLexception</exceptionname> and <exceptionname>GLUexception</exceptionname> to <exceptionname>GLerror</exceptionname> and <exceptionname>GLUerror</exceptionname>.
</listitem>
<listitem>
Killed the <classname>RTS</classname> module.
</listitem>
<listitem>
Killed the <classname>GL.Autodesk.facet_arrays</classname> module. Doesn't look as though
it is possible to support it using the current memory management
model.
</listitem>
<listitem>
<function>glRenderMode</function> now returns the instance of <classname>glFeedbackBuffer</classname> or
<classname>glSelectBuffer</classname> instead of a copy. It also resets the GL's pointer
to the buffer to <constant>NULL</constant> after it's done.
</listitem>
<listitem>
Fixed build bug in which modules with the same name like
<classname>WGL.ARB.extensions_string</classname> and <classname>WGL.EXT.extensions_string</classname> had
conflicting obj names (really a work around for a distutils bug.)
</listitem>
<listitem>
Fixed <classname>WGL.EXT.extensions_string</classname> prototype and reference in
<filename>extensions.py</filename>
</listitem>
<listitem>
Removed <function>checkExtension</function> and <function>raiseExtension</function>.
</listitem>
<listitem>
Made considerable changes to the <classname>extensions</classname> module.
</listitem>
<listitem>
<exceptionname>GLerror</exceptionname> with a code of <constant>GL_INVALID_OPERATION</constant> is now thrown on an
attempt use an unsupported extension. This is done to match the
OpenGL 1.2 behavior of GL_ARB_imaging.
</listitem>
</orderedlist>
<orderedlist id="changes-2.0a3">
<title>2.0a3</title>
<listitem>
Improved font and menu code of <classname>GLUT</classname>.
</listitem>
<listitem>
Added the <classname>GLE</classname> module.
</listitem>
<listitem>
Fixed exported name of <function>gluNurbsSurface</function>, was <function>_gluNurbsSurface</function>.
</listitem>
<listitem>
Added <classname>RTS</classname> module and <filename>hello2rts</filename> demo.
</listitem>
<listitem>
The array code of <application>PyOpenGL</application> now works even if Numeric support was
compiled in, but Numeric is not found at runtime.
</listitem>
<listitem>
A <exceptionname>NotImplementedError</exceptionname> is thrown if an extension is not available
even on systems that use static extensions. If the extension is
available and <function>glGetProcAddress</function> fails then an <exceptionname>ImportError</exceptionname> is
thrown.
</listitem>
<listitem>
Fixed Joystick callback in GLUT 4.0 code (<parameter>poll_interval</parameter> parameter
was missing.)
</listitem>
<listitem>
Added support for preliminary GLUT 4.0 code. It's inclusion
depends on the macro <constant>GLUT_XLIB_IMPLEMENTATION</constant> not on the macro
<constant>GLUT_API_VERSION</constant> since <constant>GLUT_API_VERSION</constant> does not include the minor
version number.
</listitem>
<listitem>
Added <function>glTexSubImage1D{ub|b|us|s|ui|i|f|d}</function> and
<function>glTexSubImage2D{ub|b|us|s|ui|i|f|d}</function>
</listitem>
<listitem>
Added support for 3D and 4D texturing.
</listitem>
<listitem>
Added GLU 1.3 support.
</listitem>
<listitem>
Added lots more extensions (the running tally is now at 165.)
</listitem>
</orderedlist>
<orderedlist id="changes-2.0a2">
<title>2.0a2</title>
<listitem>
Changed the base class of <exceptionname>GLUexception</exceptionname> to <exceptionname>EnvironmentError</exceptionname> instead
of <exceptionname>Exception</exceptionname>
</listitem>
<listitem>
Added support for <function>glInterleavedArrays</function>.
</listitem>
<listitem>
Removed nonsense variants of <function>glVertexPointer</function>, etc. such as
<function>glVertexPointerub</function>. No corresponding GL calls exist.
</listitem>
<listitem>
Added collection of convenience functions (<function>glVertexd</function>, <function>glVertexf</function>,
etc.) to avoid silly calls like <function>glVertex3f([0, 1, 2])</function> or
<function>glColor4f(0, 1, 2, 3)</function>
</listitem>
<listitem>
Changed the exception thrown on an attempt to use an unsupported
extension to <exceptionname>NotImplementedError</exceptionname> instead of <exceptionname>ImportError</exceptionname>.
</listitem>
<listitem>
Added the module <classname>extensions</classname> which does various useful things like
getting the list of implemented or supported extensions.
</listitem>
<listitem>
Added extension support for <classname>GLU</classname>.
</listitem>
<listitem>
Removed <function>glGetError</function> since any <classname>GL</classname> error will now throw an instance
of <exceptionname>GLexception</exceptionname> which is derived from <exceptionname>EnvironmentError</exceptionname>.
</listitem>
<listitem>
Added multi-window support to <classname>GLUT</classname>. Window callbacks are now window
specific as per the specification.
</listitem>
<listitem>
Added <function>gluScaleImagef</function>, <function>glScaleImagei</function>, etc. to <classname>GLU</classname>.
</listitem>
<listitem>
Changed implementation of <classname>GLUnurbs</classname> and <classname>GLUquadric</classname> to match that of
<classname>GLUtesselator</classname> to prepare for addition of GLU 1.3 support.
</listitem>
<listitem>
The model view matrix, projection matrix, and viewport arguments
to <function>gluProject</function> and <function>gluUnProject</function> are now optional.
</listitem>
<listitem>
Added lots more extensions....
</listitem>
</orderedlist>
</appendix>
<appendix id="licenses">
<title>Licenses</title>
<para>
Forward Note: This forward is for informational purposes only.
</para>
<para>
The <application>PyOpenGL</application> project on SourceForge was started by David Ascher,
previous maintainer of the <application>PyOpenGL</application> package, to further development of
the binding while David was unable to continue such development. At
the time of the project's start, <application>PyOpenGL</application> was version 1.5.5. You can
find this version of the package on the downloads page of the project.
</para>
<para>
Because of this history, there are two licenses which pertain to the
library, both of which are "BSD Style" licenses (though with minor
variations in wording).
</para>
<para>
For all versions up to and including 1.5.5, the <link linkend="licenses-1.5.5">PyOpenGL 1.5.5 License</link>
is applicable.
</para>
<para>
For all versions greater than 1.5.5, both the <application>PyOpenGL</application> 1.5.5 License and
the <link linkend="licenses-1.5.6">PyOpenGL 1.5.6 License</link> are applicable.
</para>
<para>
For all versions of <application>PyOpenGL</application> greater than or equal to 2.0 the following
licenses also apply
</para>
<itemizedlist>
<listitem>the <link linkend="licenses-GLE">GLE License</link> applies to the GLE module</listitem>
<listitem>the <ulink url="http://oss.sgi.com/projects/FreeB">SGI Free Software License B</ulink> applies to GL and GLU modules</listitem>
<listitem>the <link linkend="licenses-PyGLUT">PyGLUT License</link> applies to the GLUT module since PyOpenGL's GLUT module is a derivative of PyGLUT.</listitem>
</itemizedlist>
<section id="licenses-1.5.5">
<title><application>PyOpenGL</application> 1.5.5 License</title>
<para>
Copyright &copy; 1997-1998 by James Hugunin, Cambridge MA, USA, Thomas
Schwaller, Munich, Germany and David Ascher, San Francisco CA, USA.
</para>
<para>
All Rights Reserved
</para>
<para>
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of James Hugunin, Thomas
Schwaller, or David Ascher not be used in advertising or publicity
pertaining to distribution of the software without specific, written
prior permission.
</para>
<para>
JAMES HUGUNIN, THOMAS SCHWALLER AND DAVID ASCHER DISCLAIM ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL JAMES
HUGUNIN, THOMAS SCHWALLER AND DAVID ASCHER BE LIABLE FOR ANY SPECIAL,
INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
</para>
</section>
<section id="licenses-1.5.6">
<title><application>PyOpenGL</application> 1.5.6 License</title>
<para>
<application>PyOpenGL</application> 1.5.6 is based on <application>PyOpenGL</application> 1.5.5, Copyright &copy; 1997-1998 by
James Hugunin, Cambridge MA, USA, Thomas Schwaller, Munich, Germany
and David Ascher, San Francisco CA, USA.
</para>
<para>
Contributors to the <application>PyOpenGL</application> project in addition to those listed above
include:
</para>
<itemizedlist>
<listitem>David Konerding</listitem>
<listitem>Soren Renner</listitem>
<listitem>Rene Liebscher</listitem>
<listitem>Randall Hopper</listitem>
<listitem>Michael Fletcher</listitem>
<listitem>Thomas Malik</listitem>
<listitem>Thomas Hamelryck</listitem>
<listitem>Jack Jansen</listitem>
<listitem>Michel Sanner</listitem>
</itemizedlist>
<para>
Contributors to the <application>PyOpenGL</application> 2 project in addition to those listed
above include:
</para>
<itemizedlist>
<listitem>Tarn Weisner Burton</listitem>
<listitem>Andrew Cox</listitem>
</itemizedlist>
<para>
<application>PyOpenGL</application> 1.5.6 Copyright &copy; 1997-1998, 2000-2001
</para>
<para>
All rights reserved.
</para>
<para>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
</para>
<orderedlist>
<listitem>
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
</listitem>
<listitem>
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
</listitem>
<listitem>
The names of the contributors may not be used to endorse or
promote products derived from this software without specific prior
written permission.
</listitem>
</orderedlist>
<para>
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
</para>
</section>
<section id="licenses-GLE">
<title>GLE License</title>
<para>
SOFTWARE AGREEMENT
</para>
<para>
PLEASE READ THIS AGREEMENT CAREFULLY BEFORE INSTALLING OR USING THIS
SOFTWARE. IF YOU INSTALL OR USE THIS SOFTWARE, YOU AGREE TO THESE
TERMS.
</para>
<para>
This software is owned by International Business Machines Corporation
("IBM"), or its subsidiaries or IBM's suppliers, and is copyrighted
and licensed, not sold. IBM retains title to the software, and grants
you a nonexclusive license for the software.
</para>
<para>
Under this license, you may:
</para>
<orderedlist>
<listitem>
use the software on one or more machines at a time;
</listitem>
<listitem>
make copies of the software for use or backup purposes within your enterprise;
</listitem>
<listitem>
modify this software and merge it with another program; and
</listitem>
<listitem>
make copies of the original file you downloaded and distribute it, 
provided that you transfer a copy of this license to the other
party.
</listitem>
</orderedlist>
<para>
The other party agrees to these terms by its first use of this
software.
</para>
<para>
You must reproduce the copyright notice and any other legend of
ownership on each copy or partial copy of the software.
</para>
<para>
This software, as provided by IBM, is only intended to assist in the
development of a working software program. The software may not
function as written: additional code is required. In addition, the
software may not compile and/or bind successfully as written.
</para>
<para>
IBM PROVIDES THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESS 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 SOFTWARE IS
WITH YOU. SHOULD ANY PART OF THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME
THE ENTIRE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. IN
NO EVENT, UNLESS REQUIRED BY APPLICABLE LAW, SHALL IBM BE LIABLE TO
YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
SOFTWARE (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 SOFTWARE TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
IBM HAS BEEN ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.
</para>
<para>
IBM does not warrant that the contents of the software will meet your
requirements, that the software is error-free or that the software
does not infringe on any intellectual property rights of any third
party.
</para>
<para>
IBM may make improvements and/or changes in the software at any time.
</para>
<para>
Changes may or may not be made periodically to the information in the
software; these changes may be reported, for the software included
herein, in new editions.
</para>
<para>
References, if any, in the software to IBM products, programs, or
services do not imply that IBM intends to make these available in all
countries in which IBM operates. Any reference to an IBM licensed
program in the software is not intended to state or imply that only
IBM's licensed program may be used. Any functionally equivalent
program may be used.
</para>
<para>
The laws of New York State govern this agreement.
</para>
</section>
<section id="licenses-PyGLUT">
<title>PyGLUT License</title>
<para>
PyGLUT file is derived from the glut.h distributed with GLUT 3.7. 
It is a complete wrapper for GLUT API version 4 (provisional) including the 
game functionality. 
</para>
<para>
The conversion to a SWIG interface file was done by <ulink url="mailto:acox@globalnet.co.uk">Andrew Cox</ulink>.
</para>
<para>
I (Andrew Cox) place no additional limitations on what can be done with the contents of 
this file beyond those it inherits from GLUT. 
</para>
<formalpara>
DISCLAIMER:
<para>
PyGlut is provided AS IS without warranty of any kind, either express or 
implied, including but not limited to the implied warranties of 
merchantability and fitness for a particular purpose. In no event shall 
Andrew Cox be liable for any damages whatsoever including direct, indirect, 
incidental, consequential, loss of business profits or special damages, 
even if Andrew Cox has been advised of the possibility of such damages.
</para>
</formalpara>
<para>Copyright &copy; Mark J. Kilgard, 1994, 1995, 1996, 1998.</para>
<para>
This program is freely distributable without licensing fees  and is
provided without guarantee or warrantee expressed or  implied. This
program is -not- in the public domain.
</para>
</section>
</appendix>
</book>
