--- libglu-9.0.0.orig/autogen.sh +++ libglu-9.0.0/autogen.sh @@ -0,0 +1,6 @@ +#! /bin/sh + +test -n "$srcdir" || srcdir=`dirname "$0"` +test -n "$srcdir" || srcdir=. +autoreconf --force --install --verbose "$srcdir" +test -n "$NOCONFIGURE" || "$srcdir/configure" "$@" --- libglu-9.0.0.orig/configure.ac +++ libglu-9.0.0/configure.ac @@ -42,9 +42,10 @@ AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], [Enable debugging information]), - [CFLAGS="$CFLAGS -g -O0" - CXXFLAGS="$CXXFLAGS -g -O0"], - []) + [CFLAGS="$CFLAGS -g -O0 -DDEBUG" + CXXFLAGS="$CXXFLAGS -g -O0 -DDEBUG"], + [CFLAGS="$CFLAGS -DNDEBUG" + CXXFLAGS="$CXXFLAGS -DNDEBUG"]) dnl Make sure the pkg-config macros are defined m4_ifndef([PKG_PROG_PKG_CONFIG], --- libglu-9.0.0.orig/debian/changelog +++ libglu-9.0.0/debian/changelog @@ -0,0 +1,24 @@ +libglu (9.0.0-2) unstable; urgency=low + + [ Julien Cristau ] + * Note in debian/copyright that we use version 2.0 of the SGI FreeB license. + Thanks, Ansgar Burchardt! + + [ Andreas Boll ] + * Disable silent rules. + * Cherry-pick commit 0692115 (Add -D(N)DEBUG to CFLAGS dependent on -- + enable-debug) from upstream (Closes: #723577) + + -- Cyril Brulebois Thu, 19 Sep 2013 22:23:50 +0200 + +libglu (9.0.0-1) unstable; urgency=low + + * Team upload. + + [ Timo Aaltonen ] + * First release, split from upstream mesa repo. + + [ Emilio Pozuelo Monfort ] + * Upload to unstable. + + -- Emilio Pozuelo Monfort Sun, 09 Jun 2013 01:20:54 +0200 --- libglu-9.0.0.orig/debian/compat +++ libglu-9.0.0/debian/compat @@ -0,0 +1 @@ +9 --- libglu-9.0.0.orig/debian/control +++ libglu-9.0.0/debian/control @@ -0,0 +1,56 @@ +Source: libglu +Section: graphics +Priority: optional +Maintainer: Debian X Strike Force +Uploaders: Cyril Brulebois +Standards-Version: 3.9.3 +Build-Depends: + debhelper (>= 9), + dh-autoreconf, + pkg-config, + libgl1-mesa-dev, +Vcs-Git: git://git.debian.org/git/pkg-xorg/lib/libglu +Vcs-Browser: http://git.debian.org/?p=pkg-xorg/lib/libglu.git + +Package: libglu1-mesa +Section: libs +Architecture: any +Depends: + ${shlibs:Depends}, + ${misc:Depends}, +Provides: libglu1 +Conflicts: mesag3 (<< 5.0.0-1), xlibmesa3, libglu1 +Replaces: libglu1 +Pre-Depends: ${misc:Pre-Depends} +Multi-Arch: same +Description: Mesa OpenGL utility library (GLU) + GLU offers simple interfaces for building mipmaps; checking for the + presence of extensions in the OpenGL (or other libraries which follow + the same conventions for advertising extensions); drawing + piecewise-linear curves, NURBS, quadrics and other primitives + (including, but not limited to, teapots); tesselating surfaces; setting + up projection matrices and unprojecting screen coordinates to world + coordinates. + . + On Linux, this library is also known as libGLU or libGLU.so.1. + . + This package provides the SGI implementation of GLU provided by the + Mesa project (ergo the "-mesa" suffix). + +Package: libglu1-mesa-dev +Section: libdevel +Architecture: any +Depends: + libglu1-mesa (= ${binary:Version}), + libgl1-mesa-dev | libgl-dev, + ${misc:Depends}, +Provides: libglu-dev, xlibmesa-glu-dev +Conflicts: mesag-dev (<< 5.0.0-1), mesa-glide2-dev (<< 5.0.0-1), mesag3+ggi-dev (<< 5.0.0-1), xlibmesa-dev +Replaces: libglu-dev +Description: Mesa OpenGL utility library -- development files + Includes headers and static libraries for compiling programs with GLU. + . + For a complete description of GLU, please look at the libglu1-mesa + package. + +# vim: tw=0 --- libglu-9.0.0.orig/debian/copyright +++ libglu-9.0.0/debian/copyright @@ -0,0 +1,102 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: glu +Source: http://cgit.freedesktop.org/mesa/glu/ + +Files: * +Copyright: 1991-2000 Silicon Graphics, Inc. +License: SGI-2 + SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + . + Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + . + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal in + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + . + The above copyright notice including the dates of first publication and either + this permission notice or a reference to http://oss.sgi.com/projects/FreeB/ + shall be included in all copies or substantial portions of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. + . + Except as contained in this notice, the name of Silicon Graphics, Inc. shall + not be used in advertising or otherwise to promote the sale, use or other + dealings in this Software without prior written authorization from Silicon + Graphics, Inc. + +Files: src/libnurbs/internals/*.cc +Copyright: 1991-2000 Silicon Graphics, Inc. +License: SGI-1.1 + License Applicability. Except to the extent portions of this file are + made subject to an alternative license as permitted in the SGI Free + Software License B, Version 1.1 (the "License"), the contents of this + file are subject only to the provisions of the License. You may not use + this file except in compliance with the License. You may obtain a copy + of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + . + http://oss.sgi.com/projects/FreeB + . + Note that, as provided in the License, the Software is distributed on an + "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + . + Original Code. The Original Code is: OpenGL Sample Implementation, + Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + Copyright in any portions created by third parties is as indicated + elsewhere herein. All Rights Reserved. +Comment: + The SGI FreeB license version 1.1 allows the Recipient to choose to use + Covered Code under the terms of a subsequent version of the license. Debian + makes use of that possibility, using the 2.0 version as above. + +Files: include/GL/glu_mangle.h +Copyright: 1995-1998 Brian Paul +License: LGPL-2 + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + . + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + . + You should have received a copy of the GNU Library General Public + License along with this library; if not, see + . + On Debian systems, the complete text of the GNU Library General + Public License version 2 can be found in "/usr/share/common-licenses/LGPL-2". + +Files: debian/* +Copyright: 2012 Timo Aaltonen +License: GPL-2 + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + . + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see + . + On Debian systems, the complete text of the GNU General + Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". --- libglu-9.0.0.orig/debian/libglu1-mesa-dev.install.in +++ libglu-9.0.0/debian/libglu1-mesa-dev.install.in @@ -0,0 +1,5 @@ +usr/include/GL/glu.h +usr/include/GL/glu_mangle.h +usr/lib/${DEB_HOST_MULTIARCH}/libGLU.a +usr/lib/${DEB_HOST_MULTIARCH}/libGLU.so +usr/lib/${DEB_HOST_MULTIARCH}/pkgconfig/glu.pc --- libglu-9.0.0.orig/debian/libglu1-mesa.install.in +++ libglu-9.0.0/debian/libglu1-mesa.install.in @@ -0,0 +1 @@ +usr/lib/${DEB_HOST_MULTIARCH}/libGLU.so.* --- libglu-9.0.0.orig/debian/libglu1-mesa.lintian-overrides +++ libglu-9.0.0/debian/libglu1-mesa.lintian-overrides @@ -0,0 +1 @@ +package-name-doesnt-match-sonames libGLU1 --- libglu-9.0.0.orig/debian/libglu1-mesa.shlibs +++ libglu-9.0.0/debian/libglu1-mesa.shlibs @@ -0,0 +1 @@ +libGLU 1 libglu1-mesa | libglu1 --- libglu-9.0.0.orig/debian/rules +++ libglu-9.0.0/debian/rules @@ -0,0 +1,30 @@ +#!/usr/bin/make -f + +DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) + +override_dh_auto_configure: + dh_auto_configure -- --disable-silent-rules + +override_dh_clean: + for file in debian/*.in; do rm -f $${file%%.in}; done + dh_clean + +override_dh_install: + for file in debian/*.in; \ + do \ + sed -e"s,\$${DEB_HOST_MULTIARCH},$(DEB_HOST_MULTIARCH),g" \ + $${file} > $${file%%.in}; \ + done + + # purge .la files + find debian/tmp/ -name '*.la' -exec rm '{}' ';' + + dh_install --fail-missing + +%: + dh $@ --with autoreconf --builddirectory=build/ + +gentarball: SOURCE=libglu +gentarball: UV=$(shell dpkg-parsechangelog|awk '/^Version:/ {print $$2}'|sed 's/-.*$$//') +gentarball: + git archive --format=tar upstream-unstable --prefix=$(SOURCE)-$(UV)/ | gzip -9 > ../$(SOURCE)_$(UV).orig.tar.gz --- libglu-9.0.0.orig/debian/watch +++ libglu-9.0.0/debian/watch @@ -0,0 +1,3 @@ +#git=git://anongit.freedesktop.org/mesa/glu +version=3 +ftp://freedesktop.org/pub/mesa/glu/ glu-(.*)\.tar\.gz --- libglu-9.0.0.orig/src/libtess/README +++ libglu-9.0.0/src/libtess/README @@ -0,0 +1,446 @@ +/* +*/ + +General Polygon Tesselation +--------------------------- + + This note describes a tesselator for polygons consisting of one or + more closed contours. It is backward-compatible with the current + OpenGL Utilities tesselator, and is intended to replace it. Here is + a summary of the major differences: + + - input contours can be intersecting, self-intersecting, or degenerate. + + - supports a choice of several winding rules for determining which parts + of the polygon are on the "interior". This makes it possible to do + CSG operations on polygons. + + - boundary extraction: instead of tesselating the polygon, returns a + set of closed contours which separate the interior from the exterior. + + - returns the output as a small number of triangle fans and strips, + rather than a list of independent triangles (when possible). + + - output is available as an explicit mesh (a quad-edge structure), + in addition to the normal callback interface. + + - the algorithm used is extremely robust. + + +The interface +------------- + + The tesselator state is maintained in a "tesselator object". + These are allocated and destroyed using + + GLUtesselator *gluNewTess( void ); + void gluDeleteTess( GLUtesselator *tess ); + + Several tesselator objects may be used simultaneously. + + Inputs + ------ + + The input contours are specified with the following routines: + + void gluTessBeginPolygon( GLUtesselator *tess ); + void gluTessBeginContour( GLUtesselator *tess ); + void gluTessVertex( GLUtesselator *tess, GLUcoord coords[3], void *data ); + void gluTessEndContour( GLUtesselator *tess ); + void gluTessEndPolygon( GLUtesselator *tess ); + + Within each BeginPolygon/EndPolygon pair, there can be zero or more + calls to BeginContour/EndContour. Within each contour, there are zero + or more calls to gluTessVertex(). The vertices specify a closed + contour (the last vertex of each contour is automatically linked to + the first). + + "coords" give the coordinates of the vertex in 3-space. For useful + results, all vertices should lie in some plane, since the vertices + are projected onto a plane before tesselation. "data" is a pointer + to a user-defined vertex structure, which typically contains other + information such as color, texture coordinates, normal, etc. It is + used to refer to the vertex during rendering. + + The library can be compiled in single- or double-precision; the type + GLUcoord represents either "float" or "double" accordingly. The GLU + version will be available in double-precision only. Compile with + GLU_TESS_API_FLOAT defined to get the single-precision version. + + When EndPolygon is called, the tesselation algorithm determines + which regions are interior to the given contours, according to one + of several "winding rules" described below. The interior regions + are then tesselated, and the output is provided as callbacks. + + + Rendering Callbacks + ------------------- + + Callbacks are specified by the client using + + void gluTessCallback( GLUtesselator *tess, GLenum which, void (*fn)()); + + If "fn" is NULL, any previously defined callback is discarded. + + The callbacks used to provide output are: /* which == */ + + void begin( GLenum type ); /* GLU_TESS_BEGIN */ + void edgeFlag( GLboolean flag ); /* GLU_TESS_EDGE_FLAG */ + void vertex( void *data ); /* GLU_TESS_VERTEX */ + void end( void ); /* GLU_TESS_END */ + + Any of the callbacks may be left undefined; if so, the corresponding + information will not be supplied during rendering. + + The "begin" callback indicates the start of a primitive; type is one + of GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, or GL_TRIANGLES (but see the + notes on "boundary extraction" below). + + It is followed by any number of "vertex" callbacks, which supply the + vertices in the same order as expected by the corresponding glBegin() + call. After the last vertex of a given primitive, there is a callback + to "end". + + If the "edgeFlag" callback is provided, no triangle fans or strips + will be used. When edgeFlag is called, if "flag" is GL_TRUE then each + vertex which follows begins an edge which lies on the polygon boundary + (ie. an edge which separates an interior region from an exterior one). + If "flag" is GL_FALSE, each vertex which follows begins an edge which lies + in the polygon interior. "edgeFlag" will be called before the first + call to "vertex". + + Other Callbacks + --------------- + + void mesh( GLUmesh *mesh ); /* GLU_TESS_MESH */ + + - Returns an explicit mesh, represented using the quad-edge structure + (Guibas/Stolfi '85). Other implementations of this interface might + use a different mesh structure, so this is available only only as an + SGI extension. When the mesh is no longer needed, it should be freed + using + + void gluDeleteMesh( GLUmesh *mesh ); + + There is a brief description of this data structure in the include + file "mesh.h". For the full details, see L. Guibas and J. Stolfi, + Primitives for the manipulation of general subdivisions and the + computation of Voronoi diagrams, ACM Transactions on Graphics, + 4(2):74-123, April 1985. For an introduction, see the course notes + for CS348a, "Mathematical Foundations of Computer Graphics", + available at the Stanford bookstore (and taught during the fall + quarter). + + void error( GLenum errno ); /* GLU_TESS_ERROR */ + + - errno is 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 + + The first four are obvious. The interface recovers from these + errors by inserting the missing call(s). + + GLU_TESS_COORD_TOO_LARGE says 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 says that the algorithm detected an + intersection between two edges in the input data, and the "combine" + callback (below) was not provided. No output will be generated. + + + void combine( GLUcoord coords[3], void *data[4], /* GLU_TESS_COMBINE */ + GLUcoord weight[4], void **outData ); + + - When the algorithm detects an intersection, or wishes to merge + features, it needs to create a new vertex. The vertex is defined + as a linear combination of up to 4 existing vertices, referenced + by data[0..3]. The coefficients of the linear combination are + given by weight[0..3]; these weights always sum to 1.0. All vertex + pointers are valid even when some of the weights are zero. + "coords" gives the location of the new vertex. + + The user must allocate another vertex, interpolate parameters + using "data" and "weights", and return the new vertex pointer in + "outData". This handle is supplied during rendering callbacks. + For example, if the polygon lies in an arbitrary plane in 3-space, + and we associate a color with each vertex, the combine callback might + look like this: + + void myCombine( GLUcoord coords[3], VERTEX *d[4], + GLUcoord 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 algorithm detects an intersection, then the "combine" callback + must be defined, and must write a non-NULL pointer into "dataOut". + Otherwise the GLU_TESS_NEED_COMBINE_CALLBACK error occurs, and no + output is generated. This is the only error that can occur during + tesselation and rendering. + + + Control over Tesselation + ------------------------ + + void gluTessProperty( GLUtesselator *tess, GLenum which, GLUcoord value ); + + Properties defined: + + - GLU_TESS_WINDING_RULE. Possible values: + + GLU_TESS_WINDING_ODD + GLU_TESS_WINDING_NONZERO + GLU_TESS_WINDING_POSITIVE + GLU_TESS_WINDING_NEGATIVE + GLU_TESS_WINDING_ABS_GEQ_TWO + + The input contours parition the plane into regions. A winding + rule determines which of these regions are inside the polygon. + + For a single contour C, the winding number of a point x is simply + the signed number of revolutions we make around x as we travel + once around C (where CCW is positive). When there are several + contours, the individual winding numbers are summed. This + procedure associates a signed integer value with each point x in + the plane. Note that the winding number is the same for all + points in a single region. + + The winding rule classifies a region as "inside" if its winding + number belongs to the chosen category (odd, nonzero, positive, + negative, or absolute value of at least two). The current GLU + tesselator implements the "odd" rule. The "nonzero" rule is another + common way to define the interior. The other three rules are + useful for polygon CSG operations (see below). + + - GLU_TESS_BOUNDARY_ONLY. Values: TRUE (non-zero) or FALSE (zero). + + If TRUE, returns a set of closed contours which separate the + polygon interior and exterior (rather than a tesselation). + Exterior contours are oriented CCW with respect to the normal, + interior contours are oriented CW. The GLU_TESS_BEGIN callback + uses the type GL_LINE_LOOP for each contour. + + - GLU_TESS_TOLERANCE. Value: a real number between 0.0 and 1.0. + + This specifies a tolerance for merging features to reduce the size + of the output. For example, two vertices which are very close to + each other might be replaced by a single vertex. The tolerance + is multiplied by the largest coordinate magnitude of any input vertex; + this specifies the maximum distance that any feature can move as the + result of a single merge operation. If a single feature takes part + in several merge operations, the total distance moved could be larger. + + Feature merging is completely optional; the tolerance is only a hint. + The implementation is free to merge in some cases and not in others, + or to never merge features at all. The default tolerance is zero. + + The current implementation merges vertices only if they are exactly + coincident, regardless of the current tolerance. A vertex is + spliced into an edge only if the implementation is unable to + distinguish which side of the edge the vertex lies on. + Two edges are merged only when both endpoints are identical. + + + void gluTessNormal( GLUtesselator *tess, + GLUcoord x, GLUcoord y, GLUcoord z ) + + - Lets the user supply the polygon normal, if known. All input data + is projected into a plane perpendicular to the normal before + tesselation. All output triangles are oriented CCW with + respect to the normal (CW orientation can be obtained by + reversing the sign of the supplied normal). For example, if + you know that all polygons lie in the x-y plane, call + "gluTessNormal(tess, 0.0, 0.0, 1.0)" before rendering any polygons. + + - If the supplied normal is (0,0,0) (the default value), the + normal is determined as follows. The direction of the normal, + up to its sign, is found by fitting a plane to the vertices, + without regard to how the vertices are connected. It is + expected that the input data lies approximately in plane; + otherwise projection perpendicular to the computed normal may + substantially change the geometry. The sign of the normal is + chosen so that the sum of the signed areas of all input contours + is non-negative (where a CCW contour has positive area). + + - The supplied normal persists until it is changed by another + call to gluTessNormal. + + + Backward compatibility with the GLU tesselator + ---------------------------------------------- + + The preferred interface is the one described above. The following + routines are obsolete, and are provided only for backward compatibility: + + typedef GLUtesselator GLUtriangulatorObj; /* obsolete name */ + + void gluBeginPolygon( GLUtesselator *tess ); + void gluNextContour( GLUtesselator *tess, GLenum type ); + void gluEndPolygon( GLUtesselator *tess ); + + "type" is one of GLU_EXTERIOR, GLU_INTERIOR, GLU_CCW, GLU_CW, or + GLU_UNKNOWN. It is ignored by the current GLU tesselator. + + GLU_BEGIN, GLU_VERTEX, GLU_END, GLU_ERROR, and GLU_EDGE_FLAG are defined + as synonyms for GLU_TESS_BEGIN, GLU_TESS_VERTEX, GLU_TESS_END, + GLU_TESS_ERROR, and GLU_TESS_EDGE_FLAG. + + +Polygon CSG operations +---------------------- + + The features of the tesselator make it easy to find the union, difference, + or intersection of several polygons. + + First, assume that each polygon is defined so that the winding number + is 0 for each exterior region, and 1 for each interior region. Under + this model, CCW contours define the outer boundary of the polygon, and + CW contours define holes. Contours may be nested, but a nested + contour must be oriented oppositely from the contour that contains it. + + If the original polygons do not satisfy this description, they can be + converted to this form by first running the tesselator with the + GLU_TESS_BOUNDARY_ONLY property turned on. This returns a list of + contours satisfying the restriction above. By allocating two + tesselator objects, the callbacks from one tesselator can be fed + directly to the input of another. + + Given two or more polygons of the form above, CSG operations can be + implemented as follows: + + Union + Draw all the input contours as a single polygon. The winding number + of each resulting region is the number of original polygons + which cover it. The union can be extracted using the + GLU_TESS_WINDING_NONZERO or GLU_TESS_WINDING_POSITIVE winding rules. + Note that with the nonzero rule, we would get the same result if + all contour orientations were reversed. + + Intersection (two polygons at a time only) + Draw a single polygon using the contours from both input polygons. + Extract the result using GLU_TESS_WINDING_ABS_GEQ_TWO. (Since this + winding rule looks at the absolute value, reversing all contour + orientations does not change the result.) + + Difference + + Suppose we want to compute A \ (B union C union D). Draw a single + polygon consisting of the unmodified contours from A, followed by + the contours of B,C,D with the vertex order reversed (this changes + the winding number of the interior regions to -1). To extract the + result, use the GLU_TESS_WINDING_POSITIVE rule. + + If B,C,D are the result of a GLU_TESS_BOUNDARY_ONLY call, an + alternative to reversing the vertex order is to reverse the sign of + the supplied normal. For example in the x-y plane, call + gluTessNormal( tess, 0.0, 0.0, -1.0 ). + + +Performance +----------- + + The tesselator is not intended for immediate-mode rendering; when + possible the output should be cached in a user structure or display + list. General polygon tesselation is an inherently difficult problem, + especially given the goal of extreme robustness. + + The implementation makes an effort to output a small number of fans + and strips; this should improve the rendering performance when the + output is used in a display list. + + Single-contour input polygons are first tested to see whether they can + be rendered as a triangle fan with respect to the first vertex (to + avoid running the full decomposition algorithm on convex polygons). + Non-convex polygons may be rendered by this "fast path" as well, if + the algorithm gets lucky in its choice of a starting vertex. + + For best performance follow these guidelines: + + - supply the polygon normal, if available, using gluTessNormal(). + This represents about 10% of the computation time. For example, + if all polygons lie in the x-y plane, use gluTessNormal(tess,0,0,1). + + - render many polygons using the same tesselator object, rather than + allocating a new tesselator for each one. (In a multi-threaded, + multi-processor environment you may get better performance using + several tesselators.) + + +Comparison with the GLU tesselator +---------------------------------- + + On polygons which make it through the "fast path", the tesselator is + 3 to 5 times faster than the GLU tesselator. + + On polygons which don't make it through the fast path (but which don't + have self-intersections or degeneracies), it is about 2 times slower. + + On polygons with self-intersections or degeneraces, there is nothing + to compare against. + + The new tesselator generates many more fans and strips, reducing the + number of vertices that need to be sent to the hardware. + + Key to the statistics: + + vert number of input vertices on all contours + cntr number of input contours + tri number of triangles in all output primitives + strip number of triangle strips + fan number of triangle fans + ind number of independent triangles + ms number of milliseconds for tesselation + (on a 150MHz R4400 Indy) + + Convex polygon examples: + +New: 3 vert, 1 cntr, 1 tri, 0 strip, 0 fan, 1 ind, 0.0459 ms +Old: 3 vert, 1 cntr, 1 tri, 0 strip, 0 fan, 1 ind, 0.149 ms +New: 4 vert, 1 cntr, 2 tri, 0 strip, 1 fan, 0 ind, 0.0459 ms +Old: 4 vert, 1 cntr, 2 tri, 0 strip, 0 fan, 2 ind, 0.161 ms +New: 36 vert, 1 cntr, 34 tri, 0 strip, 1 fan, 0 ind, 0.153 ms +Old: 36 vert, 1 cntr, 34 tri, 0 strip, 0 fan, 34 ind, 0.621 ms + + Concave single-contour polygons: + +New: 5 vert, 1 cntr, 3 tri, 0 strip, 1 fan, 0 ind, 0.052 ms +Old: 5 vert, 1 cntr, 3 tri, 0 strip, 0 fan, 3 ind, 0.252 ms +New: 19 vert, 1 cntr, 17 tri, 2 strip, 2 fan, 1 ind, 0.911 ms +Old: 19 vert, 1 cntr, 17 tri, 0 strip, 0 fan, 17 ind, 0.529 ms +New: 151 vert, 1 cntr, 149 tri, 13 strip, 18 fan, 3 ind, 6.82 ms +Old: 151 vert, 1 cntr, 149 tri, 0 strip, 3 fan, 143 ind, 2.7 ms +New: 574 vert, 1 cntr, 572 tri, 59 strip, 54 fan, 11 ind, 26.6 ms +Old: 574 vert, 1 cntr, 572 tri, 0 strip, 31 fan, 499 ind, 12.4 ms + + Multiple contours, but no intersections: + +New: 7 vert, 2 cntr, 7 tri, 1 strip, 0 fan, 0 ind, 0.527 ms +Old: 7 vert, 2 cntr, 7 tri, 0 strip, 0 fan, 7 ind, 0.274 ms +New: 81 vert, 6 cntr, 89 tri, 9 strip, 7 fan, 6 ind, 3.88 ms +Old: 81 vert, 6 cntr, 89 tri, 0 strip, 13 fan, 61 ind, 2.2 ms +New: 391 vert, 19 cntr, 413 tri, 37 strip, 32 fan, 26 ind, 20.2 ms +Old: 391 vert, 19 cntr, 413 tri, 0 strip, 25 fan, 363 ind, 8.68 ms + + Self-intersecting and degenerate examples: + +Bowtie: 4 vert, 1 cntr, 2 tri, 0 strip, 0 fan, 2 ind, 0.483 ms +Star: 5 vert, 1 cntr, 5 tri, 0 strip, 0 fan, 5 ind, 0.91 ms +Random: 24 vert, 7 cntr, 46 tri, 2 strip, 12 fan, 7 ind, 5.32 ms +Font: 333 vert, 2 cntr, 331 tri, 32 strip, 16 fan, 3 ind, 14.1 ms +: 167 vert, 35 cntr, 254 tri, 8 strip, 56 fan, 52 ind, 46.3 ms +: 78 vert, 1 cntr, 2675 tri, 148 strip, 207 fan, 180 ind, 243 ms +: 12480 vert, 2 cntr, 12478 tri, 736 strip,1275 fan, 5 ind, 1010 ms --- libglu-9.0.0.orig/src/libtess/alg-outline +++ libglu-9.0.0/src/libtess/alg-outline @@ -0,0 +1,228 @@ +/* +*/ + +This is only a very brief overview. There is quite a bit of +additional documentation in the source code itself. + + +Goals of robust tesselation +--------------------------- + +The tesselation algorithm is fundamentally a 2D algorithm. We +initially project all data into a plane; our goal is to robustly +tesselate the projected data. The same topological tesselation is +then applied to the input data. + +Topologically, the output should always be a tesselation. If the +input is even slightly non-planar, then some triangles will +necessarily be back-facing when viewed from some angles, but the goal +is to minimize this effect. + +The algorithm needs some capability of cleaning up the input data as +well as the numerical errors in its own calculations. One way to do +this is to specify a tolerance as defined above, and clean up the +input and output during the line sweep process. At the very least, +the algorithm must handle coincident vertices, vertices incident to an +edge, and coincident edges. + + +Phases of the algorithm +----------------------- + +1. Find the polygon normal N. +2. Project the vertex data onto a plane. It does not need to be + perpendicular to the normal, eg. we can project onto the plane + perpendicular to the coordinate axis whose dot product with N + is largest. +3. Using a line-sweep algorithm, partition the plane into x-monotone + regions. Any vertical line intersects an x-monotone region in + at most one interval. +4. Triangulate the x-monotone regions. +5. Group the triangles into strips and fans. + + +Finding the normal vector +------------------------- + +A common way to find a polygon normal is to compute the signed area +when the polygon is projected along the three coordinate axes. We +can't do this, since contours can have zero area without being +degenerate (eg. a bowtie). + +We fit a plane to the vertex data, ignoring how they are connected +into contours. Ideally this would be a least-squares fit; however for +our purpose the accuracy of the normal is not important. Instead we +find three vertices which are widely separated, and compute the normal +to the triangle they form. The vertices are chosen so that the +triangle has an area at least 1/sqrt(3) times the largest area of any +triangle formed using the input vertices. + +The contours do affect the orientation of the normal; after computing +the normal, we check that the sum of the signed contour areas is +non-negative, and reverse the normal if necessary. + + +Projecting the vertices +----------------------- + +We project the vertices onto a plane perpendicular to one of the three +coordinate axes. This helps numerical accuracy by removing a +transformation step between the original input data and the data +processed by the algorithm. The projection also compresses the input +data; the 2D distance between vertices after projection may be smaller +than the original 2D distance. However by choosing the coordinate +axis whose dot product with the normal is greatest, the compression +factor is at most 1/sqrt(3). + +Even though the *accuracy* of the normal is not that important (since +we are projecting perpendicular to a coordinate axis anyway), the +*robustness* of the computation is important. For example, if there +are many vertices which lie almost along a line, and one vertex V +which is well-separated from the line, then our normal computation +should involve V otherwise the results will be garbage. + +The advantage of projecting perpendicular to the polygon normal is +that computed intersection points will be as close as possible to +their ideal locations. To get this behavior, define TRUE_PROJECT. + + +The Line Sweep +-------------- + +There are three data structures: the mesh, the event queue, and the +edge dictionary. + +The mesh is a "quad-edge" data structure which records the topology of +the current decomposition; for details see the include file "mesh.h". + +The event queue simply holds all vertices (both original and computed +ones), organized so that we can quickly extract the vertex with the +minimum x-coord (and among those, the one with the minimum y-coord). + +The edge dictionary describes the current intersection of the sweep +line with the regions of the polygon. This is just an ordering of the +edges which intersect the sweep line, sorted by their current order of +intersection. For each pair of edges, we store some information about +the monotone region between them -- these are call "active regions" +(since they are crossed by the current sweep line). + +The basic algorithm is to sweep from left to right, processing each +vertex. The processed portion of the mesh (left of the sweep line) is +a planar decomposition. As we cross each vertex, we update the mesh +and the edge dictionary, then we check any newly adjacent pairs of +edges to see if they intersect. + +A vertex can have any number of edges. Vertices with many edges can +be created as vertices are merged and intersection points are +computed. For unprocessed vertices (right of the sweep line), these +edges are in no particular order around the vertex; for processed +vertices, the topological ordering should match the geometric ordering. + +The vertex processing happens in two phases: first we process are the +left-going edges (all these edges are currently in the edge +dictionary). This involves: + + - deleting the left-going edges from the dictionary; + - relinking the mesh if necessary, so that the order of these edges around + the event vertex matches the order in the dictionary; + - marking any terminated regions (regions which lie between two left-going + edges) as either "inside" or "outside" according to their winding number. + +When there are no left-going edges, and the event vertex is in an +"interior" region, we need to add an edge (to split the region into +monotone pieces). To do this we simply join the event vertex to the +rightmost left endpoint of the upper or lower edge of the containing +region. + +Then we process the right-going edges. This involves: + + - inserting the edges in the edge dictionary; + - computing the winding number of any newly created active regions. + We can compute this incrementally using the winding of each edge + that we cross as we walk through the dictionary. + - relinking the mesh if necessary, so that the order of these edges around + the event vertex matches the order in the dictionary; + - checking any newly adjacent edges for intersection and/or merging. + +If there are no right-going edges, again we need to add one to split +the containing region into monotone pieces. In our case it is most +convenient to add an edge to the leftmost right endpoint of either +containing edge; however we may need to change this later (see the +code for details). + + +Invariants +---------- + +These are the most important invariants maintained during the sweep. +We define a function VertLeq(v1,v2) which defines the order in which +vertices cross the sweep line, and a function EdgeLeq(e1,e2; loc) +which says whether e1 is below e2 at the sweep event location "loc". +This function is defined only at sweep event locations which lie +between the rightmost left endpoint of {e1,e2}, and the leftmost right +endpoint of {e1,e2}. + +Invariants for the Edge Dictionary. + + - Each pair of adjacent edges e2=Succ(e1) satisfies EdgeLeq(e1,e2) + at any valid location of the sweep event. + - If EdgeLeq(e2,e1) as well (at any valid sweep event), then e1 and e2 + share a common endpoint. + - For each e in the dictionary, e->Dst has been processed but not e->Org. + - Each edge e satisfies VertLeq(e->Dst,event) && VertLeq(event,e->Org) + where "event" is the current sweep line event. + - No edge e has zero length. + - No two edges have identical left and right endpoints. + +Invariants for the Mesh (the processed portion). + + - The portion of the mesh left of the sweep line is a planar graph, + ie. there is *some* way to embed it in the plane. + - No processed edge has zero length. + - No two processed vertices have identical coordinates. + - Each "inside" region is monotone, ie. can be broken into two chains + of monotonically increasing vertices according to VertLeq(v1,v2) + - a non-invariant: these chains may intersect (slightly) due to + numerical errors, but this does not affect the algorithm's operation. + +Invariants for the Sweep. + + - If a vertex has any left-going edges, then these must be in the edge + dictionary at the time the vertex is processed. + - If an edge is marked "fixUpperEdge" (it is a temporary edge introduced + by ConnectRightVertex), then it is the only right-going edge from + its associated vertex. (This says that these edges exist only + when it is necessary.) + + +Robustness +---------- + +The key to the robustness of the algorithm is maintaining the +invariants above, especially the correct ordering of the edge +dictionary. We achieve this by: + + 1. Writing the numerical computations for maximum precision rather + than maximum speed. + + 2. Making no assumptions at all about the results of the edge + intersection calculations -- for sufficiently degenerate inputs, + the computed location is not much better than a random number. + + 3. When numerical errors violate the invariants, restore them + by making *topological* changes when necessary (ie. relinking + the mesh structure). + + +Triangulation and Grouping +-------------------------- + +We finish the line sweep before doing any triangulation. This is +because even after a monotone region is complete, there can be further +changes to its vertex data because of further vertex merging. + +After triangulating all monotone regions, we want to group the +triangles into fans and strips. We do this using a greedy approach. +The triangulation itself is not optimized to reduce the number of +primitives; we just try to get a reasonable decomposition of the +computed triangulation.