Perl OpenGL Module Tutorial
===========================
If you have some OpenGL experience then doing OpenGL from perl will be very
easy for you since there is little difference between calling an OpenGL
function from C than from perl. Alternatively, if you are new to OpenGL then
what you learn here will be beneficial should you do some graphics
programming in C someday. Anyways, you should have no problem using existing
man pages, books, and other OpenGL documentation. Looking through some of
the examples should also be very helpful.

First Example
-------------
The following program "simple" can be found in the examples directory:

        #!/usr/local/bin/perl
        #
        # simple example taken from listing 1-1 (or 1-2) from OpenGL book
        #

        BEGIN{ unshift(@INC,"../blib");} # in case OpenGL is built but not installed
	BEGIN{ unshift(@INC,"../blib/lib");}
	BEGIN{ unshift(@INC,"../blib/arch");}
        use OpenGL;

        glpOpenWindow;
        glClearColor(0,0,1,1);
        glClear(GL_COLOR_BUFFER_BIT);
        glLoadIdentity;
        glOrtho(-1,1,-1,1,-1,1);

        glColor3f(1,0,0);
        glBegin(GL_POLYGON);
          glVertex2f(-0.5,-0.5);
          glVertex2f(-0.5, 0.5);
          glVertex2f( 0.5, 0.5);
          glVertex2f( 0.5,-0.5);
        glEnd();
        glFlush();

        print "Program 1-1 Simple, hit control-D to quit:\n\n";
        while(<>){;}

This example was adapted from "OpenGL Programming Guide" page 6. This
program opens a window and draws a square.


Invoking Perl
-------------
The first line

        #!/usr/local/bin/perl

allows this program to be run as:

        simple

provided perl is in /usr/local/bin and simple has execute permission. Unless
your security paranoid and dont have "." in your $PATH, in which case you
can try:

        ./simple

Alternatively, the program can be run:

        perl simple


Including the Module
--------------------
The next lines:

        BEGIN{ unshift(@INC,"../blib"); }
        BEGIN{ unshift(@INC,"../blib/lib");}
        BEGIN{ unshift(@INC,"../blib/arch");}

is present in the example so that the program can find the compiled module
if OpenGL is built but not installed. i.e. you did a "make" but not a "make
install" when making the OpenGL module. "make" builds the module in the blib
directory. You can take this line out if the module is installed.

The following line:

        use OpenGL;

causes the program to include the OpenGL module.


Opening A Window
----------------
The line:

        glpOpenWindow;

opens up a window at the default size (500x500), creates a glX context,
etc.. This subroutine is not a standard OpenGL function. It was added as a
convienence routine for this module (hence the "glp" prefix). Your life is
easier this way :-)


Drawing Stuff
-------------
Next, a bunch of OpenGL functions are called to draw stuff in the window.
See the man pages for these functions to improve your understanding.

The lines:

        glClearColor(0,0,1,1);
        glClear(GL_COLOR_BUFFER_BIT);

clear the window to blue. The arguments to glClearColor are floats (actually
type GLclampf) but you dont have to put "0.0" instead of just "0". The
argument to glClear, GL_COLOR_BUFFER_BIT, is actually a perl subroutine. It
just returns the value 0x00004000, which, if you look at
/usr/include/GL/gl.h, is the correct value for this flag. This is how all
the constants (things created with "#define") in the header files are made
available to you.

The line:

        glOrtho(-1,1,-1,1,-1,1);

defines the boundaries of the window. The bottom left is (-1,-1) and the
upper right is (1,1).

the lines

        glColor3f(1,0,0);

sets the drawing color to red.

The sqare is drawn by:

        glBegin(GL_POLYGON);
          glVertex2f(-0.5,-0.5);
          glVertex2f(-0.5, 0.5);
          glVertex2f( 0.5, 0.5);
          glVertex2f( 0.5,-0.5);
        glEnd();

Because this is perl, it is unnecessary to put the "()" after functions like
glEnd().

Finally:

        glFlush();

ensures that all previous OpenGL commands are flushed to the graphics
hardware.

Note that these 11 lines of code (from glClearColor to glFlush) look like
they could have come out of a C program.



Hang Around
-----------
The last lines are:

        print "Program 1-1 Simple, hit control-D to quit:\n\n";
        while(<>){;}

As you can see, this program just blocks on stdin and doesn't do anything.
One problem here is that the program does not respond to X events (window
expose, resize, etc.).

This concludes the analysis of the "simple" example. See some of the other
examples for other aspects of using the OpenGL module.



Passing Pointers
----------------
For functions that have pointers as arguments you must properly pack() data
to feed the function:

        $light_diffuse = pack("f4", 1.0, 1.0, 1.0, 1.0 );
        glLightfv(GL_LIGHT0, GL_DIFFUSE, $light_diffuse);
        glLightfv(GL_LIGHT0, GL_AMBIENT, pack("f4", 0.0, 0.0, 0.0, 1.0 ));

Errors in packing will not be detected by the perl compiler (i.e. not found
when program first loaded).

Wherever possible use the non-vector version of the function. i.e. use:

        glVertex2d(1,2);

instead of:

        glVertex2dv(pack("f2",1,2));

Note that the following calls to glVertex2d:

        glVertex2d(1,2);

and

        @v=(1,2);
        glVertex2d(@v);

are equivalent. In other words, in perl arrays are passed by putting each
array element on the subroutine call stack.

For the next release of this module, things may change so that array
references are passed instead.



Convienence Routines
--------------------
For some functions, such as glClipPlane(Glenum,GLdouble *), we created a
non-vector version, glpClipPlane(Glenum,GLdouble,GLdouble,GLdouble,GLdouble)
that works better (no packing) from perl. Use these when available.



glpOpenWindow
-------------
In version 0.3 of the module, glpOpenWindow accepts an optional associative
array as argument to change the defaults of the window.
                           glpOpenWindow arguments

    key           default                         purpose
 x          0                    x location of window origin within parent
 y          0                    y location of window origin within parent
 width      500                  width of window
 height     500                  height of window

 parent     0                    id of parent window (0 means use root
                                 window)
 mask       StructureNotifyMask  X event input mask
 attributes [GLX_RGBA]           reference to list of glx window attributes


----------------------------------------------------------------------------

