NAME
	  fgluTessCallback - define a callback for a tessellation
	  object


     FORTRAN SPECIFICATION
	  SUBROUTINE fgluTessCallback( CHARACTER*8 tess,
				       INTEGER*4 which,
				       CHARACTER*8 (CallBackFunc)( )


     PARAMETERS
	  tess		Specifies the tessellation object (created
			with fgluNewTess).

	  which		Specifies the callback being defined. The
			following values are valid:  GLU_TESS_BEGIN,
			GLU_TESS_BEGIN_DATA, GLU_TESS_EDGE_FLAG,
			GLU_TESS_EDGE_FLAG_DATA, GLU_TESS_VERTEX,
			GLU_TESS_VERTEX_DATA, GLU_TESS_END,
			GLU_TESS_END_DATA, GLU_TESS_COMBINE,
			GLU_TESS_COMBINE_DATA, GLU_TESS_ERROR, and
			GLU_TESS_ERROR_DATA.

	  CallBackFunc	Specifies the function to be called.

     DESCRIPTION
	  fgluTessCallback is used to indicate a callback to be	used
	  by a tessellation object.  If	the specified callback is
	  already defined, then	it is replaced.	If CallBackFunc	is
	  NULL,	then the existing callback becomes undefined.

	  These	callbacks are used by the tessellation object to
	  describe how a polygon specified by the user is broken into
	  triangles. Note that there are two versions of each
	  callback: one	with user-specified polygon data and one
	  without. If both versions of a particular callback are
	  specified, then the callback with user-specified polygon
	  data will be used. Note that the polygon_data	parameter used
	  by some of the functions is a	copy of	the pointer that was
	  specified when fgluTessBeginPolygon was called. The legal
	  callbacks are	as follows:

	  GLU_TESS_BEGIN
		    The	begin callback is invoked like glBegin to
		    indicate the start of a (triangle) primitive. The
		    function takes a single argument of	type GLenum.
		    If the GLU_TESS_BOUNDARY_ONLY property is set to
		    GL_FALSE, then the argument	is set to either
		    GL_TRIANGLE_FAN, GL_TRIANGLE_STRIP,	or
		    GL_TRIANGLES. If the GLU_TESS_BOUNDARY_ONLY
		    property is	set to GL_TRUE,	then the argument will
		    be set to GL_LINE_LOOP. The	function prototype for
		    this callback is:
		    void begin ( GLenum	type );

	  GLU_TESS_BEGIN_DATA
		    The	same as	the GLU_TESS_BEGIN callback except
		    that it takes an additional	pointer	argument. This
		    pointer is identical to the	opaque pointer
		    provided when fgluTessBeginPolygon was called. The
		    function prototype for this	callback is:
		    void beginData ( GLenum type, void *polygon_data
		    );

	  GLU_TESS_EDGE_FLAG
		    The	edge flag callback is similar to glEdgeFlag.
		    The	function takes a single	boolean	flag that
		    indicates which edges lie on the polygon boundary.
		    If the flag	is GL_TRUE, then each vertex that
		    follows begins an edge that	lies on	the polygon
		    boundary, that is, an edge that separates an
		    interior region from an exterior one.  If the flag
		    is GL_FALSE, then each vertex that follows begins
		    an edge that lies in the polygon interior. The
		    edge flag callback (if defined) is invoked before
		    the	first vertex callback.

		    Since triangle fans	and triangle strips do not
		    support edge flags,	the begin callback is not
		    called with	GL_TRIANGLE_FAN	or GL_TRIANGLE_STRIP
		    if a non-NULL edge flag callback is	provided. (If
		    the	callback is initialized	to NULL, there is no
		    impact on performance). Instead, the fans and
		    strips are converted to independent	triangles. The
		    function prototype for this	callback is:
		    void edgeFlag ( GLboolean flag );

	  GLU_TESS_EDGE_FLAG_DATA
		    The	same as	the GLU_TESS_EDGE_FLAG callback	except
		    that it takes an additional	pointer	argument. This
		    pointer is identical to the	opaque pointer
		    provided when fgluTessBeginPolygon was called. The
		    function prototype for this	callback is:
		    void edgeFlagData (	GLboolean flag,	void
		    *polygon_data );

	  GLU_TESS_VERTEX
		    The	vertex callback	is invoked between the begin
		    and	end callbacks.	It is similar to glVertex, and
		    it defines the vertices of the triangles created
		    by the tessellation	process. The function takes a
		    pointer as its only	argument.  This	pointer	is
		    identical to the opaque pointer provided by	the
		    user when the vertex was described (see
		    fgluTessVertex). The function prototype for	this
		    callback is:
		    void vertex	( void *vertex_data );

	  GLU_TESS_VERTEX_DATA
		    The	same as	the GLU_TESS_VERTEX callback except
		    that it takes an additional	pointer	argument. This
		    pointer is identical to the	opaque pointer
		    provided when fgluTessBeginPolygon was called. The
		    function prototype for this	callback is:
		    void vertexData ( void *vertex_data, void
		    *polygon_data );

	  GLU_TESS_END
		    The	end callback serves the	same purpose as	glEnd.
		    It indicates the end of a primitive	and it takes
		    no arguments. The function prototype for this
		    callback is:
		    void end ( void );

	  GLU_TESS_END_DATA
		    The	same as	the GLU_TESS_END callback except that
		    it takes an	additional pointer argument. This
		    pointer is identical to the	opaque pointer
		    provided when fgluTessBeginPolygon was called. The
		    function prototype for this	callback is:
		    void endData ( void	*polygon_data);

	  GLU_TESS_COMBINE
		    The	combine	callback is called to create a new
		    vertex when	the tessellation detects an
		    intersection, or wishes to merge features. The
		    function takes four	arguments: an array of three
		    elements each of type GLdouble, an array of	four
		    pointers, an array of four elements	each of	type
		    GLfloat, and a pointer to a	pointer. The prototype
		    is:
		    void combine( GLdouble coords[3], void
		    *vertex_data[4],
				  GLfloat weight[4], void **outData );

		    The	vertex is defined as a linear combination of
		    up to four existing	vertices, stored in
		    vertex_data. The coefficients of the linear
		    combination	are given by weight; these weights
		    always add up to 1.	 All vertex pointers are valid
		    even when some of the weights are 0.  coords gives
		    the	location of the	new vertex.

		    The	user must allocate another vertex, interpolate
		    parameters using vertex_data and weight, and
		    return the new vertex pointer in outData. This
		    handle is supplied during rendering	callbacks.
		    The	user is	responsible for	freeing	the memory
		    some time after fgluTessEndPolygon is called.

		    For	example, if the	polygon	lies in	an arbitrary
		    plane in 3-space, and a color is associated	with
		    each vertex, the GLU_TESS_COMBINE callback might
		    look like this:
		    void myCombine( GLdouble coords[3],	VERTEX *d[4],
				    GLfloat w[4], VERTEX **dataOut ) {
		       VERTEX *new = new_vertex();

		       new->x =	coords[0];
		       new->y =	coords[1];
		       new->z =	coords[2];
		       new->r =	w[0]*d[0]->r + w[1]*d[1]->r +
		    w[2]*d[2]->r + w[3]*d[3]->r;
		       new->g =	w[0]*d[0]->g + w[1]*d[1]->g +
		    w[2]*d[2]->g + w[3]*d[3]->g;
		       new->b =	w[0]*d[0]->b + w[1]*d[1]->b +
		    w[2]*d[2]->b + w[3]*d[3]->b;
		       new->a =	w[0]*d[0]->a + w[1]*d[1]->a +
		    w[2]*d[2]->a + w[3]*d[3]->a;
		       *dataOut	= new; }

		    If the tessellation	detects	an intersection, then
		    the	GLU_TESS_COMBINE or GLU_TESS_COMBINE_DATA
		    callback (see below) must be defined, and it must
		    write a non-NULL pointer into dataOut. Otherwise
		    the	GLU_TESS_NEED_COMBINE_CALLBACK error occurs,
		    and	no output is generated.

	  GLU_TESS_COMBINE_DATA
		    The	same as	the GLU_TESS_COMBINE callback except
		    that it takes an additional	pointer	argument. This
		    pointer is identical to the	opaque pointer
		    provided when fgluTessBeginPolygon was called. The
		    function prototype for this	callback is:
		    void combineData ( GLdouble	coords[3], void
		    *vertex_data[4],
				       GLfloat weight[4], void
		    **outData,
				       void *polygon_data );

	  GLU_TESS_ERROR
		    The	error callback is called when an error is
		    encountered. The one argument is of	type GLenum;
		    it indicates the specific error that occurred and
		    will be set	to one of
		    GLU_TESS_MISSING_BEGIN_POLYGON,
		    GLU_TESS_MISSING_END_POLYGON,
		    GLU_TESS_MISSING_BEGIN_CONTOUR,
		    GLU_TESS_MISSING_END_CONTOUR,
		    GLU_TESS_COORD_TOO_LARGE,
		    GLU_TESS_NEED_COMBINE_CALLBACK or
		    GLU_OUT_OF_MEMORY. Character strings describing
		    these errors can be	retrieved with the
		    fgluErrorString call. The function prototype for
		    this callback is:
		    void error ( GLenum	errno );

		    The	GLU library will recover from the first	four
		    errors by inserting	the missing call(s).
		    GLU_TESS_COORD_TOO_LARGE indicates that some
		    vertex coordinate exceeded the predefined constant
		    GLU_TESS_MAX_COORD in absolute value, and that the
		    value has been clamped. (Coordinate	values must be
		    small enough so that two can be multiplied
		    together without overflow.)
		    GLU_TESS_NEED_COMBINE_CALLBACK indicates that the
		    tessellation detected an intersection between two
		    edges in the input data, and the GLU_TESS_COMBINE
		    or GLU_TESS_COMBINE_DATA callback was not
		    provided. No output	is generated.
		    GLU_OUT_OF_MEMORY indicates	that there is not
		    enough memory so no	output is generated.

	  GLU_TESS_ERROR_DATA
		    The	same as	the GLU_TESS_ERROR callback except
		    that it takes an additional	pointer	argument. This
		    pointer is identical to the	opaque pointer
		    provided when fgluTessBeginPolygon was called. The
		    function prototype for this	callback is:
		    void errorData ( GLenum errno, void	*polygon_data
		    );

     EXAMPLE
	  Polygons tessellated can be rendered directly	like this:

	  gluTessCallback(tobj,	GLU_TESS_BEGIN,	glBegin);
	  gluTessCallback(tobj,	GLU_TESS_VERTEX, glVertex3dv);
	  gluTessCallback(tobj,	GLU_TESS_END, glEnd);
	  gluTessCallback(tobj,	GLU_TESS_COMBINE, myCombine);
	  gluTessBeginPolygon(tobj, NULL);
	    gluTessBeginContour(tobj);
	      gluTessVertex(tobj, v, v);
	      ...
	    gluTessEndContour(tobj); gluTessEndPolygon(tobj);

	  Typically, the tessellated polygon should be stored in a
	  display list so that it does not need	to be retessellated
	  every	time it	is rendered.

     SEE ALSO
	  glBegin, glEdgeFlag, glVertex, fgluNewTess, fgluErrorString,
	  fgluTessVertex, fgluTessBeginPolygon,	fgluTessBeginContour,
	  fgluTessProperty, fgluTessNormal