summaryrefslogtreecommitdiffstats
path: root/src/glu/sgi/libnurbs
diff options
context:
space:
mode:
authorDavid Nusinow <[email protected]>2006-01-03 05:15:27 +0000
committerDavid Nusinow <[email protected]>2006-01-03 05:15:27 +0000
commitdf46b96ab0e5dabc7baa443c9065d66b5b9fd5ef (patch)
tree95d053225c4394c0673f6d920169ea2734b3b6d7 /src/glu/sgi/libnurbs
parentbda1e332ce5efe2057421dec58202b43707a504c (diff)
Re-add mesa-6.4.1 which was accidentally deleted
Diffstat (limited to 'src/glu/sgi/libnurbs')
-rw-r--r--src/glu/sgi/libnurbs/interface/bezierEval.cc260
-rw-r--r--src/glu/sgi/libnurbs/interface/bezierEval.h55
-rw-r--r--src/glu/sgi/libnurbs/interface/bezierPatch.cc205
-rw-r--r--src/glu/sgi/libnurbs/interface/bezierPatch.h111
-rw-r--r--src/glu/sgi/libnurbs/interface/bezierPatchMesh.cc613
-rw-r--r--src/glu/sgi/libnurbs/interface/bezierPatchMesh.h127
-rw-r--r--src/glu/sgi/libnurbs/interface/glcurveval.cc403
-rw-r--r--src/glu/sgi/libnurbs/interface/glcurveval.h161
-rw-r--r--src/glu/sgi/libnurbs/interface/glimports.h48
-rw-r--r--src/glu/sgi/libnurbs/interface/glinterface.cc471
-rw-r--r--src/glu/sgi/libnurbs/interface/glrenderer.cc301
-rw-r--r--src/glu/sgi/libnurbs/interface/glrenderer.h152
-rw-r--r--src/glu/sgi/libnurbs/interface/glsurfeval.cc1290
-rw-r--r--src/glu/sgi/libnurbs/interface/glsurfeval.h408
-rw-r--r--src/glu/sgi/libnurbs/interface/incurveeval.cc208
-rw-r--r--src/glu/sgi/libnurbs/interface/insurfeval.cc2066
-rw-r--r--src/glu/sgi/libnurbs/interface/mystdio.h66
-rw-r--r--src/glu/sgi/libnurbs/interface/mystdlib.h63
-rw-r--r--src/glu/sgi/libnurbs/internals/arc.cc347
-rw-r--r--src/glu/sgi/libnurbs/internals/arc.h139
-rw-r--r--src/glu/sgi/libnurbs/internals/arcsorter.cc174
-rw-r--r--src/glu/sgi/libnurbs/internals/arcsorter.h79
-rw-r--r--src/glu/sgi/libnurbs/internals/arctess.cc611
-rw-r--r--src/glu/sgi/libnurbs/internals/arctess.h72
-rw-r--r--src/glu/sgi/libnurbs/internals/backend.cc591
-rw-r--r--src/glu/sgi/libnurbs/internals/backend.h119
-rw-r--r--src/glu/sgi/libnurbs/internals/basiccrveval.cc138
-rw-r--r--src/glu/sgi/libnurbs/internals/basiccrveval.h67
-rw-r--r--src/glu/sgi/libnurbs/internals/basicsurfeval.cc232
-rw-r--r--src/glu/sgi/libnurbs/internals/basicsurfeval.h95
-rw-r--r--src/glu/sgi/libnurbs/internals/bezierarc.h57
-rw-r--r--src/glu/sgi/libnurbs/internals/bin.cc168
-rw-r--r--src/glu/sgi/libnurbs/internals/bin.h127
-rw-r--r--src/glu/sgi/libnurbs/internals/bufpool.cc112
-rw-r--r--src/glu/sgi/libnurbs/internals/bufpool.h146
-rw-r--r--src/glu/sgi/libnurbs/internals/cachingeval.cc80
-rw-r--r--src/glu/sgi/libnurbs/internals/cachingeval.h56
-rw-r--r--src/glu/sgi/libnurbs/internals/ccw.cc567
-rw-r--r--src/glu/sgi/libnurbs/internals/coveandtiler.cc440
-rw-r--r--src/glu/sgi/libnurbs/internals/coveandtiler.h78
-rw-r--r--src/glu/sgi/libnurbs/internals/curve.cc200
-rw-r--r--src/glu/sgi/libnurbs/internals/curve.h76
-rw-r--r--src/glu/sgi/libnurbs/internals/curvelist.cc112
-rw-r--r--src/glu/sgi/libnurbs/internals/curvelist.h68
-rw-r--r--src/glu/sgi/libnurbs/internals/curvesub.cc105
-rw-r--r--src/glu/sgi/libnurbs/internals/dataTransform.cc211
-rw-r--r--src/glu/sgi/libnurbs/internals/dataTransform.h66
-rw-r--r--src/glu/sgi/libnurbs/internals/defines.h56
-rw-r--r--src/glu/sgi/libnurbs/internals/displaylist.cc84
-rw-r--r--src/glu/sgi/libnurbs/internals/displaylist.h84
-rw-r--r--src/glu/sgi/libnurbs/internals/displaymode.h47
-rw-r--r--src/glu/sgi/libnurbs/internals/flist.cc120
-rw-r--r--src/glu/sgi/libnurbs/internals/flist.h65
-rw-r--r--src/glu/sgi/libnurbs/internals/flistsorter.cc83
-rw-r--r--src/glu/sgi/libnurbs/internals/flistsorter.h58
-rw-r--r--src/glu/sgi/libnurbs/internals/gridline.h52
-rw-r--r--src/glu/sgi/libnurbs/internals/gridtrimvertex.h95
-rw-r--r--src/glu/sgi/libnurbs/internals/gridvertex.h54
-rw-r--r--src/glu/sgi/libnurbs/internals/hull.cc167
-rw-r--r--src/glu/sgi/libnurbs/internals/hull.h75
-rw-r--r--src/glu/sgi/libnurbs/internals/intersect.cc667
-rw-r--r--src/glu/sgi/libnurbs/internals/jarcloc.h93
-rw-r--r--src/glu/sgi/libnurbs/internals/knotvector.cc139
-rw-r--r--src/glu/sgi/libnurbs/internals/knotvector.h68
-rw-r--r--src/glu/sgi/libnurbs/internals/mapdesc.cc843
-rw-r--r--src/glu/sgi/libnurbs/internals/mapdesc.h277
-rw-r--r--src/glu/sgi/libnurbs/internals/mapdescv.cc245
-rw-r--r--src/glu/sgi/libnurbs/internals/maplist.cc119
-rw-r--r--src/glu/sgi/libnurbs/internals/maplist.h87
-rw-r--r--src/glu/sgi/libnurbs/internals/mesher.cc488
-rw-r--r--src/glu/sgi/libnurbs/internals/mesher.h89
-rw-r--r--src/glu/sgi/libnurbs/internals/monoTriangulationBackend.cc399
-rw-r--r--src/glu/sgi/libnurbs/internals/monotonizer.cc262
-rw-r--r--src/glu/sgi/libnurbs/internals/monotonizer.h47
-rw-r--r--src/glu/sgi/libnurbs/internals/myassert.h57
-rw-r--r--src/glu/sgi/libnurbs/internals/mycode.cc69
-rw-r--r--src/glu/sgi/libnurbs/internals/mymath.h72
-rw-r--r--src/glu/sgi/libnurbs/internals/mysetjmp.h89
-rw-r--r--src/glu/sgi/libnurbs/internals/mystring.h62
-rw-r--r--src/glu/sgi/libnurbs/internals/nurbsconsts.h126
-rw-r--r--src/glu/sgi/libnurbs/internals/nurbsinterfac.cc537
-rw-r--r--src/glu/sgi/libnurbs/internals/nurbstess.cc693
-rw-r--r--src/glu/sgi/libnurbs/internals/nurbstess.h176
-rw-r--r--src/glu/sgi/libnurbs/internals/patch.cc506
-rw-r--r--src/glu/sgi/libnurbs/internals/patch.h100
-rw-r--r--src/glu/sgi/libnurbs/internals/patchlist.cc172
-rw-r--r--src/glu/sgi/libnurbs/internals/patchlist.h98
-rw-r--r--src/glu/sgi/libnurbs/internals/pwlarc.h84
-rw-r--r--src/glu/sgi/libnurbs/internals/quilt.cc278
-rw-r--r--src/glu/sgi/libnurbs/internals/quilt.h98
-rw-r--r--src/glu/sgi/libnurbs/internals/reader.cc148
-rw-r--r--src/glu/sgi/libnurbs/internals/reader.h138
-rw-r--r--src/glu/sgi/libnurbs/internals/renderhints.cc135
-rw-r--r--src/glu/sgi/libnurbs/internals/renderhints.h66
-rw-r--r--src/glu/sgi/libnurbs/internals/simplemath.h56
-rw-r--r--src/glu/sgi/libnurbs/internals/slicer.cc1302
-rw-r--r--src/glu/sgi/libnurbs/internals/slicer.h90
-rw-r--r--src/glu/sgi/libnurbs/internals/sorter.cc141
-rw-r--r--src/glu/sgi/libnurbs/internals/sorter.h57
-rw-r--r--src/glu/sgi/libnurbs/internals/splitarcs.cc295
-rw-r--r--src/glu/sgi/libnurbs/internals/subdivider.cc910
-rw-r--r--src/glu/sgi/libnurbs/internals/subdivider.h206
-rw-r--r--src/glu/sgi/libnurbs/internals/tobezier.cc689
-rw-r--r--src/glu/sgi/libnurbs/internals/trimline.cc225
-rw-r--r--src/glu/sgi/libnurbs/internals/trimline.h109
-rw-r--r--src/glu/sgi/libnurbs/internals/trimregion.cc116
-rw-r--r--src/glu/sgi/libnurbs/internals/trimregion.h90
-rw-r--r--src/glu/sgi/libnurbs/internals/trimvertex.h69
-rw-r--r--src/glu/sgi/libnurbs/internals/trimvertpool.cc121
-rw-r--r--src/glu/sgi/libnurbs/internals/trimvertpool.h63
-rw-r--r--src/glu/sgi/libnurbs/internals/types.h53
-rw-r--r--src/glu/sgi/libnurbs/internals/uarray.cc74
-rw-r--r--src/glu/sgi/libnurbs/internals/uarray.h61
-rw-r--r--src/glu/sgi/libnurbs/internals/varray.cc146
-rw-r--r--src/glu/sgi/libnurbs/internals/varray.h74
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/definitions.h47
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/directedLine.cc848
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/directedLine.h178
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/glimports.h48
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/gridWrap.cc295
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/gridWrap.h144
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/monoChain.cc936
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/monoChain.h110
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/monoPolyPart.cc300
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/monoPolyPart.h47
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/monoTriangulation.cc1482
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/monoTriangulation.h192
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/mystdio.h66
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/mystdlib.h63
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/partitionX.cc164
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/partitionX.h61
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/partitionY.cc838
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/partitionY.h104
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/polyDBG.cc734
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/polyDBG.h75
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/polyUtil.cc92
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/polyUtil.h54
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/primitiveStream.cc192
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/primitiveStream.h116
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/quicksort.cc79
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/quicksort.h49
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/rectBlock.cc198
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/rectBlock.h89
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/sampleComp.cc373
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/sampleComp.h93
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/sampleCompBot.cc846
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/sampleCompBot.h145
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/sampleCompRight.cc646
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/sampleCompRight.h124
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/sampleCompTop.cc1032
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/sampleCompTop.h74
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.cc2429
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.h191
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/sampledLine.cc181
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/sampledLine.h78
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/searchTree.cc284
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/searchTree.h68
-rw-r--r--src/glu/sgi/libnurbs/nurbtess/zlassert.h41
158 files changed, 40061 insertions, 0 deletions
diff --git a/src/glu/sgi/libnurbs/interface/bezierEval.cc b/src/glu/sgi/libnurbs/interface/bezierEval.cc
new file mode 100644
index 00000000000..b414f535f95
--- /dev/null
+++ b/src/glu/sgi/libnurbs/interface/bezierEval.cc
@@ -0,0 +1,260 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <math.h>
+#include "bezierEval.h"
+
+#ifdef __WATCOMC__
+#pragma warning 14 10
+#endif
+
+#define TOLERANCE 0.0001
+
+#ifndef MAX_ORDER
+#define MAX_ORDER 16
+#endif
+
+#ifndef MAX_DIMENSION
+#define MAX_DIMENSION 4
+#endif
+
+static void normalize(float vec[3]);
+static void crossProduct(float x[3], float y[3], float ret[3]);
+#if 0 // UNUSED
+static void bezierCurveEvalfast(float u0, float u1, int order, float *ctlpoints, int stride, int dimension, float u, float retpoint[]);
+#endif
+
+static float binomialCoefficients[8][8] = {
+ {1,0,0,0,0,0,0,0},
+ {1,1,0,0,0,0,0,0},
+ {1,2,1,0,0,0,0,0},
+ {1,3,3,1,0,0,0,0},
+ {1,4,6,4,1,0,0,0},
+ {1,5,10,10,5,1,0,0},
+ {1,6,15,20,15,6,1,0},
+ {1,7,21,35,35,21,7,1}
+};
+
+void bezierCurveEval(float u0, float u1, int order, float *ctlpoints, int stride, int dimension, float u, float retpoint[])
+{
+ float uprime = (u-u0)/(u1-u0);
+ float *ctlptr = ctlpoints;
+ float oneMinusX = 1.0f-uprime;
+ float XPower = 1.0f;
+
+ int i,k;
+ for(k=0; k<dimension; k++)
+ retpoint[k] = (*(ctlptr + k));
+
+ for(i=1; i<order; i++){
+ ctlptr += stride;
+ XPower *= uprime;
+ for(k=0; k<dimension; k++) {
+ retpoint[k] = retpoint[k]*oneMinusX + ctlptr[k]* binomialCoefficients[order-1][i] * XPower;
+ }
+ }
+}
+
+
+#if 0 // UNUSED
+/*order = degree +1 >=1.
+ */
+void bezierCurveEvalfast(float u0, float u1, int order, float *ctlpoints, int stride, int dimension, float u, float retpoint[])
+{
+ float uprime = (u-u0)/(u1-u0);
+ float buf[MAX_ORDER][MAX_ORDER][MAX_DIMENSION];
+ float* ctlptr = ctlpoints;
+ int r, i,j;
+ for(i=0; i<order; i++) {
+ for(j=0; j<dimension; j++)
+ buf[0][i][j] = ctlptr[j];
+ ctlptr += stride;
+ }
+ for(r=1; r<order; r++){
+ for(i=0; i<order-r; i++) {
+ for(j=0; j<dimension; j++)
+ buf[r][i][j] = (1-uprime)*buf[r-1][i][j] + uprime*buf[r-1][i+1][j];
+ }
+ }
+
+ for(j=0; j<dimension; j++)
+ retpoint[j] = buf[order-1][0][j];
+}
+#endif
+
+
+/*order = degree +1 >=1.
+ */
+void bezierCurveEvalDer(float u0, float u1, int order, float *ctlpoints, int stride, int dimension, float u, float retDer[])
+{
+ int i,k;
+ float width = u1-u0;
+ float *ctlptr = ctlpoints;
+
+ float buf[MAX_ORDER][MAX_DIMENSION];
+ if(order == 1){
+ for(k=0; k<dimension; k++)
+ retDer[k]=0;
+ }
+ for(i=0; i<order-1; i++){
+ for(k=0; k<dimension; k++) {
+ buf[i][k] = (ctlptr[stride+k] - ctlptr[k])*(order-1)/width;
+ }
+ ctlptr += stride;
+ }
+
+ bezierCurveEval(u0, u1, order-1, (float*) buf, MAX_DIMENSION, dimension, u, retDer);
+}
+
+void bezierCurveEvalDerGen(int der, float u0, float u1, int order, float *ctlpoints, int stride, int dimension, float u, float retDer[])
+{
+ int i,k,r;
+ float *ctlptr = ctlpoints;
+ float width=u1-u0;
+ float buf[MAX_ORDER][MAX_ORDER][MAX_DIMENSION];
+ if(der<0) der=0;
+ for(i=0; i<order; i++){
+ for(k=0; k<dimension; k++){
+ buf[0][i][k] = ctlptr[k];
+ }
+ ctlptr += stride;
+ }
+
+
+ for(r=1; r<=der; r++){
+ for(i=0; i<order-r; i++){
+ for(k=0; k<dimension; k++){
+ buf[r][i][k] = (buf[r-1][i+1][k] - buf[r-1][i][k])*(order-r)/width;
+ }
+ }
+ }
+
+ bezierCurveEval(u0, u1, order-der, (float *) (buf[der]), MAX_DIMENSION, dimension, u, retDer);
+}
+
+/*the Bezier bivarite polynomial is:
+ * sum[i:0,uorder-1][j:0,vorder-1] { ctlpoints[i*ustride+j*vstride] * B(i)*B(j)
+ * where B(i) and B(j) are basis functions
+ */
+void bezierSurfEvalDerGen(int uder, int vder, float u0, float u1, int uorder, float v0, float v1, int vorder, int dimension, float *ctlpoints, int ustride, int vstride, float u, float v, float ret[])
+{
+ int i;
+ float newPoints[MAX_ORDER][MAX_DIMENSION];
+
+ for(i=0; i<uorder; i++){
+
+ bezierCurveEvalDerGen(vder, v0, v1, vorder, ctlpoints+ustride*i, vstride, dimension, v, newPoints[i]);
+
+ }
+
+ bezierCurveEvalDerGen(uder, u0, u1, uorder, (float *) newPoints, MAX_DIMENSION, dimension, u, ret);
+}
+
+
+/*division by w is performed*/
+void bezierSurfEval(float u0, float u1, int uorder, float v0, float v1, int vorder, int dimension, float *ctlpoints, int ustride, int vstride, float u, float v, float ret[])
+{
+ bezierSurfEvalDerGen(0, 0, u0, u1, uorder, v0, v1, vorder, dimension, ctlpoints, ustride, vstride, u, v, ret);
+ if(dimension == 4) /*homogeneous*/{
+ ret[0] /= ret[3];
+ ret[1] /= ret[3];
+ ret[2] /= ret[3];
+ }
+}
+
+void bezierSurfEvalNormal(float u0, float u1, int uorder, float v0, float v1, int vorder, int dimension, float *ctlpoints, int ustride, int vstride, float u, float v, float retNormal[])
+{
+ float partialU[4];
+ float partialV[4];
+ assert(dimension>=3 && dimension <=4);
+ bezierSurfEvalDerGen(1,0, u0, u1, uorder, v0, v1, vorder, dimension, ctlpoints, ustride, vstride, u, v, partialU);
+ bezierSurfEvalDerGen(0,1, u0, u1, uorder, v0, v1, vorder, dimension, ctlpoints, ustride, vstride, u, v, partialV);
+
+ if(dimension == 3){/*inhomogeneous*/
+ crossProduct(partialU, partialV, retNormal);
+
+ normalize(retNormal);
+
+ return;
+ }
+ else { /*homogeneous*/
+ float val[4]; /*the point coordinates (without derivative)*/
+ float newPartialU[MAX_DIMENSION];
+ float newPartialV[MAX_DIMENSION];
+ int i;
+ bezierSurfEvalDerGen(0,0, u0, u1, uorder, v0, v1, vorder, dimension, ctlpoints, ustride, vstride, u, v, val);
+
+ for(i=0; i<=2; i++){
+ newPartialU[i] = partialU[i] * val[3] - val[i] * partialU[3];
+ newPartialV[i] = partialV[i] * val[3] - val[i] * partialV[3];
+ }
+ crossProduct(newPartialU, newPartialV, retNormal);
+ normalize(retNormal);
+ }
+}
+
+/*if size is 0, then nothing is done*/
+static void normalize(float vec[3])
+{
+ float size = (float)sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);
+
+ if(size < TOLERANCE)
+ {
+#ifdef DEBUG
+ fprintf(stderr, "Warning: in oglBSpline.c normal is 0\n");
+#endif
+ return;
+ }
+ else {
+ vec[0] = vec[0]/size;
+ vec[1] = vec[1]/size;
+ vec[2] = vec[2]/size;
+ }
+}
+
+
+static void crossProduct(float x[3], float y[3], float ret[3])
+{
+ ret[0] = x[1]*y[2] - y[1]*x[2];
+ ret[1] = x[2]*y[0] - y[2]*x[0];
+ ret[2] = x[0]*y[1] - y[0]*x[1];
+
+}
+
diff --git a/src/glu/sgi/libnurbs/interface/bezierEval.h b/src/glu/sgi/libnurbs/interface/bezierEval.h
new file mode 100644
index 00000000000..97ebd12b6d8
--- /dev/null
+++ b/src/glu/sgi/libnurbs/interface/bezierEval.h
@@ -0,0 +1,55 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/interface/bezierEval.h,v 1.1 2001/03/17 00:25:40 brianp Exp $
+*/
+
+#ifndef _BEZIEREVAL_H
+#define _BEZIEREVAL_H
+
+void bezierCurveEval(float u0, float u1, int order, float *ctlpoints, int stride, int dimension, float u, float retpoint[]);
+void bezierCurveEvalDer(float u0, float u1, int order, float *ctlpoints, int stride, int dimension, float u, float retDer[]);
+void bezierCurveEvalDerGen(int der, float u0, float u1, int order, float *ctlpoints, int stride, int dimension, float u, float retDer[]);
+
+
+void bezierSurfEvalDerGen(int uder, int vder, float u0, float u1, int uorder, float v0, float v1, int vorder, int dimension, float *ctlpoints, int ustride, int vstride, float u, float v, float ret[]);
+
+void bezierSurfEval(float u0, float u1, int uorder, float v0, float v1, int vorder, int dimension, float *ctlpoints, int ustride, int vstride, float u, float v, float ret[]);
+
+void bezierSurfEvalNormal(float u0, float u1, int uorder, float v0, float v1, int vorder, int dimension, float *ctlpoints, int ustride, int vstride, float u, float v, float retNormal[]);
+
+
+#endif
diff --git a/src/glu/sgi/libnurbs/interface/bezierPatch.cc b/src/glu/sgi/libnurbs/interface/bezierPatch.cc
new file mode 100644
index 00000000000..a723d1f4536
--- /dev/null
+++ b/src/glu/sgi/libnurbs/interface/bezierPatch.cc
@@ -0,0 +1,205 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/interface/bezierPatch.cc,v 1.1 2001/03/17 00:25:40 brianp Exp $
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <GL/glu.h> /*for drawing bzier patch*/
+#include "bezierPatch.h"
+#include "bezierEval.h"
+
+/*
+ *allocate an instance of bezierPatch. The control points are unknown. But
+ *the space of this array is allocated with size of
+ * uorder*vorder*dimension
+ *
+ */
+bezierPatch* bezierPatchMake(float umin, float vmin, float umax, float vmax, int uorder, int vorder, int dimension)
+{
+ bezierPatch* ret = (bezierPatch*) malloc(sizeof(bezierPatch));
+ assert(ret);
+ ret->umin = umin;
+ ret->vmin = vmin;
+ ret->umax = umax;
+ ret->vmax = vmax;
+ ret->uorder = uorder;
+ ret->vorder = vorder;
+ ret->dimension = dimension;
+ ret->ctlpoints = (float*) malloc(sizeof(float) * dimension * uorder * vorder);
+ assert(ret->ctlpoints);
+
+ ret->next = NULL;
+
+ return ret;
+}
+
+bezierPatch* bezierPatchMake2(float umin, float vmin, float umax, float vmax, int uorder, int vorder, int dimension, int ustride, int vstride, float* ctlpoints)
+{
+ bezierPatch* ret = (bezierPatch*) malloc(sizeof(bezierPatch));
+ assert(ret);
+ ret->umin = umin;
+ ret->vmin = vmin;
+ ret->umax = umax;
+ ret->vmax = vmax;
+ ret->uorder = uorder;
+ ret->vorder = vorder;
+ ret->dimension = dimension;
+ ret->ctlpoints = (float*) malloc(sizeof(float) * dimension * uorder * vorder);
+ assert(ret->ctlpoints);
+
+ /*copy the control points there*/
+ int the_ustride = vorder * dimension;
+ int the_vstride = dimension;
+ for(int i=0; i<uorder; i++)
+ for(int j=0; j<vorder; j++)
+ for(int k=0; k<dimension; k++)
+ ret->ctlpoints[i * the_ustride + j*the_vstride+k] = ctlpoints[i*ustride+j*vstride+k];
+
+ ret->next = NULL;
+
+ return ret;
+}
+
+/*
+ *deallocate the space as allocated by Make
+ */
+void bezierPatchDelete(bezierPatch *b)
+{
+ free(b->ctlpoints);
+ free(b);
+}
+
+/*delete the whole linked list
+ */
+void bezierPatchDeleteList(bezierPatch *b)
+{
+ bezierPatch *temp;
+ for(temp = b; temp != NULL; temp = temp->next)
+ bezierPatchDelete(temp);
+}
+
+bezierPatch* bezierPatchInsert(bezierPatch *list, bezierPatch *b)
+{
+ b->next = list;
+ return b;
+}
+
+/*print the data stored in this patch*/
+void bezierPatchPrint(bezierPatch *b)
+{
+ printf("bezierPatch:\n");
+ printf("umin,umax=(%f,%f), (vmin, vmax)=(%f,%f)\n", b->umin, b->umax, b->vmin, b->vmax);
+ printf("uorder=%i, vorder=%i\n", b->uorder, b->vorder);
+ printf("idmension = %i\n", b->dimension);
+}
+
+/*print the whole list*/
+void bezierPatchPrintList(bezierPatch *list)
+{
+ bezierPatch* temp;
+ for(temp=list; temp != NULL; temp = temp->next)
+ bezierPatchPrint(temp);
+}
+
+void bezierPatchEval(bezierPatch *b, float u, float v, float ret[])
+{
+ if( u >= b->umin && u<= b->umax
+ && v >= b->vmin && v<= b->vmax)
+ {
+
+ bezierSurfEval(b->umin, b->umax, b->uorder, b->vmin, b->vmax, b->vorder, b->dimension, b->ctlpoints, b->dimension * b->vorder, b->dimension, u, v, ret);
+
+ }
+ else if(b->next != NULL)
+ bezierPatchEval(b->next, u,v, ret);
+ else
+ bezierSurfEval(b->umin, b->umax, b->uorder, b->vmin, b->vmax, b->vorder, b->dimension, b->ctlpoints, b->dimension * b->vorder, b->dimension, u, v, ret);
+}
+
+/*the returned normal is normlized
+ */
+void bezierPatchEvalNormal(bezierPatch *b, float u, float v, float ret[])
+{
+ bezierSurfEvalNormal(b->umin, b->umax, b->uorder, b->vmin, b->vmax, b->vorder, b->dimension, b->ctlpoints, b->dimension * b->vorder, b->dimension, u, v, ret);
+
+ if( u >= b->umin && u<= b->umax
+ && v >= b->vmin && v<= b->vmax)
+ {
+ bezierSurfEvalNormal(b->umin, b->umax, b->uorder, b->vmin, b->vmax, b->vorder, b->dimension, b->ctlpoints, b->dimension * b->vorder, b->dimension, u, v, ret);
+ }
+ else if(b->next != NULL)
+ bezierPatchEvalNormal(b->next, u,v, ret);
+ else
+ bezierSurfEvalNormal(b->umin, b->umax, b->uorder, b->vmin, b->vmax, b->vorder, b->dimension, b->ctlpoints, b->dimension * b->vorder, b->dimension, u, v, ret);
+
+}
+
+void bezierPatchDraw(bezierPatch *bpatch, int u_reso, int v_reso)
+{
+ if(bpatch->dimension == 3)
+ glMap2f(GL_MAP2_VERTEX_3, bpatch->umin, bpatch->umax, 3*bpatch->vorder, bpatch->uorder, bpatch->vmin, bpatch->vmax,3, bpatch->vorder, (GLfloat*) bpatch->ctlpoints);
+ else
+ glMap2f(GL_MAP2_VERTEX_4, bpatch->umin, bpatch->umax, 4*bpatch->vorder, bpatch->uorder, bpatch->vmin, bpatch->vmax,3, bpatch->vorder, (GLfloat*) bpatch->ctlpoints);
+
+ glMapGrid2f(u_reso, bpatch->umin, bpatch->umax,
+ v_reso, bpatch->vmin, bpatch->vmax);
+ glEvalMesh2(GL_LINE, 0, u_reso, 0, v_reso);
+}
+
+void bezierPatchListDraw(bezierPatch *list, int u_reso, int v_reso)
+{
+ bezierPatch *temp;
+glEnable(GL_LIGHTING);
+glEnable(GL_LIGHT0);
+glEnable(GL_MAP2_VERTEX_3);
+glEnable(GL_AUTO_NORMAL);
+glEnable(GL_NORMALIZE);
+glColor3f(1,0,0);
+#ifdef DEBUG
+printf("mapmap\n");
+#endif
+
+
+ for(temp = list; temp != NULL; temp = temp->next)
+ bezierPatchDraw(temp, u_reso, v_reso);
+}
+
+
+
diff --git a/src/glu/sgi/libnurbs/interface/bezierPatch.h b/src/glu/sgi/libnurbs/interface/bezierPatch.h
new file mode 100644
index 00000000000..51cd599532d
--- /dev/null
+++ b/src/glu/sgi/libnurbs/interface/bezierPatch.h
@@ -0,0 +1,111 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/interface/bezierPatch.h,v 1.1 2001/03/17 00:25:40 brianp Exp $
+*/
+
+#ifndef _BEZIERPATCH_H
+#define _BEZIERPATCH_H
+
+typedef struct bezierPatch{
+ float umin, vmin, umax, vmax;
+ int uorder; /*order= degree + 1*/
+ int vorder;
+
+ /*
+ *the control points are stored in a one dimensional array.
+ *the surface is defined as:
+ * s(u,v) = sum_{i,j} P(i,j) * B_i(u) * B_j(v).
+ *where P(i,j) are the control points, B_i(.) are Bezier
+ *basis functions.
+ *Each control point can have dimension 3 or 4: (x,y,z,w).
+ *The components of P(i,j) are stored in a one dimensional
+ *array:
+ * ctlpoints[]
+ *in the order of:
+ * P[0,0], P[0,1], ..., P[0,vorder-1],
+ * P[1,0], P[1,1], ..., P[1,vorder-1],
+ * ...
+ * P[uorder-1,0], P[uorder-1,1], ..., P[uorder-1,vorder-1].
+ */
+ int dimension;
+ float* ctlpoints;
+
+ /*
+ *in case we have to manage multiple bezierPatches.
+ */
+ struct bezierPatch *next;
+
+} bezierPatch;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bezierPatch* bezierPatchMake(float umin, float vmin, float umax, float vmax, int urder, int vorder, int dimension);
+
+bezierPatch* bezierPatchMake2(float umin, float vmin, float umax, float vmax, int urder, int vorder, int dimension, int ustride, int vstride, float *ctlpoints);
+
+
+bezierPatch* bezierPatchInsert(bezierPatch *list, bezierPatch *b);
+
+void bezierPatchDelete(bezierPatch *b);
+
+void bezierPatchDeleteList(bezierPatch *b);
+
+void bezierPatchPrint(bezierPatch *b);
+
+void bezierPatchPrintList(bezierPatch *list);
+
+void bezierPatchEval(bezierPatch *b, float u, float v, float ret[]);
+
+void bezierPatchEvalNormal(bezierPatch *b, float u, float v, float retNormal[]);
+
+void bezierPatchEval(bezierPatch *b, float u, float v, float ret[]);
+
+void bezierPatchEvalNormal(bezierPatch *b, float u, float v, float ret[]);
+
+
+void bezierPatchDraw(bezierPatch *bpatch, int u_reso, int v_reso);
+
+void bezierPatchListDraw(bezierPatch *list, int u_reso, int v_reso);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/src/glu/sgi/libnurbs/interface/bezierPatchMesh.cc b/src/glu/sgi/libnurbs/interface/bezierPatchMesh.cc
new file mode 100644
index 00000000000..32c404febd2
--- /dev/null
+++ b/src/glu/sgi/libnurbs/interface/bezierPatchMesh.cc
@@ -0,0 +1,613 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/interface/bezierPatchMesh.cc,v 1.1 2001/03/17 00:25:40 brianp Exp $
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <GL/gl.h>
+#include "bezierEval.h"
+#include "bezierPatchMesh.h"
+
+static int isDegenerate(float A[2], float B[2], float C[2]);
+
+void drawStrips(float *vertex_array, float *normal_array, int *length_array, GLenum *type_array, int num_strips)
+{
+ int i,j,k;
+ k=0;
+ /*k is the index of the first component of the current vertex*/
+ for(i=0; i<num_strips; i++)
+ {
+ glBegin(type_array[i]);
+ for(j=0; j<length_array[i]; j++)
+ {
+ glNormal3fv(normal_array+k);
+ glVertex3fv(vertex_array+k);
+ k += 3;
+ }
+ glEnd();
+ }
+}
+
+void bezierPatchMeshListDelDeg(bezierPatchMesh* list)
+{
+ bezierPatchMesh* temp;
+ for(temp=list; temp != NULL; temp = temp->next)
+ {
+ bezierPatchMeshDelDeg(temp);
+ }
+}
+
+void bezierPatchMeshListDelete(bezierPatchMesh *list)
+{
+ if(list == NULL) return;
+ bezierPatchMeshListDelete(list->next);
+ bezierPatchMeshDelete(list);
+}
+
+
+
+
+bezierPatchMesh* bezierPatchMeshListReverse(bezierPatchMesh* list)
+{
+ bezierPatchMesh* ret=NULL;
+ bezierPatchMesh* temp;
+ bezierPatchMesh* nextone;
+ for(temp = list; temp != NULL; temp = nextone)
+ {
+ nextone = temp->next;
+ ret=bezierPatchMeshListInsert(ret, temp);
+ }
+ return ret;
+}
+
+/*maptype is either GL_MAP2_VERTEX_3 or GL_MAP2_VERTEX_4
+ */
+bezierPatchMesh *bezierPatchMeshMake(int maptype, float umin, float umax, int ustride, int uorder, float vmin, float vmax, int vstride, int vorder, float *ctlpoints, int size_UVarray, int size_length_array)
+{
+ int i,j,k;
+ int dimension;
+ int the_ustride;
+ int the_vstride;
+
+ bezierPatchMesh *ret = (bezierPatchMesh*) malloc(sizeof(bezierPatchMesh));
+ assert(ret);
+
+ ret->bpatch = NULL;
+ ret->bpatch_normal = NULL;
+ ret->bpatch_color = NULL;
+ ret->bpatch_texcoord = NULL;
+
+ if(maptype == GL_MAP2_VERTEX_3) dimension = 3;
+ else if (maptype==GL_MAP2_VERTEX_4) dimension = 4;
+ else {
+ fprintf(stderr, "error in inMap2f, maptype=%i is wrong, maptype,map is invalid\n", maptype);
+ return NULL;
+ }
+
+ ret->bpatch = bezierPatchMake(umin, vmin, umax, vmax, uorder, vorder, dimension);
+ /*copy the control points there*/
+ the_ustride = vorder * dimension;
+ the_vstride = dimension;
+ for(i=0; i<uorder; i++)
+ for(j=0; j<vorder; j++)
+ for(k=0; k<dimension; k++)
+ ret->bpatch->ctlpoints[i * the_ustride + j*the_vstride+k] = ctlpoints[i*ustride+j*vstride+k];
+
+
+ ret->size_UVarray = size_UVarray;
+ ret->size_length_array = size_length_array;
+ ret->UVarray = (float*) malloc(sizeof(float) * size_UVarray);
+ assert(ret->UVarray);
+ ret->length_array = (int *)malloc(sizeof(int) * size_length_array);
+ assert(ret->length_array);
+ ret->type_array = (GLenum *)malloc(sizeof(GLenum) * size_length_array);
+ assert(ret->type_array);
+
+ ret->index_UVarray = 0;
+ ret->index_length_array = 0;
+
+ ret->vertex_array = NULL;
+ ret->normal_array = NULL;
+ ret->color_array = NULL;
+ ret->texcoord_array = NULL;
+
+ ret->next = NULL;
+ return ret;
+}
+
+bezierPatchMesh *bezierPatchMeshMake2(int size_UVarray, int size_length_array)
+{
+ bezierPatchMesh *ret = (bezierPatchMesh*) malloc(sizeof(bezierPatchMesh));
+ assert(ret);
+
+ ret->bpatch = NULL;
+ ret->bpatch_normal = NULL;
+ ret->bpatch_color = NULL;
+ ret->bpatch_texcoord = NULL;
+
+ ret->size_UVarray = size_UVarray;
+ ret->size_length_array = size_length_array;
+ ret->UVarray = (float*) malloc(sizeof(float) * size_UVarray);
+ assert(ret->UVarray);
+ ret->length_array = (int *)malloc(sizeof(int) * size_length_array);
+ assert(ret->length_array);
+ ret->type_array = (GLenum *)malloc(sizeof(GLenum) * size_length_array);
+ assert(ret->type_array);
+
+ ret->index_UVarray = 0;
+ ret->index_length_array = 0;
+
+ ret->vertex_array = NULL;
+ ret->normal_array = NULL;
+ ret->color_array = NULL;
+ ret->texcoord_array = NULL;
+
+ ret->next = NULL;
+ return ret;
+}
+
+void bezierPatchMeshPutPatch(bezierPatchMesh *bpm, int maptype, float umin, float umax, int ustride, int uorder, float vmin, float vmax, int vstride, int vorder, float *ctlpoints)
+{
+ switch(maptype){
+ case GL_MAP2_VERTEX_3:
+ bpm->bpatch = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 3, ustride, vstride, ctlpoints);
+ break;
+ case GL_MAP2_VERTEX_4:
+ bpm->bpatch = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 4,ustride, vstride, ctlpoints );
+ break;
+ case GL_MAP2_NORMAL:
+ bpm->bpatch_normal = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 3, ustride, vstride, ctlpoints);
+ break;
+ case GL_MAP2_INDEX:
+ bpm->bpatch_color = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 1, ustride, vstride, ctlpoints);
+ break;
+ case GL_MAP2_COLOR_4:
+ bpm->bpatch_color = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 4, ustride, vstride, ctlpoints);
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 1, ustride, vstride, ctlpoints);
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 2, ustride, vstride, ctlpoints);
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 3, ustride, vstride, ctlpoints);
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 4, ustride, vstride, ctlpoints);
+ break;
+ default:
+ fprintf(stderr, "error in bezierPatchMeshPutPatch, maptype=%i is wrong, maptype,map is invalid\n", maptype);
+ }
+}
+
+
+/*delete everything including the arrays. So if you want to output the
+ *pointers of the arrays, you should not use this function to deallocate space.
+ *you should dealocate manually
+ */
+void bezierPatchMeshDelete(bezierPatchMesh *bpm)
+{
+ if(bpm->bpatch != NULL)
+ bezierPatchDelete(bpm->bpatch);
+ if(bpm->bpatch_normal != NULL)
+ bezierPatchDelete(bpm->bpatch_normal);
+ if(bpm->bpatch_color != NULL)
+ bezierPatchDelete(bpm->bpatch_color);
+ if(bpm->bpatch_texcoord != NULL)
+ bezierPatchDelete(bpm->bpatch_texcoord);
+
+ free(bpm->UVarray);
+ free(bpm->length_array);
+ free(bpm->vertex_array);
+ free(bpm->normal_array);
+ free(bpm->type_array);
+ free(bpm);
+}
+
+/*begin a strip
+ *type is the primitive type:
+ */
+void bezierPatchMeshBeginStrip(bezierPatchMesh *bpm, GLenum type)
+{
+ bpm->counter = 0;
+ bpm->type = type;
+}
+
+/*signal the end of the current strip*/
+void bezierPatchMeshEndStrip(bezierPatchMesh *bpm)
+{
+ int i;
+
+ /*if there are no vertices in this strip, then nothing needs to be done*/
+ if(bpm->counter == 0) return;
+
+ /*if the length_array is full, it should be expanded*/
+ if(bpm->index_length_array >= bpm->size_length_array)
+ {
+ int *temp = (int*) malloc(sizeof(int) * (bpm->size_length_array*2 + 1));
+ assert(temp);
+ GLenum *temp_type = (GLenum*) malloc(sizeof(GLenum) * (bpm->size_length_array*2 + 1));
+ assert(temp_type);
+ /*update the size*/
+ bpm->size_length_array = bpm->size_length_array*2 + 1;
+
+ /*copy*/
+ for(i=0; i<bpm->index_length_array; i++)
+ {
+ temp[i] = bpm->length_array[i];
+ temp_type[i] = bpm->type_array[i];
+ }
+
+ /*deallocate old array*/
+ free(bpm->length_array);
+ free(bpm->type_array);
+
+ /*point to the new array which is twice as bigger*/
+ bpm->length_array = temp;
+ bpm->type_array = temp_type;
+ }
+ bpm->type_array[bpm->index_length_array] = bpm->type;
+ bpm->length_array[bpm->index_length_array++] = bpm->counter;
+
+}
+
+/*insert (u,v) */
+void bezierPatchMeshInsertUV(bezierPatchMesh *bpm, float u, float v)
+{
+ int i;
+ /*if the UVarray is full, it should be expanded*/
+ if(bpm->index_UVarray+1 >= bpm->size_UVarray)
+ {
+ float *temp = (float*) malloc(sizeof(float) * (bpm->size_UVarray * 2 + 2));
+ assert(temp);
+
+ /*update the size*/
+ bpm->size_UVarray = bpm->size_UVarray*2 + 2;
+
+ /*copy*/
+ for(i=0; i<bpm->index_UVarray; i++)
+ {
+ temp[i] = bpm->UVarray[i];
+ }
+
+ /*deallocate old array*/
+ free(bpm->UVarray);
+
+ /*pointing to the new arrays*/
+ bpm->UVarray = temp;
+ }
+ /*insert the new UV*/
+ bpm->UVarray[bpm->index_UVarray] = u;
+ bpm->index_UVarray++;
+ bpm->UVarray[bpm->index_UVarray] = v;
+ bpm->index_UVarray++;
+
+ /*update counter: one more vertex*/
+ bpm->counter++;
+
+
+}
+
+void bezierPatchMeshPrint(bezierPatchMesh *bpm)
+{
+ int i;
+ printf("the bezier patch is\n");
+ bezierPatchPrint(bpm->bpatch);
+ printf("index_length_array= %i\n", bpm->index_length_array);
+ printf("size_length_array =%i\n", bpm->size_length_array);
+ printf("index_UVarray =%i\n", bpm->index_UVarray);
+ printf("size_UVarray =%i\n", bpm->size_UVarray);
+ printf("UVarray is\n");
+ for(i=0; i<bpm->index_UVarray; i++)
+ printf("%f ", bpm->UVarray[i]);
+
+ printf("length_array is\n");
+ for(i=0; i<bpm->index_length_array; i++)
+ printf("%i ", bpm->length_array[i]);
+ printf("\n");
+
+}
+
+/*insert a new patch in front of the current linked list and return the new list*/
+bezierPatchMesh* bezierPatchMeshListInsert(bezierPatchMesh* list, bezierPatchMesh* bpm)
+{
+ bpm->next=list;
+ return bpm;
+}
+
+/*print all the patches*/
+void bezierPatchMeshListPrint(bezierPatchMesh* list)
+{
+ bezierPatchMesh *temp;
+ for(temp = list; temp != NULL; temp = temp->next)
+ {
+ bezierPatchMeshPrint(temp);
+ }
+}
+
+int bezierPatchMeshListTotalStrips(bezierPatchMesh* list)
+{
+ int sum=0;
+ bezierPatchMesh *temp;
+ for(temp=list; temp != NULL; temp = temp->next)
+ {
+ sum += temp->index_length_array;
+ }
+ return sum;
+}
+
+int bezierPatchMeshListTotalVert(bezierPatchMesh* list)
+{
+ int sum=0;
+ bezierPatchMesh *temp;
+ for(temp=list; temp != NULL; temp = temp->next)
+ {
+ sum += temp->index_UVarray;
+ }
+ return sum/2;
+}
+
+int bezierPatchMeshListNumTriangles(bezierPatchMesh* list)
+{
+ int sum=0;
+ bezierPatchMesh* temp;
+ for(temp=list; temp != NULL; temp = temp->next)
+ {
+ sum += bezierPatchMeshNumTriangles(temp);
+ }
+ return sum;
+}
+
+int bezierPatchMeshNumTriangles(bezierPatchMesh* bpm)
+{
+ int i;
+ int sum=0;
+ for(i=0; i<bpm->index_length_array; i++)
+ {
+ switch(bpm->type_array[i])
+ {
+ case GL_TRIANGLES:
+ sum += bpm->length_array[i]/3;
+ break;
+ case GL_TRIANGLE_FAN:
+ if(bpm->length_array[i] > 2)
+ sum += bpm->length_array[i]-2;
+ break;
+ case GL_TRIANGLE_STRIP:
+ if(bpm->length_array[i] > 2)
+ sum += bpm->length_array[i]-2;
+ break;
+ case GL_QUAD_STRIP:
+ if(bpm->length_array[i]>2)
+ sum += (bpm->length_array[i]-2);
+ break;
+ default:
+ fprintf(stderr,"error in bezierPatchMeshListNumTriangles, type invalid\n");
+ }
+ }
+ return sum;
+}
+
+/*delete degenerate triangles*/
+void bezierPatchMeshDelDeg(bezierPatchMesh* bpm)
+{
+ if(bpm == NULL) return;
+ int i,j,k;
+ int *new_length_array;
+ GLenum *new_type_array;
+ int index_new_length_array;
+ float *new_UVarray;
+ int index_new_UVarray;
+
+ new_length_array = (int*)malloc(sizeof(int) * bpm->index_length_array);
+ assert(new_length_array);
+ new_type_array = (GLenum*)malloc(sizeof(GLenum) * bpm->index_length_array);
+ assert(new_length_array);
+ new_UVarray = (float*) malloc(sizeof(float) * bpm->index_UVarray);
+ assert(new_UVarray);
+
+ index_new_length_array = 0;
+ index_new_UVarray=0;
+ k=0;
+ for(i=0; i<bpm->index_length_array; i++){
+
+ /*(if not degenerate, we have to copy*/
+ if( (bpm->length_array[i] != 3) || (!isDegenerate(bpm->UVarray+k, bpm->UVarray+k+2, bpm->UVarray+k+4)))
+ {
+ for(j=0; j<2* bpm->length_array[i]; j++)
+ new_UVarray[index_new_UVarray++] = bpm->UVarray[k++];
+
+ new_length_array[index_new_length_array] = bpm->length_array[i];
+ new_type_array[index_new_length_array] = bpm->type_array[i];
+ index_new_length_array++;
+ }
+ else
+ {
+ k += 6;
+ }
+ }
+ free(bpm->UVarray);
+ free(bpm->length_array);
+ free(bpm->type_array);
+ bpm->UVarray=new_UVarray;
+ bpm->length_array=new_length_array;
+ bpm->type_array=new_type_array;
+ bpm->index_UVarray = index_new_UVarray;
+ bpm->index_length_array = index_new_length_array;
+
+}
+
+/*(u,v) to XYZ
+ *the xyz and normals are stored in vertex_array,
+ *and normal_array. the spaces of both are allocated here
+ */
+void bezierPatchMeshEval(bezierPatchMesh* bpm)
+{
+ int i,j,k,l;
+ float u,v;
+ float u0 = bpm->bpatch->umin;
+ float u1 = bpm->bpatch->umax;
+ int uorder = bpm->bpatch->uorder;
+ float v0 = bpm->bpatch->vmin;
+ float v1 = bpm->bpatch->vmax;
+ int vorder = bpm->bpatch->vorder;
+ int dimension = bpm->bpatch->dimension;
+ int ustride = dimension * vorder;
+ int vstride = dimension;
+ float *ctlpoints = bpm->bpatch->ctlpoints;
+
+ bpm->vertex_array = (float*) malloc(sizeof(float)* (bpm->index_UVarray/2) * 3);
+ assert(bpm->vertex_array);
+ bpm->normal_array = (float*) malloc(sizeof(float)* (bpm->index_UVarray/2) * 3);
+ assert(bpm->normal_array);
+
+ k=0;
+ l=0;
+ for(i=0; i<bpm->index_length_array; i++)
+ {
+ for(j=0; j<bpm->length_array[i]; j++)
+ {
+ u = bpm->UVarray[k];
+ v = bpm->UVarray[k+1];
+ bezierSurfEval(u0,u1,uorder, v0, v1, vorder, dimension, ctlpoints, ustride, vstride, u,v, bpm->vertex_array+l);
+ bezierSurfEvalNormal(u0,u1,uorder, v0, v1, vorder, dimension, ctlpoints, ustride, vstride, u,v, bpm->normal_array+l);
+ k += 2;
+ l += 3;
+ }
+ }
+}
+
+void bezierPatchMeshListEval(bezierPatchMesh* list)
+{
+ bezierPatchMesh* temp;
+ for(temp = list; temp != NULL; temp = temp->next)
+ {
+ bezierPatchMeshEval(temp);
+ }
+}
+
+void bezierPatchMeshDraw(bezierPatchMesh* bpm)
+{
+ int i,j,k;
+ k=0;
+ /*k is the index of the first component of the current vertex*/
+ for(i=0; i<bpm->index_length_array; i++)
+ {
+ glBegin(bpm->type_array[i]);
+ for(j=0; j<bpm->length_array[i]; j++)
+ {
+ glNormal3fv(bpm->normal_array+k);
+ glVertex3fv(bpm->vertex_array+k);
+ k+= 3;
+ }
+ glEnd();
+ }
+}
+
+void bezierPatchMeshListDraw(bezierPatchMesh* list)
+{
+ bezierPatchMesh* temp;
+ for(temp = list; temp != NULL; temp = temp->next)
+ {
+ bezierPatchMeshDraw(temp);
+ }
+}
+
+void bezierPatchMeshListCollect(bezierPatchMesh* list, float **vertex_array, float **normal_array, int **length_array, GLenum **type_array, int *num_strips)
+{
+ int i,j,k,l;
+ bezierPatchMesh *temp;
+ int total_num_vertices = bezierPatchMeshListTotalVert(list);
+ (*vertex_array) = (float *) malloc(sizeof(float) * total_num_vertices*3);
+ assert(*vertex_array);
+ (*normal_array) = (float *) malloc(sizeof(float) * total_num_vertices*3);
+ assert(*normal_array);
+
+ *num_strips = bezierPatchMeshListTotalStrips(list);
+
+ *length_array = (int*) malloc(sizeof(int) * (*num_strips));
+ assert(*length_array);
+
+ *type_array = (GLenum*) malloc(sizeof(GLenum) * (*num_strips));
+ assert(*type_array);
+
+ k=0;
+ l=0;
+ for(temp = list; temp != NULL; temp = temp->next)
+ {
+ int x=0;
+ for(i=0; i<temp->index_length_array; i++)
+ {
+ for(j=0; j<temp->length_array[i]; j++)
+ {
+ (*vertex_array)[k] = temp->vertex_array[x];
+ (*vertex_array)[k+1] = temp->vertex_array[x+1];
+ (*vertex_array)[k+2] = temp->vertex_array[x+2];
+
+ (*normal_array)[k] = temp->normal_array[x];
+ (*normal_array)[k+1] = temp->normal_array[x+1];
+ (*normal_array)[k+2] = temp->normal_array[x+2];
+
+ x += 3;
+ k += 3;
+ }
+ (*type_array)[l] = temp->type_array[i];
+ (*length_array)[l++] = temp->length_array[i];
+ }
+ }
+}
+
+
+
+static int isDegenerate(float A[2], float B[2], float C[2])
+{
+ if( (A[0] == B[0] && A[1]==B[1]) ||
+ (A[0] == C[0] && A[1]==C[1]) ||
+ (B[0] == C[0] && B[1]==C[1])
+ )
+ return 1;
+ else
+ return 0;
+}
+
+
+
+
diff --git a/src/glu/sgi/libnurbs/interface/bezierPatchMesh.h b/src/glu/sgi/libnurbs/interface/bezierPatchMesh.h
new file mode 100644
index 00000000000..c3f4652e919
--- /dev/null
+++ b/src/glu/sgi/libnurbs/interface/bezierPatchMesh.h
@@ -0,0 +1,127 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/interface/bezierPatchMesh.h,v 1.1 2001/03/17 00:25:40 brianp Exp $
+*/
+
+#ifndef _BEZIERPATCHMESH_H
+#define _BEZIERPATCHMESH_H
+
+#include "bezierPatch.h"
+
+typedef struct bezierPatchMesh{
+ bezierPatch *bpatch; /*vertex*/
+ bezierPatch *bpatch_normal;
+ bezierPatch *bpatch_texcoord; /*s,t,r,q*/
+ bezierPatch *bpatch_color; /*RGBA*/
+
+ float *UVarray; /*all UV components of all vertices of all strips*/
+ int *length_array; /*[i] is the number of vertices in the ith strip*/
+ GLenum *type_array; /*[i] is the type of the ith primitive*/
+
+ /*to support dynamic insertion*/
+ int size_UVarray;
+ int index_UVarray;
+ int size_length_array;
+ int index_length_array;
+
+ int counter; /*track the current strip size*/
+ GLenum type; /*track the current type: 0: GL_TRIANGLES, 1: GL_TRIANGLE_STRIP*/
+
+ /*we eventually want to evaluate from (u,v) to (x,y,z) and draw them*/
+ float *vertex_array; /*each vertex contains three components*/
+ float *normal_array; /*each normal contains three components*/
+ float *color_array;
+ float *texcoord_array;
+
+ /*in case we need a linked list*/
+ struct bezierPatchMesh *next;
+} bezierPatchMesh;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+bezierPatchMesh *bezierPatchMeshMake(int maptype, float umin, float umax, int ustride, int uorder, float vmin, float vmax, int vstride, int vorder, float *ctlpoints, int size_UVarray, int size_length_array);
+
+/*initilize patches to be null*/
+bezierPatchMesh *bezierPatchMeshMake2(int size_UVarray, int size_length_array);
+
+void bezierPatchMeshPutPatch(bezierPatchMesh *bpm, int maptype, float umin, float umax, int ustride, int uorder, float vmin, float vmax, int vstride, int vorder, float *ctlpoints);
+
+void bezierPatchMeshDelete(bezierPatchMesh *bpm);
+
+void bezierPatchMeshBeginStrip(bezierPatchMesh *bpm, GLenum type);
+
+void bezierPatchMeshEndStrip(bezierPatchMesh *bpm);
+
+void bezierPatchMeshInsertUV(bezierPatchMesh *bpm, float u, float v);
+
+void bezierPatchMeshPrint(bezierPatchMesh *bpm);
+
+bezierPatchMesh* bezierPatchMeshListInsert(bezierPatchMesh* list, bezierPatchMesh* bpm);
+
+void bezierPatchMeshListPrint(bezierPatchMesh* list);
+
+int bezierPatchMeshListTotalStrips(bezierPatchMesh* list);
+
+int bezierPatchMeshListTotalVert(bezierPatchMesh* list);
+int bezierPatchMeshNumTriangles(bezierPatchMesh* bpm);
+int bezierPatchMeshListNumTriangles(bezierPatchMesh* list);
+
+void bezierPatchMeshDelDeg(bezierPatchMesh* bpm);
+
+
+void bezierPatchMeshEval(bezierPatchMesh* bpm);
+
+void bezierPatchMeshDraw(bezierPatchMesh* bpm);
+
+void bezierPatchMeshListDraw(bezierPatchMesh* list);
+void bezierPatchMeshListEval(bezierPatchMesh* list);
+void bezierPatchMeshListCollect(bezierPatchMesh* list, float **vertex_array, float **normal_array, int **length_array, GLenum **type_array, int *num_strips);
+
+void bezierPatchMeshListDelDeg(bezierPatchMesh* list);
+void bezierPatchMeshListDelete(bezierPatchMesh *list);
+bezierPatchMesh* bezierPatchMeshListReverse(bezierPatchMesh* list);
+void drawStrips(float *vertex_array, float *normal_array, int *length_array, GLenum *type_array, int num_strips);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/glu/sgi/libnurbs/interface/glcurveval.cc b/src/glu/sgi/libnurbs/interface/glcurveval.cc
new file mode 100644
index 00000000000..ca28237162b
--- /dev/null
+++ b/src/glu/sgi/libnurbs/interface/glcurveval.cc
@@ -0,0 +1,403 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * glcurveval.c++
+ *
+ * $Date: 2004/05/12 15:29:36 $ $Revision: 1.6 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/interface/glcurveval.cc,v 1.6 2004/05/12 15:29:36 brianp Exp $
+ */
+
+/* Polynomial Evaluator Interface */
+
+#include "gluos.h"
+#include "glimports.h"
+#include "glrenderer.h"
+#include "glcurveval.h"
+#include "nurbsconsts.h"
+
+OpenGLCurveEvaluator::OpenGLCurveEvaluator(void)
+{
+ //no default callback functions
+ beginCallBackN = NULL;
+ endCallBackN = NULL;
+ vertexCallBackN = NULL;
+ normalCallBackN = NULL;
+ colorCallBackN = NULL;
+ texcoordCallBackN = NULL;
+ beginCallBackData = NULL;
+ endCallBackData = NULL;
+ vertexCallBackData = NULL;
+ normalCallBackData = NULL;
+ colorCallBackData = NULL;
+ texcoordCallBackData = NULL;
+
+ userData = NULL;
+
+ vertex_flag = 0;
+ normal_flag = 0;
+ color_flag = 0;
+ texcoord_flag = 0;
+
+ em_vertex.uprime = -1.0;
+ em_normal.uprime = -1.0;
+ em_color.uprime = -1.0;
+ em_texcoord.uprime = -1.0;
+}
+
+OpenGLCurveEvaluator::~OpenGLCurveEvaluator(void)
+{
+}
+
+/* added nonsense to avoid the warning messages at compile time */
+void
+OpenGLCurveEvaluator::addMap(CurveMap *m)
+{
+ m = m;
+}
+
+void
+OpenGLCurveEvaluator::range1f(long type, REAL *from, REAL *to)
+{
+ type = type;
+ from = from;
+ to = to;
+}
+
+void
+OpenGLCurveEvaluator::domain1f(REAL ulo, REAL uhi)
+{
+ ulo = ulo;
+ uhi = uhi;
+}
+
+void
+OpenGLCurveEvaluator::bgnline(void)
+{
+ if(output_triangles)
+ beginCallBack(GL_LINE_STRIP, userData);
+ else
+ glBegin((GLenum) GL_LINE_STRIP);
+}
+
+void
+OpenGLCurveEvaluator::endline(void)
+{
+ if(output_triangles)
+ endCallBack(userData);
+ else
+ glEnd();
+}
+
+/*---------------------------------------------------------------------------
+ * disable - turn off a curve map
+ *---------------------------------------------------------------------------
+ */
+void
+OpenGLCurveEvaluator::disable(long type)
+{
+ glDisable((GLenum) type);
+}
+
+/*---------------------------------------------------------------------------
+ * enable - turn on a curve map
+ *---------------------------------------------------------------------------
+ */
+void
+OpenGLCurveEvaluator::enable(long type)
+{
+ glEnable((GLenum) type);
+}
+
+/*-------------------------------------------------------------------------
+ * mapgrid1f - define a lattice of points with origin and offset
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLCurveEvaluator::mapgrid1f(long nu, REAL u0, REAL u1)
+{
+ if(output_triangles)
+ {
+ global_grid_u0 = u0;
+ global_grid_u1 = u1;
+ global_grid_nu = (int) nu;
+ }
+ else
+ glMapGrid1f((GLint) nu, (GLfloat) u0, (GLfloat) u1);
+}
+
+/*-------------------------------------------------------------------------
+ * bgnmap1 - preamble to curve definition and evaluations
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLCurveEvaluator::bgnmap1f(long)
+{
+ if(output_triangles)
+ {
+ //initialized so that no maps are set initially
+ vertex_flag = 0;
+ normal_flag = 0;
+ color_flag = 0;
+ texcoord_flag = 0;
+ //no need to worry about gl states when doing callback
+ }
+ else
+ glPushAttrib((GLbitfield) GL_EVAL_BIT);
+}
+
+/*-------------------------------------------------------------------------
+ * endmap1 - postamble to a curve map
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLCurveEvaluator::endmap1f(void)
+{
+ if(output_triangles)
+ {
+
+ }
+ else
+ glPopAttrib();
+}
+
+/*-------------------------------------------------------------------------
+ * map1f - pass a desription of a curve map
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLCurveEvaluator::map1f(
+ long type, /* map type */
+ REAL ulo, /* lower parametric bound */
+ REAL uhi, /* upper parametric bound */
+ long stride, /* distance to next point in REALS */
+ long order, /* parametric order */
+ REAL *pts /* control points */
+)
+{
+ if(output_triangles)
+ {
+ int dimension = 0;
+ int which = 0;
+ switch(type){
+ case GL_MAP1_VERTEX_3:
+ which = 0;
+ dimension = 3;
+ break;
+ case GL_MAP1_VERTEX_4:
+ which=0;
+ dimension = 4;
+ break;
+ case GL_MAP1_INDEX:
+ which=2;
+ dimension = 1;
+ break;
+ case GL_MAP1_COLOR_4:
+ which=2;
+ dimension = 4;
+ break;
+ case GL_MAP1_NORMAL:
+ which=1;
+ dimension = 3;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ which=3;
+ dimension = 1;
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ which=3;
+ dimension = 2;
+ break;
+
+ case GL_MAP1_TEXTURE_COORD_3:
+ which=3;
+ dimension = 3;
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ which=3;
+ dimension = 4;
+ break;
+ }
+ inMap1f(which, dimension, ulo, uhi, stride, order, pts);
+ }
+ else
+ glMap1f((GLenum) type, (GLfloat) ulo, (GLfloat) uhi, (GLint) stride,
+ (GLint) order, (const GLfloat *) pts);
+}
+
+/*-------------------------------------------------------------------------
+ * mapmesh1f - evaluate a mesh of points on lattice
+ *-------------------------------------------------------------------------
+ */
+void OpenGLCurveEvaluator::mapmesh1f(long style, long from, long to)
+{
+ if(output_triangles)
+ {
+ inMapMesh1f((int) from, (int) to);
+ }
+ else
+ {
+ switch(style) {
+ default:
+ case N_MESHFILL:
+ case N_MESHLINE:
+ glEvalMesh1((GLenum) GL_LINE, (GLint) from, (GLint) to);
+ break;
+ case N_MESHPOINT:
+ glEvalMesh1((GLenum) GL_POINT, (GLint) from, (GLint) to);
+ break;
+ }
+ }
+}
+
+/*-------------------------------------------------------------------------
+ * evalpoint1i - evaluate a point on a curve
+ *-------------------------------------------------------------------------
+ */
+void OpenGLCurveEvaluator::evalpoint1i(long i)
+{
+ glEvalPoint1((GLint) i);
+}
+
+/*-------------------------------------------------------------------------
+ * evalcoord1f - evaluate a point on a curve
+ *-------------------------------------------------------------------------
+ */
+void OpenGLCurveEvaluator::evalcoord1f(long, REAL u)
+{
+ glEvalCoord1f((GLfloat) u);
+}
+
+void
+#ifdef _WIN32
+OpenGLCurveEvaluator::putCallBack(GLenum which, void (GLAPIENTRY *fn)())
+#else
+OpenGLCurveEvaluator::putCallBack(GLenum which, _GLUfuncptr fn)
+#endif
+{
+ switch(which)
+ {
+ case GLU_NURBS_BEGIN:
+ beginCallBackN = (void (GLAPIENTRY *) (GLenum)) fn;
+ break;
+ case GLU_NURBS_END:
+ endCallBackN = (void (GLAPIENTRY *) (void)) fn;
+ break;
+ case GLU_NURBS_VERTEX:
+ vertexCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn;
+ break;
+ case GLU_NURBS_NORMAL:
+ normalCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn;
+ break;
+ case GLU_NURBS_COLOR:
+ colorCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn;
+ break;
+ case GLU_NURBS_TEXTURE_COORD:
+ texcoordCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn;
+ break;
+ case GLU_NURBS_BEGIN_DATA:
+ beginCallBackData = (void (GLAPIENTRY *) (GLenum, void*)) fn;
+ break;
+ case GLU_NURBS_END_DATA:
+ endCallBackData = (void (GLAPIENTRY *) (void*)) fn;
+ break;
+ case GLU_NURBS_VERTEX_DATA:
+ vertexCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn;
+ break;
+ case GLU_NURBS_NORMAL_DATA:
+ normalCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn;
+ break;
+ case GLU_NURBS_COLOR_DATA:
+ colorCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn;
+ break;
+ case GLU_NURBS_TEXTURE_COORD_DATA:
+ texcoordCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn;
+ break;
+ }
+}
+
+void
+OpenGLCurveEvaluator::beginCallBack(GLenum which, void *data)
+{
+ if(beginCallBackData)
+ beginCallBackData(which, data);
+ else if(beginCallBackN)
+ beginCallBackN(which);
+}
+
+void
+OpenGLCurveEvaluator::endCallBack(void *data)
+{
+ if(endCallBackData)
+ endCallBackData(data);
+ else if(endCallBackN)
+ endCallBackN();
+}
+
+void
+OpenGLCurveEvaluator::vertexCallBack(const GLfloat *vert, void* data)
+{
+ if(vertexCallBackData)
+ vertexCallBackData(vert, data);
+ else if(vertexCallBackN)
+ vertexCallBackN(vert);
+}
+
+
+void
+OpenGLCurveEvaluator::normalCallBack(const GLfloat *normal, void* data)
+{
+ if(normalCallBackData)
+ normalCallBackData(normal, data);
+ else if(normalCallBackN)
+ normalCallBackN(normal);
+}
+
+void
+OpenGLCurveEvaluator::colorCallBack(const GLfloat *color, void* data)
+{
+ if(colorCallBackData)
+ colorCallBackData(color, data);
+ else if(colorCallBackN)
+ colorCallBackN(color);
+}
+
+void
+OpenGLCurveEvaluator::texcoordCallBack(const GLfloat *texcoord, void* data)
+{
+ if(texcoordCallBackData)
+ texcoordCallBackData(texcoord, data);
+ else if(texcoordCallBackN)
+ texcoordCallBackN(texcoord);
+}
diff --git a/src/glu/sgi/libnurbs/interface/glcurveval.h b/src/glu/sgi/libnurbs/interface/glcurveval.h
new file mode 100644
index 00000000000..4b44f6e847e
--- /dev/null
+++ b/src/glu/sgi/libnurbs/interface/glcurveval.h
@@ -0,0 +1,161 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * glcurveval.h
+ *
+ */
+
+#ifndef __gluglcurveval_h_
+#define __gluglcurveval_h_
+
+#include "gluos.h"
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include "basiccrveval.h"
+
+class CurveMap;
+
+/*for internal evaluator callback stuff*/
+#ifndef IN_MAX_BEZIER_ORDER
+#define IN_MAX_BEZIER_ORDER 40 /*XXX should be bigger than machine order*/
+#endif
+
+#ifndef IN_MAX_DIMENSION
+#define IN_MAX_DIMENSION 4
+#endif
+
+typedef struct curveEvalMachine{
+ REAL uprime; //cached previously evaluated uprime
+ int k; //the dimension
+ REAL u1;
+ REAL u2;
+ int ustride;
+ int uorder;
+ REAL ctlpoints[IN_MAX_BEZIER_ORDER*IN_MAX_DIMENSION];
+ REAL ucoeff[IN_MAX_BEZIER_ORDER];//cache the polynomial values
+} curveEvalMachine;
+
+class OpenGLCurveEvaluator : public BasicCurveEvaluator {
+public:
+ OpenGLCurveEvaluator(void);
+ virtual ~OpenGLCurveEvaluator(void);
+ void range1f(long, REAL *, REAL *);
+ void domain1f(REAL, REAL);
+ void addMap(CurveMap *);
+
+ void enable(long);
+ void disable(long);
+ void bgnmap1f(long);
+ void map1f(long, REAL, REAL, long, long, REAL *);
+ void mapgrid1f(long, REAL, REAL);
+ void mapmesh1f(long, long, long);
+ void evalpoint1i(long);
+ void evalcoord1f(long, REAL);
+ void endmap1f(void);
+
+ void bgnline(void);
+ void endline(void);
+
+ void put_vertices_call_back(int flag)
+ {
+ output_triangles = flag;
+ }
+#ifdef _WIN32
+ void putCallBack(GLenum which, void (APIENTRY *fn)() );
+#else
+ void putCallBack(GLenum which, _GLUfuncptr fn );
+#endif
+ void set_callback_userData(void *data)
+ {
+ userData = data;
+ }
+
+/*------------------begin for curveEvalMachine------------*/
+curveEvalMachine em_vertex;
+curveEvalMachine em_normal;
+curveEvalMachine em_color;
+curveEvalMachine em_texcoord;
+int vertex_flag; //whether there is a vertex map or not
+int normal_flag; //whether there is a normal map or not
+int color_flag; //whether there is a color map or not
+int texcoord_flag; //whether there is a texture map or not
+
+REAL global_grid_u0;
+REAL global_grid_u1;
+int global_grid_nu;
+
+void inMap1f(int which, //0: vert, 1: norm, 2: color, 3: tex
+ int dimension,
+ REAL ulower,
+ REAL uupper,
+ int ustride,
+ int uorder,
+ REAL *ctlpoints);
+
+void inPreEvaluate(int order, REAL vprime, REAL *coeff);
+void inDoDomain1(curveEvalMachine *em, REAL u, REAL *retPoint);
+void inDoEvalCoord1(REAL u);
+void inMapMesh1f(int umin, int umax);
+
+void (GLAPIENTRY *beginCallBackN) (GLenum type);
+void (GLAPIENTRY *endCallBackN) (void);
+void (GLAPIENTRY *vertexCallBackN) (const GLfloat *vert);
+void (GLAPIENTRY *normalCallBackN) (const GLfloat *normal);
+void (GLAPIENTRY *colorCallBackN) (const GLfloat *color);
+void (GLAPIENTRY *texcoordCallBackN) (const GLfloat *texcoord);
+
+void (GLAPIENTRY *beginCallBackData) (GLenum type, void* data);
+void (GLAPIENTRY *endCallBackData) (void* data);
+void (GLAPIENTRY *vertexCallBackData) (const GLfloat *vert, void* data);
+void (GLAPIENTRY *normalCallBackData) (const GLfloat *normal, void* data);
+void (GLAPIENTRY *colorCallBackData) (const GLfloat *color, void* data);
+void (GLAPIENTRY *texcoordCallBackData) (const GLfloat *texcoord, void* data);
+
+void* userData; //the opaque pointer for Data callback functions
+void beginCallBack(GLenum type, void* data);
+void endCallBack(void* data);
+void vertexCallBack(const GLfloat *vert, void *data);
+void normalCallBack(const GLfloat *normal, void* data);
+void colorCallBack(const GLfloat *color, void* data);
+void texcoordCallBack(const GLfloat *texcoord, void* data);
+
+
+/*------------------end for curveEvalMachine------------*/
+
+private:
+ int output_triangles; //true 1; false 0
+};
+
+#endif /* __gluglcurveval_h_ */
diff --git a/src/glu/sgi/libnurbs/interface/glimports.h b/src/glu/sgi/libnurbs/interface/glimports.h
new file mode 100644
index 00000000000..71a66bd553d
--- /dev/null
+++ b/src/glu/sgi/libnurbs/interface/glimports.h
@@ -0,0 +1,48 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * glimports.h
+ *
+ * $Date: 2001/03/19 17:52:02 $ $Revision: 1.3 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/interface/glimports.h,v 1.3 2001/03/19 17:52:02 pesco Exp $
+ */
+
+#ifndef __gluimports_h_
+#define __gluimports_h_
+
+#include "mystdlib.h"
+#include "mystdio.h"
+
+#endif /* __gluimports_h_ */
diff --git a/src/glu/sgi/libnurbs/interface/glinterface.cc b/src/glu/sgi/libnurbs/interface/glinterface.cc
new file mode 100644
index 00000000000..16f6422345c
--- /dev/null
+++ b/src/glu/sgi/libnurbs/interface/glinterface.cc
@@ -0,0 +1,471 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/07/16 15:46:42 $ $Revision: 1.2 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/interface/glinterface.cc,v 1.2 2001/07/16 15:46:42 brianp Exp $
+*/
+
+#include "gluos.h"
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <stdio.h>
+#include "glimports.h"
+#include "glrenderer.h"
+#include "nurbsconsts.h"
+
+//#define DOWN_LOAD_NURBS
+#ifdef DOWN_LOAD_NURBS
+
+#include "oglTrimNurbs.h"
+static int surfcount = 0;
+static oglTrimNurbs* otn = NULL;
+nurbSurf* tempNurb = NULL;
+oglTrimLoops* tempTrim = NULL;
+#endif
+
+
+//for LOD
+extern "C" {void glu_LOD_eval_list(GLUnurbs *nurb, int level);}
+
+void glu_LOD_eval_list(GLUnurbs *nurb, int level)
+{
+ nurb->LOD_eval_list(level);
+}
+
+GLUnurbs * GLAPIENTRY
+gluNewNurbsRenderer(void)
+{
+ GLUnurbs *t;
+
+ t = new GLUnurbs();
+ return t;
+}
+
+void GLAPIENTRY
+gluDeleteNurbsRenderer(GLUnurbs *r)
+{
+ delete r;
+}
+
+extern "C"
+void GLAPIENTRY
+
+gluDeleteNurbsTessellatorEXT(GLUnurbsObj *r)
+{
+ delete r;
+}
+
+void GLAPIENTRY
+gluBeginSurface(GLUnurbs *r)
+{
+#ifdef DOWN_LOAD_NURBS
+surfcount++;
+tempTrim = OTL_make(10,10);
+#endif
+ r->bgnsurface(0);
+}
+
+void GLAPIENTRY
+gluBeginCurve(GLUnurbs *r)
+{
+ r->bgncurve(0);
+}
+
+void GLAPIENTRY
+gluEndCurve(GLUnurbs *r)
+{
+ r->endcurve();
+}
+
+void GLAPIENTRY
+gluEndSurface(GLUnurbs *r)
+{
+#ifdef DOWN_LOAD_NURBS
+if(surfcount == 1)
+ otn = OTN_make(1);
+OTN_insert(otn, tempNurb, tempTrim);
+if(surfcount >= 1)
+{
+#ifdef DEBUG
+printf("write file\n");
+#endif
+OTN_write(otn, "out.otn");
+
+}
+#endif
+
+ r->endsurface();
+}
+
+void GLAPIENTRY
+gluBeginTrim(GLUnurbs *r)
+{
+#ifdef DOWN_LOAD_NURBS
+OTL_bgnTrim(tempTrim);
+#endif
+
+ r->bgntrim();
+}
+
+void GLAPIENTRY
+gluEndTrim(GLUnurbs *r)
+{
+#ifdef DOWN_LOAD_NURBS
+OTL_endTrim(tempTrim);
+#endif
+ r->endtrim();
+}
+
+void GLAPIENTRY
+gluPwlCurve(GLUnurbs *r, GLint count, INREAL array[],
+ GLint stride, GLenum type)
+{
+#ifdef DOWN_LOAD_NURBS
+OTL_pwlCurve(tempTrim, count, array, stride, type);
+#endif
+
+ int realType;
+ switch(type) {
+ case GLU_MAP1_TRIM_2:
+ realType = N_P2D;
+ break;
+ case GLU_MAP1_TRIM_3:
+ realType = N_P2DR;
+ break;
+ default:
+ realType = type;
+ break;
+ }
+ r->pwlcurve(count, array, sizeof(INREAL) * stride, realType);
+}
+
+void GLAPIENTRY
+gluNurbsCurve(GLUnurbs *r, GLint nknots, INREAL knot[], GLint stride,
+ INREAL ctlarray[], GLint order, GLenum type)
+{
+#ifdef DOWN_LOAD_NURBS
+OTL_nurbsCurve(tempTrim, nknots, knot, stride, ctlarray, order, type);
+#endif
+
+ int realType;
+
+ switch(type) {
+ case GLU_MAP1_TRIM_2:
+ realType = N_P2D;
+ break;
+ case GLU_MAP1_TRIM_3:
+ realType = N_P2DR;
+ break;
+ default:
+ realType = type;
+ break;
+ }
+
+ r->nurbscurve(nknots, knot, sizeof(INREAL) * stride, ctlarray, order,
+ realType);
+}
+
+void GLAPIENTRY
+gluNurbsSurface(GLUnurbs *r, GLint sknot_count, GLfloat *sknot,
+ GLint tknot_count, GLfloat *tknot,
+ GLint s_stride, GLint t_stride,
+ GLfloat *ctlarray, GLint sorder, GLint torder,
+ GLenum type)
+{
+#ifdef DOWN_LOAD_NURBS
+ {
+ int dimension;
+ switch(type){
+ case GL_MAP2_VERTEX_3:
+ dimension = 3;
+ break;
+ case GL_MAP2_VERTEX_4:
+ dimension = 4;
+ break;
+ default:
+ fprintf(stderr, "error in glinterface.c++, type no implemented\n");
+ exit(1);
+ }
+tempNurb = nurbSurfMake(sknot_count, sknot,
+ tknot_count, tknot,
+ sorder, torder,
+ dimension,
+ ctlarray,
+ s_stride, t_stride);
+
+ }
+#endif
+
+ r->nurbssurface(sknot_count, sknot, tknot_count, tknot,
+ sizeof(INREAL) * s_stride, sizeof(INREAL) * t_stride,
+ ctlarray, sorder, torder, type);
+}
+
+void GLAPIENTRY
+gluLoadSamplingMatrices(GLUnurbs *r, const GLfloat modelMatrix[16],
+ const GLfloat projMatrix[16],
+ const GLint viewport[4])
+{
+ r->useGLMatrices(modelMatrix, projMatrix, viewport);
+}
+
+void GLAPIENTRY
+gluNurbsProperty(GLUnurbs *r, GLenum property, GLfloat value)
+{
+ GLfloat nurbsValue;
+
+ switch (property) {
+ case GLU_AUTO_LOAD_MATRIX:
+ r->setautoloadmode(value);
+ return;
+
+ case GLU_CULLING:
+ if (value != 0.0) {
+ nurbsValue = N_CULLINGON;
+ } else {
+ nurbsValue = N_NOCULLING;
+ }
+ r->setnurbsproperty(GL_MAP2_VERTEX_3, N_CULLING, nurbsValue);
+ r->setnurbsproperty(GL_MAP2_VERTEX_4, N_CULLING, nurbsValue);
+ r->setnurbsproperty(GL_MAP1_VERTEX_3, N_CULLING, nurbsValue);
+ r->setnurbsproperty(GL_MAP1_VERTEX_4, N_CULLING, nurbsValue);
+ return;
+
+ case GLU_SAMPLING_METHOD:
+ if (value == GLU_PATH_LENGTH) {
+ nurbsValue = N_PATHLENGTH;
+ } else if (value == GLU_PARAMETRIC_ERROR) {
+ nurbsValue = N_PARAMETRICDISTANCE;
+ } else if (value == GLU_DOMAIN_DISTANCE) {
+ nurbsValue = N_DOMAINDISTANCE;
+ r->set_is_domain_distance_sampling(1); //optimzing untrimmed case
+
+ } else if (value == GLU_OBJECT_PARAMETRIC_ERROR) {
+ nurbsValue = N_OBJECTSPACE_PARA;
+ r->setautoloadmode( 0.0 );
+ r->setSamplingMatrixIdentity();
+ } else if (value == GLU_OBJECT_PATH_LENGTH) {
+ nurbsValue = N_OBJECTSPACE_PATH;
+ r->setautoloadmode( 0.0 );
+ r->setSamplingMatrixIdentity();
+ } else {
+ r->postError(GLU_INVALID_VALUE);
+ return;
+ }
+
+ r->setnurbsproperty(GL_MAP2_VERTEX_3, N_SAMPLINGMETHOD, nurbsValue);
+ r->setnurbsproperty(GL_MAP2_VERTEX_4, N_SAMPLINGMETHOD, nurbsValue);
+ r->setnurbsproperty(GL_MAP1_VERTEX_3, N_SAMPLINGMETHOD, nurbsValue);
+ r->setnurbsproperty(GL_MAP1_VERTEX_4, N_SAMPLINGMETHOD, nurbsValue);
+ return;
+
+ case GLU_SAMPLING_TOLERANCE:
+ r->setnurbsproperty(GL_MAP2_VERTEX_3, N_PIXEL_TOLERANCE, value);
+ r->setnurbsproperty(GL_MAP2_VERTEX_4, N_PIXEL_TOLERANCE, value);
+ r->setnurbsproperty(GL_MAP1_VERTEX_3, N_PIXEL_TOLERANCE, value);
+ r->setnurbsproperty(GL_MAP1_VERTEX_4, N_PIXEL_TOLERANCE, value);
+ return;
+
+ case GLU_PARAMETRIC_TOLERANCE:
+ r->setnurbsproperty(GL_MAP2_VERTEX_3, N_ERROR_TOLERANCE, value);
+ r->setnurbsproperty(GL_MAP2_VERTEX_4, N_ERROR_TOLERANCE, value);
+ r->setnurbsproperty(GL_MAP1_VERTEX_3, N_ERROR_TOLERANCE, value);
+ r->setnurbsproperty(GL_MAP1_VERTEX_4, N_ERROR_TOLERANCE, value);
+ return;
+
+
+ case GLU_DISPLAY_MODE:
+
+ if (value == GLU_FILL) {
+ nurbsValue = N_FILL;
+ } else if (value == GLU_OUTLINE_POLYGON) {
+ nurbsValue = N_OUTLINE_POLY;
+ } else if (value == GLU_OUTLINE_PATCH) {
+ nurbsValue = N_OUTLINE_PATCH;
+ } else {
+ r->postError(GLU_INVALID_VALUE);
+ return;
+ }
+ r->setnurbsproperty(N_DISPLAY, nurbsValue);
+
+ break;
+
+ case GLU_U_STEP:
+ r->setnurbsproperty(GL_MAP1_VERTEX_3, N_S_STEPS, value);
+ r->setnurbsproperty(GL_MAP1_VERTEX_4, N_S_STEPS, value);
+ r->setnurbsproperty(GL_MAP2_VERTEX_3, N_S_STEPS, value);
+ r->setnurbsproperty(GL_MAP2_VERTEX_4, N_S_STEPS, value);
+
+ //added for optimizing untrimmed case
+ r->set_domain_distance_u_rate(value);
+ break;
+
+ case GLU_V_STEP:
+ r->setnurbsproperty(GL_MAP1_VERTEX_3, N_T_STEPS, value);
+ r->setnurbsproperty(GL_MAP1_VERTEX_4, N_T_STEPS, value);
+ r->setnurbsproperty(GL_MAP2_VERTEX_3, N_T_STEPS, value);
+ r->setnurbsproperty(GL_MAP2_VERTEX_4, N_T_STEPS, value);
+
+ //added for optimizing untrimmed case
+ r->set_domain_distance_v_rate(value);
+ break;
+
+ case GLU_NURBS_MODE:
+ if(value == GLU_NURBS_RENDERER)
+ r->put_callbackFlag(0);
+ else if(value == GLU_NURBS_TESSELLATOR)
+ r->put_callbackFlag(1);
+ else
+ r->postError(GLU_INVALID_ENUM);
+ break;
+
+ default:
+ r->postError(GLU_INVALID_ENUM);
+ return;
+ }
+}
+
+void GLAPIENTRY
+gluGetNurbsProperty(GLUnurbs *r, GLenum property, GLfloat *value)
+{
+ GLfloat nurbsValue;
+
+ switch(property) {
+ case GLU_AUTO_LOAD_MATRIX:
+ if (r->getautoloadmode()) {
+ *value = GL_TRUE;
+ } else {
+ *value = GL_FALSE;
+ }
+ break;
+ case GLU_CULLING:
+ r->getnurbsproperty(GL_MAP2_VERTEX_3, N_CULLING, &nurbsValue);
+ if (nurbsValue == N_CULLINGON) {
+ *value = GL_TRUE;
+ } else {
+ *value = GL_FALSE;
+ }
+ break;
+ case GLU_SAMPLING_METHOD:
+ r->getnurbsproperty(GL_MAP2_VERTEX_3, N_SAMPLINGMETHOD, value);
+ if(*value == N_PATHLENGTH)
+ *value = GLU_PATH_LENGTH;
+ else if(*value == N_PARAMETRICDISTANCE)
+ *value = GLU_PARAMETRIC_ERROR;
+ else if(*value == N_DOMAINDISTANCE)
+ *value = GLU_DOMAIN_DISTANCE;
+ else if(*value == N_OBJECTSPACE_PATH)
+ *value = GLU_OBJECT_PATH_LENGTH;
+ else if(*value == N_OBJECTSPACE_PARA)
+ *value = GLU_OBJECT_PARAMETRIC_ERROR;
+ break;
+ case GLU_SAMPLING_TOLERANCE:
+ r->getnurbsproperty(GL_MAP2_VERTEX_3, N_PIXEL_TOLERANCE, value);
+ break;
+ case GLU_PARAMETRIC_TOLERANCE:
+ r->getnurbsproperty(GL_MAP2_VERTEX_3, N_ERROR_TOLERANCE, value);
+ break;
+
+ case GLU_U_STEP:
+ r->getnurbsproperty(GL_MAP2_VERTEX_3, N_S_STEPS, value);
+ break;
+ case GLU_V_STEP:
+ r->getnurbsproperty(GL_MAP2_VERTEX_3, N_T_STEPS, value);
+ break;
+ case GLU_DISPLAY_MODE:
+ r->getnurbsproperty(N_DISPLAY, &nurbsValue);
+ if (nurbsValue == N_FILL) {
+ *value = GLU_FILL;
+ } else if (nurbsValue == N_OUTLINE_POLY) {
+ *value = GLU_OUTLINE_POLYGON;
+ } else {
+ *value = GLU_OUTLINE_PATCH;
+ }
+ break;
+
+ case GLU_NURBS_MODE:
+ if(r->is_callback())
+ *value = GLU_NURBS_TESSELLATOR;
+ else
+ *value = GLU_NURBS_RENDERER;
+ break;
+
+ default:
+ r->postError(GLU_INVALID_ENUM);
+ return;
+ }
+}
+
+extern "C" void GLAPIENTRY
+gluNurbsCallback(GLUnurbs *r, GLenum which, _GLUfuncptr fn )
+{
+ switch (which) {
+ case GLU_NURBS_BEGIN:
+ case GLU_NURBS_END:
+ case GLU_NURBS_VERTEX:
+ case GLU_NURBS_NORMAL:
+ case GLU_NURBS_TEXTURE_COORD:
+ case GLU_NURBS_COLOR:
+ case GLU_NURBS_BEGIN_DATA:
+ case GLU_NURBS_END_DATA:
+ case GLU_NURBS_VERTEX_DATA:
+ case GLU_NURBS_NORMAL_DATA:
+ case GLU_NURBS_TEXTURE_COORD_DATA:
+ case GLU_NURBS_COLOR_DATA:
+ r->putSurfCallBack(which, fn);
+ break;
+
+ case GLU_NURBS_ERROR:
+ r->errorCallback = (void (APIENTRY *)( GLenum e )) fn;
+ break;
+ default:
+ r->postError(GLU_INVALID_ENUM);
+ return;
+ }
+}
+
+extern "C"
+void GLAPIENTRY
+gluNurbsCallbackDataEXT(GLUnurbs* r, void* userData)
+{
+ r->setNurbsCallbackData(userData);
+}
+
+extern "C"
+void GLAPIENTRY
+gluNurbsCallbackData(GLUnurbs* r, void* userData)
+{
+ gluNurbsCallbackDataEXT(r,userData);
+}
diff --git a/src/glu/sgi/libnurbs/interface/glrenderer.cc b/src/glu/sgi/libnurbs/interface/glrenderer.cc
new file mode 100644
index 00000000000..17123fbc614
--- /dev/null
+++ b/src/glu/sgi/libnurbs/interface/glrenderer.cc
@@ -0,0 +1,301 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include "gluos.h"
+#include "glimports.h"
+#include "glrenderer.h"
+
+GLUnurbs::GLUnurbs()
+ : NurbsTessellator(curveEvaluator, surfaceEvaluator)
+{
+ redefineMaps();
+ defineMap(GL_MAP2_NORMAL, 0, 3);
+ defineMap(GL_MAP1_NORMAL, 0, 3);
+ defineMap(GL_MAP2_TEXTURE_COORD_1, 0, 1);
+ defineMap(GL_MAP1_TEXTURE_COORD_1, 0, 1);
+ defineMap(GL_MAP2_TEXTURE_COORD_2, 0, 2);
+ defineMap(GL_MAP1_TEXTURE_COORD_2, 0, 2);
+ defineMap(GL_MAP2_TEXTURE_COORD_3, 0, 3);
+ defineMap(GL_MAP1_TEXTURE_COORD_3, 0, 3);
+ defineMap(GL_MAP2_TEXTURE_COORD_4, 1, 4);
+ defineMap(GL_MAP1_TEXTURE_COORD_4, 1, 4);
+ defineMap(GL_MAP2_VERTEX_4, 1, 4);
+ defineMap(GL_MAP1_VERTEX_4, 1, 4);
+ defineMap(GL_MAP2_VERTEX_3, 0, 3);
+ defineMap(GL_MAP1_VERTEX_3, 0, 3);
+ defineMap(GL_MAP2_COLOR_4, 0, 4);
+ defineMap(GL_MAP1_COLOR_4, 0, 4);
+ defineMap(GL_MAP2_INDEX, 0, 1);
+ defineMap(GL_MAP1_INDEX, 0, 1);
+
+ setnurbsproperty(GL_MAP1_VERTEX_3, N_SAMPLINGMETHOD, (float) N_PATHLENGTH);
+ setnurbsproperty(GL_MAP1_VERTEX_4, N_SAMPLINGMETHOD, (float) N_PATHLENGTH);
+ setnurbsproperty(GL_MAP2_VERTEX_3, N_SAMPLINGMETHOD, (float) N_PATHLENGTH);
+ setnurbsproperty(GL_MAP2_VERTEX_4, N_SAMPLINGMETHOD, (float) N_PATHLENGTH);
+
+ setnurbsproperty(GL_MAP1_VERTEX_3, N_PIXEL_TOLERANCE, (float) 50.0);
+ setnurbsproperty(GL_MAP1_VERTEX_4, N_PIXEL_TOLERANCE, (float) 50.0);
+ setnurbsproperty(GL_MAP2_VERTEX_3, N_PIXEL_TOLERANCE, (float) 50.0);
+ setnurbsproperty(GL_MAP2_VERTEX_4, N_PIXEL_TOLERANCE, (float) 50.0);
+
+ setnurbsproperty(GL_MAP1_VERTEX_3, N_ERROR_TOLERANCE, (float) 0.50);
+ setnurbsproperty(GL_MAP1_VERTEX_4, N_ERROR_TOLERANCE, (float) 0.50);
+ setnurbsproperty(GL_MAP2_VERTEX_3, N_ERROR_TOLERANCE, (float) 0.50);
+ setnurbsproperty(GL_MAP2_VERTEX_4, N_ERROR_TOLERANCE, (float) 0.50);
+
+ setnurbsproperty(GL_MAP1_VERTEX_3, N_S_STEPS, (float) 100.0);
+ setnurbsproperty(GL_MAP1_VERTEX_4, N_S_STEPS, (float) 100.0);
+ setnurbsproperty(GL_MAP2_VERTEX_3, N_S_STEPS, (float) 100.0);
+ setnurbsproperty(GL_MAP2_VERTEX_4, N_S_STEPS, (float) 100.0);
+
+ //added for optimizing untrimmed case
+ set_domain_distance_u_rate(100.0);
+
+ setnurbsproperty(GL_MAP1_VERTEX_3, N_T_STEPS, (float) 100.0);
+ setnurbsproperty(GL_MAP1_VERTEX_4, N_T_STEPS, (float) 100.0);
+ setnurbsproperty(GL_MAP2_VERTEX_3, N_T_STEPS, (float) 100.0);
+ setnurbsproperty(GL_MAP2_VERTEX_4, N_T_STEPS, (float) 100.0);
+
+ //added for optimizing untrimmed case
+ set_domain_distance_v_rate(100.0);
+ set_is_domain_distance_sampling(0); //since the default is path_length
+
+ //default autoloadmode is true
+ autoloadmode = 1;
+
+ //default callbackFlag is 0
+ callbackFlag = 0;
+
+ errorCallback = NULL;
+}
+
+void
+GLUnurbs::bgnrender(void)
+{
+ if (autoloadmode) {
+ loadGLMatrices();
+ }
+}
+
+void
+GLUnurbs::endrender(void)
+{
+}
+
+void
+GLUnurbs::errorHandler(int i)
+{
+ int gluError;
+
+ gluError = i + (GLU_NURBS_ERROR1 - 1);
+ postError( gluError );
+}
+
+void
+GLUnurbs::loadGLMatrices(void)
+{
+ GLfloat vmat[4][4];
+ GLint viewport[4];
+
+ grabGLMatrix((GLfloat (*)[4]) vmat);
+ loadCullingMatrix((GLfloat (*)[4]) vmat);
+ ::glGetIntegerv((GLenum) GL_VIEWPORT, (GLint *) viewport);
+ loadSamplingMatrix((const GLfloat (*)[4]) vmat, (const GLint *) viewport);
+}
+
+void
+GLUnurbs::useGLMatrices(const GLfloat modelMatrix[16],
+ const GLfloat projMatrix[16],
+ const GLint viewport[4])
+{
+ GLfloat vmat[4][4];
+
+ multmatrix4d(vmat, (const GLfloat (*)[4]) modelMatrix,
+ (const GLfloat (*)[4]) projMatrix);
+ loadCullingMatrix((GLfloat (*)[4]) vmat);
+ loadSamplingMatrix((const GLfloat (*)[4]) vmat, (const GLint *) viewport);
+}
+
+/*--------------------------------------------------------------------------
+ * grabGLMatrix
+ *--------------------------------------------------------------------------
+ */
+
+void
+GLUnurbs::grabGLMatrix(GLfloat vmat[4][4])
+{
+ GLfloat m1[4][4], m2[4][4];
+
+ ::glGetFloatv((GLenum) GL_MODELVIEW_MATRIX, (GLfloat *) &(m1[0][0]));
+ ::glGetFloatv((GLenum) GL_PROJECTION_MATRIX, (GLfloat *) &(m2[0][0]));
+ multmatrix4d((GLfloat (*)[4]) vmat,
+ (const GLfloat (*)[4]) m1, (const GLfloat (*)[4]) m2);
+}
+
+//for object space tesselation: view independent
+void
+GLUnurbs::setSamplingMatrixIdentity( void )
+{
+ INREAL smat[4][4] = {
+ {1,0,0,0},
+ {0,1,0,0},
+ {0,0,1,0},
+ {0,0,0,1}
+ };
+ const long rstride = sizeof(smat[0]) / sizeof(smat[0][0]);
+ const long cstride = 1;
+
+ setnurbsproperty(GL_MAP1_VERTEX_3, N_SAMPLINGMATRIX, &smat[0][0], rstride,
+ cstride);
+ setnurbsproperty(GL_MAP1_VERTEX_4, N_SAMPLINGMATRIX, &smat[0][0], rstride,
+ cstride);
+ setnurbsproperty(GL_MAP2_VERTEX_3, N_SAMPLINGMATRIX, &smat[0][0], rstride,
+ cstride);
+ setnurbsproperty(GL_MAP2_VERTEX_4, N_SAMPLINGMATRIX, &smat[0][0], rstride,
+ cstride);
+}
+
+
+void
+GLUnurbs::loadSamplingMatrix(const GLfloat vmat[4][4],
+ const GLint viewport[4])
+{
+
+ /* rescale the mapping to correspond to pixels in x/y */
+ REAL xsize = 0.5 * (REAL) (viewport[2]);
+ REAL ysize = 0.5 * (REAL) (viewport[3]);
+
+ INREAL smat[4][4];
+ smat[0][0] = vmat[0][0] * xsize;
+ smat[1][0] = vmat[1][0] * xsize;
+ smat[2][0] = vmat[2][0] * xsize;
+ smat[3][0] = vmat[3][0] * xsize;
+
+ smat[0][1] = vmat[0][1] * ysize;
+ smat[1][1] = vmat[1][1] * ysize;
+ smat[2][1] = vmat[2][1] * ysize;
+ smat[3][1] = vmat[3][1] * ysize;
+
+ smat[0][2] = 0.0;
+ smat[1][2] = 0.0;
+ smat[2][2] = 0.0;
+ smat[3][2] = 0.0;
+
+ smat[0][3] = vmat[0][3];
+ smat[1][3] = vmat[1][3];
+ smat[2][3] = vmat[2][3];
+ smat[3][3] = vmat[3][3];
+
+ const long rstride = sizeof(smat[0]) / sizeof(smat[0][0]);
+ const long cstride = 1;
+
+ setnurbsproperty(GL_MAP1_VERTEX_3, N_SAMPLINGMATRIX, &smat[0][0], rstride,
+ cstride);
+ setnurbsproperty(GL_MAP1_VERTEX_4, N_SAMPLINGMATRIX, &smat[0][0], rstride,
+ cstride);
+ setnurbsproperty(GL_MAP2_VERTEX_3, N_SAMPLINGMATRIX, &smat[0][0], rstride,
+ cstride);
+ setnurbsproperty(GL_MAP2_VERTEX_4, N_SAMPLINGMATRIX, &smat[0][0], rstride,
+ cstride);
+}
+
+void
+GLUnurbs::loadCullingMatrix(GLfloat vmat[4][4])
+{
+ INREAL cmat[4][4];
+
+ cmat[0][0] = vmat[0][0];
+ cmat[0][1] = vmat[0][1];
+ cmat[0][2] = vmat[0][2];
+ cmat[0][3] = vmat[0][3];
+
+ cmat[1][0] = vmat[1][0];
+ cmat[1][1] = vmat[1][1];
+ cmat[1][2] = vmat[1][2];
+ cmat[1][3] = vmat[1][3];
+
+ cmat[2][0] = vmat[2][0];
+ cmat[2][1] = vmat[2][1];
+ cmat[2][2] = vmat[2][2];
+ cmat[2][3] = vmat[2][3];
+
+ cmat[3][0] = vmat[3][0];
+ cmat[3][1] = vmat[3][1];
+ cmat[3][2] = vmat[3][2];
+ cmat[3][3] = vmat[3][3];
+
+ const long rstride = sizeof(cmat[0]) / sizeof(cmat[0][0]);
+ const long cstride = 1;
+
+ setnurbsproperty(GL_MAP2_VERTEX_3, N_CULLINGMATRIX, &cmat[0][0], rstride,
+ cstride);
+ setnurbsproperty(GL_MAP2_VERTEX_4, N_CULLINGMATRIX, &cmat[0][0], rstride,
+ cstride);
+ //added for curves by zl
+ setnurbsproperty(GL_MAP1_VERTEX_3, N_CULLINGMATRIX, &cmat[0][0], rstride,
+ cstride);
+ setnurbsproperty(GL_MAP1_VERTEX_4, N_CULLINGMATRIX, &cmat[0][0], rstride,
+ cstride);
+}
+
+/*---------------------------------------------------------------------
+ * A = B * MAT ; transform a 4d vector through a 4x4 matrix
+ *---------------------------------------------------------------------
+ */
+void
+GLUnurbs::transform4d(GLfloat A[4], GLfloat B[4], GLfloat mat[4][4])
+{
+
+ A[0] = B[0]*mat[0][0] + B[1]*mat[1][0] + B[2]*mat[2][0] + B[3]*mat[3][0];
+ A[1] = B[0]*mat[0][1] + B[1]*mat[1][1] + B[2]*mat[2][1] + B[3]*mat[3][1];
+ A[2] = B[0]*mat[0][2] + B[1]*mat[1][2] + B[2]*mat[2][2] + B[3]*mat[3][2];
+ A[3] = B[0]*mat[0][3] + B[1]*mat[1][3] + B[2]*mat[2][3] + B[3]*mat[3][3];
+}
+
+/*---------------------------------------------------------------------
+ * new = [left][right] ; multiply two matrices together
+ *---------------------------------------------------------------------
+ */
+void
+GLUnurbs::multmatrix4d (GLfloat n[4][4], const GLfloat left[4][4],
+ const GLfloat right[4][4])
+{
+ transform4d ((GLfloat *) n[0],(GLfloat *) left[0],(GLfloat (*)[4]) right);
+ transform4d ((GLfloat *) n[1],(GLfloat *) left[1],(GLfloat (*)[4]) right);
+ transform4d ((GLfloat *) n[2],(GLfloat *) left[2],(GLfloat (*)[4]) right);
+ transform4d ((GLfloat *) n[3],(GLfloat *) left[3],(GLfloat (*)[4]) right);
+}
diff --git a/src/glu/sgi/libnurbs/interface/glrenderer.h b/src/glu/sgi/libnurbs/interface/glrenderer.h
new file mode 100644
index 00000000000..c8bd08823c2
--- /dev/null
+++ b/src/glu/sgi/libnurbs/interface/glrenderer.h
@@ -0,0 +1,152 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * glrenderer.h
+ *
+ * $Date: 2004/02/26 14:58:11 $ $Revision: 1.4 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/interface/glrenderer.h,v 1.4 2004/02/26 14:58:11 brianp Exp $
+ */
+
+#ifndef __gluglrenderer_h_
+#define __gluglrenderer_h_
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include "nurbstess.h"
+#include "glsurfeval.h"
+#include "glcurveval.h"
+
+extern "C" {
+ typedef void (APIENTRY *errorCallbackType)( GLenum );
+}
+
+class GLUnurbs : public NurbsTessellator {
+
+public:
+ GLUnurbs( void );
+ void loadGLMatrices( void );
+ void useGLMatrices( const GLfloat modelMatrix[16],
+ const GLfloat projMatrix[16],
+ const GLint viewport[4] );
+ void setSamplingMatrixIdentity( void );
+
+ void errorHandler( int );
+ void bgnrender( void );
+ void endrender( void );
+ void setautoloadmode( INREAL value )
+ {
+
+ if (value) autoloadmode = GL_TRUE;
+ else autoloadmode = GL_FALSE;
+
+ }
+ GLboolean getautoloadmode( void ) { return autoloadmode; }
+
+ errorCallbackType errorCallback;
+ void postError( int which )
+ { if (errorCallback) (errorCallback)( (GLenum)which ); }
+#ifdef _WIN32
+ void putSurfCallBack(GLenum which, void (GLAPIENTRY *fn)() )
+#else
+ void putSurfCallBack(GLenum which, _GLUfuncptr fn )
+#endif
+ {
+ curveEvaluator.putCallBack(which, fn);
+ surfaceEvaluator.putCallBack(which, fn);
+ }
+
+ int get_vertices_call_back()
+ {
+ return surfaceEvaluator.get_vertices_call_back();
+ }
+
+ void put_vertices_call_back(int flag)
+ {
+ surfaceEvaluator.put_vertices_call_back(flag);
+ }
+
+ int get_callback_auto_normal()
+ {
+ return surfaceEvaluator.get_callback_auto_normal();
+ }
+
+ void put_callback_auto_normal(int flag)
+ {
+ surfaceEvaluator.put_callback_auto_normal(flag);
+ }
+
+ void setNurbsCallbackData(void* userData)
+ {
+ curveEvaluator.set_callback_userData(userData);
+ surfaceEvaluator.set_callback_userData(userData);
+ }
+
+
+ //for LOD
+ void LOD_eval_list(int level)
+ {
+ surfaceEvaluator.LOD_eval_list(level);
+ }
+
+ //NEWCALLBACK
+ int is_callback()
+ {
+ return callbackFlag;
+ }
+ void put_callbackFlag(int flag)
+ {
+ callbackFlag = flag;
+ surfaceEvaluator.put_vertices_call_back(flag);
+ curveEvaluator.put_vertices_call_back(flag);
+ }
+
+private:
+ GLboolean autoloadmode;
+ OpenGLSurfaceEvaluator surfaceEvaluator;
+ OpenGLCurveEvaluator curveEvaluator;
+
+ void loadSamplingMatrix( const GLfloat vmat[4][4],
+ const GLint viewport[4] );
+ void loadCullingMatrix( GLfloat vmat[4][4] );
+ static void grabGLMatrix( GLfloat vmat[4][4] );
+ static void transform4d( GLfloat A[4], GLfloat B[4],
+ GLfloat mat[4][4] );
+ static void multmatrix4d( GLfloat n[4][4], const GLfloat left[4][4],
+ const GLfloat right[4][4] );
+
+ int callbackFlag;
+};
+
+#endif /* __gluglrenderer_h_ */
diff --git a/src/glu/sgi/libnurbs/interface/glsurfeval.cc b/src/glu/sgi/libnurbs/interface/glsurfeval.cc
new file mode 100644
index 00000000000..cb2cf8ee0be
--- /dev/null
+++ b/src/glu/sgi/libnurbs/interface/glsurfeval.cc
@@ -0,0 +1,1290 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * glsurfeval.c++
+ *
+ */
+
+/* Polynomial Evaluator Interface */
+#include "gluos.h"
+#include <stdio.h>
+#include "glimports.h"
+#include "glrenderer.h"
+#include "glsurfeval.h"
+#include "nurbsconsts.h"
+#include "bezierPatchMesh.h"
+
+
+//extern int surfcount;
+//int surfcount=0;
+
+/*#define USE_INTERNAL_EVAL*/ //use internal evaluator
+
+/*whether do evaluation or not*/
+/*#define NO_EVALUATION*/
+
+//#define USE_LOD //for LOD test, have to turn on USE_LOD in insurfeval.c++ too
+
+/*for statistics*/
+//#define STATISTICS
+#ifdef STATISTICS
+static int STAT_num_of_triangles=0;
+static int STAT_num_of_eval_vertices=0;
+static int STAT_num_of_quad_strips=0;
+#endif
+
+/*for output triangles*/
+/*#define OUTPUT_TRIANGLES*/
+
+
+/*#define FOR_CHRIS*/
+#ifdef FOR_CHRIS
+extern "C" { void evalUStripExt(int n_upper, REAL v_upper, REAL* upper_val,
+ int n_lower, REAL v_lower, REAL* lower_val);}
+
+extern "C" { void evalVStripExt(int n_left, REAL u_left, REAL* left_val,
+ int n_right, REAL u_right, REAL* right_val);
+ }
+#endif
+
+
+/**************begin for LOD_eval_list***********/
+void OpenGLSurfaceEvaluator::LOD_eval_list(int level)
+{
+ if(level == 0)
+ LOD_eval_level = 1;
+ else if(level == 1)
+ LOD_eval_level = 2;
+ else if(level == 2)
+ LOD_eval_level = 4;
+ else
+ LOD_eval_level = 8;
+
+ inBPMListEvalEM(global_bpm);
+}
+
+
+OpenGLSurfaceEvaluator::OpenGLSurfaceEvaluator()
+{
+ int i;
+
+ for (i=0; i<VERTEX_CACHE_SIZE; i++) {
+ vertexCache[i] = new StoredVertex;
+ }
+ tmeshing = 0;
+ which = 0;
+ vcount = 0;
+
+ global_uorder = 0;
+ global_vorder = 0;
+ global_uprime = -1.0;
+ global_vprime = -1.0;
+ global_vprime_BV = -1.0;
+ global_uprime_BU = -1.0;
+ global_uorder_BU = 0;
+ global_vorder_BU = 0;
+ global_uorder_BV = 0;
+ global_vorder_BV = 0;
+ global_baseData = NULL;
+
+ global_bpm = NULL;
+ output_triangles = 0; //don't output triangles by default
+
+ //no default callback functions
+ beginCallBackN = NULL;
+ endCallBackN = NULL;
+ vertexCallBackN = NULL;
+ normalCallBackN = NULL;
+ colorCallBackN = NULL;
+ texcoordCallBackN = NULL;
+ beginCallBackData = NULL;
+ endCallBackData = NULL;
+ vertexCallBackData = NULL;
+ normalCallBackData = NULL;
+ colorCallBackData = NULL;
+ texcoordCallBackData = NULL;
+
+ userData = NULL;
+
+ auto_normal_flag = 0;
+ callback_auto_normal = 0; //default of GLU_CALLBACK_AUTO_NORMAL is 0
+ vertex_flag = 0;
+ normal_flag = 0;
+ color_flag = 0;
+ texcoord_flag = 0;
+
+ em_vertex.uprime = -1.0;
+ em_vertex.vprime = -1.0;
+ em_normal.uprime = -1.0;
+ em_normal.vprime = -1.0;
+ em_color.uprime = -1.0;
+ em_color.vprime = -1.0;
+ em_texcoord.uprime = -1.0;
+ em_texcoord.vprime = -1.0;
+
+#ifdef USE_LOD
+ LOD_eval_level = 1;
+#endif
+}
+
+OpenGLSurfaceEvaluator::~OpenGLSurfaceEvaluator()
+{
+ for (int ii= 0; ii< VERTEX_CACHE_SIZE; ii++) {
+ delete vertexCache[ii];
+ vertexCache[ii]= 0;
+ }
+}
+
+/*---------------------------------------------------------------------------
+ * disable - turn off a map
+ *---------------------------------------------------------------------------
+ */
+void
+OpenGLSurfaceEvaluator::disable(long type)
+{
+ glDisable((GLenum) type);
+}
+
+/*---------------------------------------------------------------------------
+ * enable - turn on a map
+ *---------------------------------------------------------------------------
+ */
+void
+OpenGLSurfaceEvaluator::enable(long type)
+{
+ glEnable((GLenum) type);
+}
+
+/*-------------------------------------------------------------------------
+ * mapgrid2f - define a lattice of points with origin and offset
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLSurfaceEvaluator::mapgrid2f(long nu, REAL u0, REAL u1, long nv, REAL v0, REAL v1)
+{
+#ifdef USE_INTERNAL_EVAL
+ inMapGrid2f((int) nu, (REAL) u0, (REAL) u1, (int) nv,
+ (REAL) v0, (REAL) v1);
+#else
+
+ if(output_triangles)
+ {
+ global_grid_u0 = u0;
+ global_grid_u1 = u1;
+ global_grid_nu = nu;
+ global_grid_v0 = v0;
+ global_grid_v1 = v1;
+ global_grid_nv = nv;
+ }
+ else
+ glMapGrid2d((GLint) nu, (GLdouble) u0, (GLdouble) u1, (GLint) nv,
+ (GLdouble) v0, (GLdouble) v1);
+
+#endif
+}
+
+void
+OpenGLSurfaceEvaluator::polymode(long style)
+{
+ if(! output_triangles)
+ {
+ switch(style) {
+ default:
+ case N_MESHFILL:
+
+ glPolygonMode((GLenum) GL_FRONT_AND_BACK, (GLenum) GL_FILL);
+ break;
+ case N_MESHLINE:
+ glPolygonMode((GLenum) GL_FRONT_AND_BACK, (GLenum) GL_LINE);
+ break;
+ case N_MESHPOINT:
+ glPolygonMode((GLenum) GL_FRONT_AND_BACK, (GLenum) GL_POINT);
+ break;
+ }
+ }
+}
+
+void
+OpenGLSurfaceEvaluator::bgnline(void)
+{
+ if(output_triangles)
+ bezierPatchMeshBeginStrip(global_bpm, GL_LINE_STRIP);
+ else
+ glBegin((GLenum) GL_LINE_STRIP);
+}
+
+void
+OpenGLSurfaceEvaluator::endline(void)
+{
+ if(output_triangles)
+ bezierPatchMeshEndStrip(global_bpm);
+ else
+ glEnd();
+}
+
+void
+OpenGLSurfaceEvaluator::range2f(long type, REAL *from, REAL *to)
+{
+}
+
+void
+OpenGLSurfaceEvaluator::domain2f(REAL ulo, REAL uhi, REAL vlo, REAL vhi)
+{
+}
+
+void
+OpenGLSurfaceEvaluator::bgnclosedline(void)
+{
+ if(output_triangles)
+ bezierPatchMeshBeginStrip(global_bpm, GL_LINE_LOOP);
+ else
+ glBegin((GLenum) GL_LINE_LOOP);
+}
+
+void
+OpenGLSurfaceEvaluator::endclosedline(void)
+{
+ if(output_triangles)
+ bezierPatchMeshEndStrip(global_bpm);
+ else
+ glEnd();
+}
+
+
+
+
+
+void
+OpenGLSurfaceEvaluator::bgntmesh(void)
+{
+
+ tmeshing = 1;
+ which = 0;
+ vcount = 0;
+
+ if(output_triangles)
+ bezierPatchMeshBeginStrip(global_bpm, GL_TRIANGLES);
+ else
+ glBegin((GLenum) GL_TRIANGLES);
+
+}
+
+void
+OpenGLSurfaceEvaluator::swaptmesh(void)
+{
+ which = 1 - which;
+
+}
+
+void
+OpenGLSurfaceEvaluator::endtmesh(void)
+{
+ tmeshing = 0;
+
+
+ if(output_triangles)
+ bezierPatchMeshEndStrip(global_bpm);
+ else
+ glEnd();
+}
+
+void
+OpenGLSurfaceEvaluator::bgntfan(void)
+{
+
+ if(output_triangles)
+ bezierPatchMeshBeginStrip(global_bpm, GL_TRIANGLE_FAN);
+ else
+ glBegin((GLenum) GL_TRIANGLE_FAN);
+
+}
+void
+OpenGLSurfaceEvaluator::endtfan(void)
+{
+ if(output_triangles)
+ bezierPatchMeshEndStrip(global_bpm);
+ else
+ glEnd();
+}
+
+void
+OpenGLSurfaceEvaluator::evalUStrip(int n_upper, REAL v_upper, REAL* upper_val, int n_lower, REAL v_lower, REAL* lower_val)
+{
+#ifdef USE_INTERNAL_EVAL
+ inEvalUStrip(n_upper, v_upper, upper_val,
+ n_lower, v_lower, lower_val);
+#else
+
+#ifdef FOR_CHRIS
+ evalUStripExt(n_upper, v_upper, upper_val,
+ n_lower, v_lower, lower_val);
+ return;
+
+#endif
+ int i,j,k,l;
+ REAL leftMostV[2];
+
+ /*
+ *the algorithm works by scanning from left to right.
+ *leftMostV: the left most of the remaining verteces (on both upper and lower).
+ * it could an element of upperVerts or lowerVerts.
+ *i: upperVerts[i] is the first vertex to the right of leftMostV on upper line
+ *j: lowerVerts[j] is the first vertex to the right of leftMostV on lower line
+ */
+
+ /*initialize i,j,and leftMostV
+ */
+ if(upper_val[0] <= lower_val[0])
+ {
+ i=1;
+ j=0;
+
+ leftMostV[0] = upper_val[0];
+ leftMostV[1] = v_upper;
+ }
+ else
+ {
+ i=0;
+ j=1;
+
+ leftMostV[0] = lower_val[0];
+ leftMostV[1] = v_lower;
+
+ }
+
+ /*the main loop.
+ *the invariance is that:
+ *at the beginning of each loop, the meaning of i,j,and leftMostV are
+ *maintained
+ */
+ while(1)
+ {
+ if(i >= n_upper) /*case1: no more in upper*/
+ {
+ if(j<n_lower-1) /*at least two vertices in lower*/
+ {
+ bgntfan();
+ coord2f(leftMostV[0], leftMostV[1]);
+// glNormal3fv(leftMostNormal);
+// glVertex3fv(leftMostXYZ);
+
+ while(j<n_lower){
+ coord2f(lower_val[j], v_lower);
+// glNormal3fv(lowerNormal[j]);
+// glVertex3fv(lowerXYZ[j]);
+ j++;
+
+ }
+ endtfan();
+ }
+ break; /*exit the main loop*/
+ }
+ else if(j>= n_lower) /*case2: no more in lower*/
+ {
+ if(i<n_upper-1) /*at least two vertices in upper*/
+ {
+ bgntfan();
+ coord2f(leftMostV[0], leftMostV[1]);
+// glNormal3fv(leftMostNormal);
+// glVertex3fv(leftMostXYZ);
+
+ for(k=n_upper-1; k>=i; k--) /*reverse order for two-side lighting*/
+ {
+ coord2f(upper_val[k], v_upper);
+// glNormal3fv(upperNormal[k]);
+// glVertex3fv(upperXYZ[k]);
+ }
+
+ endtfan();
+ }
+ break; /*exit the main loop*/
+ }
+ else /* case3: neither is empty, plus the leftMostV, there is at least one triangle to output*/
+ {
+ if(upper_val[i] <= lower_val[j])
+ {
+ bgntfan();
+ coord2f(lower_val[j], v_lower);
+// glNormal3fv(lowerNormal[j]);
+// glVertex3fv(lowerXYZ[j]);
+
+ /*find the last k>=i such that
+ *upperverts[k][0] <= lowerverts[j][0]
+ */
+ k=i;
+
+ while(k<n_upper)
+ {
+ if(upper_val[k] > lower_val[j])
+ break;
+ k++;
+
+ }
+ k--;
+
+
+ for(l=k; l>=i; l--)/*the reverse is for two-side lighting*/
+ {
+ coord2f(upper_val[l], v_upper);
+// glNormal3fv(upperNormal[l]);
+// glVertex3fv(upperXYZ[l]);
+
+ }
+ coord2f(leftMostV[0], leftMostV[1]);
+// glNormal3fv(leftMostNormal);
+// glVertex3fv(leftMostXYZ);
+
+ endtfan();
+
+ /*update i and leftMostV for next loop
+ */
+ i = k+1;
+
+ leftMostV[0] = upper_val[k];
+ leftMostV[1] = v_upper;
+// leftMostNormal = upperNormal[k];
+// leftMostXYZ = upperXYZ[k];
+ }
+ else /*upperVerts[i][0] > lowerVerts[j][0]*/
+ {
+ bgntfan();
+ coord2f(upper_val[i], v_upper);
+// glNormal3fv(upperNormal[i]);
+// glVertex3fv(upperXYZ[i]);
+
+ coord2f(leftMostV[0], leftMostV[1]);
+// glNormal3fv(leftMostNormal);
+// glVertex3fv(leftMostXYZ);
+
+
+ /*find the last k>=j such that
+ *lowerverts[k][0] < upperverts[i][0]
+ */
+ k=j;
+ while(k< n_lower)
+ {
+ if(lower_val[k] >= upper_val[i])
+ break;
+ coord2f(lower_val[k], v_lower);
+// glNormal3fv(lowerNormal[k]);
+// glVertex3fv(lowerXYZ[k]);
+
+ k++;
+ }
+ endtfan();
+
+ /*update j and leftMostV for next loop
+ */
+ j=k;
+ leftMostV[0] = lower_val[j-1];
+ leftMostV[1] = v_lower;
+
+// leftMostNormal = lowerNormal[j-1];
+// leftMostXYZ = lowerXYZ[j-1];
+ }
+ }
+ }
+ //clean up
+// free(upperXYZ);
+// free(lowerXYZ);
+// free(upperNormal);
+// free(lowerNormal);
+#endif
+
+}
+
+
+void
+OpenGLSurfaceEvaluator::evalVStrip(int n_left, REAL u_left, REAL* left_val, int n_right, REAL u_right, REAL* right_val)
+{
+#ifdef USE_INTERNAL_EVAL
+ inEvalVStrip(n_left, u_left, left_val,
+ n_right, u_right, right_val);
+#else
+
+#ifdef FOR_CHRIS
+ evalVStripExt(n_left, u_left, left_val,
+ n_right, u_right, right_val);
+ return;
+
+#endif
+
+ int i,j,k,l;
+ REAL botMostV[2];
+ /*
+ *the algorithm works by scanning from bot to top.
+ *botMostV: the bot most of the remaining verteces (on both left and right).
+ * it could an element of leftVerts or rightVerts.
+ *i: leftVerts[i] is the first vertex to the top of botMostV on left line
+ *j: rightVerts[j] is the first vertex to the top of botMostV on rightline
+ */
+
+ /*initialize i,j,and botMostV
+ */
+ if(left_val[0] <= right_val[0])
+ {
+ i=1;
+ j=0;
+
+ botMostV[0] = u_left;
+ botMostV[1] = left_val[0];
+ }
+ else
+ {
+ i=0;
+ j=1;
+
+ botMostV[0] = u_right;
+ botMostV[1] = right_val[0];
+ }
+
+ /*the main loop.
+ *the invariance is that:
+ *at the beginning of each loop, the meaning of i,j,and botMostV are
+ *maintained
+ */
+ while(1)
+ {
+ if(i >= n_left) /*case1: no more in left*/
+ {
+ if(j<n_right-1) /*at least two vertices in right*/
+ {
+ bgntfan();
+ coord2f(botMostV[0], botMostV[1]);
+ while(j<n_right){
+ coord2f(u_right, right_val[j]);
+// glNormal3fv(rightNormal[j]);
+// glVertex3fv(rightXYZ[j]);
+ j++;
+
+ }
+ endtfan();
+ }
+ break; /*exit the main loop*/
+ }
+ else if(j>= n_right) /*case2: no more in right*/
+ {
+ if(i<n_left-1) /*at least two vertices in left*/
+ {
+ bgntfan();
+ coord2f(botMostV[0], botMostV[1]);
+// glNormal3fv(botMostNormal);
+// glVertex3fv(botMostXYZ);
+
+ for(k=n_left-1; k>=i; k--) /*reverse order for two-side lighting*/
+ {
+ coord2f(u_left, left_val[k]);
+// glNormal3fv(leftNormal[k]);
+// glVertex3fv(leftXYZ[k]);
+ }
+
+ endtfan();
+ }
+ break; /*exit the main loop*/
+ }
+ else /* case3: neither is empty, plus the botMostV, there is at least one triangle to output*/
+ {
+ if(left_val[i] <= right_val[j])
+ {
+ bgntfan();
+ coord2f(u_right, right_val[j]);
+// glNormal3fv(rightNormal[j]);
+// glVertex3fv(rightXYZ[j]);
+
+ /*find the last k>=i such that
+ *leftverts[k][0] <= rightverts[j][0]
+ */
+ k=i;
+
+ while(k<n_left)
+ {
+ if(left_val[k] > right_val[j])
+ break;
+ k++;
+
+ }
+ k--;
+
+
+ for(l=k; l>=i; l--)/*the reverse is for two-side lighting*/
+ {
+ coord2f(u_left, left_val[l]);
+// glNormal3fv(leftNormal[l]);
+// glVertex3fv(leftXYZ[l]);
+
+ }
+ coord2f(botMostV[0], botMostV[1]);
+// glNormal3fv(botMostNormal);
+// glVertex3fv(botMostXYZ);
+
+ endtfan();
+
+ /*update i and botMostV for next loop
+ */
+ i = k+1;
+
+ botMostV[0] = u_left;
+ botMostV[1] = left_val[k];
+// botMostNormal = leftNormal[k];
+// botMostXYZ = leftXYZ[k];
+ }
+ else /*left_val[i] > right_val[j])*/
+ {
+ bgntfan();
+ coord2f(u_left, left_val[i]);
+// glNormal3fv(leftNormal[i]);
+// glVertex3fv(leftXYZ[i]);
+
+ coord2f(botMostV[0], botMostV[1]);
+// glNormal3fv(botMostNormal);
+// glVertex3fv(botMostXYZ);
+
+
+ /*find the last k>=j such that
+ *rightverts[k][0] < leftverts[i][0]
+ */
+ k=j;
+ while(k< n_right)
+ {
+ if(right_val[k] >= left_val[i])
+ break;
+ coord2f(u_right, right_val[k]);
+// glNormal3fv(rightNormal[k]);
+// glVertex3fv(rightXYZ[k]);
+
+ k++;
+ }
+ endtfan();
+
+ /*update j and botMostV for next loop
+ */
+ j=k;
+ botMostV[0] = u_right;
+ botMostV[1] = right_val[j-1];
+
+// botMostNormal = rightNormal[j-1];
+// botMostXYZ = rightXYZ[j-1];
+ }
+ }
+ }
+ //clean up
+// free(leftXYZ);
+// free(leftNormal);
+// free(rightXYZ);
+// free(rightNormal);
+#endif
+}
+
+
+void
+OpenGLSurfaceEvaluator::bgnqstrip(void)
+{
+ if(output_triangles)
+ bezierPatchMeshBeginStrip(global_bpm, GL_QUAD_STRIP);
+ else
+ glBegin((GLenum) GL_QUAD_STRIP);
+
+#ifdef STATISTICS
+ STAT_num_of_quad_strips++;
+#endif
+}
+
+void
+OpenGLSurfaceEvaluator::endqstrip(void)
+{
+ if(output_triangles)
+ bezierPatchMeshEndStrip(global_bpm);
+ else
+ glEnd();
+
+}
+
+/*-------------------------------------------------------------------------
+ * bgnmap2f - preamble to surface definition and evaluations
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLSurfaceEvaluator::bgnmap2f(long)
+{
+ if(output_triangles)
+ {
+ /*deallocate the space which may has been
+ *allocated by global_bpm previously
+ */
+ if(global_bpm != NULL) {
+ bezierPatchMeshListDelete(global_bpm);
+ global_bpm = NULL;
+ }
+
+
+ /*
+ auto_normal_flag = 1; //always output normal in callback mode.
+ //we could have used the following code,
+ //but Inspector doesn't have gl context
+ //before it calls tessellator.
+ //this way is temporary.
+ */
+ //NEWCALLBACK
+ //if one of the two normal callback functions are set,
+ //then set
+ if(normalCallBackN != NULL ||
+ normalCallBackData != NULL)
+ auto_normal_flag = 1;
+ else
+ auto_normal_flag = 0;
+
+ //initialize so that no maps initially
+ vertex_flag = 0;
+ normal_flag = 0;
+ color_flag = 0;
+ texcoord_flag = 0;
+
+ /*
+ if(glIsEnabled(GL_AUTO_NORMAL) == GL_TRUE)
+ auto_normal_flag = 1;
+ else if (callback_auto_normal == 1)
+ auto_normal_flag = 1;
+ else
+ auto_normal_flag = 0;
+ */
+
+ //NEWCALLBACK: no need to worry about gl states when gling clalback
+ }
+ else
+ {
+ glPushAttrib((GLbitfield) GL_EVAL_BIT);
+
+ /*to avoid side effect, we restor the opengl state for GL_POLYGON_MODE
+ */
+ glGetIntegerv(GL_POLYGON_MODE, gl_polygon_mode);
+ }
+
+}
+
+/*-------------------------------------------------------------------------
+ * endmap2f - postamble to a map
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLSurfaceEvaluator::endmap2f(void)
+{
+
+ if(output_triangles)
+ {
+ //bezierPatchMeshListDelDeg(global_bpm);
+
+ // bezierPatchMeshListEval(global_bpm);
+
+ //surfcount++;
+ //printf("surfcount=%i\n", surfcount);
+ //if(surfcount == 8) exit(0);
+
+ inBPMListEvalEM(global_bpm);
+
+
+
+/*
+ global_bpm = bezierPatchMeshListReverse(global_bpm);
+ {
+ float *vertex_array;
+ float *normal_array;
+ int *length_array;
+ int *type_array;
+ int num_strips;
+ bezierPatchMeshListCollect(global_bpm, &vertex_array, &normal_array, &length_array, &type_array, &num_strips);
+ drawStrips(vertex_array, normal_array, length_array, type_array, num_strips);
+ free(vertex_array);
+ free(normal_array);
+ free(length_array);
+ free(type_array);
+ }
+*/
+
+ //bezierPatchMeshListPrint(global_bpm);
+ //bezierPatchMeshListDraw(global_bpm);
+
+// printf("num triangles=%i\n", bezierPatchMeshListNumTriangles(global_bpm));
+
+#ifdef USE_LOD
+#else
+ bezierPatchMeshListDelete(global_bpm);
+ global_bpm = NULL;
+#endif
+
+ }
+else
+ {
+#ifndef USE_LOD
+glPopAttrib();
+#endif
+
+#ifdef STATISTICS
+ fprintf(stderr, "num_vertices=%i,num_triangles=%i,num_quads_strips=%i\n", STAT_num_of_eval_vertices,STAT_num_of_triangles,STAT_num_of_quad_strips);
+#endif
+
+ /*to restore the gl_polygon_mode
+ */
+#ifndef USE_LOD
+ glPolygonMode( GL_FRONT, (GLenum) gl_polygon_mode[0]);
+ glPolygonMode( GL_BACK, (GLenum) gl_polygon_mode[1]);
+#endif
+}
+
+}
+
+/*-------------------------------------------------------------------------
+ * map2f - pass a desription of a surface map
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLSurfaceEvaluator::map2f(
+ long _type,
+ REAL _ulower, /* u lower domain coord */
+ REAL _uupper, /* u upper domain coord */
+ long _ustride, /* interpoint distance */
+ long _uorder, /* parametric order */
+ REAL _vlower, /* v lower domain coord */
+ REAL _vupper, /* v upper domain coord */
+ long _vstride, /* interpoint distance */
+ long _vorder, /* parametric order */
+ REAL *pts) /* control points */
+{
+#ifdef USE_INTERNAL_EVAL
+ inMap2f((int) _type, (REAL) _ulower, (REAL) _uupper,
+ (int) _ustride, (int) _uorder, (REAL) _vlower,
+ (REAL) _vupper, (int) _vstride, (int) _vorder,
+ (REAL *) pts);
+#else
+
+
+
+ if(output_triangles)
+ {
+ if(global_bpm == NULL)
+ global_bpm = bezierPatchMeshMake2(10,10);
+ if(
+ (global_bpm->bpatch == NULL &&
+ (_type == GL_MAP2_VERTEX_3 || _type == GL_MAP2_VERTEX_4))
+ ||
+ (global_bpm->bpatch_normal == NULL &&
+ (_type == GL_MAP2_NORMAL))
+ ||
+ (global_bpm->bpatch_color == NULL &&
+ (_type == GL_MAP2_INDEX || _type == GL_MAP2_COLOR_4))
+ ||
+ (global_bpm->bpatch_texcoord == NULL &&
+ (_type == GL_MAP2_TEXTURE_COORD_1 ||
+ _type == GL_MAP2_TEXTURE_COORD_2 ||
+ _type == GL_MAP2_TEXTURE_COORD_3 ||
+ _type == GL_MAP2_TEXTURE_COORD_4 )
+ ))
+ {
+ bezierPatchMeshPutPatch(global_bpm, (int) _type, _ulower, _uupper,(int) _ustride,(int) _uorder,_vlower, _vupper, (int) _vstride, (int) _vorder, pts);
+ }
+ else /*new surface patch (with multiple maps) starts*/
+ {
+ bezierPatchMesh *temp = bezierPatchMeshMake2(10,10);
+ bezierPatchMeshPutPatch(temp, (int) _type, _ulower, _uupper,(int) _ustride,(int) _uorder,_vlower, _vupper, (int) _vstride, (int) _vorder, pts);
+ global_bpm = bezierPatchMeshListInsert(global_bpm, temp);
+
+ /*
+ global_bpm = bezierPatchMeshListInsert(global_bpm,
+ bezierPatchMeshMake(
+ (int) _type, _ulower, _uupper,(int) _ustride, (int) _uorder, _vlower, _vupper, (int) _vstride, (int) _vorder, pts, 10, 10));
+ */
+ }
+ }
+ else /*not output triangles*/
+ {
+ glMap2f((GLenum) _type, (GLfloat) _ulower, (GLfloat) _uupper,
+ (GLint) _ustride, (GLint) _uorder, (GLfloat) _vlower,
+ (GLfloat) _vupper, (GLint) _vstride, (GLint) _vorder,
+ (const GLfloat *) pts);
+ }
+
+#endif
+}
+
+
+/*-------------------------------------------------------------------------
+ * mapmesh2f - evaluate a mesh of points on lattice
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLSurfaceEvaluator::mapmesh2f(long style, long umin, long umax, long vmin, long vmax)
+{
+#ifdef NO_EVALUATION
+return;
+#endif
+
+#ifdef USE_INTERNAL_EVAL
+ inEvalMesh2((int)umin, (int)vmin, (int)umax, (int)vmax);
+#else
+
+
+
+if(output_triangles)
+{
+#ifdef USE_LOD
+ bezierPatchMeshBeginStrip(global_bpm, GL_POLYGON);
+ bezierPatchMeshInsertUV(global_bpm, global_grid_u0, global_grid_v0);
+ bezierPatchMeshInsertUV(global_bpm, global_grid_u1, global_grid_v1);
+ bezierPatchMeshInsertUV(global_bpm, (REAL)global_grid_nu, (REAL)global_grid_nv);
+ bezierPatchMeshInsertUV(global_bpm, (REAL)umin, (REAL)vmin);
+ bezierPatchMeshInsertUV(global_bpm, (REAL)umax, (REAL)vmax);
+ bezierPatchMeshEndStrip(global_bpm);
+
+#else
+
+ REAL du, dv;
+ long i,j;
+ if(global_grid_nu == 0 || global_grid_nv == 0)
+ return; /*no points need to be output*/
+ du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu;
+ dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv;
+
+ if(global_grid_nu >= global_grid_nv){
+
+ for(i=umin; i<umax; i++){
+ REAL u1 = (i==global_grid_nu)? global_grid_u1:(global_grid_u0 + i*du);
+ REAL u2 = ((i+1) == global_grid_nu)? global_grid_u1: (global_grid_u0+(i+1)*du);
+
+ bgnqstrip();
+ for(j=vmax; j>=vmin; j--){
+ REAL v1 = (j == global_grid_nv)? global_grid_v1: (global_grid_v0 +j*dv);
+
+ coord2f(u1, v1);
+ coord2f(u2, v1);
+ }
+ endqstrip();
+ }
+ }
+ else{
+
+ for(i=vmin; i<vmax; i++){
+ REAL v1 = (i==global_grid_nv)? global_grid_v1:(global_grid_v0 + i*dv);
+ REAL v2 = ((i+1) == global_grid_nv)? global_grid_v1: (global_grid_v0+(i+1)*dv);
+
+ bgnqstrip();
+ for(j=umax; j>=umin; j--){
+ REAL u1 = (j == global_grid_nu)? global_grid_u1: (global_grid_u0 +j*du);
+ coord2f(u1, v2);
+ coord2f(u1, v1);
+ }
+ endqstrip();
+ }
+ }
+#endif
+}
+else
+{
+ switch(style) {
+ default:
+ case N_MESHFILL:
+ glEvalMesh2((GLenum) GL_FILL, (GLint) umin, (GLint) umax,
+ (GLint) vmin, (GLint) vmax);
+ break;
+ case N_MESHLINE:
+ glEvalMesh2((GLenum) GL_LINE, (GLint) umin, (GLint) umax,
+ (GLint) vmin, (GLint) vmax);
+ break;
+ case N_MESHPOINT:
+ glEvalMesh2((GLenum) GL_POINT, (GLint) umin, (GLint) umax,
+ (GLint) vmin, (GLint) vmax);
+ break;
+ }
+ }
+
+#endif
+
+#ifdef STATISTICS
+ STAT_num_of_quad_strips += (umax-umin)*(vmax-vmin);
+#endif
+}
+
+/*-------------------------------------------------------------------------
+ * evalcoord2f - evaluate a point on a surface
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLSurfaceEvaluator::evalcoord2f(long, REAL u, REAL v)
+{
+
+
+#ifdef NO_EVALUATION
+return;
+#endif
+
+
+ newtmeshvert(u, v);
+}
+
+/*-------------------------------------------------------------------------
+ * evalpoint2i - evaluate a grid point
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLSurfaceEvaluator::evalpoint2i(long u, long v)
+{
+#ifdef NO_EVALUATION
+return;
+#endif
+
+ newtmeshvert(u, v);
+}
+
+void
+OpenGLSurfaceEvaluator::point2i( long u, long v )
+{
+#ifdef NO_EVALUATION
+return;
+#else
+
+#ifdef USE_INTERNAL_EVAL
+ inEvalPoint2( (int)u, (int)v);
+#else
+
+
+if(output_triangles)
+{
+
+ REAL du, dv;
+ REAL fu,fv;
+ du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu;
+ dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv;
+ fu = (u==global_grid_nu)? global_grid_u1:(global_grid_u0 + u*du);
+ fv = (v == global_grid_nv)? global_grid_v1: (global_grid_v0 +v*dv);
+ coord2f(fu,fv);
+}
+else
+ glEvalPoint2((GLint) u, (GLint) v);
+
+
+#endif
+
+#ifdef STATISTICS
+ STAT_num_of_eval_vertices++;
+#endif
+
+#endif
+
+}
+
+void
+OpenGLSurfaceEvaluator::coord2f( REAL u, REAL v )
+{
+#ifdef NO_EVALUATION
+return;
+#else
+
+#ifdef USE_INTERNAL_EVAL
+ inEvalCoord2f( u, v);
+#else
+
+
+if(output_triangles)
+ bezierPatchMeshInsertUV(global_bpm, u,v);
+else
+ glEvalCoord2f((GLfloat) u, (GLfloat) v);
+
+
+#endif
+
+
+#ifdef STATISTICS
+ STAT_num_of_eval_vertices++;
+#endif
+
+#endif
+}
+
+void
+OpenGLSurfaceEvaluator::newtmeshvert( long u, long v )
+{
+#ifdef NO_EVALUATION
+return;
+#else
+
+ if (tmeshing) {
+
+ if (vcount == 2) {
+ vertexCache[0]->invoke(this);
+ vertexCache[1]->invoke(this);
+ point2i( u, v);
+
+ } else {
+ vcount++;
+ }
+
+ vertexCache[which]->saveEvalPoint(u, v);
+ which = 1 - which;
+ } else {
+ point2i( u, v);
+ }
+#endif
+}
+
+void
+OpenGLSurfaceEvaluator::newtmeshvert( REAL u, REAL v )
+{
+#ifdef NO_EVALUATION
+return;
+#else
+ if (tmeshing) {
+
+
+ if (vcount == 2) {
+ vertexCache[0]->invoke(this);
+ vertexCache[1]->invoke(this);
+ coord2f(u,v);
+
+ } else {
+ vcount++;
+ }
+
+ vertexCache[which]->saveEvalCoord(u, v);
+ which = 1 - which;
+ } else {
+
+ coord2f( u, v);
+ }
+#endif
+
+}
+
+void
+OpenGLSurfaceEvaluator::putCallBack(GLenum which, _GLUfuncptr fn )
+{
+ switch(which)
+ {
+ case GLU_NURBS_BEGIN:
+ beginCallBackN = (void (GLAPIENTRY *) (GLenum)) fn;
+ break;
+ case GLU_NURBS_END:
+ endCallBackN = (void (GLAPIENTRY *) (void)) fn;
+ break;
+ case GLU_NURBS_VERTEX:
+ vertexCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn;
+ break;
+ case GLU_NURBS_NORMAL:
+ normalCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn;
+ break;
+ case GLU_NURBS_COLOR:
+ colorCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn;
+ break;
+ case GLU_NURBS_TEXTURE_COORD:
+ texcoordCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn;
+ break;
+ case GLU_NURBS_BEGIN_DATA:
+ beginCallBackData = (void (GLAPIENTRY *) (GLenum, void*)) fn;
+ break;
+ case GLU_NURBS_END_DATA:
+ endCallBackData = (void (GLAPIENTRY *) (void*)) fn;
+ break;
+ case GLU_NURBS_VERTEX_DATA:
+ vertexCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn;
+ break;
+ case GLU_NURBS_NORMAL_DATA:
+ normalCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn;
+ break;
+ case GLU_NURBS_COLOR_DATA:
+ colorCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn;
+ break;
+ case GLU_NURBS_TEXTURE_COORD_DATA:
+ texcoordCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn;
+ break;
+
+ }
+}
+
+
+void
+OpenGLSurfaceEvaluator::beginCallBack(GLenum which, void *data)
+{
+ if(beginCallBackData)
+ beginCallBackData(which, data);
+ else if(beginCallBackN)
+ beginCallBackN(which);
+}
+
+void
+OpenGLSurfaceEvaluator::endCallBack(void *data)
+{
+ if(endCallBackData)
+ endCallBackData(data);
+ else if(endCallBackN)
+ endCallBackN();
+}
+
+void
+OpenGLSurfaceEvaluator::vertexCallBack(const GLfloat *vert, void* data)
+{
+ if(vertexCallBackData)
+ vertexCallBackData(vert, data);
+ else if(vertexCallBackN)
+ vertexCallBackN(vert);
+}
+
+
+void
+OpenGLSurfaceEvaluator::normalCallBack(const GLfloat *normal, void* data)
+{
+ if(normalCallBackData)
+ normalCallBackData(normal, data);
+ else if(normalCallBackN)
+ normalCallBackN(normal);
+}
+
+void
+OpenGLSurfaceEvaluator::colorCallBack(const GLfloat *color, void* data)
+{
+ if(colorCallBackData)
+ colorCallBackData(color, data);
+ else if(colorCallBackN)
+ colorCallBackN(color);
+}
+
+void
+OpenGLSurfaceEvaluator::texcoordCallBack(const GLfloat *texcoord, void* data)
+{
+ if(texcoordCallBackData)
+ texcoordCallBackData(texcoord, data);
+ else if(texcoordCallBackN)
+ texcoordCallBackN(texcoord);
+}
+
+
+
+
diff --git a/src/glu/sgi/libnurbs/interface/glsurfeval.h b/src/glu/sgi/libnurbs/interface/glsurfeval.h
new file mode 100644
index 00000000000..c34a58cb9b9
--- /dev/null
+++ b/src/glu/sgi/libnurbs/interface/glsurfeval.h
@@ -0,0 +1,408 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * glsurfeval.h
+ *
+ */
+
+#ifndef __gluglsurfeval_h_
+#define __gluglsurfeval_h_
+
+#include "basicsurfeval.h"
+#include "bezierPatchMesh.h" //in case output triangles
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+class SurfaceMap;
+class OpenGLSurfaceEvaluator;
+class StoredVertex;
+
+#define TYPECOORD 1
+#define TYPEPOINT 2
+
+/* Cache up to 3 vertices from tmeshes */
+#define VERTEX_CACHE_SIZE 3
+
+/*for internal evaluator callback stuff*/
+#ifndef IN_MAX_BEZIER_ORDER
+#define IN_MAX_BEZIER_ORDER 40 /*XXX should be bigger than machine order*/
+#endif
+
+#ifndef IN_MAX_DIMENSION
+#define IN_MAX_DIMENSION 4
+#endif
+
+typedef struct surfEvalMachine{
+ REAL uprime;//cached previusly evaluated uprime.
+ REAL vprime;
+ int k; /*the dimension*/
+ REAL u1;
+ REAL u2;
+ int ustride;
+ int uorder;
+ REAL v1;
+ REAL v2;
+ int vstride;
+ int vorder;
+ REAL ctlPoints[IN_MAX_BEZIER_ORDER*IN_MAX_BEZIER_ORDER*IN_MAX_DIMENSION];
+ REAL ucoeff[IN_MAX_BEZIER_ORDER]; /*cache the polynomial values*/
+ REAL vcoeff[IN_MAX_BEZIER_ORDER];
+ REAL ucoeffDeriv[IN_MAX_BEZIER_ORDER]; /*cache the polynomial derivatives*/
+ REAL vcoeffDeriv[IN_MAX_BEZIER_ORDER];
+} surfEvalMachine;
+
+
+
+class StoredVertex {
+public:
+ StoredVertex() { type = 0; }
+ ~StoredVertex(void) {}
+ void saveEvalCoord(REAL x, REAL y)
+ {coord[0] = x; coord[1] = y; type = TYPECOORD; }
+ void saveEvalPoint(long x, long y)
+ {point[0] = x; point[1] = y; type = TYPEPOINT; }
+ void invoke(OpenGLSurfaceEvaluator *eval);
+
+private:
+ int type;
+ REAL coord[2];
+ long point[2];
+};
+
+class OpenGLSurfaceEvaluator : public BasicSurfaceEvaluator {
+public:
+ OpenGLSurfaceEvaluator();
+ virtual ~OpenGLSurfaceEvaluator( void );
+ void polymode( long style );
+ void range2f( long, REAL *, REAL * );
+ void domain2f( REAL, REAL, REAL, REAL );
+ void addMap( SurfaceMap * ) { }
+
+ void enable( long );
+ void disable( long );
+ void bgnmap2f( long );
+ void map2f( long, REAL, REAL, long, long,
+ REAL, REAL, long, long, REAL * );
+ void mapgrid2f( long, REAL, REAL, long, REAL, REAL );
+ void mapmesh2f( long, long, long, long, long );
+ void evalcoord2f( long, REAL, REAL );
+ void evalpoint2i( long, long );
+ void endmap2f( void );
+
+ void bgnline( void );
+ void endline( void );
+ void bgnclosedline( void );
+ void endclosedline( void );
+ void bgntmesh( void );
+ void swaptmesh( void );
+ void endtmesh( void );
+ void bgnqstrip( void );
+ void endqstrip( void );
+
+ void bgntfan( void );
+ void endtfan( void );
+ void evalUStrip(int n_upper, REAL v_upper, REAL* upper_val,
+ int n_lower, REAL v_lower, REAL* lower_val);
+ void evalVStrip(int n_left, REAL u_left, REAL* left_val,
+ int n_right, REAL u_right, REAL* right_val);
+
+ void coord2f( REAL, REAL );
+ void point2i( long, long );
+
+ void newtmeshvert( REAL, REAL );
+ void newtmeshvert( long, long );
+
+#ifdef _WIN32
+ void putCallBack(GLenum which, void (APIENTRY *fn)() );
+#else
+ void putCallBack(GLenum which, _GLUfuncptr fn );
+#endif
+
+ int get_vertices_call_back()
+ {
+ return output_triangles;
+ }
+ void put_vertices_call_back(int flag)
+ {
+ output_triangles = flag;
+ }
+
+ void put_callback_auto_normal(int flag)
+ {
+ callback_auto_normal = flag;
+ }
+
+ int get_callback_auto_normal()
+ {
+ return callback_auto_normal;
+ }
+
+ void set_callback_userData(void* data)
+ {
+ userData = data;
+ }
+
+ /**************begin for LOD_eval_list***********/
+ void LOD_eval_list(int level);
+
+
+
+
+private:
+ StoredVertex *vertexCache[VERTEX_CACHE_SIZE];
+ int tmeshing;
+ int which;
+ int vcount;
+
+ GLint gl_polygon_mode[2];/*to save and restore so that
+ *no side effect
+ */
+ bezierPatchMesh *global_bpm; //for output triangles
+ int output_triangles; //true 1 or false 0
+
+
+
+ void (GLAPIENTRY *beginCallBackN) (GLenum type);
+ void (GLAPIENTRY *endCallBackN) (void);
+ void (GLAPIENTRY *vertexCallBackN) (const GLfloat *vert);
+ void (GLAPIENTRY *normalCallBackN) (const GLfloat *normal);
+ void (GLAPIENTRY *colorCallBackN) (const GLfloat *color);
+ void (GLAPIENTRY *texcoordCallBackN) (const GLfloat *texcoord);
+
+ void (GLAPIENTRY *beginCallBackData) (GLenum type, void* data);
+ void (GLAPIENTRY *endCallBackData) (void* data);
+ void (GLAPIENTRY *vertexCallBackData) (const GLfloat *vert, void* data);
+ void (GLAPIENTRY *normalCallBackData) (const GLfloat *normal, void* data);
+ void (GLAPIENTRY *colorCallBackData) (const GLfloat *color, void* data);
+ void (GLAPIENTRY *texcoordCallBackData) (const GLfloat *texcoord, void* data);
+
+ void beginCallBack (GLenum type, void* data);
+ void endCallBack (void* data);
+ void vertexCallBack (const GLfloat *vert, void* data);
+ void normalCallBack (const GLfloat *normal, void* data);
+ void colorCallBack (const GLfloat *color, void* data);
+ void texcoordCallBack (const GLfloat *texcoord, void* data);
+
+
+ void* userData; //the opaque pointer for Data callback functions.
+
+ /*LOD evaluation*/
+ void LOD_triangle(REAL A[2], REAL B[2], REAL C[2],
+ int level);
+ void LOD_eval(int num_vert, REAL* verts, int type, int level);
+
+ int LOD_eval_level; //set by LOD_eval_list()
+
+ /*************begin for internal evaluators*****************/
+
+ /*the following global variables are only defined in this file.
+ *They are used to cache the precomputed Bezier polynomial values.
+ *These calues may be used consecutively in which case we don't have
+ *recompute these values again.
+ */
+ int global_uorder; /*store the uorder in the previous evaluation*/
+ int global_vorder; /*store the vorder in the previous evaluation*/
+ REAL global_uprime;
+ REAL global_vprime;
+ REAL global_vprime_BV;
+ REAL global_uprime_BU;
+ int global_uorder_BV; /*store the uorder in the previous evaluation*/
+ int global_vorder_BV; /*store the vorder in the previous evaluation*/
+ int global_uorder_BU; /*store the uorder in the previous evaluation*/
+ int global_vorder_BU; /*store the vorder in the previous evaluation*/
+
+ REAL global_ucoeff[IN_MAX_BEZIER_ORDER]; /*cache the polynomial values*/
+ REAL global_vcoeff[IN_MAX_BEZIER_ORDER];
+ REAL global_ucoeffDeriv[IN_MAX_BEZIER_ORDER]; /*cache the polynomial derivatives*/
+ REAL global_vcoeffDeriv[IN_MAX_BEZIER_ORDER];
+
+ REAL global_BV[IN_MAX_BEZIER_ORDER][IN_MAX_DIMENSION];
+ REAL global_PBV[IN_MAX_BEZIER_ORDER][IN_MAX_DIMENSION];
+ REAL global_BU[IN_MAX_BEZIER_ORDER][IN_MAX_DIMENSION];
+ REAL global_PBU[IN_MAX_BEZIER_ORDER][IN_MAX_DIMENSION];
+ REAL* global_baseData;
+
+ int global_ev_k; /*the dimension*/
+ REAL global_ev_u1;
+ REAL global_ev_u2;
+ int global_ev_ustride;
+ int global_ev_uorder;
+ REAL global_ev_v1;
+ REAL global_ev_v2;
+ int global_ev_vstride;
+ int global_ev_vorder;
+ REAL global_ev_ctlPoints[IN_MAX_BEZIER_ORDER*IN_MAX_BEZIER_ORDER*IN_MAX_DIMENSION];
+
+ REAL global_grid_u0;
+ REAL global_grid_u1;
+ int global_grid_nu;
+ REAL global_grid_v0;
+ REAL global_grid_v1;
+ int global_grid_nv;
+
+/*functions*/
+ void inDoDomain2WithDerivs(int k, REAL u, REAL v,
+ REAL u1, REAL u2, int uorder,
+ REAL v1, REAL v2, int vorder,
+ REAL *baseData,
+ REAL *retPoint, REAL *retdu, REAL *retdv);
+ void inPreEvaluate(int order, REAL vprime, REAL *coeff);
+ void inPreEvaluateWithDeriv(int order, REAL vprime, REAL *coeff, REAL *coeffDeriv);
+ void inComputeFirstPartials(REAL *p, REAL *pu, REAL *pv);
+ void inComputeNormal2(REAL *pu, REAL *pv, REAL *n);
+ void inDoEvalCoord2(REAL u, REAL v,
+ REAL *retPoint, REAL *retNormal);
+ void inDoEvalCoord2NOGE(REAL u, REAL v,
+ REAL *retPoint, REAL *retNormal);
+ void inMap2f(int k,
+ REAL ulower,
+ REAL uupper,
+ int ustride,
+ int uorder,
+ REAL vlower,
+ REAL vupper,
+ int vstride,
+ int vorder,
+ REAL *ctlPoints);
+
+ void inMapGrid2f(int nu, REAL u0, REAL u1,
+ int nv, REAL v0, REAL v1);
+
+ void inEvalMesh2(int lowU, int lowV, int highU, int highV);
+ void inEvalPoint2(int i, int j);
+ void inEvalCoord2f(REAL u, REAL v);
+
+void inEvalULine(int n_points, REAL v, REAL* u_vals,
+ int stride, REAL ret_points[][3], REAL ret_normals[][3]);
+
+void inEvalVLine(int n_points, REAL u, REAL* v_vals,
+ int stride, REAL ret_points[][3], REAL ret_normals[][3]);
+
+void inEvalUStrip(int n_upper, REAL v_upper, REAL* upper_val,
+ int n_lower, REAL v_lower, REAL* lower_val
+ );
+void inEvalVStrip(int n_left, REAL u_left, REAL* left_val, int n_right, REAL u_right, REAL* right_val);
+
+void inPreEvaluateBV(int k, int uorder, int vorder, REAL vprime, REAL *baseData);
+void inPreEvaluateBU(int k, int uorder, int vorder, REAL uprime, REAL *baseData);
+void inPreEvaluateBV_intfac(REAL v )
+ {
+ inPreEvaluateBV(global_ev_k, global_ev_uorder, global_ev_vorder, (v-global_ev_v1)/(global_ev_v2-global_ev_v1), global_ev_ctlPoints);
+ }
+
+void inPreEvaluateBU_intfac(REAL u)
+ {
+ inPreEvaluateBU(global_ev_k, global_ev_uorder, global_ev_vorder, (u-global_ev_u1)/(global_ev_u2-global_ev_u1), global_ev_ctlPoints);
+ }
+
+void inDoDomain2WithDerivsBV(int k, REAL u, REAL v,
+ REAL u1, REAL u2, int uorder,
+ REAL v1, REAL v2, int vorder,
+ REAL *baseData,
+ REAL *retPoint, REAL* retdu, REAL *retdv);
+
+void inDoDomain2WithDerivsBU(int k, REAL u, REAL v,
+ REAL u1, REAL u2, int uorder,
+ REAL v1, REAL v2, int vorder,
+ REAL *baseData,
+ REAL *retPoint, REAL* retdu, REAL *retdv);
+
+
+void inDoEvalCoord2NOGE_BV(REAL u, REAL v,
+ REAL *retPoint, REAL *retNormal);
+
+void inDoEvalCoord2NOGE_BU(REAL u, REAL v,
+ REAL *retPoint, REAL *retNormal);
+
+void inBPMEval(bezierPatchMesh* bpm);
+void inBPMListEval(bezierPatchMesh* list);
+
+/*-------------begin for surfEvalMachine -------------*/
+surfEvalMachine em_vertex;
+surfEvalMachine em_normal;
+surfEvalMachine em_color;
+surfEvalMachine em_texcoord;
+
+int auto_normal_flag; //whether to output normla or not in callback
+ //determined by GL_AUTO_NORMAL and callback_auto_normal
+int callback_auto_normal; //GLU_CALLBACK_AUTO_NORMAL_EXT
+int vertex_flag;
+int normal_flag;
+int color_flag;
+int texcoord_flag;
+
+void inMap2fEM(int which, //0:vert,1:norm,2:color,3:tex
+ int dimension,
+ REAL ulower,
+ REAL uupper,
+ int ustride,
+ int uorder,
+ REAL vlower,
+ REAL vupper,
+ int vstride,
+ int vorder,
+ REAL *ctlPoints);
+
+void inDoDomain2WithDerivsEM(surfEvalMachine *em, REAL u, REAL v,
+ REAL *retPoint, REAL *retdu, REAL *retdv);
+void inDoDomain2EM(surfEvalMachine *em, REAL u, REAL v,
+ REAL *retPoint);
+ void inDoEvalCoord2EM(REAL u, REAL v);
+
+void inBPMEvalEM(bezierPatchMesh* bpm);
+void inBPMListEvalEM(bezierPatchMesh* list);
+
+/*-------------end for surfEvalMachine -------------*/
+
+
+ /*************end for internal evaluators*****************/
+
+};
+
+inline void StoredVertex::invoke(OpenGLSurfaceEvaluator *eval)
+{
+ switch(type) {
+ case TYPECOORD:
+ eval->coord2f(coord[0], coord[1]);
+ break;
+ case TYPEPOINT:
+ eval->point2i(point[0], point[1]);
+ break;
+ default:
+ break;
+ }
+}
+
+#endif /* __gluglsurfeval_h_ */
diff --git a/src/glu/sgi/libnurbs/interface/incurveeval.cc b/src/glu/sgi/libnurbs/interface/incurveeval.cc
new file mode 100644
index 00000000000..7eb9cbd04b5
--- /dev/null
+++ b/src/glu/sgi/libnurbs/interface/incurveeval.cc
@@ -0,0 +1,208 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2004/05/12 15:29:36 $ $Revision: 1.2 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/interface/incurveeval.cc,v 1.2 2004/05/12 15:29:36 brianp Exp $
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "glcurveval.h"
+
+
+/*
+ *compute the Bezier polynomials C[n,j](v) for all j at v with
+ *return values stored in coeff[], where
+ * C[n,j](v) = (n,j) * v^j * (1-v)^(n-j),
+ * j=0,1,2,...,n.
+ *order : n+1
+ *vprime: v
+ *coeff : coeff[j]=C[n,j](v), this array store the returned values.
+ *The algorithm is a recursive scheme:
+ * C[0,0]=1;
+ * C[n,j](v) = (1-v)*C[n-1,j](v) + v*C[n-1,j-1](v), n>=1
+ *This code is copied from opengl/soft/so_eval.c:PreEvaluate
+ */
+void OpenGLCurveEvaluator::inPreEvaluate(int order, REAL vprime, REAL *coeff)
+{
+ int i, j;
+ REAL oldval, temp;
+ REAL oneMinusvprime;
+
+ /*
+ * Minor optimization
+ * Compute orders 1 and 2 outright, and set coeff[0], coeff[1] to
+ * their i==1 loop values to avoid the initialization and the i==1 loop.
+ */
+ if (order == 1) {
+ coeff[0] = 1.0;
+ return;
+ }
+
+ oneMinusvprime = 1-vprime;
+ coeff[0] = oneMinusvprime;
+ coeff[1] = vprime;
+ if (order == 2) return;
+
+ for (i = 2; i < order; i++) {
+ oldval = coeff[0] * vprime;
+ coeff[0] = oneMinusvprime * coeff[0];
+ for (j = 1; j < i; j++) {
+ temp = oldval;
+ oldval = coeff[j] * vprime;
+ coeff[j] = temp + oneMinusvprime * coeff[j];
+ }
+ coeff[j] = oldval;
+ }
+}
+
+void OpenGLCurveEvaluator::inMap1f(int which, //0: vert, 1: norm, 2: color, 3: tex
+ int k, //dimension
+ REAL ulower,
+ REAL uupper,
+ int ustride,
+ int uorder,
+ REAL *ctlpoints)
+{
+ int i,x;
+ curveEvalMachine *temp_em;
+ switch(which){
+ case 0: //vertex
+ vertex_flag = 1;
+ temp_em = &em_vertex;
+ break;
+ case 1: //normal
+ normal_flag = 1;
+ temp_em = &em_normal;
+ break;
+ case 2: //color
+ color_flag = 1;
+ temp_em = &em_color;
+ break;
+ default:
+ texcoord_flag = 1;
+ temp_em = &em_texcoord;
+ break;
+ }
+
+ REAL *data = temp_em->ctlpoints;
+ temp_em->uprime = -1; //initialized
+ temp_em->k = k;
+ temp_em->u1 = ulower;
+ temp_em->u2 = uupper;
+ temp_em->ustride = ustride;
+ temp_em->uorder = uorder;
+ /*copy the control points*/
+ for(i=0; i<uorder; i++){
+ for(x=0; x<k; x++){
+ data[x] = ctlpoints[x];
+ }
+ ctlpoints += ustride;
+ data += k;
+ }
+}
+
+void OpenGLCurveEvaluator::inDoDomain1(curveEvalMachine *em, REAL u, REAL *retPoint)
+{
+ int j, row;
+ REAL the_uprime;
+ REAL *data;
+
+ if(em->u2 == em->u1)
+ return;
+ the_uprime = (u-em->u1) / (em->u2-em->u1);
+ /*use already cached values if possible*/
+ if(em->uprime != the_uprime){
+ inPreEvaluate(em->uorder, the_uprime, em->ucoeff);
+ em->uprime = the_uprime;
+ }
+
+ for(j=0; j<em->k; j++){
+ data = em->ctlpoints+j;
+ retPoint[j] = 0.0;
+ for(row=0; row<em->uorder; row++)
+ {
+ retPoint[j] += em->ucoeff[row] * (*data);
+ data += em->k;
+ }
+ }
+}
+
+void OpenGLCurveEvaluator::inDoEvalCoord1(REAL u)
+{
+ REAL temp_vertex[4];
+ REAL temp_normal[3];
+ REAL temp_color[4];
+ REAL temp_texcoord[4];
+ if(texcoord_flag) //there is a texture map
+ {
+ inDoDomain1(&em_texcoord, u, temp_texcoord);
+ texcoordCallBack(temp_texcoord, userData);
+ }
+#ifdef DEBUG
+printf("color_flag = %i\n", color_flag);
+#endif
+ if(color_flag) //there is a color map
+ {
+ inDoDomain1(&em_color, u, temp_color);
+ colorCallBack(temp_color, userData);
+ }
+ if(normal_flag) //there is a normal map
+ {
+ inDoDomain1(&em_normal, u, temp_normal);
+ normalCallBack(temp_normal, userData);
+ }
+ if(vertex_flag)
+ {
+ inDoDomain1(&em_vertex, u, temp_vertex);
+ vertexCallBack(temp_vertex, userData);
+ }
+}
+
+void OpenGLCurveEvaluator::inMapMesh1f(int umin, int umax)
+{
+ REAL du, u;
+ int i;
+ if(global_grid_nu == 0)
+ return; //no points to output
+ du = (global_grid_u1 - global_grid_u0) / (REAL) global_grid_nu;
+ bgnline();
+ for(i=umin; i<= umax; i++){
+ u = (i==global_grid_nu)? global_grid_u1: global_grid_u0 + i*du;
+ inDoEvalCoord1(u);
+ }
+ endline();
+}
diff --git a/src/glu/sgi/libnurbs/interface/insurfeval.cc b/src/glu/sgi/libnurbs/interface/insurfeval.cc
new file mode 100644
index 00000000000..7f87800dc4c
--- /dev/null
+++ b/src/glu/sgi/libnurbs/interface/insurfeval.cc
@@ -0,0 +1,2066 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2004/05/12 15:29:36 $ $Revision: 1.3 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/interface/insurfeval.cc,v 1.3 2004/05/12 15:29:36 brianp Exp $
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <GL/gl.h>
+#include <math.h>
+#include <assert.h>
+
+#include "glsurfeval.h"
+
+//extern int surfcount;
+
+//#define CRACK_TEST
+
+#define AVOID_ZERO_NORMAL
+
+#ifdef AVOID_ZERO_NORMAL
+#define myabs(x) ((x>0)? x: (-x))
+#define MYZERO 0.000001
+#define MYDELTA 0.001
+#endif
+
+//#define USE_LOD
+#ifdef USE_LOD
+//#define LOD_EVAL_COORD(u,v) inDoEvalCoord2EM(u,v)
+#define LOD_EVAL_COORD(u,v) glEvalCoord2f(u,v)
+
+static void LOD_interpolate(REAL A[2], REAL B[2], REAL C[2], int j, int k, int pow2_level,
+ REAL& u, REAL& v)
+{
+ REAL a,a1,b,b1;
+
+ a = ((REAL) j) / ((REAL) pow2_level);
+ a1 = 1-a;
+
+ if(j != 0)
+ {
+ b = ((REAL) k) / ((REAL)j);
+ b1 = 1-b;
+ }
+ REAL x,y,z;
+ x = a1;
+ if(j==0)
+ {
+ y=0; z=0;
+ }
+ else{
+ y = b1*a;
+ z = b *a;
+ }
+
+ u = x*A[0] + y*B[0] + z*C[0];
+ v = x*A[1] + y*B[1] + z*C[1];
+}
+
+void OpenGLSurfaceEvaluator::LOD_triangle(REAL A[2], REAL B[2], REAL C[2],
+ int level)
+{
+ int k,j;
+ int pow2_level;
+ /*compute 2^level*/
+ pow2_level = 1;
+
+ for(j=0; j<level; j++)
+ pow2_level *= 2;
+ for(j=0; j<=pow2_level-1; j++)
+ {
+ REAL u,v;
+
+/* beginCallBack(GL_TRIANGLE_STRIP);*/
+glBegin(GL_TRIANGLE_STRIP);
+ LOD_interpolate(A,B,C, j+1, j+1, pow2_level, u,v);
+#ifdef USE_LOD
+ LOD_EVAL_COORD(u,v);
+// glEvalCoord2f(u,v);
+#else
+ inDoEvalCoord2EM(u,v);
+#endif
+
+ for(k=0; k<=j; k++)
+ {
+ LOD_interpolate(A,B,C,j,j-k,pow2_level, u,v);
+#ifdef USE_LOD
+ LOD_EVAL_COORD(u,v);
+// glEvalCoord2f(u,v);
+#else
+ inDoEvalCoord2EM(u,v);
+#endif
+
+ LOD_interpolate(A,B,C,j+1,j-k,pow2_level, u,v);
+
+#ifdef USE_LOD
+ LOD_EVAL_COORD(u,v);
+// glEvalCoord2f(u,v);
+#else
+ inDoEvalCoord2EM(u,v);
+#endif
+ }
+// endCallBack();
+glEnd();
+ }
+}
+
+void OpenGLSurfaceEvaluator::LOD_eval(int num_vert, REAL* verts, int type,
+ int level
+ )
+{
+ int i,k;
+ switch(type){
+ case GL_TRIANGLE_STRIP:
+ case GL_QUAD_STRIP:
+ for(i=2, k=4; i<=num_vert-2; i+=2, k+=4)
+ {
+ LOD_triangle(verts+k-4, verts+k-2, verts+k,
+ level
+ );
+ LOD_triangle(verts+k-2, verts+k+2, verts+k,
+ level
+ );
+ }
+ if(num_vert % 2 ==1)
+ {
+ LOD_triangle(verts+2*(num_vert-3), verts+2*(num_vert-2), verts+2*(num_vert-1),
+ level
+ );
+ }
+ break;
+ case GL_TRIANGLE_FAN:
+ for(i=1, k=2; i<=num_vert-2; i++, k+=2)
+ {
+ LOD_triangle(verts,verts+k, verts+k+2,
+ level
+ );
+ }
+ break;
+
+ default:
+ fprintf(stderr, "typy not supported in LOD_\n");
+ }
+}
+
+
+#endif //USE_LOD
+
+//#define GENERIC_TEST
+#ifdef GENERIC_TEST
+extern float xmin, xmax, ymin, ymax, zmin, zmax; /*bounding box*/
+extern int temp_signal;
+
+static void gTessVertexSphere(float u, float v, float temp_normal[3], float temp_vertex[3])
+{
+ float r=2.0;
+ float Ox = 0.5*(xmin+xmax);
+ float Oy = 0.5*(ymin+ymax);
+ float Oz = 0.5*(zmin+zmax);
+ float nx = cos(v) * sin(u);
+ float ny = sin(v) * sin(u);
+ float nz = cos(u);
+ float x= Ox+r * nx;
+ float y= Oy+r * ny;
+ float z= Oz+r * nz;
+
+ temp_normal[0] = nx;
+ temp_normal[1] = ny;
+ temp_normal[2] = nz;
+ temp_vertex[0] = x;
+ temp_vertex[1] = y;
+ temp_vertex[2] = z;
+
+// glNormal3f(nx,ny,nz);
+// glVertex3f(x,y,z);
+}
+
+static void gTessVertexCyl(float u, float v, float temp_normal[3], float temp_vertex[3])
+{
+ float r=2.0;
+ float Ox = 0.5*(xmin+xmax);
+ float Oy = 0.5*(ymin+ymax);
+ float Oz = 0.5*(zmin+zmax);
+ float nx = cos(v);
+ float ny = sin(v);
+ float nz = 0;
+ float x= Ox+r * nx;
+ float y= Oy+r * ny;
+ float z= Oz - 2*u;
+
+ temp_normal[0] = nx;
+ temp_normal[1] = ny;
+ temp_normal[2] = nz;
+ temp_vertex[0] = x;
+ temp_vertex[1] = y;
+ temp_vertex[2] = z;
+
+/*
+ glNormal3f(nx,ny,nz);
+ glVertex3f(x,y,z);
+*/
+}
+
+#endif //GENERIC_TEST
+
+void OpenGLSurfaceEvaluator::inBPMListEval(bezierPatchMesh* list)
+{
+ bezierPatchMesh* temp;
+ for(temp = list; temp != NULL; temp = temp->next)
+ {
+ inBPMEval(temp);
+ }
+}
+
+void OpenGLSurfaceEvaluator::inBPMEval(bezierPatchMesh* bpm)
+{
+ int i,j,k,l;
+ float u,v;
+
+ int ustride = bpm->bpatch->dimension * bpm->bpatch->vorder;
+ int vstride = bpm->bpatch->dimension;
+ inMap2f(
+ (bpm->bpatch->dimension == 3)? GL_MAP2_VERTEX_3 : GL_MAP2_VERTEX_4,
+ bpm->bpatch->umin,
+ bpm->bpatch->umax,
+ ustride,
+ bpm->bpatch->uorder,
+ bpm->bpatch->vmin,
+ bpm->bpatch->vmax,
+ vstride,
+ bpm->bpatch->vorder,
+ bpm->bpatch->ctlpoints);
+
+ bpm->vertex_array = (float*) malloc(sizeof(float)* (bpm->index_UVarray/2) * 3+1); /*in case the origional dimenion is 4, then we need 4 space to pass to evaluator.*/
+ assert(bpm->vertex_array);
+ bpm->normal_array = (float*) malloc(sizeof(float)* (bpm->index_UVarray/2) * 3);
+ assert(bpm->normal_array);
+#ifdef CRACK_TEST
+if( global_ev_u1 ==2 && global_ev_u2 == 3
+ && global_ev_v1 ==2 && global_ev_v2 == 3)
+{
+REAL vertex[4];
+REAL normal[4];
+#ifdef DEBUG
+printf("***number 1\n");
+#endif
+
+beginCallBack(GL_QUAD_STRIP, NULL);
+inEvalCoord2f(3.0, 3.0);
+inEvalCoord2f(2.0, 3.0);
+inEvalCoord2f(3.0, 2.7);
+inEvalCoord2f(2.0, 2.7);
+inEvalCoord2f(3.0, 2.0);
+inEvalCoord2f(2.0, 2.0);
+endCallBack(NULL);
+
+
+beginCallBack(GL_TRIANGLE_STRIP, NULL);
+inEvalCoord2f(2.0, 3.0);
+inEvalCoord2f(2.0, 2.0);
+inEvalCoord2f(2.0, 2.7);
+endCallBack(NULL);
+
+}
+
+/*
+if( global_ev_u1 ==2 && global_ev_u2 == 3
+ && global_ev_v1 ==1 && global_ev_v2 == 2)
+{
+#ifdef DEBUG
+printf("***number 2\n");
+#endif
+beginCallBack(GL_QUAD_STRIP);
+inEvalCoord2f(2.0, 2.0);
+inEvalCoord2f(2.0, 1.0);
+inEvalCoord2f(3.0, 2.0);
+inEvalCoord2f(3.0, 1.0);
+endCallBack();
+}
+*/
+if( global_ev_u1 ==1 && global_ev_u2 == 2
+ && global_ev_v1 ==2 && global_ev_v2 == 3)
+{
+#ifdef DEBUG
+printf("***number 3\n");
+#endif
+beginCallBack(GL_QUAD_STRIP, NULL);
+inEvalCoord2f(2.0, 3.0);
+inEvalCoord2f(1.0, 3.0);
+inEvalCoord2f(2.0, 2.3);
+inEvalCoord2f(1.0, 2.3);
+inEvalCoord2f(2.0, 2.0);
+inEvalCoord2f(1.0, 2.0);
+endCallBack(NULL);
+
+beginCallBack(GL_TRIANGLE_STRIP, NULL);
+inEvalCoord2f(2.0, 2.3);
+inEvalCoord2f(2.0, 2.0);
+inEvalCoord2f(2.0, 3.0);
+endCallBack(NULL);
+
+}
+return;
+#endif
+
+ k=0;
+ l=0;
+
+ for(i=0; i<bpm->index_length_array; i++)
+ {
+ beginCallBack(bpm->type_array[i], userData);
+ for(j=0; j<bpm->length_array[i]; j++)
+ {
+ u = bpm->UVarray[k];
+ v = bpm->UVarray[k+1];
+ inDoEvalCoord2NOGE(u,v,
+ bpm->vertex_array+l,
+ bpm->normal_array+l);
+
+ normalCallBack(bpm->normal_array+l, userData);
+ vertexCallBack(bpm->vertex_array+l, userData);
+
+ k += 2;
+ l += 3;
+ }
+ endCallBack(userData);
+ }
+}
+
+void OpenGLSurfaceEvaluator::inEvalPoint2(int i, int j)
+{
+ REAL du, dv;
+ REAL point[4];
+ REAL normal[3];
+ REAL u,v;
+ du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu;
+ dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv;
+ u = (i==global_grid_nu)? global_grid_u1:(global_grid_u0 + i*du);
+ v = (j == global_grid_nv)? global_grid_v1: (global_grid_v0 +j*dv);
+ inDoEvalCoord2(u,v,point,normal);
+}
+
+void OpenGLSurfaceEvaluator::inEvalCoord2f(REAL u, REAL v)
+{
+
+ REAL point[4];
+ REAL normal[3];
+ inDoEvalCoord2(u,v,point, normal);
+}
+
+
+
+/*define a grid. store the values into the global variabls:
+ * global_grid_*
+ *These values will be used later by evaluating functions
+ */
+void OpenGLSurfaceEvaluator::inMapGrid2f(int nu, REAL u0, REAL u1,
+ int nv, REAL v0, REAL v1)
+{
+ global_grid_u0 = u0;
+ global_grid_u1 = u1;
+ global_grid_nu = nu;
+ global_grid_v0 = v0;
+ global_grid_v1 = v1;
+ global_grid_nv = nv;
+}
+
+void OpenGLSurfaceEvaluator::inEvalMesh2(int lowU, int lowV, int highU, int highV)
+{
+ REAL du, dv;
+ int i,j;
+ REAL point[4];
+ REAL normal[3];
+ if(global_grid_nu == 0 || global_grid_nv == 0)
+ return; /*no points need to be output*/
+ du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu;
+ dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv;
+
+ if(global_grid_nu >= global_grid_nv){
+ for(i=lowU; i<highU; i++){
+ REAL u1 = (i==global_grid_nu)? global_grid_u1:(global_grid_u0 + i*du);
+ REAL u2 = ((i+1) == global_grid_nu)? global_grid_u1: (global_grid_u0+(i+1)*du);
+
+ bgnqstrip();
+ for(j=highV; j>=lowV; j--){
+ REAL v1 = (j == global_grid_nv)? global_grid_v1: (global_grid_v0 +j*dv);
+
+ inDoEvalCoord2(u1, v1, point, normal);
+ inDoEvalCoord2(u2, v1, point, normal);
+ }
+ endqstrip();
+ }
+ }
+
+ else{
+ for(i=lowV; i<highV; i++){
+ REAL v1 = (i==global_grid_nv)? global_grid_v1:(global_grid_v0 + i*dv);
+ REAL v2 = ((i+1) == global_grid_nv)? global_grid_v1: (global_grid_v0+(i+1)*dv);
+
+ bgnqstrip();
+ for(j=highU; j>=lowU; j--){
+ REAL u1 = (j == global_grid_nu)? global_grid_u1: (global_grid_u0 +j*du);
+ inDoEvalCoord2(u1, v2, point, normal);
+ inDoEvalCoord2(u1, v1, point, normal);
+ }
+ endqstrip();
+ }
+ }
+
+}
+
+void OpenGLSurfaceEvaluator::inMap2f(int k,
+ REAL ulower,
+ REAL uupper,
+ int ustride,
+ int uorder,
+ REAL vlower,
+ REAL vupper,
+ int vstride,
+ int vorder,
+ REAL *ctlPoints)
+{
+ int i,j,x;
+ REAL *data = global_ev_ctlPoints;
+
+
+
+ if(k == GL_MAP2_VERTEX_3) k=3;
+ else if (k==GL_MAP2_VERTEX_4) k =4;
+ else {
+ printf("error in inMap2f, maptype=%i is wrong, k,map is not updated\n", k);
+ return;
+ }
+
+ global_ev_k = k;
+ global_ev_u1 = ulower;
+ global_ev_u2 = uupper;
+ global_ev_ustride = ustride;
+ global_ev_uorder = uorder;
+ global_ev_v1 = vlower;
+ global_ev_v2 = vupper;
+ global_ev_vstride = vstride;
+ global_ev_vorder = vorder;
+
+ /*copy the contrl points from ctlPoints to global_ev_ctlPoints*/
+ for (i=0; i<uorder; i++) {
+ for (j=0; j<vorder; j++) {
+ for (x=0; x<k; x++) {
+ data[x] = ctlPoints[x];
+ }
+ ctlPoints += vstride;
+ data += k;
+ }
+ ctlPoints += ustride - vstride * vorder;
+ }
+
+}
+
+
+/*
+ *given a point p with homegeneous coordiante (x,y,z,w),
+ *let pu(x,y,z,w) be its partial derivative vector with
+ *respect to u
+ *and pv(x,y,z,w) be its partial derivative vector with repect to v.
+ *This function returns the partial derivative vectors of the
+ *inhomegensous coordinates, i.e.,
+ * (x/w, y/w, z/w) with respect to u and v.
+ */
+void OpenGLSurfaceEvaluator::inComputeFirstPartials(REAL *p, REAL *pu, REAL *pv)
+{
+ pu[0] = pu[0]*p[3] - pu[3]*p[0];
+ pu[1] = pu[1]*p[3] - pu[3]*p[1];
+ pu[2] = pu[2]*p[3] - pu[3]*p[2];
+
+ pv[0] = pv[0]*p[3] - pv[3]*p[0];
+ pv[1] = pv[1]*p[3] - pv[3]*p[1];
+ pv[2] = pv[2]*p[3] - pv[3]*p[2];
+}
+
+/*compute the cross product of pu and pv and normalize.
+ *the normal is returned in retNormal
+ * pu: dimension 3
+ * pv: dimension 3
+ * n: return normal, of dimension 3
+ */
+void OpenGLSurfaceEvaluator::inComputeNormal2(REAL *pu, REAL *pv, REAL *n)
+{
+ REAL mag;
+
+ n[0] = pu[1]*pv[2] - pu[2]*pv[1];
+ n[1] = pu[2]*pv[0] - pu[0]*pv[2];
+ n[2] = pu[0]*pv[1] - pu[1]*pv[0];
+
+ mag = sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
+
+ if (mag > 0.0) {
+ n[0] /= mag;
+ n[1] /= mag;
+ n[2] /= mag;
+ }
+}
+
+
+
+/*Compute point and normal
+ *see the head of inDoDomain2WithDerivs
+ *for the meaning of the arguments
+ */
+void OpenGLSurfaceEvaluator::inDoEvalCoord2(REAL u, REAL v,
+ REAL *retPoint, REAL *retNormal)
+{
+
+ REAL du[4];
+ REAL dv[4];
+
+
+ assert(global_ev_k>=3 && global_ev_k <= 4);
+ /*compute homegeneous point and partial derivatives*/
+ inDoDomain2WithDerivs(global_ev_k, u, v, global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, retPoint, du, dv);
+
+#ifdef AVOID_ZERO_NORMAL
+
+ if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
+ {
+
+ REAL tempdu[4];
+ REAL tempdata[4];
+ REAL u1 = global_ev_u1;
+ REAL u2 = global_ev_u2;
+ if(u-MYDELTA*(u2-u1) < u1)
+ u = u+ MYDELTA*(u2-u1);
+ else
+ u = u-MYDELTA*(u2-u1);
+ inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, tempdu, dv);
+ }
+ if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
+ {
+ REAL tempdv[4];
+ REAL tempdata[4];
+ REAL v1 = global_ev_v1;
+ REAL v2 = global_ev_v2;
+ if(v-MYDELTA*(v2-v1) < v1)
+ v = v+ MYDELTA*(v2-v1);
+ else
+ v = v-MYDELTA*(v2-v1);
+ inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, du, tempdv);
+ }
+#endif
+
+
+ /*compute normal*/
+ switch(global_ev_k){
+ case 3:
+ inComputeNormal2(du, dv, retNormal);
+
+ break;
+ case 4:
+ inComputeFirstPartials(retPoint, du, dv);
+ inComputeNormal2(du, dv, retNormal);
+ /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
+ retPoint[0] /= retPoint[3];
+ retPoint[1] /= retPoint[3];
+ retPoint[2] /= retPoint[3];
+ break;
+ }
+ /*output this vertex*/
+/* inMeshStreamInsert(global_ms, retPoint, retNormal);*/
+
+
+
+ glNormal3fv(retNormal);
+ glVertex3fv(retPoint);
+
+
+
+
+ #ifdef DEBUG
+ printf("vertex(%f,%f,%f)\n", retPoint[0],retPoint[1],retPoint[2]);
+ #endif
+
+
+
+}
+
+/*Compute point and normal
+ *see the head of inDoDomain2WithDerivs
+ *for the meaning of the arguments
+ */
+void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE_BU(REAL u, REAL v,
+ REAL *retPoint, REAL *retNormal)
+{
+
+ REAL du[4];
+ REAL dv[4];
+
+
+ assert(global_ev_k>=3 && global_ev_k <= 4);
+ /*compute homegeneous point and partial derivatives*/
+// inPreEvaluateBU(global_ev_k, global_ev_uorder, global_ev_vorder, (u-global_ev_u1)/(global_ev_u2-global_ev_u1), global_ev_ctlPoints);
+ inDoDomain2WithDerivsBU(global_ev_k, u, v, global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, retPoint, du, dv);
+
+
+#ifdef AVOID_ZERO_NORMAL
+
+ if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
+ {
+
+ REAL tempdu[4];
+ REAL tempdata[4];
+ REAL u1 = global_ev_u1;
+ REAL u2 = global_ev_u2;
+ if(u-MYDELTA*(u2-u1) < u1)
+ u = u+ MYDELTA*(u2-u1);
+ else
+ u = u-MYDELTA*(u2-u1);
+ inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, tempdu, dv);
+ }
+ if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
+ {
+ REAL tempdv[4];
+ REAL tempdata[4];
+ REAL v1 = global_ev_v1;
+ REAL v2 = global_ev_v2;
+ if(v-MYDELTA*(v2-v1) < v1)
+ v = v+ MYDELTA*(v2-v1);
+ else
+ v = v-MYDELTA*(v2-v1);
+ inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, du, tempdv);
+ }
+#endif
+
+ /*compute normal*/
+ switch(global_ev_k){
+ case 3:
+ inComputeNormal2(du, dv, retNormal);
+ break;
+ case 4:
+ inComputeFirstPartials(retPoint, du, dv);
+ inComputeNormal2(du, dv, retNormal);
+ /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
+ retPoint[0] /= retPoint[3];
+ retPoint[1] /= retPoint[3];
+ retPoint[2] /= retPoint[3];
+ break;
+ }
+}
+
+/*Compute point and normal
+ *see the head of inDoDomain2WithDerivs
+ *for the meaning of the arguments
+ */
+void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE_BV(REAL u, REAL v,
+ REAL *retPoint, REAL *retNormal)
+{
+
+ REAL du[4];
+ REAL dv[4];
+
+
+ assert(global_ev_k>=3 && global_ev_k <= 4);
+ /*compute homegeneous point and partial derivatives*/
+// inPreEvaluateBV(global_ev_k, global_ev_uorder, global_ev_vorder, (v-global_ev_v1)/(global_ev_v2-global_ev_v1), global_ev_ctlPoints);
+
+ inDoDomain2WithDerivsBV(global_ev_k, u, v, global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, retPoint, du, dv);
+
+
+#ifdef AVOID_ZERO_NORMAL
+
+ if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
+ {
+
+ REAL tempdu[4];
+ REAL tempdata[4];
+ REAL u1 = global_ev_u1;
+ REAL u2 = global_ev_u2;
+ if(u-MYDELTA*(u2-u1) < u1)
+ u = u+ MYDELTA*(u2-u1);
+ else
+ u = u-MYDELTA*(u2-u1);
+ inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, tempdu, dv);
+ }
+ if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
+ {
+ REAL tempdv[4];
+ REAL tempdata[4];
+ REAL v1 = global_ev_v1;
+ REAL v2 = global_ev_v2;
+ if(v-MYDELTA*(v2-v1) < v1)
+ v = v+ MYDELTA*(v2-v1);
+ else
+ v = v-MYDELTA*(v2-v1);
+ inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, du, tempdv);
+ }
+#endif
+
+ /*compute normal*/
+ switch(global_ev_k){
+ case 3:
+ inComputeNormal2(du, dv, retNormal);
+ break;
+ case 4:
+ inComputeFirstPartials(retPoint, du, dv);
+ inComputeNormal2(du, dv, retNormal);
+ /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
+ retPoint[0] /= retPoint[3];
+ retPoint[1] /= retPoint[3];
+ retPoint[2] /= retPoint[3];
+ break;
+ }
+}
+
+
+/*Compute point and normal
+ *see the head of inDoDomain2WithDerivs
+ *for the meaning of the arguments
+ */
+void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE(REAL u, REAL v,
+ REAL *retPoint, REAL *retNormal)
+{
+
+ REAL du[4];
+ REAL dv[4];
+
+
+ assert(global_ev_k>=3 && global_ev_k <= 4);
+ /*compute homegeneous point and partial derivatives*/
+ inDoDomain2WithDerivs(global_ev_k, u, v, global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, retPoint, du, dv);
+
+
+#ifdef AVOID_ZERO_NORMAL
+
+ if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
+ {
+
+ REAL tempdu[4];
+ REAL tempdata[4];
+ REAL u1 = global_ev_u1;
+ REAL u2 = global_ev_u2;
+ if(u-MYDELTA*(u2-u1) < u1)
+ u = u+ MYDELTA*(u2-u1);
+ else
+ u = u-MYDELTA*(u2-u1);
+ inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, tempdu, dv);
+ }
+ if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
+ {
+ REAL tempdv[4];
+ REAL tempdata[4];
+ REAL v1 = global_ev_v1;
+ REAL v2 = global_ev_v2;
+ if(v-MYDELTA*(v2-v1) < v1)
+ v = v+ MYDELTA*(v2-v1);
+ else
+ v = v-MYDELTA*(v2-v1);
+ inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, du, tempdv);
+ }
+#endif
+
+ /*compute normal*/
+ switch(global_ev_k){
+ case 3:
+ inComputeNormal2(du, dv, retNormal);
+ break;
+ case 4:
+ inComputeFirstPartials(retPoint, du, dv);
+ inComputeNormal2(du, dv, retNormal);
+ /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
+ retPoint[0] /= retPoint[3];
+ retPoint[1] /= retPoint[3];
+ retPoint[2] /= retPoint[3];
+ break;
+ }
+// glNormal3fv(retNormal);
+// glVertex3fv(retPoint);
+}
+
+void OpenGLSurfaceEvaluator::inPreEvaluateBV(int k, int uorder, int vorder, REAL vprime, REAL *baseData)
+{
+ int j,row,col;
+ REAL p, pdv;
+ REAL *data;
+
+ if(global_vprime != vprime || global_vorder != vorder) {
+ inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv);
+ global_vprime = vprime;
+ global_vorder = vorder;
+ }
+
+ for(j=0; j<k; j++){
+ data = baseData+j;
+ for(row=0; row<uorder; row++){
+ p = global_vcoeff[0] * (*data);
+ pdv = global_vcoeffDeriv[0] * (*data);
+ data += k;
+ for(col = 1; col < vorder; col++){
+ p += global_vcoeff[col] * (*data);
+ pdv += global_vcoeffDeriv[col] * (*data);
+ data += k;
+ }
+ global_BV[row][j] = p;
+ global_PBV[row][j] = pdv;
+ }
+ }
+}
+
+void OpenGLSurfaceEvaluator::inPreEvaluateBU(int k, int uorder, int vorder, REAL uprime, REAL *baseData)
+{
+ int j,row,col;
+ REAL p, pdu;
+ REAL *data;
+
+ if(global_uprime != uprime || global_uorder != uorder) {
+ inPreEvaluateWithDeriv(uorder, uprime, global_ucoeff, global_ucoeffDeriv);
+ global_uprime = uprime;
+ global_uorder = uorder;
+ }
+
+ for(j=0; j<k; j++){
+ data = baseData+j;
+ for(col=0; col<vorder; col++){
+ data = baseData+j + k*col;
+ p = global_ucoeff[0] * (*data);
+ pdu = global_ucoeffDeriv[0] * (*data);
+ data += k*uorder;
+ for(row = 1; row < uorder; row++){
+ p += global_ucoeff[row] * (*data);
+ pdu += global_ucoeffDeriv[row] * (*data);
+ data += k * uorder;
+ }
+ global_BU[col][j] = p;
+ global_PBU[col][j] = pdu;
+ }
+ }
+}
+
+void OpenGLSurfaceEvaluator::inDoDomain2WithDerivsBU(int k, REAL u, REAL v,
+ REAL u1, REAL u2, int uorder,
+ REAL v1, REAL v2, int vorder,
+ REAL *baseData,
+ REAL *retPoint, REAL* retdu, REAL *retdv)
+{
+ int j, col;
+
+ REAL vprime;
+
+
+ if((u2 == u1) || (v2 == v1))
+ return;
+
+ vprime = (v - v1) / (v2 - v1);
+
+
+ if(global_vprime != vprime || global_vorder != vorder) {
+ inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv);
+ global_vprime = vprime;
+ global_vorder = vorder;
+ }
+
+
+ for(j=0; j<k; j++)
+ {
+ retPoint[j] = retdu[j] = retdv[j] = 0.0;
+ for (col = 0; col < vorder; col++) {
+ retPoint[j] += global_BU[col][j] * global_vcoeff[col];
+ retdu[j] += global_PBU[col][j] * global_vcoeff[col];
+ retdv[j] += global_BU[col][j] * global_vcoeffDeriv[col];
+ }
+ }
+}
+
+void OpenGLSurfaceEvaluator::inDoDomain2WithDerivsBV(int k, REAL u, REAL v,
+ REAL u1, REAL u2, int uorder,
+ REAL v1, REAL v2, int vorder,
+ REAL *baseData,
+ REAL *retPoint, REAL* retdu, REAL *retdv)
+{
+ int j, row;
+ REAL uprime;
+
+
+ if((u2 == u1) || (v2 == v1))
+ return;
+ uprime = (u - u1) / (u2 - u1);
+
+
+ if(global_uprime != uprime || global_uorder != uorder) {
+ inPreEvaluateWithDeriv(uorder, uprime, global_ucoeff, global_ucoeffDeriv);
+ global_uprime = uprime;
+ global_uorder = uorder;
+ }
+
+
+ for(j=0; j<k; j++)
+ {
+ retPoint[j] = retdu[j] = retdv[j] = 0.0;
+ for (row = 0; row < uorder; row++) {
+ retPoint[j] += global_BV[row][j] * global_ucoeff[row];
+ retdu[j] += global_BV[row][j] * global_ucoeffDeriv[row];
+ retdv[j] += global_PBV[row][j] * global_ucoeff[row];
+ }
+ }
+}
+
+
+/*
+ *given a Bezier surface, and parameter (u,v), compute the point in the object space,
+ *and the normal
+ *k: the dimension of the object space: usually 2,3,or 4.
+ *u,v: the paramter pair.
+ *u1,u2,uorder: the Bezier polynomial of u coord is defined on [u1,u2] with order uorder.
+ *v1,v2,vorder: the Bezier polynomial of v coord is defined on [v1,v2] with order vorder.
+ *baseData: contrl points. arranged as: (u,v,k).
+ *retPoint: the computed point (one point) with dimension k.
+ *retdu: the computed partial derivative with respect to u.
+ *retdv: the computed partial derivative with respect to v.
+ */
+void OpenGLSurfaceEvaluator::inDoDomain2WithDerivs(int k, REAL u, REAL v,
+ REAL u1, REAL u2, int uorder,
+ REAL v1, REAL v2, int vorder,
+ REAL *baseData,
+ REAL *retPoint, REAL *retdu, REAL *retdv)
+{
+ int j, row, col;
+ REAL uprime;
+ REAL vprime;
+ REAL p;
+ REAL pdv;
+ REAL *data;
+
+ if((u2 == u1) || (v2 == v1))
+ return;
+ uprime = (u - u1) / (u2 - u1);
+ vprime = (v - v1) / (v2 - v1);
+
+ /* Compute coefficients for values and derivs */
+
+ /* Use already cached values if possible */
+ if(global_uprime != uprime || global_uorder != uorder) {
+ inPreEvaluateWithDeriv(uorder, uprime, global_ucoeff, global_ucoeffDeriv);
+ global_uorder = uorder;
+ global_uprime = uprime;
+ }
+ if (global_vprime != vprime ||
+ global_vorder != vorder) {
+ inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv);
+ global_vorder = vorder;
+ global_vprime = vprime;
+ }
+
+ for (j = 0; j < k; j++) {
+ data=baseData+j;
+ retPoint[j] = retdu[j] = retdv[j] = 0.0;
+ for (row = 0; row < uorder; row++) {
+ /*
+ ** Minor optimization.
+ ** The col == 0 part of the loop is extracted so we don't
+ ** have to initialize p and pdv to 0.
+ */
+ p = global_vcoeff[0] * (*data);
+ pdv = global_vcoeffDeriv[0] * (*data);
+ data += k;
+ for (col = 1; col < vorder; col++) {
+ /* Incrementally build up p, pdv value */
+ p += global_vcoeff[col] * (*data);
+ pdv += global_vcoeffDeriv[col] * (*data);
+ data += k;
+ }
+ /* Use p, pdv value to incrementally add up r, du, dv */
+ retPoint[j] += global_ucoeff[row] * p;
+ retdu[j] += global_ucoeffDeriv[row] * p;
+ retdv[j] += global_ucoeff[row] * pdv;
+ }
+ }
+}
+
+
+/*
+ *compute the Bezier polynomials C[n,j](v) for all j at v with
+ *return values stored in coeff[], where
+ * C[n,j](v) = (n,j) * v^j * (1-v)^(n-j),
+ * j=0,1,2,...,n.
+ *order : n+1
+ *vprime: v
+ *coeff : coeff[j]=C[n,j](v), this array store the returned values.
+ *The algorithm is a recursive scheme:
+ * C[0,0]=1;
+ * C[n,j](v) = (1-v)*C[n-1,j](v) + v*C[n-1,j-1](v), n>=1
+ *This code is copied from opengl/soft/so_eval.c:PreEvaluate
+ */
+void OpenGLSurfaceEvaluator::inPreEvaluate(int order, REAL vprime, REAL *coeff)
+{
+ int i, j;
+ REAL oldval, temp;
+ REAL oneMinusvprime;
+
+ /*
+ * Minor optimization
+ * Compute orders 1 and 2 outright, and set coeff[0], coeff[1] to
+ * their i==1 loop values to avoid the initialization and the i==1 loop.
+ */
+ if (order == 1) {
+ coeff[0] = 1.0;
+ return;
+ }
+
+ oneMinusvprime = 1-vprime;
+ coeff[0] = oneMinusvprime;
+ coeff[1] = vprime;
+ if (order == 2) return;
+
+ for (i = 2; i < order; i++) {
+ oldval = coeff[0] * vprime;
+ coeff[0] = oneMinusvprime * coeff[0];
+ for (j = 1; j < i; j++) {
+ temp = oldval;
+ oldval = coeff[j] * vprime;
+ coeff[j] = temp + oneMinusvprime * coeff[j];
+ }
+ coeff[j] = oldval;
+ }
+}
+
+/*
+ *compute the Bezier polynomials C[n,j](v) and derivatives for all j at v with
+ *return values stored in coeff[] and coeffDeriv[].
+ *see the head of function inPreEvaluate for the definition of C[n,j](v)
+ *and how to compute the values.
+ *The algorithm to compute the derivative is:
+ * dC[0,0](v) = 0.
+ * dC[n,j](v) = n*(dC[n-1,j-1](v) - dC[n-1,j](v)).
+ *
+ *This code is copied from opengl/soft/so_eval.c:PreEvaluateWidthDeriv
+ */
+void OpenGLSurfaceEvaluator::inPreEvaluateWithDeriv(int order, REAL vprime,
+ REAL *coeff, REAL *coeffDeriv)
+{
+ int i, j;
+ REAL oldval, temp;
+ REAL oneMinusvprime;
+
+ oneMinusvprime = 1-vprime;
+ /*
+ * Minor optimization
+ * Compute orders 1 and 2 outright, and set coeff[0], coeff[1] to
+ * their i==1 loop values to avoid the initialization and the i==1 loop.
+ */
+ if (order == 1) {
+ coeff[0] = 1.0;
+ coeffDeriv[0] = 0.0;
+ return;
+ } else if (order == 2) {
+ coeffDeriv[0] = -1.0;
+ coeffDeriv[1] = 1.0;
+ coeff[0] = oneMinusvprime;
+ coeff[1] = vprime;
+ return;
+ }
+ coeff[0] = oneMinusvprime;
+ coeff[1] = vprime;
+ for (i = 2; i < order - 1; i++) {
+ oldval = coeff[0] * vprime;
+ coeff[0] = oneMinusvprime * coeff[0];
+ for (j = 1; j < i; j++) {
+ temp = oldval;
+ oldval = coeff[j] * vprime;
+ coeff[j] = temp + oneMinusvprime * coeff[j];
+ }
+ coeff[j] = oldval;
+ }
+ coeffDeriv[0] = -coeff[0];
+ /*
+ ** Minor optimization:
+ ** Would make this a "for (j=1; j<order-1; j++)" loop, but it is always
+ ** executed at least once, so this is more efficient.
+ */
+ j=1;
+ do {
+ coeffDeriv[j] = coeff[j-1] - coeff[j];
+ j++;
+ } while (j < order - 1);
+ coeffDeriv[j] = coeff[j-1];
+
+ oldval = coeff[0] * vprime;
+ coeff[0] = oneMinusvprime * coeff[0];
+ for (j = 1; j < i; j++) {
+ temp = oldval;
+ oldval = coeff[j] * vprime;
+ coeff[j] = temp + oneMinusvprime * coeff[j];
+ }
+ coeff[j] = oldval;
+}
+
+void OpenGLSurfaceEvaluator::inEvalULine(int n_points, REAL v, REAL* u_vals,
+ int stride, REAL ret_points[][3], REAL ret_normals[][3])
+{
+ int i,k;
+ REAL temp[4];
+inPreEvaluateBV_intfac(v);
+
+ for(i=0,k=0; i<n_points; i++, k += stride)
+ {
+ inDoEvalCoord2NOGE_BV(u_vals[k],v,temp, ret_normals[i]);
+
+ ret_points[i][0] = temp[0];
+ ret_points[i][1] = temp[1];
+ ret_points[i][2] = temp[2];
+
+ }
+
+}
+
+void OpenGLSurfaceEvaluator::inEvalVLine(int n_points, REAL u, REAL* v_vals,
+ int stride, REAL ret_points[][3], REAL ret_normals[][3])
+{
+ int i,k;
+ REAL temp[4];
+inPreEvaluateBU_intfac(u);
+ for(i=0,k=0; i<n_points; i++, k += stride)
+ {
+ inDoEvalCoord2NOGE_BU(u, v_vals[k], temp, ret_normals[i]);
+ ret_points[i][0] = temp[0];
+ ret_points[i][1] = temp[1];
+ ret_points[i][2] = temp[2];
+ }
+}
+
+
+/*triangulate a strip bounded by two lines which are parallel to U-axis
+ *upperVerts: the verteces on the upper line
+ *lowerVertx: the verteces on the lower line
+ *n_upper >=1
+ *n_lower >=1
+ */
+void OpenGLSurfaceEvaluator::inEvalUStrip(int n_upper, REAL v_upper, REAL* upper_val, int n_lower, REAL v_lower, REAL* lower_val)
+{
+ int i,j,k,l;
+ REAL leftMostV[2];
+ typedef REAL REAL3[3];
+
+ REAL3* upperXYZ = (REAL3*) malloc(sizeof(REAL3)*n_upper);
+ assert(upperXYZ);
+ REAL3* upperNormal = (REAL3*) malloc(sizeof(REAL3) * n_upper);
+ assert(upperNormal);
+ REAL3* lowerXYZ = (REAL3*) malloc(sizeof(REAL3)*n_lower);
+ assert(lowerXYZ);
+ REAL3* lowerNormal = (REAL3*) malloc(sizeof(REAL3) * n_lower);
+ assert(lowerNormal);
+
+ inEvalULine(n_upper, v_upper, upper_val, 1, upperXYZ, upperNormal);
+ inEvalULine(n_lower, v_lower, lower_val, 1, lowerXYZ, lowerNormal);
+
+
+
+ REAL* leftMostXYZ;
+ REAL* leftMostNormal;
+
+ /*
+ *the algorithm works by scanning from left to right.
+ *leftMostV: the left most of the remaining verteces (on both upper and lower).
+ * it could an element of upperVerts or lowerVerts.
+ *i: upperVerts[i] is the first vertex to the right of leftMostV on upper line *j: lowerVerts[j] is the first vertex to the right of leftMostV on lower line */
+
+ /*initialize i,j,and leftMostV
+ */
+ if(upper_val[0] <= lower_val[0])
+ {
+ i=1;
+ j=0;
+
+ leftMostV[0] = upper_val[0];
+ leftMostV[1] = v_upper;
+ leftMostXYZ = upperXYZ[0];
+ leftMostNormal = upperNormal[0];
+ }
+ else
+ {
+ i=0;
+ j=1;
+
+ leftMostV[0] = lower_val[0];
+ leftMostV[1] = v_lower;
+
+ leftMostXYZ = lowerXYZ[0];
+ leftMostNormal = lowerNormal[0];
+ }
+
+ /*the main loop.
+ *the invariance is that:
+ *at the beginning of each loop, the meaning of i,j,and leftMostV are
+ *maintained
+ */
+ while(1)
+ {
+ if(i >= n_upper) /*case1: no more in upper*/
+ {
+ if(j<n_lower-1) /*at least two vertices in lower*/
+ {
+ bgntfan();
+ glNormal3fv(leftMostNormal);
+ glVertex3fv(leftMostXYZ);
+
+ while(j<n_lower){
+ glNormal3fv(lowerNormal[j]);
+ glVertex3fv(lowerXYZ[j]);
+ j++;
+
+ }
+ endtfan();
+ }
+ break; /*exit the main loop*/
+ }
+ else if(j>= n_lower) /*case2: no more in lower*/
+ {
+ if(i<n_upper-1) /*at least two vertices in upper*/
+ {
+ bgntfan();
+ glNormal3fv(leftMostNormal);
+ glVertex3fv(leftMostXYZ);
+
+ for(k=n_upper-1; k>=i; k--) /*reverse order for two-side lighting*/
+ {
+ glNormal3fv(upperNormal[k]);
+ glVertex3fv(upperXYZ[k]);
+ }
+
+ endtfan();
+ }
+ break; /*exit the main loop*/
+ }
+ else /* case3: neither is empty, plus the leftMostV, there is at least one triangle to output*/
+ {
+ if(upper_val[i] <= lower_val[j])
+ {
+ bgntfan();
+
+ glNormal3fv(lowerNormal[j]);
+ glVertex3fv(lowerXYZ[j]);
+
+ /*find the last k>=i such that
+ *upperverts[k][0] <= lowerverts[j][0]
+ */
+ k=i;
+
+ while(k<n_upper)
+ {
+ if(upper_val[k] > lower_val[j])
+ break;
+ k++;
+
+ }
+ k--;
+
+
+ for(l=k; l>=i; l--)/*the reverse is for two-side lighting*/
+ {
+ glNormal3fv(upperNormal[l]);
+ glVertex3fv(upperXYZ[l]);
+
+ }
+ glNormal3fv(leftMostNormal);
+ glVertex3fv(leftMostXYZ);
+
+ endtfan();
+
+ /*update i and leftMostV for next loop
+ */
+ i = k+1;
+
+ leftMostV[0] = upper_val[k];
+ leftMostV[1] = v_upper;
+ leftMostNormal = upperNormal[k];
+ leftMostXYZ = upperXYZ[k];
+ }
+ else /*upperVerts[i][0] > lowerVerts[j][0]*/
+ {
+ bgntfan();
+ glNormal3fv(upperNormal[i]);
+ glVertex3fv(upperXYZ[i]);
+
+ glNormal3fv(leftMostNormal);
+ glVertex3fv(leftMostXYZ);
+
+
+ /*find the last k>=j such that
+ *lowerverts[k][0] < upperverts[i][0]
+ */
+ k=j;
+ while(k< n_lower)
+ {
+ if(lower_val[k] >= upper_val[i])
+ break;
+ glNormal3fv(lowerNormal[k]);
+ glVertex3fv(lowerXYZ[k]);
+
+ k++;
+ }
+ endtfan();
+
+ /*update j and leftMostV for next loop
+ */
+ j=k;
+ leftMostV[0] = lower_val[j-1];
+ leftMostV[1] = v_lower;
+
+ leftMostNormal = lowerNormal[j-1];
+ leftMostXYZ = lowerXYZ[j-1];
+ }
+ }
+ }
+ //clean up
+ free(upperXYZ);
+ free(lowerXYZ);
+ free(upperNormal);
+ free(lowerNormal);
+}
+
+/*triangulate a strip bounded by two lines which are parallel to V-axis
+ *leftVerts: the verteces on the left line
+ *rightVertx: the verteces on the right line
+ *n_left >=1
+ *n_right >=1
+ */
+void OpenGLSurfaceEvaluator::inEvalVStrip(int n_left, REAL u_left, REAL* left_val, int n_right, REAL u_right, REAL* right_val)
+{
+ int i,j,k,l;
+ REAL botMostV[2];
+ typedef REAL REAL3[3];
+
+ REAL3* leftXYZ = (REAL3*) malloc(sizeof(REAL3)*n_left);
+ assert(leftXYZ);
+ REAL3* leftNormal = (REAL3*) malloc(sizeof(REAL3) * n_left);
+ assert(leftNormal);
+ REAL3* rightXYZ = (REAL3*) malloc(sizeof(REAL3)*n_right);
+ assert(rightXYZ);
+ REAL3* rightNormal = (REAL3*) malloc(sizeof(REAL3) * n_right);
+ assert(rightNormal);
+
+ inEvalVLine(n_left, u_left, left_val, 1, leftXYZ, leftNormal);
+ inEvalVLine(n_right, u_right, right_val, 1, rightXYZ, rightNormal);
+
+
+
+ REAL* botMostXYZ;
+ REAL* botMostNormal;
+
+ /*
+ *the algorithm works by scanning from bot to top.
+ *botMostV: the bot most of the remaining verteces (on both left and right).
+ * it could an element of leftVerts or rightVerts.
+ *i: leftVerts[i] is the first vertex to the top of botMostV on left line
+ *j: rightVerts[j] is the first vertex to the top of botMostV on rightline */
+
+ /*initialize i,j,and botMostV
+ */
+ if(left_val[0] <= right_val[0])
+ {
+ i=1;
+ j=0;
+
+ botMostV[0] = u_left;
+ botMostV[1] = left_val[0];
+ botMostXYZ = leftXYZ[0];
+ botMostNormal = leftNormal[0];
+ }
+ else
+ {
+ i=0;
+ j=1;
+
+ botMostV[0] = u_right;
+ botMostV[1] = right_val[0];
+
+ botMostXYZ = rightXYZ[0];
+ botMostNormal = rightNormal[0];
+ }
+
+ /*the main loop.
+ *the invariance is that:
+ *at the beginning of each loop, the meaning of i,j,and botMostV are
+ *maintained
+ */
+ while(1)
+ {
+ if(i >= n_left) /*case1: no more in left*/
+ {
+ if(j<n_right-1) /*at least two vertices in right*/
+ {
+ bgntfan();
+ glNormal3fv(botMostNormal);
+ glVertex3fv(botMostXYZ);
+
+ while(j<n_right){
+ glNormal3fv(rightNormal[j]);
+ glVertex3fv(rightXYZ[j]);
+ j++;
+
+ }
+ endtfan();
+ }
+ break; /*exit the main loop*/
+ }
+ else if(j>= n_right) /*case2: no more in right*/
+ {
+ if(i<n_left-1) /*at least two vertices in left*/
+ {
+ bgntfan();
+ glNormal3fv(botMostNormal);
+ glVertex3fv(botMostXYZ);
+
+ for(k=n_left-1; k>=i; k--) /*reverse order for two-side lighting*/
+ {
+ glNormal3fv(leftNormal[k]);
+ glVertex3fv(leftXYZ[k]);
+ }
+
+ endtfan();
+ }
+ break; /*exit the main loop*/
+ }
+ else /* case3: neither is empty, plus the botMostV, there is at least one triangle to output*/
+ {
+ if(left_val[i] <= right_val[j])
+ {
+ bgntfan();
+
+ glNormal3fv(rightNormal[j]);
+ glVertex3fv(rightXYZ[j]);
+
+ /*find the last k>=i such that
+ *leftverts[k][0] <= rightverts[j][0]
+ */
+ k=i;
+
+ while(k<n_left)
+ {
+ if(left_val[k] > right_val[j])
+ break;
+ k++;
+
+ }
+ k--;
+
+
+ for(l=k; l>=i; l--)/*the reverse is for two-side lighting*/
+ {
+ glNormal3fv(leftNormal[l]);
+ glVertex3fv(leftXYZ[l]);
+
+ }
+ glNormal3fv(botMostNormal);
+ glVertex3fv(botMostXYZ);
+
+ endtfan();
+
+ /*update i and botMostV for next loop
+ */
+ i = k+1;
+
+ botMostV[0] = u_left;
+ botMostV[1] = left_val[k];
+ botMostNormal = leftNormal[k];
+ botMostXYZ = leftXYZ[k];
+ }
+ else /*left_val[i] > right_val[j])*/
+ {
+ bgntfan();
+ glNormal3fv(leftNormal[i]);
+ glVertex3fv(leftXYZ[i]);
+
+ glNormal3fv(botMostNormal);
+ glVertex3fv(botMostXYZ);
+
+
+ /*find the last k>=j such that
+ *rightverts[k][0] < leftverts[i][0]
+ */
+ k=j;
+ while(k< n_right)
+ {
+ if(right_val[k] >= left_val[i])
+ break;
+ glNormal3fv(rightNormal[k]);
+ glVertex3fv(rightXYZ[k]);
+
+ k++;
+ }
+ endtfan();
+
+ /*update j and botMostV for next loop
+ */
+ j=k;
+ botMostV[0] = u_right;
+ botMostV[1] = right_val[j-1];
+
+ botMostNormal = rightNormal[j-1];
+ botMostXYZ = rightXYZ[j-1];
+ }
+ }
+ }
+ //clean up
+ free(leftXYZ);
+ free(leftXYZ);
+ free(rightNormal);
+ free(rightNormal);
+}
+
+/*-----------------------begin evalMachine-------------------*/
+void OpenGLSurfaceEvaluator::inMap2fEM(int which, int k,
+ REAL ulower,
+ REAL uupper,
+ int ustride,
+ int uorder,
+ REAL vlower,
+ REAL vupper,
+ int vstride,
+ int vorder,
+ REAL *ctlPoints)
+{
+ int i,j,x;
+ surfEvalMachine *temp_em;
+ switch(which){
+ case 0: //vertex
+ vertex_flag = 1;
+ temp_em = &em_vertex;
+ break;
+ case 1: //normal
+ normal_flag = 1;
+ temp_em = &em_normal;
+ break;
+ case 2: //color
+ color_flag = 1;
+ temp_em = &em_color;
+ break;
+ default:
+ texcoord_flag = 1;
+ temp_em = &em_texcoord;
+ break;
+ }
+
+ REAL *data = temp_em->ctlPoints;
+
+ temp_em->uprime = -1;//initilized
+ temp_em->vprime = -1;
+
+ temp_em->k = k;
+ temp_em->u1 = ulower;
+ temp_em->u2 = uupper;
+ temp_em->ustride = ustride;
+ temp_em->uorder = uorder;
+ temp_em->v1 = vlower;
+ temp_em->v2 = vupper;
+ temp_em->vstride = vstride;
+ temp_em->vorder = vorder;
+
+ /*copy the contrl points from ctlPoints to global_ev_ctlPoints*/
+ for (i=0; i<uorder; i++) {
+ for (j=0; j<vorder; j++) {
+ for (x=0; x<k; x++) {
+ data[x] = ctlPoints[x];
+ }
+ ctlPoints += vstride;
+ data += k;
+ }
+ ctlPoints += ustride - vstride * vorder;
+ }
+}
+
+void OpenGLSurfaceEvaluator::inDoDomain2WithDerivsEM(surfEvalMachine *em, REAL u, REAL v,
+ REAL *retPoint, REAL *retdu, REAL *retdv)
+{
+ int j, row, col;
+ REAL the_uprime;
+ REAL the_vprime;
+ REAL p;
+ REAL pdv;
+ REAL *data;
+
+ if((em->u2 == em->u1) || (em->v2 == em->v1))
+ return;
+ the_uprime = (u - em->u1) / (em->u2 - em->u1);
+ the_vprime = (v - em->v1) / (em->v2 - em->v1);
+
+ /* Compute coefficients for values and derivs */
+
+ /* Use already cached values if possible */
+ if(em->uprime != the_uprime) {
+ inPreEvaluateWithDeriv(em->uorder, the_uprime, em->ucoeff, em->ucoeffDeriv);
+ em->uprime = the_uprime;
+ }
+ if (em->vprime != the_vprime) {
+ inPreEvaluateWithDeriv(em->vorder, the_vprime, em->vcoeff, em->vcoeffDeriv);
+ em->vprime = the_vprime;
+ }
+
+ for (j = 0; j < em->k; j++) {
+ data=em->ctlPoints+j;
+ retPoint[j] = retdu[j] = retdv[j] = 0.0;
+ for (row = 0; row < em->uorder; row++) {
+ /*
+ ** Minor optimization.
+ ** The col == 0 part of the loop is extracted so we don't
+ ** have to initialize p and pdv to 0.
+ */
+ p = em->vcoeff[0] * (*data);
+ pdv = em->vcoeffDeriv[0] * (*data);
+ data += em->k;
+ for (col = 1; col < em->vorder; col++) {
+ /* Incrementally build up p, pdv value */
+ p += em->vcoeff[col] * (*data);
+ pdv += em->vcoeffDeriv[col] * (*data);
+ data += em->k;
+ }
+ /* Use p, pdv value to incrementally add up r, du, dv */
+ retPoint[j] += em->ucoeff[row] * p;
+ retdu[j] += em->ucoeffDeriv[row] * p;
+ retdv[j] += em->ucoeff[row] * pdv;
+ }
+ }
+}
+
+void OpenGLSurfaceEvaluator::inDoDomain2EM(surfEvalMachine *em, REAL u, REAL v,
+ REAL *retPoint)
+{
+ int j, row, col;
+ REAL the_uprime;
+ REAL the_vprime;
+ REAL p;
+ REAL *data;
+
+ if((em->u2 == em->u1) || (em->v2 == em->v1))
+ return;
+ the_uprime = (u - em->u1) / (em->u2 - em->u1);
+ the_vprime = (v - em->v1) / (em->v2 - em->v1);
+
+ /* Compute coefficients for values and derivs */
+
+ /* Use already cached values if possible */
+ if(em->uprime != the_uprime) {
+ inPreEvaluate(em->uorder, the_uprime, em->ucoeff);
+ em->uprime = the_uprime;
+ }
+ if (em->vprime != the_vprime) {
+ inPreEvaluate(em->vorder, the_vprime, em->vcoeff);
+ em->vprime = the_vprime;
+ }
+
+ for (j = 0; j < em->k; j++) {
+ data=em->ctlPoints+j;
+ retPoint[j] = 0.0;
+ for (row = 0; row < em->uorder; row++) {
+ /*
+ ** Minor optimization.
+ ** The col == 0 part of the loop is extracted so we don't
+ ** have to initialize p and pdv to 0.
+ */
+ p = em->vcoeff[0] * (*data);
+ data += em->k;
+ for (col = 1; col < em->vorder; col++) {
+ /* Incrementally build up p, pdv value */
+ p += em->vcoeff[col] * (*data);
+ data += em->k;
+ }
+ /* Use p, pdv value to incrementally add up r, du, dv */
+ retPoint[j] += em->ucoeff[row] * p;
+ }
+ }
+}
+
+
+void OpenGLSurfaceEvaluator::inDoEvalCoord2EM(REAL u, REAL v)
+{
+ REAL temp_vertex[5];
+ REAL temp_normal[3];
+ REAL temp_color[4];
+ REAL temp_texcoord[4];
+
+ if(texcoord_flag)
+ {
+ inDoDomain2EM(&em_texcoord, u,v, temp_texcoord);
+ texcoordCallBack(temp_texcoord, userData);
+ }
+ if(color_flag)
+ {
+ inDoDomain2EM(&em_color, u,v, temp_color);
+ colorCallBack(temp_color, userData);
+ }
+
+ if(normal_flag) //there is a normla map
+ {
+ inDoDomain2EM(&em_normal, u,v, temp_normal);
+ normalCallBack(temp_normal, userData);
+
+ if(vertex_flag)
+ {
+ inDoDomain2EM(&em_vertex, u,v,temp_vertex);
+ if(em_vertex.k == 4)
+ {
+ temp_vertex[0] /= temp_vertex[3];
+ temp_vertex[1] /= temp_vertex[3];
+ temp_vertex[2] /= temp_vertex[3];
+ }
+ temp_vertex[3]=u;
+ temp_vertex[4]=v;
+ vertexCallBack(temp_vertex, userData);
+ }
+ }
+ else if(auto_normal_flag) //no normal map but there is a normal callbackfunctin
+ {
+ REAL du[4];
+ REAL dv[4];
+
+ /*compute homegeneous point and partial derivatives*/
+ inDoDomain2WithDerivsEM(&em_vertex, u,v,temp_vertex,du,dv);
+
+ if(em_vertex.k ==4)
+ inComputeFirstPartials(temp_vertex, du, dv);
+
+#ifdef AVOID_ZERO_NORMAL
+ if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
+ {
+
+ REAL tempdu[4];
+ REAL tempdata[4];
+ REAL u1 = em_vertex.u1;
+ REAL u2 = em_vertex.u2;
+ if(u-MYDELTA*(u2-u1) < u1)
+ u = u+ MYDELTA*(u2-u1);
+ else
+ u = u-MYDELTA*(u2-u1);
+ inDoDomain2WithDerivsEM(&em_vertex,u,v, tempdata, tempdu, dv);
+
+ if(em_vertex.k ==4)
+ inComputeFirstPartials(temp_vertex, du, dv);
+ }
+ else if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
+ {
+ REAL tempdv[4];
+ REAL tempdata[4];
+ REAL v1 = em_vertex.v1;
+ REAL v2 = em_vertex.v2;
+ if(v-MYDELTA*(v2-v1) < v1)
+ v = v+ MYDELTA*(v2-v1);
+ else
+ v = v-MYDELTA*(v2-v1);
+ inDoDomain2WithDerivsEM(&em_vertex,u,v, tempdata, du, tempdv);
+
+ if(em_vertex.k ==4)
+ inComputeFirstPartials(temp_vertex, du, dv);
+ }
+#endif
+
+ /*compute normal*/
+ switch(em_vertex.k){
+ case 3:
+
+ inComputeNormal2(du, dv, temp_normal);
+ break;
+ case 4:
+
+// inComputeFirstPartials(temp_vertex, du, dv);
+ inComputeNormal2(du, dv, temp_normal);
+
+ /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
+ temp_vertex[0] /= temp_vertex[3];
+ temp_vertex[1] /= temp_vertex[3];
+ temp_vertex[2] /= temp_vertex[3];
+ break;
+ }
+ normalCallBack(temp_normal, userData);
+ temp_vertex[3] = u;
+ temp_vertex[4] = v;
+ vertexCallBack(temp_vertex, userData);
+
+ }/*end if auto_normal*/
+ else //no normal map, and no normal callback function
+ {
+ if(vertex_flag)
+ {
+ inDoDomain2EM(&em_vertex, u,v,temp_vertex);
+ if(em_vertex.k == 4)
+ {
+ temp_vertex[0] /= temp_vertex[3];
+ temp_vertex[1] /= temp_vertex[3];
+ temp_vertex[2] /= temp_vertex[3];
+ }
+ temp_vertex[3] = u;
+ temp_vertex[4] = v;
+ vertexCallBack(temp_vertex, userData);
+ }
+ }
+}
+
+
+void OpenGLSurfaceEvaluator::inBPMEvalEM(bezierPatchMesh* bpm)
+{
+ int i,j,k;
+ float u,v;
+
+ int ustride;
+ int vstride;
+
+#ifdef USE_LOD
+ if(bpm->bpatch != NULL)
+ {
+ bezierPatch* p=bpm->bpatch;
+ ustride = p->dimension * p->vorder;
+ vstride = p->dimension;
+
+ glMap2f( (p->dimension == 3)? GL_MAP2_VERTEX_3 : GL_MAP2_VERTEX_4,
+ p->umin,
+ p->umax,
+ ustride,
+ p->uorder,
+ p->vmin,
+ p->vmax,
+ vstride,
+ p->vorder,
+ p->ctlpoints);
+
+
+/*
+ inMap2fEM(0, p->dimension,
+ p->umin,
+ p->umax,
+ ustride,
+ p->uorder,
+ p->vmin,
+ p->vmax,
+ vstride,
+ p->vorder,
+ p->ctlpoints);
+*/
+ }
+#else
+
+ if(bpm->bpatch != NULL){
+ bezierPatch* p = bpm->bpatch;
+ ustride = p->dimension * p->vorder;
+ vstride = p->dimension;
+ inMap2fEM(0, p->dimension,
+ p->umin,
+ p->umax,
+ ustride,
+ p->uorder,
+ p->vmin,
+ p->vmax,
+ vstride,
+ p->vorder,
+ p->ctlpoints);
+ }
+ if(bpm->bpatch_normal != NULL){
+ bezierPatch* p = bpm->bpatch_normal;
+ ustride = p->dimension * p->vorder;
+ vstride = p->dimension;
+ inMap2fEM(1, p->dimension,
+ p->umin,
+ p->umax,
+ ustride,
+ p->uorder,
+ p->vmin,
+ p->vmax,
+ vstride,
+ p->vorder,
+ p->ctlpoints);
+ }
+ if(bpm->bpatch_color != NULL){
+ bezierPatch* p = bpm->bpatch_color;
+ ustride = p->dimension * p->vorder;
+ vstride = p->dimension;
+ inMap2fEM(2, p->dimension,
+ p->umin,
+ p->umax,
+ ustride,
+ p->uorder,
+ p->vmin,
+ p->vmax,
+ vstride,
+ p->vorder,
+ p->ctlpoints);
+ }
+ if(bpm->bpatch_texcoord != NULL){
+ bezierPatch* p = bpm->bpatch_texcoord;
+ ustride = p->dimension * p->vorder;
+ vstride = p->dimension;
+ inMap2fEM(3, p->dimension,
+ p->umin,
+ p->umax,
+ ustride,
+ p->uorder,
+ p->vmin,
+ p->vmax,
+ vstride,
+ p->vorder,
+ p->ctlpoints);
+ }
+#endif
+
+
+ k=0;
+ for(i=0; i<bpm->index_length_array; i++)
+ {
+#ifdef USE_LOD
+ if(bpm->type_array[i] == GL_POLYGON) //a mesh
+ {
+ GLfloat *temp = bpm->UVarray+k;
+ GLfloat u0 = temp[0];
+ GLfloat v0 = temp[1];
+ GLfloat u1 = temp[2];
+ GLfloat v1 = temp[3];
+ GLint nu = (GLint) ( temp[4]);
+ GLint nv = (GLint) ( temp[5]);
+ GLint umin = (GLint) ( temp[6]);
+ GLint vmin = (GLint) ( temp[7]);
+ GLint umax = (GLint) ( temp[8]);
+ GLint vmax = (GLint) ( temp[9]);
+
+ glMapGrid2f(LOD_eval_level*nu, u0, u1, LOD_eval_level*nv, v0, v1);
+ glEvalMesh2(GL_FILL, LOD_eval_level*umin, LOD_eval_level*umax, LOD_eval_level*vmin, LOD_eval_level*vmax);
+ }
+ else
+ {
+ LOD_eval(bpm->length_array[i], bpm->UVarray+k, bpm->type_array[i],
+ 0
+ );
+ }
+ k+= 2*bpm->length_array[i];
+
+#else //undef USE_LOD
+
+#ifdef CRACK_TEST
+if( bpm->bpatch->umin == 2 && bpm->bpatch->umax == 3
+ && bpm->bpatch->vmin ==2 && bpm->bpatch->vmax == 3)
+{
+REAL vertex[4];
+REAL normal[4];
+#ifdef DEBUG
+printf("***number ****1\n");
+#endif
+
+beginCallBack(GL_QUAD_STRIP, NULL);
+inDoEvalCoord2EM(3.0, 3.0);
+inDoEvalCoord2EM(2.0, 3.0);
+inDoEvalCoord2EM(3.0, 2.7);
+inDoEvalCoord2EM(2.0, 2.7);
+inDoEvalCoord2EM(3.0, 2.0);
+inDoEvalCoord2EM(2.0, 2.0);
+endCallBack(NULL);
+
+beginCallBack(GL_TRIANGLE_STRIP, NULL);
+inDoEvalCoord2EM(2.0, 3.0);
+inDoEvalCoord2EM(2.0, 2.0);
+inDoEvalCoord2EM(2.0, 2.7);
+endCallBack(NULL);
+
+}
+if( bpm->bpatch->umin == 1 && bpm->bpatch->umax == 2
+ && bpm->bpatch->vmin ==2 && bpm->bpatch->vmax == 3)
+{
+#ifdef DEBUG
+printf("***number 3\n");
+#endif
+beginCallBack(GL_QUAD_STRIP, NULL);
+inDoEvalCoord2EM(2.0, 3.0);
+inDoEvalCoord2EM(1.0, 3.0);
+inDoEvalCoord2EM(2.0, 2.3);
+inDoEvalCoord2EM(1.0, 2.3);
+inDoEvalCoord2EM(2.0, 2.0);
+inDoEvalCoord2EM(1.0, 2.0);
+endCallBack(NULL);
+
+beginCallBack(GL_TRIANGLE_STRIP, NULL);
+inDoEvalCoord2EM(2.0, 2.3);
+inDoEvalCoord2EM(2.0, 2.0);
+inDoEvalCoord2EM(2.0, 3.0);
+endCallBack(NULL);
+
+}
+return;
+#endif //CRACK_TEST
+
+ beginCallBack(bpm->type_array[i], userData);
+
+ for(j=0; j<bpm->length_array[i]; j++)
+ {
+ u = bpm->UVarray[k];
+ v = bpm->UVarray[k+1];
+#ifdef USE_LOD
+ LOD_EVAL_COORD(u,v);
+// glEvalCoord2f(u,v);
+#else
+
+#ifdef GENERIC_TEST
+ float temp_normal[3];
+ float temp_vertex[3];
+ if(temp_signal == 0)
+ {
+ gTessVertexSphere(u,v, temp_normal, temp_vertex);
+//printf("normal=(%f,%f,%f)\n", temp_normal[0], temp_normal[1], temp_normal[2])//printf("veretx=(%f,%f,%f)\n", temp_vertex[0], temp_vertex[1], temp_vertex[2]);
+ normalCallBack(temp_normal, userData);
+ vertexCallBack(temp_vertex, userData);
+ }
+ else if(temp_signal == 1)
+ {
+ gTessVertexCyl(u,v, temp_normal, temp_vertex);
+//printf("normal=(%f,%f,%f)\n", temp_normal[0], temp_normal[1], temp_normal[2])//printf("veretx=(%f,%f,%f)\n", temp_vertex[0], temp_vertex[1], temp_vertex[2]);
+ normalCallBack(temp_normal, userData);
+ vertexCallBack(temp_vertex, userData);
+ }
+ else
+#endif //GENERIC_TEST
+
+ inDoEvalCoord2EM(u,v);
+
+#endif //USE_LOD
+
+ k += 2;
+ }
+ endCallBack(userData);
+
+#endif //USE_LOD
+ }
+}
+
+void OpenGLSurfaceEvaluator::inBPMListEvalEM(bezierPatchMesh* list)
+{
+ bezierPatchMesh* temp;
+ for(temp = list; temp != NULL; temp = temp->next)
+ {
+ inBPMEvalEM(temp);
+ }
+}
+
diff --git a/src/glu/sgi/libnurbs/interface/mystdio.h b/src/glu/sgi/libnurbs/interface/mystdio.h
new file mode 100644
index 00000000000..34ad1f80344
--- /dev/null
+++ b/src/glu/sgi/libnurbs/interface/mystdio.h
@@ -0,0 +1,66 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * mystdio.h
+ *
+ * $Date: 2001/03/19 17:52:02 $ $Revision: 1.3 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/interface/mystdio.h,v 1.3 2001/03/19 17:52:02 pesco Exp $
+ */
+
+#ifndef __glumystdio_h_
+#define __glumystdio_h_
+
+#ifdef STANDALONE
+inline void dprintf( char *, ... ) { }
+#endif
+
+#ifdef LIBRARYBUILD
+#ifndef NDEBUG
+#include <stdio.h>
+#define dprintf printf
+#else
+inline void dprintf( char *, ... ) { }
+#endif
+#endif
+
+#ifdef GLBUILD
+inline void dprintf( char *, ... ) { }
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#endif /* __glumystdio_h_ */
diff --git a/src/glu/sgi/libnurbs/interface/mystdlib.h b/src/glu/sgi/libnurbs/interface/mystdlib.h
new file mode 100644
index 00000000000..fba74b9ef70
--- /dev/null
+++ b/src/glu/sgi/libnurbs/interface/mystdlib.h
@@ -0,0 +1,63 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * mystdlib.h
+ *
+ * $Date: 2001/03/19 17:52:02 $ $Revision: 1.3 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/interface/mystdlib.h,v 1.3 2001/03/19 17:52:02 pesco Exp $
+ */
+
+#ifndef __glumystdlib_h_
+#define __glumystdlib_h_
+
+#ifdef STANDALONE
+typedef unsigned int size_t;
+extern "C" void abort( void );
+extern "C" void * malloc( size_t );
+extern "C" void free( void * );
+#endif
+
+#ifdef LIBRARYBUILD
+#include <stdlib.h>
+#endif
+
+#ifdef GLBUILD
+typedef unsigned int size_t;
+extern "C" void abort( void );
+extern "C" void * malloc( size_t );
+extern "C" void free( void * );
+#endif
+
+#endif /* __glumystdlib_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/arc.cc b/src/glu/sgi/libnurbs/internals/arc.cc
new file mode 100644
index 00000000000..f795e00cd7e
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/arc.cc
@@ -0,0 +1,347 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * arc.c++
+ *
+ */
+
+#include <stdio.h>
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "arc.h"
+#include "bin.h"
+#include "bezierarc.h"
+#include "pwlarc.h"
+#include "simplemath.h"
+
+/* local preprocessor definitions */
+#define ZERO 0.00001/*0.000001*/
+
+const int Arc::bezier_tag = (1<<13);
+const int Arc::arc_tag = (1<<3);
+const int Arc::tail_tag = (1<<6);
+
+/*--------------------------------------------------------------------------
+ * makeSide - attach a pwl arc to an arc and mark it as a border arc
+ *--------------------------------------------------------------------------
+ */
+
+void
+Arc::makeSide( PwlArc *pwl, arc_side side )
+{
+ assert( pwl != 0);
+ assert( pwlArc == 0 );
+ assert( pwl->npts > 0 );
+ assert( pwl->pts != 0);
+ pwlArc = pwl;
+ clearbezier();
+ setside( side );
+}
+
+
+/*--------------------------------------------------------------------------
+ * numpts - count number of points on arc loop
+ *--------------------------------------------------------------------------
+ */
+
+int
+Arc::numpts( void )
+{
+ Arc_ptr jarc = this;
+ int npts = 0;
+ do {
+ npts += jarc->pwlArc->npts;
+ jarc = jarc->next;
+ } while( jarc != this );
+ return npts;
+}
+
+/*--------------------------------------------------------------------------
+ * markverts - mark each point with id of arc
+ *--------------------------------------------------------------------------
+ */
+
+void
+Arc::markverts( void )
+{
+ Arc_ptr jarc = this;
+
+ do {
+ TrimVertex *p = jarc->pwlArc->pts;
+ for( int i=0; i<jarc->pwlArc->npts; i++ )
+ p[i].nuid = jarc->nuid;
+ jarc = jarc->next;
+ } while( jarc != this );
+}
+
+/*--------------------------------------------------------------------------
+ * getextrema - find axis extrema on arc loop
+ *--------------------------------------------------------------------------
+ */
+
+void
+Arc::getextrema( Arc_ptr extrema[4] )
+{
+ REAL leftpt, botpt, rightpt, toppt;
+
+ extrema[0] = extrema[1] = extrema[2] = extrema[3] = this;
+
+ leftpt = rightpt = this->tail()[0];
+ botpt = toppt = this->tail()[1];
+
+ for( Arc_ptr jarc = this->next; jarc != this; jarc = jarc->next ) {
+ if ( jarc->tail()[0] < leftpt ||
+ (jarc->tail()[0] <= leftpt && jarc->rhead()[0]<=leftpt)) {
+ leftpt = jarc->pwlArc->pts->param[0];
+ extrema[1] = jarc;
+ }
+ if ( jarc->tail()[0] > rightpt ||
+ (jarc->tail()[0] >= rightpt && jarc->rhead()[0] >= rightpt)) {
+ rightpt = jarc->pwlArc->pts->param[0];
+ extrema[3] = jarc;
+ }
+ if ( jarc->tail()[1] < botpt ||
+ (jarc->tail()[1] <= botpt && jarc->rhead()[1] <= botpt )) {
+ botpt = jarc->pwlArc->pts->param[1];
+ extrema[2] = jarc;
+ }
+ if ( jarc->tail()[1] > toppt ||
+ (jarc->tail()[1] >= toppt && jarc->rhead()[1] >= toppt)) {
+ toppt = jarc->pwlArc->pts->param[1];
+ extrema[0] = jarc;
+ }
+ }
+}
+
+
+/*-------------------------------------------------------------------------
+ * show - print to the stdout the vertices of a pwl arc
+ *-------------------------------------------------------------------------
+ */
+
+void
+Arc::show()
+{
+#ifndef NDEBUG
+ dprintf( "\tPWLARC NP: %d FL: 1\n", pwlArc->npts );
+ for( int i = 0; i < pwlArc->npts; i++ ) {
+ dprintf( "\t\tVERTEX %f %f\n", pwlArc->pts[i].param[0],
+ pwlArc->pts[i].param[1] );
+ }
+#endif
+}
+
+/*-------------------------------------------------------------------------
+ * print - print out the vertices of all pwl arcs on a loop
+ *-------------------------------------------------------------------------
+ */
+
+void
+Arc::print( void )
+{
+ Arc_ptr jarc = this;
+
+#ifndef NDEBUG
+ dprintf( "BGNTRIM\n" );
+#endif
+ do {
+ jarc->show( );
+ jarc = jarc->next;
+ } while (jarc != this);
+#ifndef NDEBUG
+ dprintf("ENDTRIM\n" );
+#endif
+}
+
+/*-------------------------------------------------------------------------
+ * isDisconnected - check if tail of arc and head of prev meet
+ *-------------------------------------------------------------------------
+ */
+
+int
+Arc::isDisconnected( void )
+{
+ if( pwlArc == 0 ) return 0;
+ if( prev->pwlArc == 0 ) return 0;
+
+ REAL *p0 = tail();
+ REAL *p1 = prev->rhead();
+
+ if( ((p0[0] - p1[0]) > ZERO) || ((p1[0] - p0[0]) > ZERO) ||
+ ((p0[1] - p1[1]) > ZERO) || ((p1[1] - p0[1]) > ZERO) ) {
+#ifndef NDEBUG
+ dprintf( "x coord = %f %f %f\n", p0[0], p1[0], p0[0] - p1[0] );
+ dprintf( "y coord = %f %f %f\n", p0[1], p1[1], p0[1] - p1[1] );
+#endif
+ return 1;
+ } else {
+ /* average two points together */
+ p0[0] = p1[0] = (p1[0] + p0[0]) * 0.5;
+ p0[1] = p1[1] = (p1[1] + p0[1]) * 0.5;
+ return 0;
+ }
+}
+
+/*-------------------------------------------------------------------------
+ * neq_vert - assert that two 2D vertices are not equal
+ *-------------------------------------------------------------------------
+ */
+
+inline static int
+neq_vert( REAL *v1, REAL *v2 )
+{
+ return ((v1[0] != v2[0]) || (v1[1] != v2[1] )) ? 1 : 0;
+}
+
+/*-------------------------------------------------------------------------
+ * check - verify consistency of a loop, including
+ * 1) if pwl, no two consecutive vertices are identical
+ * 2) the circular link pointers are valid
+ * 3) the geometric info at the head and tail are consistent
+ *-------------------------------------------------------------------------
+ */
+
+int
+Arc::check( void )
+{
+ if( this == 0 ) return 1;
+ Arc_ptr jarc = this;
+ do {
+ assert( (jarc->pwlArc != 0) || (jarc->bezierArc != 0) );
+
+ if (jarc->prev == 0 || jarc->next == 0) {
+#ifndef NDEBUG
+ dprintf( "checkjarc:null next/prev pointer\n");
+ jarc->print( );
+#endif
+ return 0;
+ }
+
+ if (jarc->next->prev != jarc) {
+#ifndef NDEBUG
+ dprintf( "checkjarc: pointer linkage screwed up\n");
+ jarc->print( );
+#endif
+ return 0;
+ }
+
+ if( jarc->pwlArc ) {
+#ifndef NDEBUG
+ assert( jarc->pwlArc->npts >= 1 );
+ assert( jarc->pwlArc->npts < 100000 );
+/*
+ for( int i=0; i < jarc->pwlArc->npts-1; i++ )
+ assert( neq_vert( jarc->pwlArc->pts[i].param,
+ jarc->pwlArc->pts[i+1].param) );
+*/
+#endif
+ if( jarc->prev->pwlArc ) {
+ if( jarc->tail()[1] != jarc->prev->rhead()[1] ) {
+#ifndef NDEBUG
+ dprintf( "checkjarc: geometric linkage screwed up 1\n");
+ jarc->prev->show();
+ jarc->show();
+#endif
+ return 0;
+ }
+ if( jarc->tail()[0] != jarc->prev->rhead()[0] ) {
+
+#ifndef NDEBUG
+ dprintf( "checkjarc: geometric linkage screwed up 2\n");
+ jarc->prev->show();
+ jarc->show();
+#endif
+ return 0;
+ }
+ }
+ if( jarc->next->pwlArc ) {
+ if( jarc->next->tail()[0] != jarc->rhead()[0] ) {
+#ifndef NDEBUG
+ dprintf( "checkjarc: geometric linkage screwed up 3\n");
+ jarc->show();
+ jarc->next->show();
+#endif
+ return 0;
+ }
+ if( jarc->next->tail()[1] != jarc->rhead()[1] ) {
+#ifndef NDEBUG
+ dprintf( "checkjarc: geometric linkage screwed up 4\n");
+ jarc->show();
+ jarc->next->show();
+#endif
+ return 0;
+ }
+ }
+ if( jarc->isbezier() ) {
+ assert( jarc->pwlArc->npts == 2 );
+ assert( (jarc->pwlArc->pts[0].param[0] == \
+ jarc->pwlArc->pts[1].param[0]) ||\
+ (jarc->pwlArc->pts[0].param[1] == \
+ jarc->pwlArc->pts[1].param[1]) );
+ }
+ }
+ jarc = jarc->next;
+ } while (jarc != this);
+ return 1;
+}
+
+
+#define TOL 0.00001
+
+inline long tooclose( REAL x, REAL y )
+{
+ return (glu_abs(x-y) < TOL) ? 1 : 0;
+}
+
+
+/*--------------------------------------------------------------------------
+ * append - append a jordan arc to a circularly linked list
+ *--------------------------------------------------------------------------
+ */
+
+Arc_ptr
+Arc::append( Arc_ptr jarc )
+{
+ if( jarc != 0 ) {
+ next = jarc->next;
+ prev = jarc;
+ next->prev = prev->next = this;
+ } else {
+ next = prev = this;
+ }
+ return this;
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/arc.h b/src/glu/sgi/libnurbs/internals/arc.h
new file mode 100644
index 00000000000..d30ac9011db
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/arc.h
@@ -0,0 +1,139 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * arc.h
+ *
+ * $Date: 2001/08/07 17:34:11 $ $Revision: 1.2 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/arc.h,v 1.2 2001/08/07 17:34:11 brianp Exp $
+ */
+
+#ifndef __gluarc_h_
+#define __gluarc_h_
+
+#include "myassert.h"
+#include "bufpool.h"
+#include "mystdio.h"
+#include "types.h"
+#include "pwlarc.h"
+#include "trimvertex.h"
+
+class Bin;
+class Arc;
+struct BezierArc;
+
+typedef class Arc *Arc_ptr;
+
+enum arc_side { arc_none = 0, arc_right, arc_top, arc_left, arc_bottom };
+
+
+class Arc: public PooledObj { /* an arc, in two list, the trim list and bin */
+
+public:
+ static const int bezier_tag;
+ static const int arc_tag;
+ static const int tail_tag;
+ Arc_ptr prev; /* trim list pointer */
+ Arc_ptr next; /* trim list pointer */
+ Arc_ptr link; /* bin pointers */
+ BezierArc * bezierArc; /* associated bezier arc */
+ PwlArc * pwlArc; /* associated pwl arc */
+ long type; /* curve type */
+ long nuid;
+
+ inline Arc( Arc *, PwlArc * );
+ inline Arc( arc_side, long );
+
+ Arc_ptr append( Arc_ptr );
+ int check( void );
+ int isMonotone( void );
+ int isDisconnected( void );
+ int numpts( void );
+ void markverts( void );
+ void getextrema( Arc_ptr[4] );
+ void print( void );
+ void show( void );
+ void makeSide( PwlArc *, arc_side );
+ inline int isTessellated() { return pwlArc ? 1 : 0; }
+ inline long isbezier() { return type & bezier_tag; }
+ inline void setbezier() { type |= bezier_tag; }
+ inline void clearbezier() { type &= ~bezier_tag; }
+ inline long npts() { return pwlArc->npts; }
+ inline TrimVertex * pts() { return pwlArc->pts; }
+ inline REAL * tail() { return pwlArc->pts[0].param; }
+ inline REAL * head() { return next->pwlArc->pts[0].param; }
+ inline REAL * rhead() { return pwlArc->pts[pwlArc->npts-1].param; }
+ inline long ismarked() { return type & arc_tag; }
+ inline void setmark() { type |= arc_tag; }
+ inline void clearmark() { type &= (~arc_tag); }
+ inline void clearside() { type &= ~(0x7 << 8); }
+ inline void setside( arc_side s ) { clearside(); type |= (((long)s)<<8); }
+ inline arc_side getside() { return (arc_side) ((type>>8) & 0x7); }
+ inline int getitail() { return type & tail_tag; }
+ inline void setitail() { type |= tail_tag; }
+ inline void clearitail() { type &= (~tail_tag); }
+};
+
+/*--------------------------------------------------------------------------
+ * Arc - initialize a new Arc with the same type and uid of
+ * a given Arc and a given pwl arc
+ *--------------------------------------------------------------------------
+ */
+
+inline
+Arc::Arc( Arc *j, PwlArc *p )
+{
+ bezierArc = NULL;
+ pwlArc = p;
+ type = j->type;
+ nuid = j->nuid;
+}
+
+/*--------------------------------------------------------------------------
+ * Arc - initialize a new Arc with the same type and uid of
+ * a given Arc and a given pwl arc
+ *--------------------------------------------------------------------------
+ */
+
+inline
+Arc::Arc( arc_side side, long _nuid )
+{
+ bezierArc = NULL;
+ pwlArc = NULL;
+ type = 0;
+ setside( side );
+ nuid = _nuid;
+}
+
+#endif /* __gluarc_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/arcsorter.cc b/src/glu/sgi/libnurbs/internals/arcsorter.cc
new file mode 100644
index 00000000000..d0b72c2ad10
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/arcsorter.cc
@@ -0,0 +1,174 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * arcsorter.c++
+ *
+ * $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/arcsorter.cc,v 1.1 2001/03/17 00:25:40 brianp Exp $
+ */
+
+#ifndef __gluarcsorter_c_
+#define __gluarcsorter_c_
+
+#include "glimports.h"
+#include "arc.h"
+#include "arcsorter.h"
+#include "subdivider.h"
+
+ArcSorter::ArcSorter(Subdivider &s) : Sorter( sizeof( Arc ** ) ), subdivider(s)
+{
+}
+
+int
+ArcSorter::qscmp( char *, char * )
+{
+ dprintf( "ArcSorter::qscmp: pure virtual called\n" );
+ return 0;
+}
+
+void
+ArcSorter::qsort( Arc **a, int n )
+{
+ Sorter::qsort( (void *) a, n );
+}
+
+void
+ArcSorter::qsexc( char *i, char *j )// i<-j, j<-i
+{
+ Arc **jarc1 = (Arc **) i;
+ Arc **jarc2 = (Arc **) j;
+ Arc *tmp = *jarc1;
+ *jarc1 = *jarc2;
+ *jarc2 = tmp;
+}
+
+void
+ArcSorter::qstexc( char *i, char *j, char *k )// i<-k, k<-j, j<-i
+{
+ Arc **jarc1 = (Arc **) i;
+ Arc **jarc2 = (Arc **) j;
+ Arc **jarc3 = (Arc **) k;
+ Arc *tmp = *jarc1;
+ *jarc1 = *jarc3;
+ *jarc3 = *jarc2;
+ *jarc2 = tmp;
+}
+
+
+ArcSdirSorter::ArcSdirSorter( Subdivider &s ) : ArcSorter(s)
+{
+}
+
+int
+ArcSdirSorter::qscmp( char *i, char *j )
+{
+ Arc *jarc1 = *(Arc **) i;
+ Arc *jarc2 = *(Arc **) j;
+
+ int v1 = (jarc1->getitail() ? 0 : (jarc1->pwlArc->npts - 1));
+ int v2 = (jarc2->getitail() ? 0 : (jarc2->pwlArc->npts - 1));
+
+ REAL diff = jarc1->pwlArc->pts[v1].param[1] -
+ jarc2->pwlArc->pts[v2].param[1];
+
+ if( diff < 0.0)
+ return -1;
+ else if( diff > 0.0)
+ return 1;
+ else {
+ if( v1 == 0 ) {
+ if( jarc2->tail()[0] < jarc1->tail()[0] ) {
+ return subdivider.ccwTurn_sl( jarc2, jarc1 ) ? 1 : -1;
+ } else {
+ return subdivider.ccwTurn_sr( jarc2, jarc1 ) ? -1 : 1;
+ }
+ } else {
+ if( jarc2->head()[0] < jarc1->head()[0] ) {
+ return subdivider.ccwTurn_sl( jarc1, jarc2 ) ? -1 : 1;
+ } else {
+ return subdivider.ccwTurn_sr( jarc1, jarc2 ) ? 1 : -1;
+ }
+ }
+ }
+}
+
+ArcTdirSorter::ArcTdirSorter( Subdivider &s ) : ArcSorter(s)
+{
+}
+
+/*----------------------------------------------------------------------------
+ * ArcTdirSorter::qscmp -
+ * compare two axis monotone arcs that are incident
+ * to the line T == compare_value. Determine which of the
+ * two intersects that line with a LESSER S value. If
+ * jarc1 does, return 1. If jarc2 does, return -1.
+ *----------------------------------------------------------------------------
+ */
+int
+ArcTdirSorter::qscmp( char *i, char *j )
+{
+ Arc *jarc1 = *(Arc **) i;
+ Arc *jarc2 = *(Arc **) j;
+
+ int v1 = (jarc1->getitail() ? 0 : (jarc1->pwlArc->npts - 1));
+ int v2 = (jarc2->getitail() ? 0 : (jarc2->pwlArc->npts - 1));
+
+ REAL diff = jarc1->pwlArc->pts[v1].param[0] -
+ jarc2->pwlArc->pts[v2].param[0];
+
+ if( diff < 0.0)
+ return 1;
+ else if( diff > 0.0)
+ return -1;
+ else {
+ if( v1 == 0 ) {
+ if (jarc2->tail()[1] < jarc1->tail()[1]) {
+ return subdivider.ccwTurn_tl( jarc2, jarc1 ) ? 1 : -1;
+ } else {
+ return subdivider.ccwTurn_tr( jarc2, jarc1 ) ? -1 : 1;
+ }
+ } else {
+ if( jarc2->head()[1] < jarc1->head()[1] ) {
+ return subdivider.ccwTurn_tl( jarc1, jarc2 ) ? -1 : 1;
+ } else {
+ return subdivider.ccwTurn_tr( jarc1, jarc2 ) ? 1 : -1;
+ }
+ }
+ }
+}
+
+
+
+#endif /* __gluarcsorter_c_ */
diff --git a/src/glu/sgi/libnurbs/internals/arcsorter.h b/src/glu/sgi/libnurbs/internals/arcsorter.h
new file mode 100644
index 00000000000..06fa4321114
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/arcsorter.h
@@ -0,0 +1,79 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * arcsorter.h
+ *
+ * $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/arcsorter.h,v 1.1 2001/03/17 00:25:40 brianp Exp $
+ */
+
+#ifndef __gluarcsorter_h_
+#define __gluarcsorter_h_
+
+#include "sorter.h"
+#include "arcsorter.h"
+
+class Arc;
+class Subdivider;
+
+class ArcSorter : private Sorter {
+public:
+ ArcSorter(Subdivider &);
+ void qsort( Arc **a, int n );
+protected:
+ virtual int qscmp( char *, char * );
+ Subdivider& subdivider;
+private:
+ void qsexc( char *i, char *j ); // i<-j, j<-i
+ void qstexc( char *i, char *j, char *k ); // i<-k, k<-j, j<-i
+};
+
+
+class ArcSdirSorter : public ArcSorter {
+public:
+ ArcSdirSorter( Subdivider & );
+private:
+ int qscmp( char *, char * );
+};
+
+
+class ArcTdirSorter : public ArcSorter {
+public:
+ ArcTdirSorter( Subdivider & );
+private:
+ int qscmp( char *, char * );
+};
+
+#endif /* __gluarcsorter_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/arctess.cc b/src/glu/sgi/libnurbs/internals/arctess.cc
new file mode 100644
index 00000000000..e633626de06
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/arctess.cc
@@ -0,0 +1,611 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * arctessellator.c++
+ *
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "arctess.h"
+#include "bufpool.h"
+#include "simplemath.h"
+#include "bezierarc.h"
+#include "trimvertex.h"
+#include "trimvertpool.h"
+
+#define NOELIMINATION
+
+#define steps_function(large, small, rate) (max(1, 1+ (int) ((large-small)/rate)));
+
+/*-----------------------------------------------------------------------------
+ * ArcTessellator - construct an ArcTessellator
+ *-----------------------------------------------------------------------------
+ */
+
+ArcTessellator::ArcTessellator( TrimVertexPool& t, Pool& p )
+ : pwlarcpool(p), trimvertexpool(t)
+{
+}
+
+/*-----------------------------------------------------------------------------
+ * ~ArcTessellator - destroy an ArcTessellator
+ *-----------------------------------------------------------------------------
+ */
+
+ArcTessellator::~ArcTessellator( void )
+{
+}
+
+/*-----------------------------------------------------------------------------
+ * bezier - construct a bezier arc and attach it to an Arc
+ *-----------------------------------------------------------------------------
+ */
+
+void
+ArcTessellator::bezier( Arc *arc, REAL s1, REAL s2, REAL t1, REAL t2 )
+{
+ assert( arc != 0 );
+ assert( ! arc->isTessellated() );
+
+#ifndef NDEBUG
+ switch( arc->getside() ) {
+ case arc_left:
+ assert( s1 == s2 );
+ assert( t2 < t1 );
+ break;
+ case arc_right:
+ assert( s1 == s2 );
+ assert( t1 < t2 );
+ break;
+ case arc_top:
+ assert( t1 == t2 );
+ assert( s2 < s1 );
+ break;
+ case arc_bottom:
+ assert( t1 == t2 );
+ assert( s1 < s2 );
+ break;
+ case arc_none:
+ (void) abort();
+ break;
+ }
+#endif
+
+ TrimVertex *p = trimvertexpool.get(2);
+ arc->pwlArc = new(pwlarcpool) PwlArc( 2, p );
+ p[0].param[0] = s1;
+ p[0].param[1] = t1;
+ p[1].param[0] = s2;
+ p[1].param[1] = t2;
+ assert( (s1 == s2) || (t1 == t2) );
+ arc->setbezier();
+}
+
+
+/*-----------------------------------------------------------------------------
+ * pwl_left - construct a left boundary pwl arc and attach it to an arc
+ *-----------------------------------------------------------------------------
+ */
+
+void
+ArcTessellator::pwl_left( Arc *arc, REAL s, REAL t1, REAL t2, REAL rate )
+{
+ assert( t2 < t1 );
+
+/* if(rate <= 0.06) rate = 0.06;*/
+/* int nsteps = 1 + (int) ((t1 - t2) / rate ); */
+ int nsteps = steps_function(t1, t2, rate);
+
+
+ REAL stepsize = (t1 - t2) / (REAL) nsteps;
+
+ TrimVertex *newvert = trimvertexpool.get( nsteps+1 );
+ int i;
+ for( i = nsteps; i > 0; i-- ) {
+ newvert[i].param[0] = s;
+ newvert[i].param[1] = t2;
+ t2 += stepsize;
+ }
+ newvert[i].param[0] = s;
+ newvert[i].param[1] = t1;
+
+ arc->makeSide( new(pwlarcpool) PwlArc( nsteps+1, newvert ), arc_left );
+}
+
+/*-----------------------------------------------------------------------------
+ * pwl_right - construct a right boundary pwl arc and attach it to an arc
+ *-----------------------------------------------------------------------------
+ */
+
+void
+ArcTessellator::pwl_right( Arc *arc, REAL s, REAL t1, REAL t2, REAL rate )
+{
+ assert( t1 < t2 );
+
+/* if(rate <= 0.06) rate = 0.06;*/
+
+/* int nsteps = 1 + (int) ((t2 - t1) / rate ); */
+ int nsteps = steps_function(t2,t1,rate);
+ REAL stepsize = (t2 - t1) / (REAL) nsteps;
+
+ TrimVertex *newvert = trimvertexpool.get( nsteps+1 );
+ int i;
+ for( i = 0; i < nsteps; i++ ) {
+ newvert[i].param[0] = s;
+ newvert[i].param[1] = t1;
+ t1 += stepsize;
+ }
+ newvert[i].param[0] = s;
+ newvert[i].param[1] = t2;
+
+ arc->makeSide( new(pwlarcpool) PwlArc( nsteps+1, newvert ), arc_right );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * pwl_top - construct a top boundary pwl arc and attach it to an arc
+ *-----------------------------------------------------------------------------
+ */
+
+void
+ArcTessellator::pwl_top( Arc *arc, REAL t, REAL s1, REAL s2, REAL rate )
+{
+ assert( s2 < s1 );
+
+/* if(rate <= 0.06) rate = 0.06;*/
+
+/* int nsteps = 1 + (int) ((s1 - s2) / rate ); */
+ int nsteps = steps_function(s1,s2,rate);
+ REAL stepsize = (s1 - s2) / (REAL) nsteps;
+
+ TrimVertex *newvert = trimvertexpool.get( nsteps+1 );
+ int i;
+ for( i = nsteps; i > 0; i-- ) {
+ newvert[i].param[0] = s2;
+ newvert[i].param[1] = t;
+ s2 += stepsize;
+ }
+ newvert[i].param[0] = s1;
+ newvert[i].param[1] = t;
+
+ arc->makeSide( new(pwlarcpool) PwlArc( nsteps+1, newvert ), arc_top );
+}
+
+/*-----------------------------------------------------------------------------
+ * pwl_bottom - construct a bottom boundary pwl arc and attach it to an arc
+ *-----------------------------------------------------------------------------
+ */
+
+void
+ArcTessellator::pwl_bottom( Arc *arc, REAL t, REAL s1, REAL s2, REAL rate )
+{
+ assert( s1 < s2 );
+
+/* if(rate <= 0.06) rate = 0.06;*/
+
+/* int nsteps = 1 + (int) ((s2 - s1) / rate ); */
+ int nsteps = steps_function(s2,s1,rate);
+ REAL stepsize = (s2 - s1) / (REAL) nsteps;
+
+ TrimVertex *newvert = trimvertexpool.get( nsteps+1 );
+ int i;
+ for( i = 0; i < nsteps; i++ ) {
+ newvert[i].param[0] = s1;
+ newvert[i].param[1] = t;
+ s1 += stepsize;
+ }
+ newvert[i].param[0] = s2;
+ newvert[i].param[1] = t;
+
+ arc->makeSide( new(pwlarcpool) PwlArc( nsteps+1, newvert ), arc_bottom );
+}
+
+/*-----------------------------------------------------------------------------
+ * pwl - construct a pwl arc and attach it to an arc
+ *-----------------------------------------------------------------------------
+ */
+
+void
+ArcTessellator::pwl( Arc *arc, REAL s1, REAL s2, REAL t1, REAL t2, REAL rate )
+{
+
+/* if(rate <= 0.06) rate = 0.06;*/
+
+ int snsteps = 1 + (int) (glu_abs(s2 - s1) / rate );
+ int tnsteps = 1 + (int) (glu_abs(t2 - t1) / rate );
+ int nsteps = max(1,max( snsteps, tnsteps ));
+
+ REAL sstepsize = (s2 - s1) / (REAL) nsteps;
+ REAL tstepsize = (t2 - t1) / (REAL) nsteps;
+ TrimVertex *newvert = trimvertexpool.get( nsteps+1 );
+ long i;
+ for( i = 0; i < nsteps; i++ ) {
+ newvert[i].param[0] = s1;
+ newvert[i].param[1] = t1;
+ s1 += sstepsize;
+ t1 += tstepsize;
+ }
+ newvert[i].param[0] = s2;
+ newvert[i].param[1] = t2;
+
+ /* arc->makeSide( new(pwlarcpool) PwlArc( nsteps+1, newvert ), arc_bottom ); */
+ arc->pwlArc = new(pwlarcpool) PwlArc( nsteps+1, newvert );
+
+ arc->clearbezier();
+ arc->clearside( );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * tessellateLinear - constuct a linear pwl arc and attach it to an Arc
+ *-----------------------------------------------------------------------------
+ */
+
+void
+ArcTessellator::tessellateLinear( Arc *arc, REAL geo_stepsize, REAL arc_stepsize, int isrational )
+{
+ assert( arc->pwlArc == NULL );
+ REAL s1, s2, t1, t2;
+
+ //we don't need to scale by arc_stepsize if the trim curve
+ //is piecewise linear. Reason: In pwl_right, pwl_left, pwl_top, pwl_left,
+ //and pwl, the nsteps is computed by deltaU (or V) /stepsize.
+ //The quantity deltaU/arc_stepsize doesn't have any meaning. And
+ //it causes problems: see bug 517641
+ REAL stepsize = geo_stepsize; /* * arc_stepsize*/;
+
+ BezierArc *b = arc->bezierArc;
+
+ if( isrational ) {
+ s1 = b->cpts[0] / b->cpts[2];
+ t1 = b->cpts[1] / b->cpts[2];
+ s2 = b->cpts[b->stride+0] / b->cpts[b->stride+2];
+ t2 = b->cpts[b->stride+1] / b->cpts[b->stride+2];
+ } else {
+ s1 = b->cpts[0];
+ t1 = b->cpts[1];
+ s2 = b->cpts[b->stride+0];
+ t2 = b->cpts[b->stride+1];
+ }
+ if( s1 == s2 )
+ if( t1 < t2 )
+ pwl_right( arc, s1, t1, t2, stepsize );
+ else
+ pwl_left( arc, s1, t1, t2, stepsize );
+ else if( t1 == t2 )
+ if( s1 < s2 )
+ pwl_bottom( arc, t1, s1, s2, stepsize );
+ else
+ pwl_top( arc, t1, s1, s2, stepsize );
+ else
+ pwl( arc, s1, s2, t1, t2, stepsize );
+}
+
+/*-----------------------------------------------------------------------------
+ * tessellateNonlinear - constuct a nonlinear pwl arc and attach it to an Arc
+ *-----------------------------------------------------------------------------
+ */
+
+void
+ArcTessellator::tessellateNonlinear( Arc *arc, REAL geo_stepsize, REAL arc_stepsize, int isrational )
+{
+ assert( arc->pwlArc == NULL );
+
+ REAL stepsize = geo_stepsize * arc_stepsize;
+
+ BezierArc *bezierArc = arc->bezierArc;
+
+ REAL size; //bounding box size of the curve in UV
+ {
+ int i,j;
+ REAL min_u, min_v, max_u,max_v;
+ min_u = max_u = bezierArc->cpts[0];
+ min_v = max_v = bezierArc->cpts[1];
+ for(i=1, j=2; i<bezierArc->order; i++, j+= bezierArc->stride)
+ {
+ if(bezierArc->cpts[j] < min_u)
+ min_u = bezierArc->cpts[j];
+ if(bezierArc->cpts[j] > max_u)
+ max_u = bezierArc->cpts[j];
+ if(bezierArc->cpts[j+1] < min_v)
+ min_v = bezierArc->cpts[j+1];
+ if(bezierArc->cpts[j+1] > max_v)
+ max_v = bezierArc->cpts[j+1];
+ }
+
+ size = max_u - min_u;
+ if(size < max_v - min_v)
+ size = max_v - min_v;
+ }
+
+ /*int nsteps = 1 + (int) (1.0/stepsize);*/
+
+ int nsteps = (int) (size/stepsize);
+ if(nsteps <=0)
+ nsteps=1;
+
+ TrimVertex *vert = trimvertexpool.get( nsteps+1 );
+ REAL dp = 1.0/nsteps;
+
+
+ arc->pwlArc = new(pwlarcpool) PwlArc();
+ arc->pwlArc->pts = vert;
+
+ if( isrational ) {
+ REAL pow_u[MAXORDER], pow_v[MAXORDER], pow_w[MAXORDER];
+ trim_power_coeffs( bezierArc, pow_u, 0 );
+ trim_power_coeffs( bezierArc, pow_v, 1 );
+ trim_power_coeffs( bezierArc, pow_w, 2 );
+
+ /* compute first point exactly */
+ REAL *b = bezierArc->cpts;
+ vert->param[0] = b[0]/b[2];
+ vert->param[1] = b[1]/b[2];
+
+ /* strength reduction on p = dp * step would introduce error */
+ int step;
+#ifndef NOELIMINATION
+ int ocanremove = 0;
+#endif
+ register long order = bezierArc->order;
+ for( step=1, ++vert; step<nsteps; step++, vert++ ) {
+ register REAL p = dp * step;
+ register REAL u = pow_u[0];
+ register REAL v = pow_v[0];
+ register REAL w = pow_w[0];
+ for( register int i = 1; i < order; i++ ) {
+ u = u * p + pow_u[i];
+ v = v * p + pow_v[i];
+ w = w * p + pow_w[i];
+ }
+ vert->param[0] = u/w;
+ vert->param[1] = v/w;
+#ifndef NOELIMINATION
+ REAL ds = glu_abs(vert[0].param[0] - vert[-1].param[0]);
+ REAL dt = glu_abs(vert[0].param[1] - vert[-1].param[1]);
+ int canremove = (ds<geo_stepsize && dt<geo_stepsize) ? 1 : 0;
+ REAL ods=0.0, odt=0.0;
+
+ if( ocanremove && canremove ) {
+ REAL nds = ds + ods;
+ REAL ndt = dt + odt;
+ if( nds<geo_stepsize && ndt<geo_stepsize ) {
+ // remove previous point
+ --vert;
+ vert[0].param[0] = vert[1].param[0];
+ vert[0].param[1] = vert[1].param[1];
+ ods = nds;
+ odt = ndt;
+ ocanremove = 1;
+ } else {
+ ocanremove = canremove;
+ ods = ds;
+ odt = dt;
+ }
+ } else {
+ ocanremove = canremove;
+ ods = ds;
+ odt = dt;
+ }
+#endif
+ }
+
+ /* compute last point exactly */
+ b += (order - 1) * bezierArc->stride;
+ vert->param[0] = b[0]/b[2];
+ vert->param[1] = b[1]/b[2];
+
+ } else {
+ REAL pow_u[MAXORDER], pow_v[MAXORDER];
+ trim_power_coeffs( bezierArc, pow_u, 0 );
+ trim_power_coeffs( bezierArc, pow_v, 1 );
+
+ /* compute first point exactly */
+ REAL *b = bezierArc->cpts;
+ vert->param[0] = b[0];
+ vert->param[1] = b[1];
+
+ /* strength reduction on p = dp * step would introduce error */
+ int step;
+#ifndef NOELIMINATION
+ int ocanremove = 0;
+#endif
+ register long order = bezierArc->order;
+ for( step=1, ++vert; step<nsteps; step++, vert++ ) {
+ register REAL p = dp * step;
+ register REAL u = pow_u[0];
+ register REAL v = pow_v[0];
+ for( register int i = 1; i < bezierArc->order; i++ ) {
+ u = u * p + pow_u[i];
+ v = v * p + pow_v[i];
+ }
+ vert->param[0] = u;
+ vert->param[1] = v;
+#ifndef NOELIMINATION
+ REAL ds = glu_abs(vert[0].param[0] - vert[-1].param[0]);
+ REAL dt = glu_abs(vert[0].param[1] - vert[-1].param[1]);
+ int canremove = (ds<geo_stepsize && dt<geo_stepsize) ? 1 : 0;
+ REAL ods=0.0, odt=0.0;
+
+ if( ocanremove && canremove ) {
+ REAL nds = ds + ods;
+ REAL ndt = dt + odt;
+ if( nds<geo_stepsize && ndt<geo_stepsize ) {
+ // remove previous point
+ --vert;
+ vert[0].param[0] = vert[1].param[0];
+ vert[0].param[1] = vert[1].param[1];
+ ods = nds;
+ odt = ndt;
+ ocanremove = 1;
+ } else {
+ ocanremove = canremove;
+ ods = ds;
+ odt = dt;
+ }
+ } else {
+ ocanremove = canremove;
+ ods = ds;
+ odt = dt;
+ }
+#endif
+ }
+
+ /* compute last point exactly */
+ b += (order - 1) * bezierArc->stride;
+ vert->param[0] = b[0];
+ vert->param[1] = b[1];
+ }
+ arc->pwlArc->npts = vert - arc->pwlArc->pts + 1;
+/*
+ for( TrimVertex *vt=pwlArc->pts; vt != vert-1; vt++ ) {
+ if( tooclose( vt[0].param[0], vt[1].param[0] ) )
+ vt[1].param[0] = vt[0].param[0];
+ if( tooclose( vt[0].param[1], vt[1].param[1] ) )
+ vt[1].param[1] = vt[0].param[1];
+ }
+*/
+}
+
+const REAL ArcTessellator::gl_Bernstein[][MAXORDER][MAXORDER] = {
+ {
+ {1, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ {
+ {-1, 1, 0, 0, 0, 0, 0, 0 },
+ {1, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ {
+ {1, -2, 1, 0, 0, 0, 0, 0 },
+ {-2, 2, 0, 0, 0, 0, 0, 0 },
+ {1, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ {
+ {-1, 3, -3, 1, 0, 0, 0, 0 },
+ {3, -6, 3, 0, 0, 0, 0, 0 },
+ {-3, 3, 0, 0, 0, 0, 0, 0 },
+ {1, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ {
+ {1, -4, 6, -4, 1, 0, 0, 0 },
+ {-4, 12, -12, 4, 0, 0, 0, 0 },
+ {6, -12, 6, 0, 0, 0, 0, 0 },
+ {-4, 4, 0, 0, 0, 0, 0, 0 },
+ {1, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ {
+ {-1, 5, -10, 10, -5, 1, 0, 0 },
+ {5, -20, 30, -20, 5, 0, 0, 0 },
+ {-10, 30, -30, 10, 0, 0, 0, 0 },
+ {10, -20, 10, 0, 0, 0, 0, 0 },
+ {-5, 5, 0, 0, 0, 0, 0, 0 },
+ {1, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ {
+ {1, -6, 15, -20, 15, -6, 1, 0 },
+ {-6, 30, -60, 60, -30, 6, 0, 0 },
+ {15, -60, 90, -60, 15, 0, 0, 0 },
+ {-20, 60, -60, 20, 0, 0, 0, 0 },
+ {15, -30, 15, 0, 0, 0, 0, 0 },
+ {-6, 6, 0, 0, 0, 0, 0, 0 },
+ {1, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ {
+ {-1, 7, -21, 35, -35, 21, -7, 1 },
+ {7, -42, 105, -140, 105, -42, 7, 0 },
+ {-21, 105, -210, 210, -105, 21, 0, 0 },
+ {35, -140, 210, -140, 35, 0, 0, 0 },
+ {-35, 105, -105, 35, 0, 0, 0, 0 },
+ {21, -42, 21, 0, 0, 0, 0, 0 },
+ {-7, 7, 0, 0, 0, 0, 0, 0 },
+ {1, 0, 0, 0, 0, 0, 0, 0 }
+ }};
+
+
+/*-----------------------------------------------------------------------------
+ * trim_power_coeffs - compute power basis coefficients from bezier coeffients
+ *-----------------------------------------------------------------------------
+ */
+void
+ArcTessellator::trim_power_coeffs( BezierArc *bez_arc, REAL *p, int coord )
+{
+ register int stride = bez_arc->stride;
+ register int order = bez_arc->order;
+ register REAL *base = bez_arc->cpts + coord;
+
+ REAL const (*mat)[MAXORDER][MAXORDER] = &gl_Bernstein[order-1];
+ REAL const (*lrow)[MAXORDER] = &(*mat)[order];
+
+ /* WIN32 didn't like the following line within the for-loop */
+ REAL const (*row)[MAXORDER] = &(*mat)[0];
+ for( ; row != lrow; row++ ) {
+ register REAL s = 0.0;
+ register REAL *point = base;
+ register REAL const *mlast = *row + order;
+ for( REAL const *m = *row; m != mlast; m++, point += stride )
+ s += *(m) * (*point);
+ *(p++) = s;
+ }
+}
diff --git a/src/glu/sgi/libnurbs/internals/arctess.h b/src/glu/sgi/libnurbs/internals/arctess.h
new file mode 100644
index 00000000000..2399f29419c
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/arctess.h
@@ -0,0 +1,72 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * arctess.h
+ *
+ * $Date: 2001/08/07 17:34:11 $ $Revision: 1.2 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/arctess.h,v 1.2 2001/08/07 17:34:11 brianp Exp $
+ */
+
+#ifndef __gluarctess_h_
+#define __gluarctess_h_
+
+#include "defines.h"
+#include "types.h"
+#include "arc.h"
+
+struct BezierArc;
+class Pool;
+class TrimVertexPool;
+
+class ArcTessellator {
+public:
+ ArcTessellator( TrimVertexPool&, Pool& );
+ ~ArcTessellator( void );
+ void bezier( Arc_ptr, REAL, REAL, REAL, REAL );
+ void pwl( Arc_ptr, REAL, REAL, REAL, REAL, REAL );
+ void pwl_left( Arc_ptr, REAL, REAL, REAL, REAL );
+ void pwl_right( Arc_ptr, REAL, REAL, REAL, REAL );
+ void pwl_top( Arc_ptr, REAL, REAL, REAL, REAL );
+ void pwl_bottom( Arc_ptr, REAL, REAL, REAL, REAL );
+ void tessellateLinear( Arc_ptr, REAL, REAL, int );
+ void tessellateNonlinear( Arc_ptr, REAL, REAL, int );
+private:
+ static const REAL gl_Bernstein[][MAXORDER][MAXORDER];
+ Pool& pwlarcpool;
+ TrimVertexPool& trimvertexpool;
+ static void trim_power_coeffs( BezierArc *, REAL[MAXORDER], int );
+};
+
+#endif /* __gluarctess_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/backend.cc b/src/glu/sgi/libnurbs/internals/backend.cc
new file mode 100644
index 00000000000..fdb3578ab8d
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/backend.cc
@@ -0,0 +1,591 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * backend.c++
+ *
+ * $Date: 2004/05/12 15:29:36 $ $Revision: 1.2 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/backend.cc,v 1.2 2004/05/12 15:29:36 brianp Exp $
+ */
+
+/* Bezier surface backend
+ - interprets display mode (wireframe,shaded,...)
+*/
+#include <stdio.h>
+#include "glimports.h"
+#include "mystdio.h"
+#include "backend.h"
+#include "basiccrveval.h"
+#include "basicsurfeval.h"
+#include "nurbsconsts.h"
+
+#define NOWIREFRAME
+
+
+/*-------------------------------------------------------------------------
+ * bgnsurf - preamble to surface definition and evaluations
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::bgnsurf( int wiretris, int wirequads, long nuid )
+{
+/*#ifndef NOWIREFRAME*/ //need this for old version
+ wireframetris = wiretris;
+ wireframequads = wirequads;
+/*#endif*/
+
+ /*in the spec, GLU_DISPLAY_MODE is either
+ * GLU_FILL
+ * GLU_OUTLINE_POLY
+ * GLU_OUTLINE_PATCH.
+ *In fact, GLU_FLL is has the same effect as
+ * set GL_FRONT_AND_BACK to be GL_FILL
+ * and GLU_OUTLINE_POLY is the same as set
+ * GL_FRONT_AND_BACK to be GL_LINE
+ *It is more efficient to do this once at the beginning of
+ *each surface than to do it for each primitive.
+ * The internal has more options: outline_triangle and outline_quad
+ *can be seperated. But since this is not in spec, and more importantly,
+ *this is not so useful, so we don't need to keep this option.
+ */
+
+ surfaceEvaluator.bgnmap2f( nuid );
+
+ if(wiretris)
+ surfaceEvaluator.polymode(N_MESHLINE);
+ else
+ surfaceEvaluator.polymode(N_MESHFILL);
+}
+
+void
+Backend::patch( REAL ulo, REAL uhi, REAL vlo, REAL vhi )
+{
+ surfaceEvaluator.domain2f( ulo, uhi, vlo, vhi );
+}
+
+void
+Backend::surfbbox( long type, REAL *from, REAL *to )
+{
+ surfaceEvaluator.range2f( type, from, to );
+}
+
+/*-------------------------------------------------------------------------
+ * surfpts - pass a desription of a surface map
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::surfpts(
+ long type, /* geometry, color, texture, normal */
+ REAL *pts, /* control points */
+ long ustride, /* distance to next point in u direction */
+ long vstride, /* distance to next point in v direction */
+ int uorder, /* u parametric order */
+ int vorder, /* v parametric order */
+ REAL ulo, /* u lower bound */
+ REAL uhi, /* u upper bound */
+ REAL vlo, /* v lower bound */
+ REAL vhi ) /* v upper bound */
+{
+ surfaceEvaluator.map2f( type,ulo,uhi,ustride,uorder,vlo,vhi,vstride,vorder,pts );
+ surfaceEvaluator.enable( type );
+}
+
+/*-------------------------------------------------------------------------
+ * surfgrid - define a lattice of points with origin and offset
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::surfgrid( REAL u0, REAL u1, long nu, REAL v0, REAL v1, long nv )
+{
+ surfaceEvaluator.mapgrid2f( nu, u0, u1, nv, v0, v1 );
+}
+
+/*-------------------------------------------------------------------------
+ * surfmesh - evaluate a mesh of points on lattice
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::surfmesh( long u, long v, long n, long m )
+{
+#ifndef NOWIREFRAME
+ if( wireframequads ) {
+ long v0, v1;
+ long u0f = u, u1f = u+n;
+ long v0f = v, v1f = v+m;
+ long parity = (u & 1);
+
+ for( v0 = v0f, v1 = v0f++ ; v0<v1f; v0 = v1, v1++ ) {
+ surfaceEvaluator.bgnline();
+ for( long u = u0f; u<=u1f; u++ ) {
+ if( parity ) {
+ surfaceEvaluator.evalpoint2i( u, v0 );
+ surfaceEvaluator.evalpoint2i( u, v1 );
+ } else {
+ surfaceEvaluator.evalpoint2i( u, v1 );
+ surfaceEvaluator.evalpoint2i( u, v0 );
+ }
+ parity = 1 - parity;
+ }
+ surfaceEvaluator.endline();
+ }
+ } else {
+ surfaceEvaluator.mapmesh2f( N_MESHFILL, u, u+n, v, v+m );
+ }
+#else
+ if( wireframequads ) {
+
+ surfaceEvaluator.mapmesh2f( N_MESHLINE, u, u+n, v, v+m );
+ } else {
+
+ surfaceEvaluator.mapmesh2f( N_MESHFILL, u, u+n, v, v+m );
+ }
+#endif
+}
+
+/*-------------------------------------------------------------------------
+ * endsurf - postamble to surface
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::endsurf( void )
+{
+ surfaceEvaluator.endmap2f();
+}
+
+/***************************************/
+void
+Backend::bgntfan( void )
+{
+ surfaceEvaluator.bgntfan();
+/*
+ if(wireframetris)
+ surfaceEvaluator.polymode( N_MESHLINE );
+ else
+ surfaceEvaluator.polymode( N_MESHFILL );
+*/
+}
+
+void
+Backend::endtfan( void )
+{
+ surfaceEvaluator.endtfan();
+}
+
+void
+Backend::bgnqstrip( void )
+{
+ surfaceEvaluator.bgnqstrip();
+/*
+ if(wireframequads)
+ surfaceEvaluator.polymode( N_MESHLINE );
+ else
+ surfaceEvaluator.polymode( N_MESHFILL );
+*/
+}
+
+void
+Backend::endqstrip( void )
+{
+ surfaceEvaluator.endqstrip();
+}
+
+void
+Backend::evalUStrip(int n_upper, REAL v_upper, REAL* upper_val,
+ int n_lower, REAL v_lower, REAL* lower_val
+ )
+{
+ surfaceEvaluator.evalUStrip(n_upper, v_upper, upper_val,
+ n_lower, v_lower, lower_val);
+}
+
+void
+Backend::evalVStrip(int n_left, REAL u_left, REAL* left_val,
+ int n_right, REAL u_right, REAL* right_val
+ )
+{
+ surfaceEvaluator.evalVStrip(n_left, u_left, left_val,
+ n_right, u_right, right_val);
+}
+
+/***************************************/
+
+
+/*-------------------------------------------------------------------------
+ * bgntmesh - preamble to a triangle mesh
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::bgntmesh( char * )
+{
+#ifndef NOWIREFRAME
+
+ meshindex = 0; /* I think these need to be initialized to zero */
+ npts = 0;
+
+ if( !wireframetris ) {
+ surfaceEvaluator.bgntmesh();
+ }
+#else
+
+ if( wireframetris ) {
+ surfaceEvaluator.bgntmesh();
+ surfaceEvaluator.polymode( N_MESHLINE );
+ } else {
+ surfaceEvaluator.bgntmesh();
+ surfaceEvaluator.polymode( N_MESHFILL );
+ }
+#endif
+}
+
+void
+Backend::tmeshvert( GridTrimVertex *v )
+{
+ if( v->isGridVert() ) {
+ tmeshvert( v->g );
+ } else {
+ tmeshvert( v->t );
+ }
+}
+
+void
+Backend::tmeshvertNOGE(TrimVertex *t)
+{
+// surfaceEvaluator.inDoEvalCoord2NOGE( t->param[0], t->param[1], temp, ttt);
+#ifdef USE_OPTTT
+ surfaceEvaluator.inDoEvalCoord2NOGE( t->param[0], t->param[1], t->cache_point, t->cache_normal);
+#endif
+}
+
+//opt for a line with the same u.
+void
+Backend::tmeshvertNOGE_BU(TrimVertex *t)
+{
+#ifdef USE_OPTTT
+ surfaceEvaluator.inDoEvalCoord2NOGE_BU( t->param[0], t->param[1], t->cache_point, t->cache_normal);
+#endif
+}
+
+//opt for a line with the same v.
+void
+Backend::tmeshvertNOGE_BV(TrimVertex *t)
+{
+#ifdef USE_OPTTT
+ surfaceEvaluator.inDoEvalCoord2NOGE_BV( t->param[0], t->param[1], t->cache_point, t->cache_normal);
+#endif
+}
+
+void
+Backend::preEvaluateBU(REAL u)
+{
+ surfaceEvaluator.inPreEvaluateBU_intfac(u);
+}
+
+void
+Backend::preEvaluateBV(REAL v)
+{
+ surfaceEvaluator.inPreEvaluateBV_intfac(v);
+}
+
+
+/*-------------------------------------------------------------------------
+ * tmeshvert - evaluate a point on a triangle mesh
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::tmeshvert( TrimVertex *t )
+{
+
+#ifndef NOWIREFRAME
+ const long nuid = t->nuid;
+#endif
+ const REAL u = t->param[0];
+ const REAL v = t->param[1];
+
+#ifndef NOWIREFRAME
+ npts++;
+ if( wireframetris ) {
+ if( npts >= 3 ) {
+ surfaceEvaluator.bgnclosedline();
+ if( mesh[0][2] == 0 )
+ surfaceEvaluator.evalcoord2f( mesh[0][3], mesh[0][0], mesh[0][1] );
+ else
+ surfaceEvaluator.evalpoint2i( (long) mesh[0][0], (long) mesh[0][1] );
+ if( mesh[1][2] == 0 )
+ surfaceEvaluator.evalcoord2f( mesh[1][3], mesh[1][0], mesh[1][1] );
+ else
+ surfaceEvaluator.evalpoint2i( (long) mesh[1][0], (long) mesh[1][1] );
+ surfaceEvaluator.evalcoord2f( nuid, u, v );
+ surfaceEvaluator.endclosedline();
+ }
+ mesh[meshindex][0] = u;
+ mesh[meshindex][1] = v;
+ mesh[meshindex][2] = 0;
+ mesh[meshindex][3] = nuid;
+ meshindex = (meshindex+1) % 2;
+ } else {
+ surfaceEvaluator.evalcoord2f( nuid, u, v );
+ }
+#else
+
+ surfaceEvaluator.evalcoord2f( 0, u, v );
+//for uninitial memory read surfaceEvaluator.evalcoord2f( nuid, u, v );
+#endif
+}
+
+//the same as tmeshvert(trimvertex), for efficiency purpose
+void
+Backend::tmeshvert( REAL u, REAL v )
+{
+#ifndef NOWIREFRAME
+ const long nuid = 0;
+
+ npts++;
+ if( wireframetris ) {
+ if( npts >= 3 ) {
+ surfaceEvaluator.bgnclosedline();
+ if( mesh[0][2] == 0 )
+ surfaceEvaluator.evalcoord2f( mesh[0][3], mesh[0][0], mesh[0][1] );
+ else
+ surfaceEvaluator.evalpoint2i( (long) mesh[0][0], (long) mesh[0][1] );
+ if( mesh[1][2] == 0 )
+ surfaceEvaluator.evalcoord2f( mesh[1][3], mesh[1][0], mesh[1][1] );
+ else
+ surfaceEvaluator.evalpoint2i( (long) mesh[1][0], (long) mesh[1][1] );
+ surfaceEvaluator.evalcoord2f( nuid, u, v );
+ surfaceEvaluator.endclosedline();
+ }
+ mesh[meshindex][0] = u;
+ mesh[meshindex][1] = v;
+ mesh[meshindex][2] = 0;
+ mesh[meshindex][3] = nuid;
+ meshindex = (meshindex+1) % 2;
+ } else {
+ surfaceEvaluator.evalcoord2f( nuid, u, v );
+ }
+#else
+
+ surfaceEvaluator.evalcoord2f( 0, u, v );
+#endif
+}
+
+/*-------------------------------------------------------------------------
+ * tmeshvert - evaluate a grid point of a triangle mesh
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::tmeshvert( GridVertex *g )
+{
+ const long u = g->gparam[0];
+ const long v = g->gparam[1];
+
+#ifndef NOWIREFRAME
+ npts++;
+ if( wireframetris ) {
+ if( npts >= 3 ) {
+ surfaceEvaluator.bgnclosedline();
+ if( mesh[0][2] == 0 )
+ surfaceEvaluator.evalcoord2f( (long) mesh[0][3], mesh[0][0], mesh[0][1] );
+ else
+ surfaceEvaluator.evalpoint2i( (long) mesh[0][0], (long) mesh[0][1] );
+ if( mesh[1][2] == 0 )
+ surfaceEvaluator.evalcoord2f( (long) mesh[1][3], mesh[1][0], mesh[1][1] );
+ else
+ surfaceEvaluator.evalpoint2i( (long) mesh[1][0], (long) mesh[1][1] );
+ surfaceEvaluator.evalpoint2i( u, v );
+ surfaceEvaluator.endclosedline();
+ }
+ mesh[meshindex][0] = u;
+ mesh[meshindex][1] = v;
+ mesh[meshindex][2] = 1;
+ meshindex = (meshindex+1) % 2;
+ } else {
+ surfaceEvaluator.evalpoint2i( u, v );
+ }
+#else
+ surfaceEvaluator.evalpoint2i( u, v );
+#endif
+}
+
+/*-------------------------------------------------------------------------
+ * swaptmesh - perform a swap of the triangle mesh pointers
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::swaptmesh( void )
+{
+#ifndef NOWIREFRAME
+ if( wireframetris ) {
+ meshindex = 1 - meshindex;
+ } else {
+ surfaceEvaluator.swaptmesh();
+ }
+#else
+ surfaceEvaluator.swaptmesh();
+#endif
+}
+
+/*-------------------------------------------------------------------------
+ * endtmesh - postamble to triangle mesh
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::endtmesh( void )
+{
+#ifndef NOWIREFRAME
+ if( ! wireframetris )
+ surfaceEvaluator.endtmesh();
+#else
+ surfaceEvaluator.endtmesh();
+/* surfaceEvaluator.polymode( N_MESHFILL );*/
+#endif
+}
+
+
+/*-------------------------------------------------------------------------
+ * bgnoutline - preamble to outlined rendering
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::bgnoutline( void )
+{
+ surfaceEvaluator.bgnline();
+}
+
+/*-------------------------------------------------------------------------
+ * linevert - evaluate a point on an outlined contour
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::linevert( TrimVertex *t )
+{
+ surfaceEvaluator.evalcoord2f( t->nuid, t->param[0], t->param[1] );
+}
+
+/*-------------------------------------------------------------------------
+ * linevert - evaluate a grid point of an outlined contour
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::linevert( GridVertex *g )
+{
+ surfaceEvaluator.evalpoint2i( g->gparam[0], g->gparam[1] );
+}
+
+/*-------------------------------------------------------------------------
+ * endoutline - postamble to outlined rendering
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::endoutline( void )
+{
+ surfaceEvaluator.endline();
+}
+
+/*-------------------------------------------------------------------------
+ * triangle - output a triangle
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::triangle( TrimVertex *a, TrimVertex *b, TrimVertex *c )
+{
+/* bgntmesh( "spittriangle" );*/
+ bgntfan();
+ tmeshvert( a );
+ tmeshvert( b );
+ tmeshvert( c );
+ endtfan();
+/* endtmesh();*/
+}
+
+void
+Backend::bgncurv( void )
+{
+ curveEvaluator.bgnmap1f( 0 );
+}
+
+void
+Backend::segment( REAL ulo, REAL uhi )
+{
+ curveEvaluator.domain1f( ulo, uhi );
+}
+
+void
+Backend::curvpts(
+ long type, /* geometry, color, texture, normal */
+ REAL *pts, /* control points */
+ long stride, /* distance to next point */
+ int order, /* parametric order */
+ REAL ulo, /* lower parametric bound */
+ REAL uhi ) /* upper parametric bound */
+
+{
+ curveEvaluator.map1f( type, ulo, uhi, stride, order, pts );
+ curveEvaluator.enable( type );
+}
+
+void
+Backend::curvgrid( REAL u0, REAL u1, long nu )
+{
+ curveEvaluator.mapgrid1f( nu, u0, u1 );
+}
+
+void
+Backend::curvmesh( long from, long n )
+{
+ curveEvaluator.mapmesh1f( N_MESHFILL, from, from+n );
+}
+
+void
+Backend::curvpt(REAL u)
+{
+ curveEvaluator.evalcoord1f( 0, u );
+}
+
+void
+Backend::bgnline( void )
+{
+ curveEvaluator.bgnline();
+}
+
+void
+Backend::endline( void )
+{
+ curveEvaluator.endline();
+}
+
+void
+Backend::endcurv( void )
+{
+ curveEvaluator.endmap1f();
+}
diff --git a/src/glu/sgi/libnurbs/internals/backend.h b/src/glu/sgi/libnurbs/internals/backend.h
new file mode 100644
index 00000000000..d27a05bdcc1
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/backend.h
@@ -0,0 +1,119 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * backend.h
+ *
+ * $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/backend.h,v 1.1 2001/03/17 00:25:40 brianp Exp $
+ */
+
+#ifndef __glubackend_h_
+#define __glubackend_h_
+
+#include "trimvertex.h"
+#include "gridvertex.h"
+#include "gridtrimvertex.h"
+
+class BasicCurveEvaluator;
+class BasicSurfaceEvaluator;
+
+class Backend {
+private:
+ BasicCurveEvaluator& curveEvaluator;
+ BasicSurfaceEvaluator& surfaceEvaluator;
+public:
+ Backend( BasicCurveEvaluator &c, BasicSurfaceEvaluator& e )
+ : curveEvaluator(c), surfaceEvaluator(e) {}
+
+ /* surface backend routines */
+ void bgnsurf( int, int, long );
+ void patch( REAL, REAL, REAL, REAL );
+ void surfpts( long, REAL *, long, long, int, int,
+ REAL, REAL, REAL, REAL );
+ void surfbbox( long, REAL *, REAL * );
+ void surfgrid( REAL, REAL, long, REAL, REAL, long );
+ void surfmesh( long, long, long, long );
+ void bgntmesh( char * );
+ void endtmesh( void );
+ void swaptmesh( void );
+ void tmeshvert( GridTrimVertex * );
+ void tmeshvert( TrimVertex * );
+ void tmeshvert( GridVertex * );
+ void tmeshvert( REAL u, REAL v );
+ void linevert( TrimVertex * );
+ void linevert( GridVertex * );
+ void bgnoutline( void );
+ void endoutline( void );
+ void endsurf( void );
+ void triangle( TrimVertex*, TrimVertex*, TrimVertex* );
+
+ void bgntfan();
+ void endtfan();
+ void bgnqstrip();
+ void endqstrip();
+ void evalUStrip(int n_upper, REAL v_upper, REAL* upper_val,
+ int n_lower, REAL v_lower, REAL* lower_val
+ );
+ void evalVStrip(int n_left, REAL u_left, REAL* left_val,
+ int n_right, REAL v_right, REAL* right_val
+ );
+ void tmeshvertNOGE(TrimVertex *t);
+ void tmeshvertNOGE_BU(TrimVertex *t);
+ void tmeshvertNOGE_BV(TrimVertex *t);
+ void preEvaluateBU(REAL u);
+ void preEvaluateBV(REAL v);
+
+
+ /* curve backend routines */
+ void bgncurv( void );
+ void segment( REAL, REAL );
+ void curvpts( long, REAL *, long, int, REAL, REAL );
+ void curvgrid( REAL, REAL, long );
+ void curvmesh( long, long );
+ void curvpt( REAL );
+ void bgnline( void );
+ void endline( void );
+ void endcurv( void );
+private:
+#ifndef NOWIREFRAME
+ int wireframetris;
+ int wireframequads;
+ int npts;
+ REAL mesh[3][4];
+ int meshindex;
+#endif
+};
+
+#endif /* __glubackend_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/basiccrveval.cc b/src/glu/sgi/libnurbs/internals/basiccrveval.cc
new file mode 100644
index 00000000000..c7e4282360b
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/basiccrveval.cc
@@ -0,0 +1,138 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * basiccrveval.c++
+ *
+ */
+
+#include "mystdio.h"
+#include "types.h"
+#include "basiccrveval.h"
+
+void
+BasicCurveEvaluator::domain1f( REAL, REAL )
+{
+#ifndef NDEBUG
+ dprintf( "domain1f\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::range1f( long , REAL *, REAL * )
+{
+#ifndef NDEBUG
+ dprintf( "range1f\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::enable( long )
+{
+#ifndef NDEBUG
+ dprintf( "enable\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::disable( long )
+{
+#ifndef NDEBUG
+ dprintf( "disable\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::bgnmap1f( long )
+{
+#ifndef NDEBUG
+ dprintf( "bgnmap1f\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::map1f( long, REAL, REAL, long, long, REAL * )
+{
+#ifndef NDEBUG
+ dprintf( "map1f\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::mapgrid1f( long, REAL, REAL )
+{
+#ifndef NDEBUG
+ dprintf( "mapgrid1f\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::mapmesh1f( long, long, long )
+{
+#ifndef NDEBUG
+ dprintf( "mapmesh1f\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::evalcoord1f( long, REAL )
+{
+#ifndef NDEBUG
+ dprintf( "evalcoord1f\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::endmap1f( void )
+{
+#ifndef NDEBUG
+ dprintf( "endmap1f\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::bgnline( void )
+{
+#ifndef NDEBUG
+ dprintf( "bgnline\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::endline( void )
+{
+#ifndef NDEBUG
+ dprintf( "endline\n" );
+#endif
+}
diff --git a/src/glu/sgi/libnurbs/internals/basiccrveval.h b/src/glu/sgi/libnurbs/internals/basiccrveval.h
new file mode 100644
index 00000000000..23a3ae9fdf5
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/basiccrveval.h
@@ -0,0 +1,67 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * basiccurveeval.h
+ *
+ * $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/basiccrveval.h,v 1.1 2001/03/17 00:25:40 brianp Exp $
+ */
+
+#ifndef __glubasiccrveval_h_
+#define __glubasiccrveval_h_
+
+#include "types.h"
+#include "displaymode.h"
+#include "cachingeval.h"
+
+class BasicCurveEvaluator : public CachingEvaluator {
+public:
+ virtual void domain1f( REAL, REAL );
+ virtual void range1f( long, REAL *, REAL * );
+
+ virtual void enable( long );
+ virtual void disable( long );
+ virtual void bgnmap1f( long );
+ virtual void map1f( long, REAL, REAL, long, long, REAL * );
+ virtual void mapgrid1f( long, REAL, REAL );
+ virtual void mapmesh1f( long, long, long );
+ virtual void evalcoord1f( long, REAL );
+ virtual void endmap1f( void );
+
+ virtual void bgnline( void );
+ virtual void endline( void );
+};
+
+#endif /* __glubasiccrveval_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/basicsurfeval.cc b/src/glu/sgi/libnurbs/internals/basicsurfeval.cc
new file mode 100644
index 00000000000..ff212bf0b4b
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/basicsurfeval.cc
@@ -0,0 +1,232 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * basicsurfaceevaluator.c++
+ *
+ */
+
+#include "mystdio.h"
+#include "types.h"
+#include "basicsurfeval.h"
+
+#ifdef __WATCOMC__
+#pragma warning 726 10
+#endif
+
+void
+BasicSurfaceEvaluator::domain2f( REAL, REAL, REAL, REAL )
+{
+#ifndef NDEBUG
+ dprintf( "domain2f\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::polymode( long )
+{
+#ifndef NDEBUG
+ dprintf( "polymode\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::range2f( long type, REAL *from, REAL *to )
+{
+#ifndef NDEBUG
+ dprintf( "range2f type %ld, from (%g,%g), to (%g,%g)\n",
+ type, from[0], from[1], to[0], to[1] );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::enable( long )
+{
+#ifndef NDEBUG
+ dprintf( "enable\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::disable( long )
+{
+#ifndef NDEBUG
+ dprintf( "disable\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::bgnmap2f( long )
+{
+#ifndef NDEBUG
+ dprintf( "bgnmap2f\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::endmap2f( void )
+{
+#ifndef NDEBUG
+ dprintf( "endmap2f\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::map2f( long, REAL, REAL, long, long,
+ REAL, REAL, long, long,
+ REAL * )
+{
+#ifndef NDEBUG
+ dprintf( "map2f\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::mapgrid2f( long, REAL, REAL, long, REAL, REAL )
+{
+#ifndef NDEBUG
+ dprintf( "mapgrid2f\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::mapmesh2f( long, long, long, long, long )
+{
+#ifndef NDEBUG
+ dprintf( "mapmesh2f\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::evalcoord2f( long, REAL, REAL )
+{
+#ifndef NDEBUG
+ dprintf( "evalcoord2f\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::evalpoint2i( long, long )
+{
+#ifndef NDEBUG
+ dprintf( "evalpoint2i\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::bgnline( void )
+{
+#ifndef NDEBUG
+ dprintf( "bgnline\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::endline( void )
+{
+#ifndef NDEBUG
+ dprintf( "endline\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::bgnclosedline( void )
+{
+#ifndef NDEBUG
+ dprintf( "bgnclosedline\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::endclosedline( void )
+{
+#ifndef NDEBUG
+ dprintf( "endclosedline\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::bgntfan( void )
+{
+#ifndef NDEBUG
+ dprintf( "bgntfan\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::endtfan( void )
+{
+}
+
+
+void
+BasicSurfaceEvaluator::bgntmesh( void )
+{
+#ifndef NDEBUG
+ dprintf( "bgntmesh\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::swaptmesh( void )
+{
+#ifndef NDEBUG
+ dprintf( "swaptmesh\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::endtmesh( void )
+{
+#ifndef NDEBUG
+ dprintf( "endtmesh\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::bgnqstrip( void )
+{
+#ifndef NDEBUG
+ dprintf( "bgnqstrip\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::endqstrip( void )
+{
+#ifndef NDEBUG
+ dprintf( "endqstrip\n" );
+#endif
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/basicsurfeval.h b/src/glu/sgi/libnurbs/internals/basicsurfeval.h
new file mode 100644
index 00000000000..e47b46daaea
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/basicsurfeval.h
@@ -0,0 +1,95 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * basicsurfeval.h
+ *
+ * $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/basicsurfeval.h,v 1.1 2001/03/17 00:25:40 brianp Exp $
+ */
+
+#ifndef __glubasicsurfeval_h_
+#define __glubasicsurfeval_h_
+
+#include "types.h"
+#include "displaymode.h"
+#include "cachingeval.h"
+
+class BasicSurfaceEvaluator : public CachingEvaluator {
+public:
+ virtual void range2f( long, REAL *, REAL * );
+ virtual void domain2f( REAL, REAL, REAL, REAL );
+
+ virtual void enable( long );
+ virtual void disable( long );
+ virtual void bgnmap2f( long );
+ virtual void map2f( long, REAL, REAL, long, long,
+ REAL, REAL, long, long,
+ REAL * );
+ virtual void mapgrid2f( long, REAL, REAL, long, REAL, REAL );
+ virtual void mapmesh2f( long, long, long, long, long );
+ virtual void evalcoord2f( long, REAL, REAL );
+ virtual void evalpoint2i( long, long );
+ virtual void endmap2f( void );
+
+ virtual void polymode( long );
+ virtual void bgnline( void );
+ virtual void endline( void );
+ virtual void bgnclosedline( void );
+ virtual void endclosedline( void );
+ virtual void bgntmesh( void );
+ virtual void swaptmesh( void );
+ virtual void endtmesh( void );
+ virtual void bgnqstrip( void );
+ virtual void endqstrip( void );
+
+ virtual void bgntfan( void );
+ virtual void endtfan( void );
+
+ virtual void evalUStrip(int n_upper, REAL v_upper, REAL* upper_val,
+ int n_lower, REAL v_lower, REAL* lower_val
+ ) = 0;
+
+ virtual void evalVStrip(int n_left, REAL u_left, REAL* left_val,
+ int n_right, REAL u_right, REAL* right_val
+ ) = 0;
+ virtual void inDoEvalCoord2NOGE(REAL u, REAL v, REAL* ret_point, REAL* ret_normal) = 0;
+ virtual void inDoEvalCoord2NOGE_BU(REAL u, REAL v, REAL* ret_point, REAL* ret_normal) = 0;
+ virtual void inDoEvalCoord2NOGE_BV(REAL u, REAL v, REAL* ret_point, REAL* ret_normal) = 0;
+ virtual void inPreEvaluateBV_intfac(REAL v ) = 0;
+ virtual void inPreEvaluateBU_intfac(REAL u ) = 0;
+
+};
+
+#endif /* __glubasicsurfeval_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/bezierarc.h b/src/glu/sgi/libnurbs/internals/bezierarc.h
new file mode 100644
index 00000000000..3942f1321ff
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/bezierarc.h
@@ -0,0 +1,57 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * bezierarc.h
+ *
+ * $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/bezierarc.h,v 1.1 2001/03/17 00:25:40 brianp Exp $
+ */
+
+#ifndef __glubezierarc_h
+#define __glubezierarc_h
+
+#include "myassert.h"
+
+class Mapdesc;
+
+struct BezierArc : public PooledObj { /* a bezier arc */
+ REAL * cpts; /* control points of arc */
+ int order; /* order of arc */
+ int stride; /* REAL distance between points */
+ long type; /* curve type */
+ Mapdesc * mapdesc;
+};
+
+#endif /* __glubezierarc_h */
diff --git a/src/glu/sgi/libnurbs/internals/bin.cc b/src/glu/sgi/libnurbs/internals/bin.cc
new file mode 100644
index 00000000000..6fa296e1cbb
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/bin.cc
@@ -0,0 +1,168 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * bin.c++
+ *
+ * $Date: 2004/05/12 15:29:36 $ $Revision: 1.2 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/bin.cc,v 1.2 2004/05/12 15:29:36 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "bin.h"
+
+/*----------------------------------------------------------------------------
+ * Constructor and destructor
+ *----------------------------------------------------------------------------
+ */
+Bin::Bin()
+{
+ head = NULL;
+}
+
+Bin::~Bin()
+{
+ assert( head == NULL);
+}
+
+/*----------------------------------------------------------------------------
+ * remove_this_arc - remove given Arc_ptr from bin
+ *----------------------------------------------------------------------------
+ */
+
+void
+Bin::remove_this_arc( Arc_ptr arc )
+{
+ Arc_ptr *j;
+ for( j = &(head); (*j != 0) && (*j != arc); j = &((*j)->link) );
+
+ if( *j != 0 ) {
+ if( *j == current )
+ current = (*j)->link;
+ *j = (*j)->link;
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * numarcs - count number of arcs in bin
+ *----------------------------------------------------------------------------
+ */
+
+int
+Bin::numarcs()
+{
+ long count = 0;
+ for( Arc_ptr jarc = firstarc(); jarc; jarc = nextarc() )
+ count++;
+ return count;
+}
+
+/*----------------------------------------------------------------------------
+ * adopt - place an orphaned arcs into their new parents bin
+ *----------------------------------------------------------------------------
+ */
+
+void
+Bin::adopt()
+{
+ markall();
+
+ Arc_ptr orphan;
+ while( (orphan = removearc()) != NULL ) {
+ for( Arc_ptr parent = orphan->next; parent != orphan; parent = parent->next ) {
+ if (! parent->ismarked() ) {
+ orphan->link = parent->link;
+ parent->link = orphan;
+ orphan->clearmark();
+ break;
+ }
+ }
+ }
+}
+
+
+/*----------------------------------------------------------------------------
+ * show - print out descriptions of the arcs in the bin
+ *----------------------------------------------------------------------------
+ */
+
+void
+Bin::show( char *name )
+{
+#ifndef NDEBUG
+ dprintf( "%s\n", name );
+ for( Arc_ptr jarc = firstarc(); jarc; jarc = nextarc() )
+ jarc->show( );
+#endif
+}
+
+
+
+/*----------------------------------------------------------------------------
+ * markall - mark all arcs with an identifying tag
+ *----------------------------------------------------------------------------
+ */
+
+void
+Bin::markall()
+{
+ for( Arc_ptr jarc=firstarc(); jarc; jarc=nextarc() )
+ jarc->setmark();
+}
+
+/*----------------------------------------------------------------------------
+ * listBezier - print out all arcs that are untessellated border arcs
+ *----------------------------------------------------------------------------
+ */
+
+void
+Bin::listBezier( void )
+{
+ for( Arc_ptr jarc=firstarc(); jarc; jarc=nextarc() ) {
+ if( jarc->isbezier( ) ) {
+ assert( jarc->pwlArc->npts == 2 );
+#ifndef NDEBUG
+ TrimVertex *pts = jarc->pwlArc->pts;
+ REAL s1 = pts[0].param[0];
+ REAL t1 = pts[0].param[1];
+ REAL s2 = pts[1].param[0];
+ REAL t2 = pts[1].param[1];
+ dprintf( "arc (%g,%g) (%g,%g)\n", s1, t1, s2, t2 );
+#endif
+ }
+ }
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/bin.h b/src/glu/sgi/libnurbs/internals/bin.h
new file mode 100644
index 00000000000..f12b6212088
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/bin.h
@@ -0,0 +1,127 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * bin.h
+ *
+ * $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/bin.h,v 1.1 2001/03/17 00:25:40 brianp Exp $
+ */
+
+#ifndef __glubin_h_
+#define __glubin_h_
+
+#include "myassert.h"
+#include "arc.h"
+#include "defines.h"
+
+class Bin
+{ /* a linked list of jordan arcs */
+private:
+ Arc_ptr head;/*first arc on list */
+ Arc_ptr current; /* current arc on list */
+public:
+ Bin();
+ ~Bin();
+ inline Arc_ptr firstarc( void );
+ inline Arc_ptr nextarc( void );
+ inline Arc_ptr removearc( void );
+ inline int isnonempty( void ) { return (head ? 1 : 0); }
+ inline void addarc( Arc_ptr );
+ void remove_this_arc( Arc_ptr );
+ int numarcs( void );
+ void adopt( void );
+ void markall( void );
+ void show( char * );
+ void listBezier( void );
+};
+
+/*----------------------------------------------------------------------------
+ * Bin::addarc - add an Arc_ptr to head of linked list of Arc_ptr
+ *----------------------------------------------------------------------------
+ */
+
+inline void
+Bin::addarc( Arc_ptr jarc )
+{
+ jarc->link = head;
+ head = jarc;
+}
+
+/*----------------------------------------------------------------------------
+ * Bin::removearc - remove first Arc_ptr from bin
+ *----------------------------------------------------------------------------
+ */
+
+inline Arc_ptr
+Bin::removearc( void )
+{
+ Arc_ptr jarc = head;
+
+ if( jarc ) head = jarc->link;
+ return jarc;
+}
+
+
+/*----------------------------------------------------------------------------
+ * BinIter::nextarc - return current arc in bin and advance pointer to next arc
+ *----------------------------------------------------------------------------
+ */
+
+inline Arc_ptr
+Bin::nextarc( void )
+{
+ Arc_ptr jarc = current;
+
+#ifdef DEBUG
+ assert( jarc->check() != 0 );
+#endif
+
+ if( jarc ) current = jarc->link;
+ return jarc;
+}
+
+/*----------------------------------------------------------------------------
+ * BinIter::firstarc - set current arc to first arc of bin advance to next arc
+ *----------------------------------------------------------------------------
+ */
+
+inline Arc_ptr
+Bin::firstarc( void )
+{
+ current = head;
+ return nextarc( );
+}
+
+#endif /* __glubin_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/bufpool.cc b/src/glu/sgi/libnurbs/internals/bufpool.cc
new file mode 100644
index 00000000000..0a77693f443
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/bufpool.cc
@@ -0,0 +1,112 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * bufpool.c++
+ *
+ * $Date: 2004/05/12 15:29:36 $ $Revision: 1.2 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/bufpool.cc,v 1.2 2004/05/12 15:29:36 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "bufpool.h"
+
+
+/*-----------------------------------------------------------------------------
+ * Pool - allocate a new pool of buffers
+ *-----------------------------------------------------------------------------
+ */
+Pool::Pool( int _buffersize, int initpoolsize, char *n )
+{
+ if((unsigned)_buffersize < sizeof(Buffer))
+ buffersize = sizeof(Buffer);
+ else
+ buffersize = _buffersize;
+ initsize = initpoolsize * buffersize;
+ nextsize = initsize;
+ name = n;
+ magic = is_allocated;
+ nextblock = 0;
+ curblock = 0;
+ freelist = 0;
+ nextfree = 0;
+}
+
+/*-----------------------------------------------------------------------------
+ * ~Pool - free a pool of buffers and the pool itself
+ *-----------------------------------------------------------------------------
+ */
+
+Pool::~Pool( void )
+{
+ assert( (this != 0) && (magic == is_allocated) );
+
+ while( nextblock ) {
+ delete [] blocklist[--nextblock];
+ blocklist[nextblock] = 0;
+ }
+ magic = is_free;
+}
+
+
+void Pool::grow( void )
+{
+ assert( (this != 0) && (magic == is_allocated) );
+ curblock = new char[nextsize];
+ blocklist[nextblock++] = curblock;
+ nextfree = nextsize;
+ nextsize *= 2;
+}
+
+/*-----------------------------------------------------------------------------
+ * Pool::clear - free buffers associated with pool but keep pool
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Pool::clear( void )
+{
+ assert( (this != 0) && (magic == is_allocated) );
+
+ while( nextblock ) {
+ delete [] blocklist[--nextblock];
+ blocklist[nextblock] = 0;
+ }
+ curblock = 0;
+ freelist = 0;
+ nextfree = 0;
+ if( nextsize > initsize )
+ nextsize /= 2;
+}
diff --git a/src/glu/sgi/libnurbs/internals/bufpool.h b/src/glu/sgi/libnurbs/internals/bufpool.h
new file mode 100644
index 00000000000..3090374c217
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/bufpool.h
@@ -0,0 +1,146 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * bufpool.h
+ *
+ * $Date: 2001/03/22 11:38:36 $ $Revision: 1.2 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/bufpool.h,v 1.2 2001/03/22 11:38:36 joukj Exp $
+ */
+
+#ifndef __glubufpool_h_
+#define __glubufpool_h_
+
+#include "gluos.h"
+#include "myassert.h"
+#include "mystdlib.h"
+
+#define NBLOCKS 32
+
+class Buffer {
+ friend class Pool;
+ Buffer * next; /* next buffer on free list */
+};
+
+class Pool {
+public:
+ Pool( int, int, char * );
+ ~Pool( void );
+ inline void* new_buffer( void );
+ inline void free_buffer( void * );
+ void clear( void );
+
+private:
+ void grow( void );
+
+protected:
+ Buffer *freelist; /* linked list of free buffers */
+ char *blocklist[NBLOCKS]; /* blocks of malloced memory */
+ int nextblock; /* next free block index */
+ char *curblock; /* last malloced block */
+ int buffersize; /* bytes per buffer */
+ int nextsize; /* size of next block of memory */
+ int nextfree; /* byte offset past next free buffer */
+ int initsize;
+ enum Magic { is_allocated = 0xf3a1, is_free = 0xf1a2 };
+ char *name; /* name of the pool */
+ Magic magic; /* marker for valid pool */
+};
+
+/*-----------------------------------------------------------------------------
+ * Pool::free_buffer - return a buffer to a pool
+ *-----------------------------------------------------------------------------
+ */
+
+inline void
+Pool::free_buffer( void *b )
+{
+ assert( (this != 0) && (magic == is_allocated) );
+
+ /* add buffer to singly connected free list */
+
+ ((Buffer *) b)->next = freelist;
+ freelist = (Buffer *) b;
+}
+
+
+/*-----------------------------------------------------------------------------
+ * Pool::new_buffer - allocate a buffer from a pool
+ *-----------------------------------------------------------------------------
+ */
+
+inline void *
+Pool::new_buffer( void )
+{
+ void *buffer;
+
+ assert( (this != 0) && (magic == is_allocated) );
+
+ /* find free buffer */
+
+ if( freelist ) {
+ buffer = (void *) freelist;
+ freelist = freelist->next;
+ } else {
+ if( ! nextfree )
+ grow( );
+ nextfree -= buffersize;;
+ buffer = (void *) (curblock + nextfree);
+ }
+ return buffer;
+}
+
+class PooledObj {
+public:
+ inline void * operator new( size_t, Pool & );
+ inline void * operator new( size_t, void *);
+ inline void * operator new( size_t s)
+ { return ::new char[s]; }
+ inline void operator delete( void * ) { assert( 0 ); }
+ inline void deleteMe( Pool & );
+};
+
+inline void *
+PooledObj::operator new( size_t, Pool& pool )
+{
+ return pool.new_buffer();
+}
+
+inline void
+PooledObj::deleteMe( Pool& pool )
+{
+ pool.free_buffer( (void *) this );
+}
+
+#endif /* __glubufpool_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/cachingeval.cc b/src/glu/sgi/libnurbs/internals/cachingeval.cc
new file mode 100644
index 00000000000..7e8dc0e9895
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/cachingeval.cc
@@ -0,0 +1,80 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * cachingeval.c++
+ *
+ * $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/cachingeval.cc,v 1.1 2001/03/17 00:25:40 brianp Exp $
+ */
+
+#include "cachingeval.h"
+
+int
+CachingEvaluator::canRecord( void )
+{
+ return 0;
+}
+
+int
+CachingEvaluator::canPlayAndRecord( void )
+{
+ return 0;
+}
+
+int
+CachingEvaluator::createHandle( int )
+{
+ return 0;
+}
+
+void
+CachingEvaluator::beginOutput( ServiceMode, int )
+{
+}
+
+void
+CachingEvaluator::endOutput( void )
+{
+}
+
+void
+CachingEvaluator::discardRecording( int )
+{
+}
+
+void
+CachingEvaluator::playRecording( int )
+{
+}
diff --git a/src/glu/sgi/libnurbs/internals/cachingeval.h b/src/glu/sgi/libnurbs/internals/cachingeval.h
new file mode 100644
index 00000000000..a4f489e9311
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/cachingeval.h
@@ -0,0 +1,56 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * cachingeval.h
+ *
+ * $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/cachingeval.h,v 1.1 2001/03/17 00:25:40 brianp Exp $
+ */
+
+#ifndef __glucachingval_h_
+#define __glucachingval_h_
+
+class CachingEvaluator {
+public:
+ enum ServiceMode { play, record, playAndRecord };
+ virtual int canRecord( void );
+ virtual int canPlayAndRecord( void );
+ virtual int createHandle( int handle );
+ virtual void beginOutput( ServiceMode, int handle );
+ virtual void endOutput( void );
+ virtual void discardRecording( int handle );
+ virtual void playRecording( int handle );
+};
+#endif /* __glucachingval_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/ccw.cc b/src/glu/sgi/libnurbs/internals/ccw.cc
new file mode 100644
index 00000000000..b7a77b65b1c
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/ccw.cc
@@ -0,0 +1,567 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * ccw.c++
+ *
+ * $Date: 2002/11/01 23:35:07 $ $Revision: 1.2 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/ccw.cc,v 1.2 2002/11/01 23:35:07 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "subdivider.h"
+#include "types.h"
+#include "arc.h"
+#include "trimvertex.h"
+#include "simplemath.h"
+
+inline int
+Subdivider::bbox( TrimVertex *a, TrimVertex *b, TrimVertex *c, int p )
+{
+ return bbox( a->param[p], b->param[p], c->param[p],
+ a->param[1-p], b->param[1-p], c->param[1-p] );
+}
+
+int
+Subdivider::ccwTurn_sr( Arc_ptr j1, Arc_ptr j2 ) // dir = 1
+{
+ register TrimVertex *v1 = &j1->pwlArc->pts[j1->pwlArc->npts-1];
+ register TrimVertex *v1last = &j1->pwlArc->pts[0];
+ register TrimVertex *v2 = &j2->pwlArc->pts[0];
+ register TrimVertex *v2last = &j2->pwlArc->pts[j2->pwlArc->npts-1];
+ register TrimVertex *v1next = v1-1;
+ register TrimVertex *v2next = v2+1;
+ int sgn;
+
+ assert( v1 != v1last );
+ assert( v2 != v2last );
+
+#ifndef NDEBUG
+ dprintf( "arc_ccw_turn, p = %d\n", 0 );
+#endif
+
+ // the arcs lie on the line (0 == v1->param[0])
+ if( v1->param[0] == v1next->param[0] && v2->param[0] == v2next->param[0] )
+ return 0;
+
+ if( v2next->param[0] < v2->param[0] || v1next->param[0] < v1->param[0] )
+ ::mylongjmp( jumpbuffer, 28 );
+
+ if( v1->param[1] < v2->param[1] )
+ return 0;
+ else if( v1->param[1] > v2->param[1] )
+ return 1;
+
+ while( 1 ) {
+ if( v1next->param[0] < v2next->param[0] ) {
+#ifndef NDEBUG
+ dprintf( "case a\n" );
+#endif
+ assert( v1->param[0] <= v1next->param[0] );
+ assert( v2->param[0] <= v1next->param[0] );
+ switch( bbox( v2, v2next, v1next, 1 ) ) {
+ case -1:
+ return 0;
+ case 0:
+ sgn = ccw( v1next, v2, v2next );
+ if( sgn != -1 ) {
+ return sgn;
+ } else {
+#ifdef DEBUG
+ dprintf( "decr\n" );
+#endif
+ v1 = v1next--;
+ if( v1 == v1last ) {
+#ifdef DEBUG
+ dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 1;
+ }
+ } else if( v1next->param[0] > v2next->param[0] ) {
+#ifndef NDEBUG
+ dprintf( "case b\n" );
+#endif
+ assert( v1->param[0] <= v2next->param[0] );
+ assert( v2->param[0] <= v2next->param[0] );
+ switch( bbox( v1, v1next, v2next, 1 ) ) {
+ case -1:
+ return 1;
+ case 0:
+ sgn = ccw( v1next, v1, v2next );
+ if( sgn != -1 ) {
+ return sgn;
+ } else {
+#ifdef DEBUG
+ dprintf( "incr\n" );
+#endif
+ v2 = v2next++;
+ if( v2 == v2last ) {
+#ifdef DEBUG
+ dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 0;
+ }
+ } else {
+#ifndef NDEBUG
+ dprintf( "case ab\n" );
+#endif
+ if( v1next->param[1] < v2next->param[1] )
+ return 0;
+ else if( v1next->param[1] > v2next->param[1] )
+ return 1;
+ else {
+#ifdef DEBUG
+ dprintf( "incr\n" );
+#endif
+ v2 = v2next++;
+ if( v2 == v2last ) {
+#ifdef DEBUG
+ dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ }
+ }
+}
+
+int
+Subdivider::ccwTurn_sl( Arc_ptr j1, Arc_ptr j2 ) // dir = 0
+{
+ register TrimVertex *v1 = &j1->pwlArc->pts[j1->pwlArc->npts-1];
+ register TrimVertex *v1last = &j1->pwlArc->pts[0];
+ register TrimVertex *v2 = &j2->pwlArc->pts[0];
+ register TrimVertex *v2last = &j2->pwlArc->pts[j2->pwlArc->npts-1];
+ register TrimVertex *v1next = v1-1;
+ register TrimVertex *v2next = v2+1;
+ int sgn;
+
+ assert( v1 != v1last );
+ assert( v2 != v2last );
+
+#ifndef NDEBUG
+ dprintf( "arc_ccw_turn, p = %d\n", 0 );
+#endif
+
+ // the arcs lie on the line (0 == v1->param[0])
+ if( v1->param[0] == v1next->param[0] && v2->param[0] == v2next->param[0] )
+ return 0;
+
+ if( v2next->param[0] > v2->param[0] || v1next->param[0] > v1->param[0] )
+ ::mylongjmp( jumpbuffer, 28 );
+
+ if( v1->param[1] < v2->param[1] )
+ return 1;
+ else if( v1->param[1] > v2->param[1] )
+ return 0;
+
+ while( 1 ) {
+ if( v1next->param[0] > v2next->param[0] ) {
+#ifndef NDEBUG
+ dprintf( "case c\n" );
+#endif
+ assert( v1->param[0] >= v1next->param[0] );
+ assert( v2->param[0] >= v1next->param[0] );
+ switch( bbox( v2next, v2, v1next, 1 ) ) {
+ case -1:
+ return 1;
+ case 0:
+ sgn = ccw( v1next, v2, v2next );
+ if( sgn != -1 )
+ return sgn;
+ else {
+ v1 = v1next--;
+#ifdef DEBUG
+ dprintf( "decr\n" );
+#endif
+ if( v1 == v1last ) {
+#ifdef DEBUG
+ dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 0;
+ }
+ } else if( v1next->param[0] < v2next->param[0] ) {
+#ifndef NDEBUG
+ dprintf( "case d\n" );
+#endif
+ assert( v1->param[0] >= v2next->param[0] );
+ assert( v2->param[0] >= v2next->param[0] );
+ switch( bbox( v1next, v1, v2next, 1 ) ) {
+ case -1:
+ return 0;
+ case 0:
+ sgn = ccw( v1next, v1, v2next );
+ if( sgn != -1 )
+ return sgn;
+ else {
+ v2 = v2next++;
+#ifdef DEBUG
+ dprintf( "incr\n" );
+#endif
+ if( v2 == v2last ) {
+#ifdef DEBUG
+ dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 1;
+ }
+ } else {
+#ifdef DEBUG
+ dprintf( "case cd\n" );
+#endif
+ if( v1next->param[1] < v2next->param[1] )
+ return 1;
+ else if( v1next->param[1] > v2next->param[1] )
+ return 0;
+ else {
+ v2 = v2next++;
+#ifdef DEBUG
+ dprintf( "incr\n" );
+#endif
+ if( v2 == v2last ) {
+#ifdef DEBUG
+ dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ }
+ }
+}
+
+int
+Subdivider::ccwTurn_tr( Arc_ptr j1, Arc_ptr j2 ) // dir = 1
+{
+ register TrimVertex *v1 = &j1->pwlArc->pts[j1->pwlArc->npts-1];
+ register TrimVertex *v1last = &j1->pwlArc->pts[0];
+ register TrimVertex *v2 = &j2->pwlArc->pts[0];
+ register TrimVertex *v2last = &j2->pwlArc->pts[j2->pwlArc->npts-1];
+ register TrimVertex *v1next = v1-1;
+ register TrimVertex *v2next = v2+1;
+ int sgn;
+
+ assert( v1 != v1last );
+ assert( v2 != v2last );
+
+#ifndef NDEBUG
+ dprintf( "arc_ccw_turn, p = %d\n", 1 );
+#endif
+
+ // the arcs lie on the line (1 == v1->param[1])
+ if( v1->param[1] == v1next->param[1] && v2->param[1] == v2next->param[1] )
+ return 0;
+
+ if( v2next->param[1] < v2->param[1] || v1next->param[1] < v1->param[1] )
+ ::mylongjmp( jumpbuffer, 28 );
+
+ if( v1->param[0] < v2->param[0] )
+ return 1;
+ else if( v1->param[0] > v2->param[0] )
+ return 0;
+
+ while( 1 ) {
+ if( v1next->param[1] < v2next->param[1] ) {
+#ifndef NDEBUG
+ dprintf( "case a\n" );
+#endif
+ assert( v1->param[1] <= v1next->param[1] );
+ assert( v2->param[1] <= v1next->param[1] );
+ switch( bbox( v2, v2next, v1next, 0 ) ) {
+ case -1:
+ return 1;
+ case 0:
+ sgn = ccw( v1next, v2, v2next );
+ if( sgn != -1 ) {
+ return sgn;
+ } else {
+#ifdef DEBUG
+ dprintf( "decr\n" );
+#endif
+ v1 = v1next--;
+ if( v1 == v1last ) {
+#ifdef DEBUG
+ dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 0;
+ }
+ } else if( v1next->param[1] > v2next->param[1] ) {
+#ifndef NDEBUG
+ dprintf( "case b\n" );
+#endif
+ assert( v1->param[1] <= v2next->param[1] );
+ assert( v2->param[1] <= v2next->param[1] );
+ switch( bbox( v1, v1next, v2next, 0 ) ) {
+ case -1:
+ return 0;
+ case 0:
+ sgn = ccw( v1next, v1, v2next );
+ if( sgn != -1 ) {
+ return sgn;
+ } else {
+#ifdef DEBUG
+ dprintf( "incr\n" );
+#endif
+ v2 = v2next++;
+ if( v2 == v2last ) {
+#ifdef DEBUG
+ dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 1;
+ }
+ } else {
+#ifdef DEBUG
+ dprintf( "case ab\n" );
+#endif
+ if( v1next->param[0] < v2next->param[0] )
+ return 1;
+ else if( v1next->param[0] > v2next->param[0] )
+ return 0;
+ else {
+#ifdef DEBUG
+ dprintf( "incr\n" );
+#endif
+ v2 = v2next++;
+ if( v2 == v2last ) {
+#ifdef DEBUG
+ dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ }
+ }
+}
+
+int
+Subdivider::ccwTurn_tl( Arc_ptr j1, Arc_ptr j2 )
+{
+ register TrimVertex *v1 = &j1->pwlArc->pts[j1->pwlArc->npts-1];
+ register TrimVertex *v1last = &j1->pwlArc->pts[0];
+ register TrimVertex *v2 = &j2->pwlArc->pts[0];
+ register TrimVertex *v2last = &j2->pwlArc->pts[j2->pwlArc->npts-1];
+ register TrimVertex *v1next = v1-1;
+ register TrimVertex *v2next = v2+1;
+ int sgn;
+
+ assert( v1 != v1last );
+ assert( v2 != v2last );
+
+#ifndef NDEBUG
+ dprintf( "arc_ccw_turn, p = %d\n", 1 );
+#endif
+
+ // the arcs lie on the line (1 == v1->param[1])
+ if( v1->param[1] == v1next->param[1] && v2->param[1] == v2next->param[1] )
+ return 0;
+
+ if( v2next->param[1] > v2->param[1] || v1next->param[1] > v1->param[1] )
+ ::mylongjmp( jumpbuffer, 28 );
+
+ if( v1->param[0] < v2->param[0] )
+ return 0;
+ else if( v1->param[0] > v2->param[0] )
+ return 1;
+
+ while( 1 ) {
+ if( v1next->param[1] > v2next->param[1] ) {
+#ifndef NDEBUG
+ dprintf( "case c\n" );
+#endif
+ assert( v1->param[1] >= v1next->param[1] );
+ assert( v2->param[1] >= v1next->param[1] );
+ switch( bbox( v2next, v2, v1next, 0 ) ) {
+ case -1:
+ return 0;
+ case 0:
+ sgn = ccw( v1next, v2, v2next );
+ if( sgn != -1 )
+ return sgn;
+ else {
+ v1 = v1next--;
+#ifdef DEBUG
+ dprintf( "decr\n" );
+#endif
+ if( v1 == v1last ) {
+#ifdef DEBUG
+ dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 1;
+ }
+ } else if( v1next->param[1] < v2next->param[1] ) {
+#ifndef NDEBUG
+ dprintf( "case d\n" );
+ assert( v1->param[1] >= v2next->param[1] );
+ assert( v2->param[1] >= v2next->param[1] );
+#endif
+ switch( bbox( v1next, v1, v2next, 0 ) ) {
+ case -1:
+ return 1;
+ case 0:
+ sgn = ccw( v1next, v1, v2next );
+ if( sgn != -1 )
+ return sgn;
+ else {
+ v2 = v2next++;
+#ifdef DEBUG
+ dprintf( "incr\n" );
+#endif
+ if( v2 == v2last ) {
+#ifdef DEBUG
+ dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 0;
+ }
+ } else {
+#ifdef DEBUG
+ dprintf( "case cd\n" );
+#endif
+ if( v1next->param[0] < v2next->param[0] )
+ return 0;
+ else if( v1next->param[0] > v2next->param[0] )
+ return 1;
+ else {
+ v2 = v2next++;
+#ifdef DEBUG
+ dprintf( "incr\n" );
+#endif
+ if( v2 == v2last ) {
+#ifdef DEBUG
+ dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ }
+ }
+}
+
+
+#ifndef NDEBUG
+int
+Subdivider::bbox( register REAL sa, register REAL sb, register REAL sc,
+ register REAL ta, register REAL tb, register REAL tc )
+#else
+int
+Subdivider::bbox( register REAL sa, register REAL sb, register REAL sc,
+ register REAL , register REAL , register REAL )
+#endif
+{
+#ifndef NDEBUG
+ assert( tc >= ta );
+ assert( tc <= tb );
+#endif
+
+ if( sa < sb ) {
+ if( sc <= sa ) {
+ return -1;
+ } else if( sb <= sc ) {
+ return 1;
+ } else {
+ return 0;
+ }
+ } else if( sa > sb ) {
+ if( sc >= sa ) {
+ return 1;
+ } else if( sb >= sc ) {
+ return -1;
+ } else {
+ return 0;
+ }
+ } else {
+ if( sc > sa ) {
+ return 1;
+ } else if( sb > sc ) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * ccw - determine how three points are oriented by computing their
+ * determinant.
+ * Return 1 if the vertices are ccw oriented,
+ * 0 if they are cw oriented, or
+ * -1 if the computation is ill-conditioned.
+ *----------------------------------------------------------------------------
+ */
+int
+Subdivider::ccw( TrimVertex *a, TrimVertex *b, TrimVertex *c )
+{
+ REAL d = det3( a, b, c );
+ if( glu_abs(d) < 0.0001 ) return -1;
+ return (d < 0.0) ? 0 : 1;
+}
diff --git a/src/glu/sgi/libnurbs/internals/coveandtiler.cc b/src/glu/sgi/libnurbs/internals/coveandtiler.cc
new file mode 100644
index 00000000000..ca5bf36b363
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/coveandtiler.cc
@@ -0,0 +1,440 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * coveandtiler.c++
+ *
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "coveandtiler.h"
+#include "gridvertex.h"
+#include "gridtrimvertex.h"
+#include "uarray.h"
+#include "backend.h"
+
+
+const int CoveAndTiler::MAXSTRIPSIZE = 1000;
+
+CoveAndTiler::CoveAndTiler( Backend& b )
+ : backend( b )
+{ }
+
+CoveAndTiler::~CoveAndTiler( void )
+{ }
+
+inline void
+CoveAndTiler::output( GridVertex &gv )
+{
+ backend.tmeshvert( &gv );
+}
+
+inline void
+CoveAndTiler::output( TrimVertex *tv )
+{
+ backend.tmeshvert( tv );
+}
+
+inline void
+CoveAndTiler::output( GridTrimVertex& g )
+{
+ backend.tmeshvert( &g );
+}
+
+void
+CoveAndTiler::coveAndTile( void )
+{
+ long ustart = (top.ustart >= bot.ustart) ? top.ustart : bot.ustart;
+ long uend = (top.uend <= bot.uend) ? top.uend : bot.uend;
+ if( ustart <= uend ) {
+ tile( bot.vindex, ustart, uend );
+ if( top.ustart >= bot.ustart )
+ coveUpperLeft();
+ else
+ coveLowerLeft();
+
+ if( top.uend <= bot.uend )
+ coveUpperRight();
+ else
+ coveLowerRight();
+ } else {
+ TrimVertex blv, tlv, *bl, *tl;
+ GridTrimVertex bllv, tllv;
+ TrimVertex *lf = left.first();
+ TrimVertex *ll = left.last();
+ if( lf->param[0] >= ll->param[0] ) {
+ blv.param[0] = lf->param[0];
+ blv.param[1] = ll->param[1];
+ blv.nuid = 0; // XXX
+ assert( blv.param[1] == bot.vval );
+ bl = &blv;
+ tl = lf;
+ tllv.set( lf );
+ if( ll->param[0] > uarray.uarray[top.ustart-1] ) {
+ bllv.set( ll );
+ assert( ll->param[0] <= uarray.uarray[bot.ustart] );
+ } else {
+ bllv.set( top.ustart-1, bot.vindex );
+ }
+ coveUpperLeftNoGrid( bl );
+ } else {
+ tlv.param[0] = ll->param[0];
+ tlv.param[1] = lf->param[1];
+ tlv.nuid = 0; // XXX
+ assert( tlv.param[1] == top.vval );
+ tl = &tlv;
+ bl = ll;
+ bllv.set( ll );
+ if( lf->param[0] > uarray.uarray[bot.ustart-1] ) {
+ assert( lf->param[0] <= uarray.uarray[bot.ustart] );
+ tllv.set( lf );
+ } else {
+ tllv.set( bot.ustart-1, top.vindex );
+ }
+ coveLowerLeftNoGrid( tl );
+ }
+
+ TrimVertex brv, trv, *br, *tr;
+ GridTrimVertex brrv, trrv;
+ TrimVertex *rf = right.first();
+ TrimVertex *rl = right.last();
+
+ if( rf->param[0] <= rl->param[0] ) {
+ brv.param[0] = rf->param[0];
+ brv.param[1] = rl->param[1];
+ brv.nuid = 0; // XXX
+ assert( brv.param[1] == bot.vval );
+ br = &brv;
+ tr = rf;
+ trrv.set( rf );
+ if( rl->param[0] < uarray.uarray[top.uend+1] ) {
+ assert( rl->param[0] >= uarray.uarray[top.uend] );
+ brrv.set( rl );
+ } else {
+ brrv.set( top.uend+1, bot.vindex );
+ }
+ coveUpperRightNoGrid( br );
+ } else {
+ trv.param[0] = rl->param[0];
+ trv.param[1] = rf->param[1];
+ trv.nuid = 0; // XXX
+ assert( trv.param[1] == top.vval );
+ tr = &trv;
+ br = rl;
+ brrv.set( rl );
+ if( rf->param[0] < uarray.uarray[bot.uend+1] ) {
+ assert( rf->param[0] >= uarray.uarray[bot.uend] );
+ trrv.set( rf );
+ } else {
+ trrv.set( bot.uend+1, top.vindex );
+ }
+ coveLowerRightNoGrid( tr );
+ }
+
+ backend.bgntmesh( "doit" );
+ output(trrv);
+ output(tllv);
+ output( tr );
+ output( tl );
+ output( br );
+ output( bl );
+ output(brrv);
+ output(bllv);
+ backend.endtmesh();
+ }
+}
+
+void
+CoveAndTiler::tile( long vindex, long ustart, long uend )
+{
+ long numsteps = uend - ustart;
+
+ if( numsteps == 0 ) return;
+
+ if( numsteps > MAXSTRIPSIZE ) {
+ long umid = ustart + (uend - ustart) / 2;
+ tile( vindex, ustart, umid );
+ tile( vindex, umid, uend );
+ } else {
+ backend.surfmesh( ustart, vindex-1, numsteps, 1 );
+ }
+}
+
+void
+CoveAndTiler::coveUpperRight( void )
+{
+ GridVertex tgv( top.uend, top.vindex );
+ GridVertex gv( top.uend, bot.vindex );
+
+ right.first();
+ backend.bgntmesh( "coveUpperRight" );
+ output( right.next() );
+ output( tgv );
+ backend.swaptmesh();
+ output( gv );
+ coveUR();
+ backend.endtmesh();
+}
+
+void
+CoveAndTiler::coveUpperRightNoGrid( TrimVertex* br )
+{
+ backend.bgntmesh( "coveUpperRight" );
+ output( right.first() );
+ output( right.next() );
+ backend.swaptmesh();
+ output( br );
+ coveUR();
+ backend.endtmesh();
+}
+
+void
+CoveAndTiler::coveUR( )
+{
+ GridVertex gv( top.uend, bot.vindex );
+ TrimVertex *vert = right.next();
+ if( vert == NULL ) return;
+
+ assert( vert->param[0] >= uarray.uarray[gv.gparam[0]] );
+
+ if( gv.nextu() >= bot.uend ) {
+ for( ; vert; vert = right.next() ) {
+ output( vert );
+ backend.swaptmesh();
+ }
+ } else while( 1 ) {
+ if( vert->param[0] < uarray.uarray[gv.gparam[0]] ) {
+ output( vert );
+ backend.swaptmesh();
+ vert = right.next();
+ if( vert == NULL ) break;
+ } else {
+ backend.swaptmesh();
+ output( gv );
+ if( gv.nextu() == bot.uend ) {
+ for( ; vert; vert = right.next() ) {
+ output( vert );
+ backend.swaptmesh();
+ }
+ break;
+ }
+ }
+ }
+}
+
+void
+CoveAndTiler::coveUpperLeft( void )
+{
+ GridVertex tgv( top.ustart, top.vindex );
+ GridVertex gv( top.ustart, bot.vindex );
+
+ left.first();
+ backend.bgntmesh( "coveUpperLeft" );
+ output( tgv );
+ output( left.next() );
+ output( gv );
+ backend.swaptmesh();
+ coveUL();
+ backend.endtmesh();
+}
+
+void
+CoveAndTiler::coveUpperLeftNoGrid( TrimVertex* bl )
+{
+ backend.bgntmesh( "coveUpperLeftNoGrid" );
+ output( left.first() );
+ output( left.next() );
+ output( bl );
+ backend.swaptmesh();
+ coveUL();
+ backend.endtmesh();
+}
+
+void
+CoveAndTiler::coveUL()
+{
+ GridVertex gv( top.ustart, bot.vindex );
+ TrimVertex *vert = left.next();
+ if( vert == NULL ) return;
+ assert( vert->param[0] <= uarray.uarray[gv.gparam[0]] );
+
+ if( gv.prevu() <= bot.ustart ) {
+ for( ; vert; vert = left.next() ) {
+ backend.swaptmesh();
+ output( vert );
+ }
+ } else while( 1 ) {
+ if( vert->param[0] > uarray.uarray[gv.gparam[0]] ) {
+ backend.swaptmesh();
+ output( vert );
+ vert = left.next();
+ if( vert == NULL ) break;
+ } else {
+ output( gv );
+ backend.swaptmesh();
+ if( gv.prevu() == bot.ustart ) {
+ for( ; vert; vert = left.next() ) {
+ backend.swaptmesh();
+ output( vert );
+ }
+ break;
+ }
+ }
+ }
+}
+
+void
+CoveAndTiler::coveLowerLeft( void )
+{
+ GridVertex bgv( bot.ustart, bot.vindex );
+ GridVertex gv( bot.ustart, top.vindex );
+
+ left.last();
+ backend.bgntmesh( "coveLowerLeft" );
+ output( left.prev() );
+ output( bgv );
+ backend.swaptmesh();
+ output( gv );
+ coveLL();
+ backend.endtmesh();
+}
+
+void
+CoveAndTiler::coveLowerLeftNoGrid( TrimVertex* tl )
+{
+ backend.bgntmesh( "coveLowerLeft" );
+ output( left.last() );
+ output( left.prev() );
+ backend.swaptmesh();
+ output( tl );
+ coveLL( );
+ backend.endtmesh();
+}
+
+void
+CoveAndTiler::coveLL()
+{
+ GridVertex gv( bot.ustart, top.vindex );
+ TrimVertex *vert = left.prev();
+ if( vert == NULL ) return;
+ assert( vert->param[0] <= uarray.uarray[gv.gparam[0]] );
+
+ if( gv.prevu() <= top.ustart ) {
+ for( ; vert; vert = left.prev() ) {
+ output( vert );
+ backend.swaptmesh();
+ }
+ } else while( 1 ) {
+ if( vert->param[0] > uarray.uarray[gv.gparam[0]] ){
+ output( vert );
+ backend.swaptmesh();
+ vert = left.prev();
+ if( vert == NULL ) break;
+ } else {
+ backend.swaptmesh();
+ output( gv );
+ if( gv.prevu() == top.ustart ) {
+ for( ; vert; vert = left.prev() ) {
+ output( vert );
+ backend.swaptmesh();
+ }
+ break;
+ }
+ }
+ }
+}
+
+void
+CoveAndTiler::coveLowerRight( void )
+{
+ GridVertex bgv( bot.uend, bot.vindex );
+ GridVertex gv( bot.uend, top.vindex );
+
+ right.last();
+ backend.bgntmesh( "coveLowerRight" );
+ output( bgv );
+ output( right.prev() );
+ output( gv );
+ backend.swaptmesh();
+ coveLR();
+ backend.endtmesh( );
+}
+
+void
+CoveAndTiler::coveLowerRightNoGrid( TrimVertex* tr )
+{
+ backend.bgntmesh( "coveLowerRIght" );
+ output( right.last() );
+ output( right.prev() );
+ output( tr );
+ backend.swaptmesh();
+ coveLR();
+ backend.endtmesh();
+}
+
+void
+CoveAndTiler::coveLR( )
+{
+ GridVertex gv( bot.uend, top.vindex );
+ TrimVertex *vert = right.prev();
+ if( vert == NULL ) return;
+ assert( vert->param[0] >= uarray.uarray[gv.gparam[0]] );
+
+ if( gv.nextu() >= top.uend ) {
+ for( ; vert; vert = right.prev() ) {
+ backend.swaptmesh();
+ output( vert );
+ }
+ } else while( 1 ) {
+ if( vert->param[0] < uarray.uarray[gv.gparam[0]] ) {
+ backend.swaptmesh();
+ output( vert );
+ vert = right.prev();
+ if( vert == NULL ) break;
+ } else {
+ output( gv );
+ backend.swaptmesh();
+ if( gv.nextu() == top.uend ) {
+ for( ; vert; vert = right.prev() ) {
+ backend.swaptmesh();
+ output( vert );
+ }
+ break;
+ }
+ }
+ }
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/coveandtiler.h b/src/glu/sgi/libnurbs/internals/coveandtiler.h
new file mode 100644
index 00000000000..f6cc87948a0
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/coveandtiler.h
@@ -0,0 +1,78 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * coveandtiler.h
+ *
+ * $Date: 2001/07/16 15:46:42 $ $Revision: 1.2 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/coveandtiler.h,v 1.2 2001/07/16 15:46:42 brianp Exp $
+ */
+
+#ifndef __glucoveandtiler_h
+#define __glucoveandtiler_h
+
+#include "trimregion.h"
+#include "trimvertex.h"
+#include "gridvertex.h"
+
+class Backend;
+class GridTrimVertex;
+
+class CoveAndTiler : virtual public TrimRegion {
+public:
+ CoveAndTiler( Backend& );
+ ~CoveAndTiler( void );
+ void coveAndTile( void );
+private:
+ Backend& backend;
+ static const int MAXSTRIPSIZE;
+ void tile( long, long, long );
+ void coveLowerLeft( void );
+ void coveLowerRight( void );
+ void coveUpperLeft( void );
+ void coveUpperRight( void );
+ void coveUpperLeftNoGrid( TrimVertex * );
+ void coveUpperRightNoGrid( TrimVertex * );
+ void coveLowerLeftNoGrid( TrimVertex * );
+ void coveLowerRightNoGrid( TrimVertex * );
+ void coveLL( void );
+ void coveLR( void );
+ void coveUL( void );
+ void coveUR( void );
+ inline void output( GridTrimVertex& );
+ inline void output( GridVertex& );
+ inline void output( TrimVertex* );
+};
+
+#endif /* __glucoveandtiler_h */
diff --git a/src/glu/sgi/libnurbs/internals/curve.cc b/src/glu/sgi/libnurbs/internals/curve.cc
new file mode 100644
index 00000000000..a69686a972f
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/curve.cc
@@ -0,0 +1,200 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * curve.c++
+ *
+ * $Date: 2004/05/12 15:29:36 $ $Revision: 1.3 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/curve.cc,v 1.3 2004/05/12 15:29:36 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "mymath.h"
+#include "curve.h"
+#include "mapdesc.h"
+#include "types.h"
+#include "quilt.h"
+#include "nurbsconsts.h"
+
+/*--------------------------------------------------------------------------
+ * Curve::Curve - copy curve from quilt and transform control points
+ *--------------------------------------------------------------------------
+ */
+
+Curve::Curve( Quilt_ptr geo, REAL pta, REAL ptb, Curve *c )
+{
+ mapdesc = geo->mapdesc;
+ next = c;
+ needsSampling = mapdesc->isRangeSampling() ? 1 : 0;
+ cullval = mapdesc->isCulling() ? CULL_ACCEPT : CULL_TRIVIAL_ACCEPT;
+ order = geo->qspec[0].order;
+ stride = MAXCOORDS;
+
+ REAL *ps = geo->cpts;
+ Quiltspec_ptr qs = geo->qspec;
+ ps += qs->offset;
+ ps += qs->index * qs->order * qs->stride;
+
+ if( needsSampling )
+ mapdesc->xformSampling( ps, qs->order, qs->stride, spts, stride );
+
+ if( cullval == CULL_ACCEPT )
+ mapdesc->xformCulling( ps, qs->order, qs->stride, cpts, stride );
+
+ /* set untrimmed curve range */
+ range[0] = qs->breakpoints[qs->index];
+ range[1] = qs->breakpoints[qs->index+1];
+ range[2] = range[1] - range[0];
+
+ if( range[0] != pta ) {
+ Curve lower( *this, pta, 0 );
+ lower.next = next;
+ *this = lower;
+ }
+ if( range[1] != ptb ) {
+ Curve lower( *this, ptb, 0 );
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Curve::Curve - subdivide a curve along an isoparametric line
+ *--------------------------------------------------------------------------
+ */
+
+Curve::Curve( Curve& upper, REAL value, Curve *c )
+{
+ Curve &lower = *this;
+
+ lower.next = c;
+ lower.mapdesc = upper.mapdesc;
+ lower.needsSampling = upper.needsSampling;
+ lower.order = upper.order;
+ lower.stride = upper.stride;
+ lower.cullval = upper.cullval;
+
+ REAL d = (value - upper.range[0]) / upper.range[2];
+
+ if( needsSampling )
+ mapdesc->subdivide( upper.spts, lower.spts, d, upper.stride, upper.order );
+
+ if( cullval == CULL_ACCEPT )
+ mapdesc->subdivide( upper.cpts, lower.cpts, d, upper.stride, upper.order );
+
+ lower.range[0] = upper.range[0];
+ lower.range[1] = value;
+ lower.range[2] = value - upper.range[0];
+ upper.range[0] = value;
+ upper.range[2] = upper.range[1] - value;
+}
+
+
+/*--------------------------------------------------------------------------
+ * Curve::clamp - clamp the sampling rate to a given maximum
+ *--------------------------------------------------------------------------
+ */
+
+void
+Curve::clamp( void )
+{
+ if( stepsize < minstepsize )
+ stepsize = mapdesc->clampfactor * minstepsize;
+}
+
+void
+Curve::setstepsize( REAL max )
+{
+ stepsize = ( max >= 1.0 ) ? (range[2] / max) : range[2];
+ minstepsize = stepsize;
+}
+
+void
+Curve::getstepsize( void )
+{
+ minstepsize= 0;
+
+ if( mapdesc->isConstantSampling() ) {
+ // fixed number of samples per patch in each direction
+ // maxrate is number of s samples per patch
+ setstepsize( mapdesc->maxrate );
+ } else if( mapdesc->isDomainSampling() ) {
+ // maxrate is number of s samples per unit s length of domain
+ setstepsize( mapdesc->maxrate * range[2] );
+ } else {
+ // upper bound on path length between sample points
+
+ assert( order <= MAXORDER );
+
+ /* points have been transformed, therefore they are homogeneous */
+ REAL tmp[MAXORDER][MAXCOORDS];
+ const int tstride = sizeof(tmp[0]) / sizeof(REAL);
+ int val = mapdesc->project( spts, stride, &tmp[0][0], tstride, order );
+
+ if( val == 0 ) {
+ // control points cross infinity, therefore derivatives are undefined
+ setstepsize( mapdesc->maxrate );
+ } else {
+ REAL t = mapdesc->getProperty( N_PIXEL_TOLERANCE );
+ if( mapdesc->isParametricDistanceSampling() ) {
+ REAL d = mapdesc->calcPartialVelocity( &tmp[0][0], tstride, order, 2, range[2] );
+ stepsize = (d > 0.0) ? sqrtf( 8.0 * t / d ) : range[2];
+ minstepsize = ( mapdesc->maxrate > 0.0 ) ? (range[2] / mapdesc->maxrate) : 0.0;
+ } else if( mapdesc->isPathLengthSampling() ) {
+ // t is upper bound on path (arc) length
+ REAL d = mapdesc->calcPartialVelocity( &tmp[0][0], tstride, order, 1, range[2] );
+ stepsize = ( d > 0.0 ) ? (t / d) : range[2];
+ minstepsize = ( mapdesc->maxrate > 0.0 ) ? (range[2] / mapdesc->maxrate) : 0.0;
+ } else {
+ // control points cross infinity, therefore partials are undefined
+ setstepsize( mapdesc->maxrate );
+ }
+ }
+ }
+}
+
+int
+Curve::needsSamplingSubdivision( void )
+{
+ return ( stepsize < minstepsize ) ? 1 : 0;
+}
+
+int
+Curve::cullCheck( void )
+{
+ if( cullval == CULL_ACCEPT )
+ cullval = mapdesc->cullCheck( cpts, order, stride );
+ return cullval;
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/curve.h b/src/glu/sgi/libnurbs/internals/curve.h
new file mode 100644
index 00000000000..37aaae73237
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/curve.h
@@ -0,0 +1,76 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * curve.h
+ *
+ * $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/curve.h,v 1.1 2001/03/17 00:25:40 brianp Exp $
+ */
+
+#ifndef __glucurve_h_
+#define __glucurve_h_
+
+#include "types.h"
+#include "defines.h"
+
+class Mapdesc;
+class Quilt;
+
+
+class Curve {
+public:
+friend class Curvelist;
+ Curve( Quilt *, REAL, REAL, Curve * );
+ Curve( Curve&, REAL, Curve * );
+ Curve * next;
+private:
+ Mapdesc * mapdesc;
+ int stride;
+ int order;
+ int cullval;
+ int needsSampling;
+ REAL cpts[MAXORDER*MAXCOORDS];
+ REAL spts[MAXORDER*MAXCOORDS];
+ REAL stepsize;
+ REAL minstepsize;
+ REAL range[3];
+
+ void clamp( void );
+ void setstepsize( REAL );
+ void getstepsize( void );
+ int cullCheck( void );
+ int needsSamplingSubdivision( void );
+};
+#endif /* __glucurve_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/curvelist.cc b/src/glu/sgi/libnurbs/internals/curvelist.cc
new file mode 100644
index 00000000000..e6b2133d554
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/curvelist.cc
@@ -0,0 +1,112 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * curvelist.c++
+ *
+ * $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/curvelist.cc,v 1.1 2001/03/17 00:25:40 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "quilt.h"
+#include "curvelist.h"
+#include "curve.h"
+#include "nurbsconsts.h"
+#include "types.h"
+
+Curvelist::Curvelist( Quilt *quilts, REAL pta, REAL ptb )
+{
+ curve = 0;
+ for( Quilt *q = quilts; q; q = q->next )
+ curve = new Curve( q, pta, ptb, curve );
+ range[0] = pta;
+ range[1] = ptb;
+ range[2] = ptb - pta;
+}
+
+Curvelist::Curvelist( Curvelist &upper, REAL value )
+{
+ Curvelist &lower = *this;
+ curve = 0;
+ for( Curve *c = upper.curve; c; c = c->next )
+ curve = new Curve( *c, value, curve );
+
+ lower.range[0] = upper.range[0];
+ lower.range[1] = value;
+ lower.range[2] = value - upper.range[0];
+ upper.range[0] = value;
+ upper.range[2] = upper.range[1] - value;
+}
+
+Curvelist::~Curvelist()
+{
+ while( curve ) {
+ Curve *c = curve;
+ curve = curve->next;
+ delete c;
+ }
+}
+
+int
+Curvelist::cullCheck( void )
+{
+ for( Curve *c = curve; c; c = c->next )
+ if( c->cullCheck() == CULL_TRIVIAL_REJECT )
+ return CULL_TRIVIAL_REJECT;
+ return CULL_ACCEPT;
+}
+
+void
+Curvelist::getstepsize( void )
+{
+ stepsize = range[2];
+ Curve *c;
+ for( c = curve; c; c = c->next ) {
+ c->getstepsize();
+ c->clamp();
+ stepsize = ((c->stepsize < stepsize) ? c->stepsize : stepsize);
+ if( c->needsSamplingSubdivision() ) break;
+ }
+ needsSubdivision = ( c ) ? 1 : 0;
+}
+
+int
+Curvelist::needsSamplingSubdivision( void )
+{
+ return needsSubdivision;
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/curvelist.h b/src/glu/sgi/libnurbs/internals/curvelist.h
new file mode 100644
index 00000000000..23ffa2b55b7
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/curvelist.h
@@ -0,0 +1,68 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * curvelist.h
+ *
+ * $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/curvelist.h,v 1.1 2001/03/17 00:25:40 brianp Exp $
+ */
+
+#ifndef __glucurvelist_h_
+#define __glucurvelist_h_
+
+#include "types.h"
+#include "defines.h"
+
+class Mapdesc;
+class Quilt;
+class Curve;
+
+class Curvelist
+{
+friend class Subdivider;
+public:
+ Curvelist( Quilt *, REAL, REAL );
+ Curvelist( Curvelist &, REAL );
+ ~Curvelist( void );
+ int cullCheck( void );
+ void getstepsize( void );
+ int needsSamplingSubdivision();
+private:
+ Curve *curve;
+ float range[3];
+ int needsSubdivision;
+ float stepsize;
+};
+#endif /* __glucurvelist_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/curvesub.cc b/src/glu/sgi/libnurbs/internals/curvesub.cc
new file mode 100644
index 00000000000..63b8ac1eeb3
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/curvesub.cc
@@ -0,0 +1,105 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * curvesub.c++
+ *
+ * $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/curvesub.cc,v 1.1 2001/03/17 00:25:40 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "subdivider.h"
+#include "renderhints.h"
+#include "backend.h"
+#include "quilt.h"
+#include "curvelist.h"
+#include "curve.h"
+#include "nurbsconsts.h"
+
+/*--------------------------------------------------------------------------
+ * drawCurves - main curve rendering entry point
+ *--------------------------------------------------------------------------
+ */
+
+void
+Subdivider::drawCurves( void )
+{
+ REAL from[1], to[1];
+ Flist bpts;
+ qlist->getRange( from, to, bpts );
+
+ renderhints.init( );
+
+ backend.bgncurv();
+ for( int i=bpts.start; i<bpts.end-1; i++ ) {
+ REAL pta, ptb;
+ pta = bpts.pts[i];
+ ptb = bpts.pts[i+1];
+
+ qlist->downloadAll( &pta, &ptb, backend );
+
+ Curvelist curvelist( qlist, pta, ptb );
+ samplingSplit( curvelist, renderhints.maxsubdivisions );
+ }
+ backend.endcurv();
+}
+
+
+/*--------------------------------------------------------------------------
+ * samplingSplit - recursively subdivide patch, cull check each subpatch
+ *--------------------------------------------------------------------------
+ */
+
+void
+Subdivider::samplingSplit( Curvelist& curvelist, int subdivisions )
+{
+ if( curvelist.cullCheck() == CULL_TRIVIAL_REJECT ) return;
+
+ curvelist.getstepsize();
+
+ if( curvelist.needsSamplingSubdivision() && (subdivisions > 0) ) {
+ REAL mid = ( curvelist.range[0] + curvelist.range[1] ) * 0.5;
+ Curvelist lowerlist( curvelist, mid );
+ samplingSplit( lowerlist, subdivisions-1 ); // lower
+ samplingSplit( curvelist, subdivisions-1 ); // upper
+ } else {
+ long nu = 1 + ((long) (curvelist.range[2] / curvelist.stepsize));
+ backend.curvgrid( curvelist.range[0], curvelist.range[1], nu );
+ backend.curvmesh( 0, nu );
+ }
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/dataTransform.cc b/src/glu/sgi/libnurbs/internals/dataTransform.cc
new file mode 100644
index 00000000000..1aabd363ea9
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/dataTransform.cc
@@ -0,0 +1,211 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2005/10/28 13:09:08 $ $Revision: 1.1.30.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/dataTransform.cc,v 1.1.30.1 2005/10/28 13:09:08 brianp Exp $
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "glimports.h"
+#include "myassert.h"
+#include "nurbsconsts.h"
+#include "trimvertex.h"
+#include "dataTransform.h"
+
+extern directedLine* arcLoopToDLineLoop(Arc_ptr loop);
+
+#if 0 // UNUSED
+static directedLine* copy_loop(Arc_ptr loop, Real2* vertArray, int& index, directedLine dline_buf[], sampledLine sline_buf[], int& index_dline)
+{
+ directedLine *ret;
+ int old_index = index;
+ int i = index;
+ int j;
+ for(j=0; j<loop->pwlArc->npts-1; j++, i++)
+ {
+ vertArray[i][0] = loop->pwlArc->pts[j].param[0];
+ vertArray[i][1] = loop->pwlArc->pts[j].param[1];
+ }
+ loop->clearmark();
+
+ for(Arc_ptr jarc = loop->next; jarc != loop; jarc=jarc->next)
+ {
+ for(j=0; j<jarc->pwlArc->npts-1; j++, i++)
+ {
+ vertArray[i][0] = jarc->pwlArc->pts[j].param[0];
+ vertArray[i][1] = jarc->pwlArc->pts[j].param[1];
+ }
+ jarc->clearmark();
+ }
+ //copy the first vertex again
+ vertArray[i][0] = loop->pwlArc->pts[0].param[0];
+ vertArray[i][1] = loop->pwlArc->pts[0].param[1];
+ i++;
+ index=i;
+
+ directedLine* dline;
+ sampledLine* sline;
+ sline = &sline_buf[index_dline];
+ dline = &dline_buf[index_dline];
+ sline->init(2, &vertArray[old_index]);
+ dline->init(INCREASING, sline);
+ ret = dline;
+ index_dline++;
+
+ for(i=old_index+1; i<= index-2; i++)
+ {
+ sline = &sline_buf[index_dline];
+ dline = &dline_buf[index_dline];
+ sline->init(2, &vertArray[i]);
+ dline->init(INCREASING, sline);
+ ret->insert(dline);
+ index_dline++;
+ }
+ return ret;
+}
+#endif
+
+#if 0 // UNUSED
+static int num_edges(Bin& bin)
+{
+ int sum=0;
+ for(Arc_ptr jarc = bin.firstarc(); jarc; jarc=bin.nextarc())
+ sum += jarc->pwlArc->npts-1;
+ return sum;
+}
+#endif
+
+/*
+directedLine* bin_to_DLineLoops(Bin& bin)
+{
+ directedLine *ret=NULL;
+ directedLine *temp;
+
+ int numedges = num_edges(bin);
+ directedLine* dline_buf = new directedLine[numedges]; //not work for N32?
+ sampledLine* sline_buf=new sampledLine[numedges];
+
+ Real2* vertArray = new Real2[numedges*2];
+ int index = 0;
+ int index_dline = 0;
+ bin.markall();
+
+ for(Arc_ptr jarc = bin.firstarc(); jarc; jarc=bin.nextarc())
+ {
+ if(jarc->ismarked())
+ {
+ assert(jarc->check() != 0);
+ Arc_ptr jarchead = jarc;
+ do {
+ jarc->clearmark();
+ jarc = jarc->next;
+ } while(jarc != jarchead);
+ temp=copy_loop(jarchead, vertArray, index, dline_buf, sline_buf, index_dline);
+ ret = temp->insertPolygon(ret);
+ }
+ }
+
+ return ret;
+}
+*/
+
+
+directedLine* bin_to_DLineLoops(Bin& bin)
+{
+ directedLine *ret=NULL;
+ directedLine *temp;
+ bin.markall();
+ for(Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc()){
+ if(jarc->ismarked()) {
+ assert(jarc->check() != 0);
+ Arc_ptr jarchead = jarc;
+ do {
+ jarc->clearmark();
+ jarc = jarc->next;
+ } while(jarc != jarchead);
+ temp = arcLoopToDLineLoop(jarc);
+ ret = temp->insertPolygon(ret);
+ }
+ }
+ return ret;
+}
+
+directedLine* o_pwlcurve_to_DLines(directedLine* original, O_pwlcurve* pwl)
+{
+ directedLine* ret = original;
+ for(Int i=0; i<pwl->npts-1; i++)
+ {
+ sampledLine* sline = new sampledLine(2);
+ sline->setPoint(0, pwl->pts[i].param);
+ sline->setPoint(1, pwl->pts[i+1].param);
+ directedLine* dline = new directedLine(INCREASING, sline);
+ if(ret == NULL)
+ ret = dline;
+ else
+ ret->insert(dline);
+ }
+ return ret;
+}
+
+directedLine* o_curve_to_DLineLoop(O_curve* cur)
+{
+ directedLine *ret;
+ if(cur == NULL)
+ return NULL;
+ assert(cur->curvetype == ct_pwlcurve);
+ ret = o_pwlcurve_to_DLines(NULL, cur->curve.o_pwlcurve);
+ for(O_curve* temp = cur->next; temp != NULL; temp = temp->next)
+ {
+ assert(temp->curvetype == ct_pwlcurve);
+ ret = o_pwlcurve_to_DLines(ret, temp->curve.o_pwlcurve);
+ }
+ return ret;
+}
+
+directedLine* o_trim_to_DLineLoops(O_trim* trim)
+{
+ O_trim* temp;
+ directedLine *ret;
+ if(trim == NULL)
+ return NULL;
+ ret = o_curve_to_DLineLoop(trim->o_curve);
+
+ for(temp=trim->next; temp != NULL; temp = temp->next)
+ {
+ ret = ret->insertPolygon(o_curve_to_DLineLoop(temp->o_curve));
+ }
+ return ret;
+}
diff --git a/src/glu/sgi/libnurbs/internals/dataTransform.h b/src/glu/sgi/libnurbs/internals/dataTransform.h
new file mode 100644
index 00000000000..48c60e5f363
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/dataTransform.h
@@ -0,0 +1,66 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/dataTransform.h,v 1.1 2001/03/17 00:25:40 brianp Exp $
+*/
+
+#ifndef _DATA_TRANSFORM_H
+#define _DATA_TRANSFORM_H
+
+#include "reader.h"
+#include "directedLine.h"
+#include "bin.h"
+directedLine* bin_to_DLineLoops(Bin& bin);
+
+/*transform the pwlcurve into a number of directedline lines
+ *insert these directedlines into orignal which is supposed to be
+ *the part of the trimming loop obtained so far.
+ *return the updated trimkming loop.
+ */
+directedLine* o_pwlcurve_to_DLines(directedLine* original, O_pwlcurve* pwl);
+
+/*transform a trim loop (curve) into a directedLine loop
+ */
+directedLine* o_curve_to_DLineLoop(O_curve* curve);
+
+/*transform a list of trim loops (trim) into
+ *a list of polygons represented as directedLine*.
+ */
+directedLine* o_trim_to_DLineLoops(O_trim* trim);
+
+
+#endif
+
diff --git a/src/glu/sgi/libnurbs/internals/defines.h b/src/glu/sgi/libnurbs/internals/defines.h
new file mode 100644
index 00000000000..1dde7c95ece
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/defines.h
@@ -0,0 +1,56 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * defines.h
+ *
+ * $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/defines.h,v 1.1 2001/03/17 00:25:40 brianp Exp $
+ */
+
+#ifndef __gludefines_h_
+#define __gludefines_h_
+
+/* culling constants */
+#define CULL_TRIVIAL_REJECT 0
+#define CULL_TRIVIAL_ACCEPT 1
+#define CULL_ACCEPT 2
+
+/* maximum order of a B-Spline */
+#define MAXORDER 24
+
+/* maximum dimension of any B-spline range space */
+#define MAXCOORDS 5
+
+#endif /* __gludefines_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/displaylist.cc b/src/glu/sgi/libnurbs/internals/displaylist.cc
new file mode 100644
index 00000000000..00e5a411783
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/displaylist.cc
@@ -0,0 +1,84 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * displaylist.c++
+ *
+ * $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/displaylist.cc,v 1.1 2001/03/17 00:25:40 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "nurbstess.h"
+#include "displaylist.h"
+
+
+DisplayList::DisplayList( NurbsTessellator *_nt ) :
+ dlnodePool( sizeof( Dlnode ), 1, "dlnodepool" )
+{
+ lastNode = &nodes;
+ nt = _nt;
+}
+
+DisplayList::~DisplayList( void )
+{
+ for( Dlnode *nextNode; nodes; nodes = nextNode ) {
+ nextNode = nodes->next;
+ if( nodes->cleanup != 0 ) (nt->*nodes->cleanup)( nodes->arg );
+ //nodes->deleteMe(dlnodePool);
+ }
+}
+
+void
+DisplayList::play( void )
+{
+ for( Dlnode *node = nodes; node; node = node->next )
+ if( node->work != 0 ) (nt->*node->work)( node->arg );
+}
+
+void
+DisplayList::endList( void )
+{
+ *lastNode = 0;
+}
+
+void
+DisplayList::append( PFVS work, void *arg, PFVS cleanup )
+{
+ Dlnode *node = new(dlnodePool) Dlnode( work, arg, cleanup );
+ *lastNode = node;
+ lastNode = &(node->next);
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/displaylist.h b/src/glu/sgi/libnurbs/internals/displaylist.h
new file mode 100644
index 00000000000..5a508552a36
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/displaylist.h
@@ -0,0 +1,84 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * displaylist.h
+ *
+ * $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/displaylist.h,v 1.1 2001/03/17 00:25:40 brianp Exp $
+ */
+
+#ifndef __gludisplaylist_h_
+#define __gludisplaylist_h_
+
+#include "glimports.h"
+#include "mysetjmp.h"
+#include "mystdio.h"
+#include "bufpool.h"
+
+class NurbsTessellator;
+
+typedef void (NurbsTessellator::*PFVS)( void * );
+
+struct Dlnode : public PooledObj {
+ Dlnode( PFVS, void *, PFVS );
+ PFVS work;
+ void * arg;
+ PFVS cleanup;
+ Dlnode * next;
+};
+
+inline
+Dlnode::Dlnode( PFVS _work, void *_arg, PFVS _cleanup )
+{
+ work = _work;
+ arg = _arg;
+ cleanup = _cleanup;
+}
+
+class DisplayList {
+public:
+ DisplayList( NurbsTessellator * );
+ ~DisplayList( void );
+ void play( void );
+ void append( PFVS work, void *arg, PFVS cleanup );
+ void endList( void );
+private:
+ Dlnode *nodes;
+ Pool dlnodePool;
+ Dlnode **lastNode;
+ NurbsTessellator *nt;
+};
+
+#endif /* __gludisplaylist_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/displaymode.h b/src/glu/sgi/libnurbs/internals/displaymode.h
new file mode 100644
index 00000000000..f007d513e0a
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/displaymode.h
@@ -0,0 +1,47 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/displaymode.h,v 1.1 2001/03/17 00:25:40 brianp Exp $
+*/
+
+#ifndef __gludisplaymode_h_
+#define __gludisplaymode_h_
+
+#define N_MESHFILL 0
+#define N_MESHLINE 1
+#define N_MESHPOINT 2
+
+#endif /* __gludisplaymode_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/flist.cc b/src/glu/sgi/libnurbs/internals/flist.cc
new file mode 100644
index 00000000000..0c4f215f48e
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/flist.cc
@@ -0,0 +1,120 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * flist.c++
+ *
+ * $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/flist.cc,v 1.1 2001/03/17 00:25:40 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "flist.h"
+
+/*----------------------------------------------------------------------------
+ * Flist::Flist - initialize a REAL number array
+ *----------------------------------------------------------------------------
+ */
+Flist::Flist( void )
+{
+ npts = 0;
+ pts = 0;
+ start = end = 0;
+}
+
+/*----------------------------------------------------------------------------
+ * Flist::~Flist - free a REAL number array
+ *----------------------------------------------------------------------------
+ */
+Flist::~Flist( void )
+{
+ if( npts ) delete[] pts;
+}
+
+void
+Flist::add( REAL x )
+{
+ pts[end++] = x;
+ assert( end <= npts );
+}
+
+/*----------------------------------------------------------------------------
+ * Flist::filter - remove duplicate numbers from array
+ *----------------------------------------------------------------------------
+ */
+void Flist::filter( void )
+{
+ sorter.qsort( pts, end );
+ start = 0;
+
+ int j = 0;
+ for( int i = 1; i < end; i++ ) {
+ if( pts[i] == pts[i-j-1] )
+ j++;
+ pts[i-j] = pts[i];
+ }
+ end -= j;
+}
+
+/*----------------------------------------------------------------------------
+ * Flist::grow - ensure that array is large enough
+ *----------------------------------------------------------------------------
+ */
+void Flist::grow( int maxpts )
+{
+ if( npts < maxpts ) {
+ if( npts ) delete[] pts;
+ npts = 2 * maxpts;
+ pts = new REAL[npts];
+ assert( pts != 0 );
+ }
+ start = end = 0;
+}
+
+/*----------------------------------------------------------------------------
+ * Flist::taper - ignore head and tail of array
+ *----------------------------------------------------------------------------
+ */
+void Flist::taper( REAL from, REAL to )
+{
+ while( pts[start] != from )
+ start++;
+
+ while( pts[end-1] != to )
+ end--;
+}
+
+
diff --git a/src/glu/sgi/libnurbs/internals/flist.h b/src/glu/sgi/libnurbs/internals/flist.h
new file mode 100644
index 00000000000..5d013891895
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/flist.h
@@ -0,0 +1,65 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * flist.h
+ *
+ * $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/flist.h,v 1.1 2001/03/17 00:25:40 brianp Exp $
+ */
+
+#ifndef __gluflist_h_
+#define __gluflist_h_
+
+#include "types.h"
+#include "flistsorter.h"
+
+class Flist {
+public:
+ REAL * pts; /* head of array */
+ int npts; /* number of points in array */
+ int start; /* first important point index */
+ int end; /* last important point index */
+
+ Flist( void );
+ ~Flist( void );
+ void add( REAL x );
+ void filter( void );
+ void grow( int);
+ void taper( REAL , REAL );
+protected:
+ FlistSorter sorter;
+};
+
+#endif /* __gluflist_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/flistsorter.cc b/src/glu/sgi/libnurbs/internals/flistsorter.cc
new file mode 100644
index 00000000000..3daf8de7797
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/flistsorter.cc
@@ -0,0 +1,83 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * flistsorter.c++
+ *
+ * $Date: 2001/03/17 00:25:40 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/flistsorter.cc,v 1.1 2001/03/17 00:25:40 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "flistsorter.h"
+
+FlistSorter::FlistSorter( void ) : Sorter( sizeof( REAL ) )
+{
+}
+
+void
+FlistSorter::qsort( REAL *p, int n )
+{
+ Sorter::qsort( (char *)p, n );
+}
+
+int
+FlistSorter::qscmp( char *i, char *j )
+{
+ REAL f0 = *(REAL *)i;
+ REAL f1 = *(REAL *)j;
+ return (f0 < f1) ? -1 : 1;
+}
+
+void
+FlistSorter::qsexc( char *i, char *j )
+{
+ REAL *f0 = (REAL *)i;
+ REAL *f1 = (REAL *)j;
+ REAL tmp = *f0;
+ *f0 = *f1;
+ *f1 = tmp;
+}
+
+void
+FlistSorter::qstexc( char *i, char *j, char *k )
+{
+ REAL *f0 = (REAL *)i;
+ REAL *f1 = (REAL *)j;
+ REAL *f2 = (REAL *)k;
+ REAL tmp = *f0;
+ *f0 = *f2;
+ *f2 = *f1;
+ *f1 = tmp;
+}
diff --git a/src/glu/sgi/libnurbs/internals/flistsorter.h b/src/glu/sgi/libnurbs/internals/flistsorter.h
new file mode 100644
index 00000000000..beec36da563
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/flistsorter.h
@@ -0,0 +1,58 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * flistsorter.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/flistsorter.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __gluflistsorter_h_
+#define __gluflistsorter_h_
+
+#include "sorter.h"
+#include "types.h"
+
+class FlistSorter : public Sorter {
+public:
+ FlistSorter(void);
+ void qsort( REAL *a, int n );
+
+protected:
+ virtual int qscmp( char *, char * );
+ virtual void qsexc( char *i, char *j ); // i<-j, j<-i
+ virtual void qstexc( char *i, char *j, char *k ); // i<-k, k<-j, j<-i
+};
+#endif /* __gluflistsorter_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/gridline.h b/src/glu/sgi/libnurbs/internals/gridline.h
new file mode 100644
index 00000000000..be612ee256c
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/gridline.h
@@ -0,0 +1,52 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * gridline.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/gridline.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __glugridline_h_
+#define __glugridline_h_
+
+struct Gridline {
+ long v;
+ REAL vval;
+ long vindex;
+ long ustart;
+ long uend;
+ };
+#endif /* __glugridline_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/gridtrimvertex.h b/src/glu/sgi/libnurbs/internals/gridtrimvertex.h
new file mode 100644
index 00000000000..42edb13a3e7
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/gridtrimvertex.h
@@ -0,0 +1,95 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * gridtrimvertex.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/gridtrimvertex.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __glugridtrimvertex_h_
+#define __glugridtrimvertex_h_
+
+#include "mystdlib.h"
+#include "bufpool.h"
+#include "trimvertex.h"
+#include "gridvertex.h"
+
+class GridTrimVertex : public PooledObj
+{
+private:
+ TrimVertex dummyt;
+ GridVertex dummyg;
+public:
+ GridTrimVertex() { g = 0; t = 0; }
+ TrimVertex *t;
+ GridVertex *g;
+
+ inline void set( long, long );
+ inline void set( REAL, REAL );
+ inline void set( TrimVertex * );
+ inline void clear( void ) { t = 0; g = 0; };
+ inline int isGridVert() { return g ? 1 : 0 ; }
+ inline int isTrimVert() { return t ? 1 : 0 ; }
+ inline void output();
+};
+
+inline void
+GridTrimVertex::set( long x, long y )
+{
+ g = &dummyg;
+ dummyg.gparam[0] = x;
+ dummyg.gparam[1] = y;
+}
+
+inline void
+GridTrimVertex::set( REAL x, REAL y )
+{
+ g = 0;
+ t = &dummyt;
+ dummyt.param[0] = x;
+ dummyt.param[1] = y;
+ dummyt.nuid = 0;
+}
+
+inline void
+GridTrimVertex::set( TrimVertex *v )
+{
+ g = 0;
+ t = v;
+}
+
+typedef GridTrimVertex *GridTrimVertex_p;
+#endif /* __glugridtrimvertex_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/gridvertex.h b/src/glu/sgi/libnurbs/internals/gridvertex.h
new file mode 100644
index 00000000000..bf512443e05
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/gridvertex.h
@@ -0,0 +1,54 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * gridvertex.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/gridvertex.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __glugridvertex_h_
+#define __glugridvertex_h_
+
+struct GridVertex {
+ long gparam[2];
+ GridVertex( void ) {}
+ GridVertex( long u, long v ) { gparam[0] = u, gparam[1] = v; }
+ void set( long u, long v ) { gparam[0] = u, gparam[1] = v; }
+ long nextu() { return gparam[0]++; }
+ long prevu() { return gparam[0]--; }
+};
+
+#endif /* __glugridvertex_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/hull.cc b/src/glu/sgi/libnurbs/internals/hull.cc
new file mode 100644
index 00000000000..305d9aaffb8
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/hull.cc
@@ -0,0 +1,167 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * hull.c++
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/hull.cc,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "hull.h"
+#include "gridvertex.h"
+#include "gridtrimvertex.h"
+#include "gridline.h"
+#include "trimline.h"
+#include "uarray.h"
+#include "trimregion.h"
+
+Hull::Hull( void )
+{}
+
+Hull::~Hull( void )
+{}
+
+/*----------------------------------------------------------------------
+ * Hull:init - this routine does the initialization needed before any
+ * calls to nextupper or nextlower can be made.
+ *----------------------------------------------------------------------
+ */
+void
+Hull::init( void )
+{
+ TrimVertex *lfirst = left.first();
+ TrimVertex *llast = left.last();
+ if( lfirst->param[0] <= llast->param[0] ) {
+ fakeleft.init( left.first() );
+ upper.left = &fakeleft;
+ lower.left = &left;
+ } else {
+ fakeleft.init( left.last() );
+ lower.left = &fakeleft;
+ upper.left = &left;
+ }
+ upper.left->last();
+ lower.left->first();
+
+ if( top.ustart <= top.uend ) {
+ upper.line = &top;
+ upper.index = top.ustart;
+ } else
+ upper.line = 0;
+
+ if( bot.ustart <= bot.uend ) {
+ lower.line = &bot;
+ lower.index = bot.ustart;
+ } else
+ lower.line = 0;
+
+ TrimVertex *rfirst = right.first();
+ TrimVertex *rlast = right.last();
+ if( rfirst->param[0] <= rlast->param[0] ) {
+ fakeright.init( right.last() );
+ lower.right = &fakeright;
+ upper.right = &right;
+ } else {
+ fakeright.init( right.first() );
+ upper.right = &fakeright;
+ lower.right = &right;
+ }
+ upper.right->first();
+ lower.right->last();
+}
+
+/*----------------------------------------------------------------------
+ * nextupper - find next vertex on upper hull of trim region.
+ * - if vertex is on trim curve, set vtop point to
+ * that vertex. if vertex is on grid, set vtop to
+ * point to temporary area and stuff coordinants into
+ * temporary vertex. Also, place grid coords in temporary
+ * grid vertex.
+ *----------------------------------------------------------------------
+ */
+GridTrimVertex *
+Hull::nextupper( GridTrimVertex *gv )
+{
+ if( upper.left ) {
+ gv->set( upper.left->prev() );
+ if( gv->isTrimVert() ) return gv;
+ upper.left = 0;
+ }
+
+ if( upper.line ) {
+ assert( upper.index <= upper.line->uend );
+ gv->set( uarray.uarray[upper.index], upper.line->vval );
+ gv->set( upper.index, upper.line->vindex );
+ if( upper.index++ == upper.line->uend ) upper.line = 0;
+ return gv;
+ }
+
+ if( upper.right ) {
+ gv->set( upper.right->next() );
+ if( gv->isTrimVert() ) return gv;
+ upper.right = 0;
+ }
+
+ return 0;
+}
+
+GridTrimVertex *
+Hull::nextlower( register GridTrimVertex *gv )
+{
+ if( lower.left ) {
+ gv->set( lower.left->next() );
+ if( gv->isTrimVert() ) return gv;
+ lower.left = 0;
+ }
+
+ if( lower.line ) {
+ gv->set( uarray.uarray[lower.index], lower.line->vval );
+ gv->set( lower.index, lower.line->vindex );
+ if( lower.index++ == lower.line->uend ) lower.line = 0;
+ return gv;
+ }
+
+ if( lower.right ) {
+ gv->set( lower.right->prev() );
+ if( gv->isTrimVert() ) return gv;
+ lower.right = 0;
+ }
+
+ return 0;
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/hull.h b/src/glu/sgi/libnurbs/internals/hull.h
new file mode 100644
index 00000000000..00a1d4614ae
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/hull.h
@@ -0,0 +1,75 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * hull.h
+ *
+ * $Date: 2001/08/07 17:34:11 $ $Revision: 1.2 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/hull.h,v 1.2 2001/08/07 17:34:11 brianp Exp $
+ */
+
+#ifndef __gluhull_h_
+#define __gluhull_h_
+
+#include "trimline.h"
+#include "trimregion.h"
+#include "trimvertex.h"
+#include "gridtrimvertex.h"
+
+struct Gridline;
+class Uarray;
+
+class Hull : virtual public TrimRegion {
+public:
+ Hull( void );
+ ~Hull( void );
+ void init( void );
+ GridTrimVertex * nextlower( GridTrimVertex * );
+ GridTrimVertex * nextupper( GridTrimVertex * );
+private:
+ struct Side {
+ Trimline *left;
+ Gridline *line;
+ Trimline *right;
+ long index;
+ };
+
+ Side lower;
+ Side upper;
+ Trimline fakeleft;
+ Trimline fakeright;
+};
+
+
+#endif /* __gluhull_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/intersect.cc b/src/glu/sgi/libnurbs/internals/intersect.cc
new file mode 100644
index 00000000000..b1e60fbce95
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/intersect.cc
@@ -0,0 +1,667 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * intersect.c++
+ *
+ * $Date: 2005/10/28 13:09:08 $ $Revision: 1.2.8.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/intersect.cc,v 1.2.8.1 2005/10/28 13:09:08 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "subdivider.h"
+#include "arc.h"
+#include "bin.h"
+#include "backend.h"
+#include "trimvertpool.h"
+
+/*#define NOTDEF*/
+
+enum i_result { INTERSECT_VERTEX, INTERSECT_EDGE };
+
+/* local functions */
+#ifndef NDEBUG // for asserts only
+static int arc_classify( Arc_ptr, int, REAL );
+#endif
+static enum i_result pwlarc_intersect( PwlArc *, int, REAL, int, int[3] );
+
+
+void
+Subdivider::partition( Bin & bin, Bin & left, Bin & intersections,
+ Bin & right, Bin & unknown, int param, REAL value )
+{
+ Bin headonleft, headonright, tailonleft, tailonright;
+
+ for( Arc_ptr jarc = bin.removearc(); jarc; jarc = bin.removearc() ) {
+
+ REAL tdiff = jarc->tail()[param] - value;
+ REAL hdiff = jarc->head()[param] - value;
+
+ if( tdiff > 0.0 ) {
+ if( hdiff > 0.0 ) {
+ right.addarc( jarc );
+ } else if( hdiff == 0.0 ) {
+ tailonright.addarc( jarc );
+ } else {
+ Arc_ptr jtemp;
+ switch( arc_split(jarc, param, value, 0) ) {
+ case 2:
+ tailonright.addarc( jarc );
+ headonleft.addarc( jarc->next );
+ break;
+ case 31:
+ assert( jarc->head()[param] > value );
+ right.addarc( jarc );
+ tailonright.addarc( jtemp = jarc->next );
+ headonleft.addarc( jtemp->next );
+ break;
+ case 32:
+ assert( jarc->head()[param] <= value );
+ tailonright .addarc( jarc );
+ headonleft.addarc( jtemp = jarc->next );
+ left.addarc( jtemp->next );
+ break;
+ case 4:
+ right.addarc( jarc );
+ tailonright.addarc( jtemp = jarc->next );
+ headonleft.addarc( jtemp = jtemp->next );
+ left.addarc( jtemp->next );
+ }
+ }
+ } else if( tdiff == 0.0 ) {
+ if( hdiff > 0.0 ) {
+ headonright.addarc( jarc );
+ } else if( hdiff == 0.0 ) {
+ unknown.addarc( jarc );
+ } else {
+ headonleft.addarc( jarc );
+ }
+ } else {
+ if( hdiff > 0.0 ) {
+ Arc_ptr jtemp;
+ switch( arc_split(jarc, param, value, 1) ) {
+ case 2:
+ tailonleft.addarc( jarc );
+ headonright.addarc( jarc->next );
+ break;
+ case 31:
+ assert( jarc->head()[param] < value );
+ left.addarc( jarc );
+ tailonleft.addarc( jtemp = jarc->next );
+ headonright.addarc( jtemp->next );
+ break;
+ case 32:
+ assert( jarc->head()[param] >= value );
+ tailonleft.addarc( jarc );
+ headonright.addarc( jtemp = jarc->next );
+ right.addarc( jtemp->next );
+ break;
+ case 4:
+ left.addarc( jarc );
+ tailonleft.addarc( jtemp = jarc->next );
+ headonright.addarc( jtemp = jtemp->next );
+ right.addarc( jtemp->next );
+ }
+ } else if( hdiff == 0.0 ) {
+ tailonleft.addarc( jarc );
+ } else {
+ left.addarc( jarc );
+ }
+ }
+ }
+ if( param == 0 ) {
+ classify_headonleft_s( headonleft, intersections, left, value );
+ classify_tailonleft_s( tailonleft, intersections, left, value );
+ classify_headonright_s( headonright, intersections, right, value );
+ classify_tailonright_s( tailonright, intersections, right, value );
+ } else {
+ classify_headonleft_t( headonleft, intersections, left, value );
+ classify_tailonleft_t( tailonleft, intersections, left, value );
+ classify_headonright_t( headonright, intersections, right, value );
+ classify_tailonright_t( tailonright, intersections, right, value );
+ }
+}
+
+inline static void
+vert_interp( TrimVertex *n, TrimVertex *l, TrimVertex *r, int p, REAL val )
+{
+ assert( val > l->param[p]);
+ assert( val < r->param[p]);
+
+ n->nuid = l->nuid;
+
+ n->param[p] = val;
+ if( l->param[1-p] != r->param[1-p] ) {
+ REAL ratio = (val - l->param[p]) / (r->param[p] - l->param[p]);
+ n->param[1-p] = l->param[1-p] +
+ ratio * (r->param[1-p] - l->param[1-p]);
+ } else {
+ n->param[1-p] = l->param[1-p];
+ }
+}
+
+int
+Subdivider::arc_split( Arc_ptr jarc, int param, REAL value, int dir )
+{
+ int maxvertex = jarc->pwlArc->npts;
+ Arc_ptr jarc1;
+ TrimVertex* v = jarc->pwlArc->pts;
+
+ int loc[3];
+ switch( pwlarc_intersect( jarc->pwlArc, param, value, dir, loc ) ) {
+
+ // When the parameter value lands on a vertex, life is sweet
+ case INTERSECT_VERTEX: {
+ jarc1 = new(arcpool) Arc( jarc, new( pwlarcpool) PwlArc( maxvertex-loc[1], &v[loc[1]] ) );
+ jarc->pwlArc->npts = loc[1] + 1;
+ jarc1->next = jarc->next;
+ jarc1->next->prev = jarc1;
+ jarc->next = jarc1;
+ jarc1->prev = jarc;
+ assert(jarc->check() != 0);
+ return 2;
+ }
+
+ // When the parameter value intersects an edge, we have to
+ // interpolate a new vertex. There are special cases
+ // if the new vertex is adjacent to one or both of the
+ // endpoints of the arc.
+ case INTERSECT_EDGE: {
+ int i, j;
+ if( dir == 0 ) {
+ i = loc[0];
+ j = loc[2];
+ } else {
+ i = loc[2];
+ j = loc[0];
+ }
+
+#ifndef NOTDEF
+ // The split is between vertices at index j and i, in that
+ // order (j < i)
+
+ // JEB: This code is my idea of how to do the split without
+ // increasing the number of links. I'm doing this so that
+ // the is_rect routine can recognize rectangles created by
+ // subdivision. In exchange for simplifying the curve list,
+ // however, it costs in allocated space and vertex copies.
+
+ TrimVertex *newjunk = trimvertexpool.get(maxvertex -i+1 /*-j*/);
+ int k;
+ for(k=0; k<maxvertex-i; k++)
+ {
+ newjunk[k+1] = v[i+k];
+ newjunk[k+1].nuid = jarc->nuid;
+ }
+
+ TrimVertex *vcopy = trimvertexpool.get(maxvertex);
+ for(k=0; k<maxvertex; k++)
+ {
+ vcopy[k].param[0] = v[k].param[0];
+ vcopy[k].param[1] = v[k].param[1];
+ }
+ jarc->pwlArc->pts=vcopy;
+
+ v[i].nuid = jarc->nuid;
+ v[j].nuid = jarc->nuid;
+ vert_interp( &newjunk[0], &v[loc[0]], &v[loc[2]], param, value );
+
+ if( showingDegenerate() )
+ backend.triangle( &v[i], &newjunk[0], &v[j] );
+
+ vcopy[j+1].param[0]=newjunk[0].param[0];
+ vcopy[j+1].param[1]=newjunk[0].param[1];
+
+
+ jarc1 = new(arcpool) Arc( jarc,
+ new(pwlarcpool) PwlArc(maxvertex-i+1 , newjunk ) );
+
+ jarc->pwlArc->npts = j+2;
+ jarc1->next = jarc->next;
+ jarc1->next->prev = jarc1;
+ jarc->next = jarc1;
+ jarc1->prev = jarc;
+ assert(jarc->check() != 0);
+
+ return 2;
+#endif //not NOTDEF
+ // JEB: This is the original version:
+#ifdef NOTDEF
+ Arc_ptr jarc2, jarc3;
+
+ TrimVertex *newjunk = trimvertexpool.get(3);
+ v[i].nuid = jarc->nuid;
+ v[j].nuid = jarc->nuid;
+ newjunk[0] = v[j];
+ newjunk[2] = v[i];
+ vert_interp( &newjunk[1], &v[loc[0]], &v[loc[2]], param, value );
+
+ if( showingDegenerate() )
+ backend.triangle( &newjunk[2], &newjunk[1], &newjunk[0] );
+
+ // New vertex adjacent to both endpoints
+ if (maxvertex == 2) {
+ jarc1 = new(arcpool) Arc( jarc, new(pwlarcpool) PwlArc( 2, newjunk+1 ) );
+ jarc->pwlArc->npts = 2;
+ jarc->pwlArc->pts = newjunk;
+ jarc1->next = jarc->next;
+ jarc1->next->prev = jarc1;
+ jarc->next = jarc1;
+ jarc1->prev = jarc;
+ assert(jarc->check() != 0);
+
+ return 2;
+
+ // New vertex adjacent to ending point of arc
+ } else if (maxvertex - j == 2) {
+ jarc1 = new(arcpool) Arc( jarc, new(pwlarcpool) PwlArc( 2, newjunk ) );
+ jarc2 = new(arcpool) Arc( jarc, new(pwlarcpool) PwlArc( 2, newjunk+1 ) );
+ jarc->pwlArc->npts = maxvertex-1;
+ jarc2->next = jarc->next;
+ jarc2->next->prev = jarc2;
+ jarc->next = jarc1;
+ jarc1->prev = jarc;
+ jarc1->next = jarc2;
+ jarc2->prev = jarc1;
+ assert(jarc->check() != 0);
+ return 31;
+
+ // New vertex adjacent to starting point of arc
+ } else if (i == 1) {
+ jarc1 = new(arcpool) Arc( jarc, new(pwlarcpool) PwlArc( 2, newjunk+1 ) );
+ jarc2 = new(arcpool) Arc( jarc,
+ new(pwlarcpool) PwlArc( maxvertex-1, &jarc->pwlArc->pts[1] ) );
+ jarc->pwlArc->npts = 2;
+ jarc->pwlArc->pts = newjunk;
+ jarc2->next = jarc->next;
+ jarc2->next->prev = jarc2;
+ jarc->next = jarc1;
+ jarc1->prev = jarc;
+ jarc1->next = jarc2;
+ jarc2->prev = jarc1;
+ assert(jarc->check() != 0);
+ return 32;
+
+ // It's somewhere in the middle
+ } else {
+ jarc1 = new(arcpool) Arc( jarc, new(pwlarcpool) PwlArc( 2, newjunk ) );
+ jarc2 = new(arcpool) Arc( jarc, new(pwlarcpool) PwlArc( 2, newjunk+1 ) );
+ jarc3 = new(arcpool) Arc( jarc, new(pwlarcpool) PwlArc( maxvertex-i, v+i ) );
+ jarc->pwlArc->npts = j + 1;
+ jarc3->next = jarc->next;
+ jarc3->next->prev = jarc3;
+ jarc->next = jarc1;
+ jarc1->prev = jarc;
+ jarc1->next = jarc2;
+ jarc2->prev = jarc1;
+ jarc2->next = jarc3;
+ jarc3->prev = jarc2;
+ assert(jarc->check() != 0);
+ return 4;
+ }
+#endif // NOTDEF
+ }
+ default:
+ return -1; //picked -1 since it's not used
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * pwlarc_intersect - find intersection of pwlArc and isoparametric line
+ *----------------------------------------------------------------------------
+ */
+
+static enum i_result
+pwlarc_intersect(
+ PwlArc *pwlArc,
+ int param,
+ REAL value,
+ int dir,
+ int loc[3] )
+{
+ assert( pwlArc->npts > 0 );
+
+ if( dir ) {
+ TrimVertex *v = pwlArc->pts;
+ int imin = 0;
+ int imax = pwlArc->npts - 1;
+ assert( value > v[imin].param[param] );
+ assert( value < v[imax].param[param] );
+ while( (imax - imin) > 1 ) {
+ int imid = (imax + imin)/2;
+ if( v[imid].param[param] > value )
+ imax = imid;
+ else if( v[imid].param[param] < value )
+ imin = imid;
+ else {
+ loc[1] = imid;
+ return INTERSECT_VERTEX;
+ }
+ }
+ loc[0] = imin;
+ loc[2] = imax;
+ return INTERSECT_EDGE;
+ } else {
+ TrimVertex *v = pwlArc->pts;
+ int imax = 0;
+ int imin = pwlArc->npts - 1;
+ assert( value > v[imin].param[param] );
+ assert( value < v[imax].param[param] );
+ while( (imin - imax) > 1 ) {
+ int imid = (imax + imin)/2;
+ if( v[imid].param[param] > value )
+ imax = imid;
+ else if( v[imid].param[param] < value )
+ imin = imid;
+ else {
+ loc[1] = imid;
+ return INTERSECT_VERTEX;
+ }
+ }
+ loc[0] = imin;
+ loc[2] = imax;
+ return INTERSECT_EDGE;
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * arc_classify - determine which side of a line a jarc lies
+ *----------------------------------------------------------------------------
+ */
+
+#ifndef NDEBUG // for asserts only
+static int
+arc_classify( Arc_ptr jarc, int param, REAL value )
+{
+ REAL tdiff, hdiff;
+ if( param == 0 ) {
+ tdiff = jarc->tail()[0] - value;
+ hdiff = jarc->head()[0] - value;
+ } else {
+ tdiff = jarc->tail()[1] - value;
+ hdiff = jarc->head()[1] - value;
+ }
+
+ if( tdiff > 0.0 ) {
+ if( hdiff > 0.0 ) {
+ return 0x11;
+ } else if( hdiff == 0.0 ) {
+ return 0x12;
+ } else {
+ return 0x10;
+ }
+ } else if( tdiff == 0.0 ) {
+ if( hdiff > 0.0 ) {
+ return 0x21;
+ } else if( hdiff == 0.0 ) {
+ return 0x22;
+ } else {
+ return 0x20;
+ }
+ } else {
+ if( hdiff > 0.0 ) {
+ return 0x01;
+ } else if( hdiff == 0.0 ) {
+ return 0x02;
+ } else {
+ return 0;
+ }
+ }
+}
+#endif
+
+void
+Subdivider::classify_tailonleft_s( Bin& bin, Bin& in, Bin& out, REAL val )
+{
+ /* tail at left, head on line */
+ Arc_ptr j;
+
+ while( (j = bin.removearc()) != NULL ) {
+ assert( arc_classify( j, 0, val ) == 0x02 );
+ j->clearitail();
+
+ REAL diff = j->next->head()[0] - val;
+ if( diff > 0.0 ) {
+ in.addarc( j );
+ } else if( diff < 0.0 ) {
+ if( ccwTurn_sl( j, j->next ) )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ } else {
+ if( j->next->tail()[1] > j->next->head()[1] )
+ in.addarc(j);
+ else
+ out.addarc(j);
+ }
+ }
+}
+
+void
+Subdivider::classify_tailonleft_t( Bin& bin, Bin& in, Bin& out, REAL val )
+{
+ /* tail at left, head on line */
+ Arc_ptr j;
+
+ while( (j = bin.removearc()) != NULL ) {
+ assert( arc_classify( j, 1, val ) == 0x02 );
+ j->clearitail();
+
+ REAL diff = j->next->head()[1] - val;
+ if( diff > 0.0 ) {
+ in.addarc( j );
+ } else if( diff < 0.0 ) {
+ if( ccwTurn_tl( j, j->next ) )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ } else {
+ if (j->next->tail()[0] > j->next->head()[0] )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ }
+ }
+}
+
+void
+Subdivider::classify_headonleft_s( Bin& bin, Bin& in, Bin& out, REAL val )
+{
+ /* tail on line, head at left */
+ Arc_ptr j;
+
+ while( (j = bin.removearc()) != NULL ) {
+ assert( arc_classify( j, 0, val ) == 0x20 );
+
+ j->setitail();
+
+ REAL diff = j->prev->tail()[0] - val;
+ if( diff > 0.0 ) {
+ out.addarc( j );
+ } else if( diff < 0.0 ) {
+ if( ccwTurn_sl( j->prev, j ) )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ } else {
+ if( j->prev->tail()[1] > j->prev->head()[1] )
+ in.addarc( j );
+ else
+ out.addarc( j );
+ }
+ }
+}
+
+void
+Subdivider::classify_headonleft_t( Bin& bin, Bin& in, Bin& out, REAL val )
+{
+ /* tail on line, head at left */
+ Arc_ptr j;
+
+ while( (j = bin.removearc()) != NULL ) {
+ assert( arc_classify( j, 1, val ) == 0x20 );
+ j->setitail();
+
+ REAL diff = j->prev->tail()[1] - val;
+ if( diff > 0.0 ) {
+ out.addarc( j );
+ } else if( diff < 0.0 ) {
+ if( ccwTurn_tl( j->prev, j ) )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ } else {
+ if( j->prev->tail()[0] > j->prev->head()[0] )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ }
+ }
+}
+
+
+void
+Subdivider::classify_tailonright_s( Bin& bin, Bin& in, Bin& out, REAL val )
+{
+ /* tail at right, head on line */
+ Arc_ptr j;
+
+ while( (j = bin.removearc()) != NULL ) {
+ assert( arc_classify( j, 0, val ) == 0x12);
+
+ j->clearitail();
+
+ REAL diff = j->next->head()[0] - val;
+ if( diff > 0.0 ) {
+ if( ccwTurn_sr( j, j->next ) )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ } else if( diff < 0.0 ) {
+ in.addarc( j );
+ } else {
+ if( j->next->tail()[1] > j->next->head()[1] )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ }
+ }
+}
+
+void
+Subdivider::classify_tailonright_t( Bin& bin, Bin& in, Bin& out, REAL val )
+{
+ /* tail at right, head on line */
+ Arc_ptr j;
+
+ while( (j = bin.removearc()) != NULL ) {
+ assert( arc_classify( j, 1, val ) == 0x12);
+
+ j->clearitail();
+
+ REAL diff = j->next->head()[1] - val;
+ if( diff > 0.0 ) {
+ if( ccwTurn_tr( j, j->next ) )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ } else if( diff < 0.0 ) {
+ in.addarc( j );
+ } else {
+ if( j->next->tail()[0] > j->next->head()[0] )
+ in.addarc( j );
+ else
+ out.addarc( j );
+ }
+ }
+}
+
+void
+Subdivider::classify_headonright_s( Bin& bin, Bin& in, Bin& out, REAL val )
+{
+ /* tail on line, head at right */
+ Arc_ptr j;
+
+ while( (j = bin.removearc()) != NULL ) {
+ assert( arc_classify( j, 0, val ) == 0x21 );
+
+ j->setitail();
+
+ REAL diff = j->prev->tail()[0] - val;
+ if( diff > 0.0 ) {
+ if( ccwTurn_sr( j->prev, j ) )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ } else if( diff < 0.0 ) {
+ out.addarc( j );
+ } else {
+ if( j->prev->tail()[1] > j->prev->head()[1] )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ }
+ }
+}
+
+void
+Subdivider::classify_headonright_t( Bin& bin, Bin& in, Bin& out, REAL val )
+{
+ /* tail on line, head at right */
+ Arc_ptr j;
+
+ while( (j = bin.removearc()) != NULL ) {
+ assert( arc_classify( j, 1, val ) == 0x21 );
+
+ j->setitail();
+
+ REAL diff = j->prev->tail()[1] - val;
+ if( diff > 0.0 ) {
+ if( ccwTurn_tr( j->prev, j ) )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ } else if( diff < 0.0 ) {
+ out.addarc( j );
+ } else {
+ if( j->prev->tail()[0] > j->prev->head()[0] )
+ in.addarc( j );
+ else
+ out.addarc( j );
+ }
+ }
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/jarcloc.h b/src/glu/sgi/libnurbs/internals/jarcloc.h
new file mode 100644
index 00000000000..faaf454a063
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/jarcloc.h
@@ -0,0 +1,93 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * jarcloc.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/jarcloc.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __glujarcloc_h_
+#define __glujarcloc_h_
+
+#include "arc.h"
+
+class Jarcloc {
+private:
+ Arc_ptr arc;
+ TrimVertex *p;
+ TrimVertex *plast;
+public:
+ inline void init( Arc_ptr a, long first, long last ) { arc = a; p=&a->pwlArc->pts[first]; plast = &a->pwlArc->pts[last]; }
+ inline TrimVertex * getnextpt( void );
+ inline TrimVertex * getprevpt( void );
+ inline void reverse();
+};
+
+inline void
+Jarcloc::reverse()
+{
+ if( plast == &arc->pwlArc->pts[0] )
+ plast = &arc->pwlArc->pts[arc->pwlArc->npts - 1];
+ else
+ plast = &arc->pwlArc->pts[0];
+}
+
+inline TrimVertex *
+Jarcloc::getnextpt()
+{
+ assert( p <= plast );
+ if( p == plast ) {
+ arc = arc->next;
+ p = &arc->pwlArc->pts[0];
+ plast = &arc->pwlArc->pts[arc->pwlArc->npts - 1];
+ assert( p < plast );
+ }
+ return p++;
+}
+
+inline TrimVertex *
+Jarcloc::getprevpt()
+{
+ assert( p >= plast );
+ if( p == plast ) {
+ arc = arc->prev;
+ p = &arc->pwlArc->pts[arc->pwlArc->npts - 1];
+ plast = &arc->pwlArc->pts[0];
+ assert( p > plast );
+ }
+ return p--;
+}
+#endif /* __glujarcloc_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/knotvector.cc b/src/glu/sgi/libnurbs/internals/knotvector.cc
new file mode 100644
index 00000000000..50556f622dd
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/knotvector.cc
@@ -0,0 +1,139 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * knotvector.c++
+ *
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "knotvector.h"
+#include "defines.h"
+
+#ifdef __WATCOMC__
+#pragma warning 726 10
+#endif
+
+void Knotvector::init( long _knotcount, long _stride, long _order, INREAL *_knotlist )
+{
+ knotcount = _knotcount;
+ stride = _stride;
+ order = _order;
+ knotlist = new Knot[_knotcount];
+ assert( knotlist != 0 );
+
+ for( int i = 0; i != _knotcount; i++ )
+ knotlist[i] = (Knot) _knotlist[i];
+}
+
+Knotvector::Knotvector( void )
+{
+ knotlist = 0;
+}
+
+Knotvector::~Knotvector( void )
+{
+ if( knotlist ) delete[] knotlist;
+}
+
+int Knotvector::validate( void )
+{
+ /* kindex is used as an array index so subtract one first,
+ * this propagates throughout the code so study carefully */
+ long kindex = knotcount-1;
+
+ if( order < 1 || order > MAXORDER ) {
+ // spline order un-supported
+ return( 1 );
+ }
+
+ if( knotcount < (2 * order) ) {
+ // too few knots
+ return( 2 );
+ }
+
+ if( identical( knotlist[kindex-(order-1)], knotlist[order-1]) ) {
+ // valid knot range is empty
+ return( 3 );
+ }
+
+ for( long i = 0; i < kindex; i++)
+ if( knotlist[i] > knotlist[i+1] ) {
+ // decreasing knot sequence
+ return( 4 );
+ }
+
+ /* check for valid multiplicity */
+
+ /* kindex is currently the index of the last knot.
+ * In the next loop it is decremented to ignore the last knot
+ * and the loop stops when kindex is 2 so as to ignore the first
+ * knot as well. These knots are not used in computing
+ * knot multiplicities.
+ */
+
+ long multi = 1;
+ for( ; kindex >= 1; kindex-- ) {
+ if( knotlist[kindex] - knotlist[kindex-1] < TOLERANCE ) {
+ multi++;
+ continue;
+ }
+ if ( multi > order ) {
+ // knot multiplicity greater than order of spline
+ return( 5 );
+ }
+ multi = 1;
+ }
+
+ if ( multi > order ) {
+ // knot multiplicity greater than order of spline
+ return( 5 );
+ }
+
+ return 0;
+}
+
+void Knotvector::show( char *msg )
+{
+#ifndef NDEBUG
+ dprintf( "%s\n", msg );
+ dprintf( "order = %ld, count = %ld\n", order, knotcount );
+
+ for( int i=0; i<knotcount; i++ )
+ dprintf( "knot[%d] = %g\n", i, knotlist[i] );
+#endif
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/knotvector.h b/src/glu/sgi/libnurbs/internals/knotvector.h
new file mode 100644
index 00000000000..eee6424a50b
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/knotvector.h
@@ -0,0 +1,68 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * knotvector.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/knotvector.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __gluknotvector_h_
+#define __gluknotvector_h_
+
+#include "types.h"
+
+struct Knotvector { /* a knot vector */
+ Knotvector( void );
+ ~Knotvector( void );
+ void init( long, long, long, INREAL * );
+ int validate( void );
+ void show( char * );
+
+ long order; /* order of spline */
+ long knotcount; /* number of knots */
+ long stride; /* bytes between points */
+ Knot * knotlist; /* global knot vector */
+};
+
+/* tolerance to test knot coincidence */
+#define TOLERANCE 1.0e-5
+
+inline int
+identical( Knot x, Knot y )
+{
+ return ((x-y) < TOLERANCE) ? 1 : 0;
+}
+#endif /* __gluknotvector_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/mapdesc.cc b/src/glu/sgi/libnurbs/internals/mapdesc.cc
new file mode 100644
index 00000000000..56fb8a63bea
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/mapdesc.cc
@@ -0,0 +1,843 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * mapdesc.c++
+ *
+ * $Date: 2001/11/29 16:16:55 $ $Revision: 1.2 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/mapdesc.cc,v 1.2 2001/11/29 16:16:55 kschultz Exp $
+ */
+
+#include <stdio.h>
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "mystring.h"
+#include "mymath.h"
+#include "backend.h"
+#include "nurbsconsts.h"
+#include "mapdesc.h"
+
+Mapdesc::Mapdesc( long _type, int _israt, int _ncoords, Backend& b )
+ : backend( b )
+{
+ type = _type;
+ isrational = _israt;
+ ncoords = _ncoords;
+ hcoords = _ncoords + (_israt ? 0 : 1 );
+ inhcoords = _ncoords - (_israt ? 1 : 0 );
+ mask = ((1<<(inhcoords*2))-1);
+ next = 0;
+
+ assert( hcoords <= MAXCOORDS );
+ assert( inhcoords >= 1 );
+
+ pixel_tolerance = 1.0;
+ error_tolerance = 1.0;
+ bbox_subdividing = N_NOBBOXSUBDIVISION;
+ culling_method = N_NOCULLING;
+ sampling_method = N_NOSAMPLING;
+ clampfactor = N_NOCLAMPING;
+ minsavings = N_NOSAVINGSSUBDIVISION;
+ s_steps = 0.0;
+ t_steps = 0.0;
+ maxrate = ( s_steps < 0.0 ) ? 0.0 : s_steps;
+ maxsrate = ( s_steps < 0.0 ) ? 0.0 : s_steps;
+ maxtrate = ( t_steps < 0.0 ) ? 0.0 : t_steps;
+ identify( bmat );
+ identify( cmat );
+ identify( smat );
+ for( int i = 0; i != inhcoords; i++ )
+ bboxsize[i] = 1.0;
+}
+
+void
+Mapdesc::setBboxsize( INREAL *mat )
+{
+ for( int i = 0; i != inhcoords; i++ )
+ bboxsize[i] = (REAL) mat[i];
+}
+
+void
+Mapdesc::identify( REAL dest[MAXCOORDS][MAXCOORDS] )
+{
+ memset( dest, 0, sizeof( dest ) );
+ for( int i=0; i != hcoords; i++ )
+ dest[i][i] = 1.0;
+}
+
+void
+Mapdesc::surfbbox( REAL bb[2][MAXCOORDS] )
+{
+ backend.surfbbox( type, bb[0], bb[1] );
+}
+
+void
+Mapdesc::copy( REAL dest[MAXCOORDS][MAXCOORDS], long n, INREAL *src,
+ long rstride, long cstride )
+{
+ assert( n >= 0 );
+ for( int i=0; i != n; i++ )
+ for( int j=0; j != n; j++ )
+ dest[i][j] = src[i*rstride + j*cstride];
+}
+
+/*--------------------------------------------------------------------------
+ * copyPt - copy a homogeneous point
+ *--------------------------------------------------------------------------
+ */
+void
+Mapdesc::copyPt( REAL *d, REAL *s )
+{
+ assert( hcoords > 0 );
+ switch( hcoords ) {
+ case 4:
+ d[3] = s[3];
+ d[2] = s[2];
+ d[1] = s[1];
+ d[0] = s[0];
+ break;
+ case 3:
+ d[2] = s[2];
+ d[1] = s[1];
+ d[0] = s[0];
+ break;
+ case 2:
+ d[1] = s[1];
+ d[0] = s[0];
+ break;
+ case 1:
+ d[0] = s[0];
+ break;
+ case 5:
+ d[4] = s[4];
+ d[3] = s[3];
+ d[2] = s[2];
+ d[1] = s[1];
+ d[0] = s[0];
+ break;
+ default:
+ memcpy( d, s, hcoords * sizeof( REAL ) );
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * sumPt - compute affine combination of two homogeneous points
+ *--------------------------------------------------------------------------
+ */
+void
+Mapdesc::sumPt( REAL *dst, REAL *src1, REAL *src2, register REAL alpha, register REAL beta )
+{
+ assert( hcoords > 0 );
+ switch( hcoords ) {
+ case 4:
+ dst[3] = src1[3] * alpha + src2[3] * beta;
+ dst[2] = src1[2] * alpha + src2[2] * beta;
+ dst[1] = src1[1] * alpha + src2[1] * beta;
+ dst[0] = src1[0] * alpha + src2[0] * beta;
+ break;
+ case 3:
+ dst[2] = src1[2] * alpha + src2[2] * beta;
+ dst[1] = src1[1] * alpha + src2[1] * beta;
+ dst[0] = src1[0] * alpha + src2[0] * beta;
+ break;
+ case 2:
+ dst[1] = src1[1] * alpha + src2[1] * beta;
+ dst[0] = src1[0] * alpha + src2[0] * beta;
+ break;
+ case 1:
+ dst[0] = src1[0] * alpha + src2[0] * beta;
+ break;
+ case 5:
+ dst[4] = src1[4] * alpha + src2[4] * beta;
+ dst[3] = src1[3] * alpha + src2[3] * beta;
+ dst[2] = src1[2] * alpha + src2[2] * beta;
+ dst[1] = src1[1] * alpha + src2[1] * beta;
+ dst[0] = src1[0] * alpha + src2[0] * beta;
+ break;
+ default: {
+ for( int i = 0; i != hcoords; i++ )
+ dst[i] = src1[i] * alpha + src2[i] * beta;
+ }
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * clipbits - compute bit-vector indicating point/window position
+ * of a (transformed) homogeneous point
+ *--------------------------------------------------------------------------
+ */
+unsigned int
+Mapdesc::clipbits( REAL *p )
+{
+ assert( inhcoords >= 0 );
+ assert( inhcoords <= 3 );
+
+ register int nc = inhcoords;
+ register REAL pw = p[nc];
+ register REAL nw = -pw;
+ register unsigned int bits = 0;
+
+ if( pw == 0.0 ) return mask;
+
+ if( pw > 0.0 ) {
+ switch( nc ) {
+ case 3:
+ if( p[2] <= pw ) bits |= (1<<5);
+ if( p[2] >= nw ) bits |= (1<<4);
+ if( p[1] <= pw ) bits |= (1<<3);
+ if( p[1] >= nw ) bits |= (1<<2);
+ if( p[0] <= pw ) bits |= (1<<1);
+ if( p[0] >= nw ) bits |= (1<<0);
+ return bits;
+ case 2:
+ if( p[1] <= pw ) bits |= (1<<3);
+ if( p[1] >= nw ) bits |= (1<<2);
+ if( p[0] <= pw ) bits |= (1<<1);
+ if( p[0] >= nw ) bits |= (1<<0);
+ return bits;
+ case 1:
+ if( p[0] <= pw ) bits |= (1<<1);
+ if( p[0] >= nw ) bits |= (1<<0);
+ return bits;
+ default: {
+ int bit = 1;
+ for( int i=0; i<nc; i++ ) {
+ if( p[i] >= nw ) bits |= bit;
+ bit <<= 1;
+ if( p[i] <= pw ) bits |= bit;
+ bit <<= 1;
+ }
+ abort();
+ break;
+ }
+ }
+ } else {
+ switch( nc ) {
+ case 3:
+ if( p[2] <= nw ) bits |= (1<<5);
+ if( p[2] >= pw ) bits |= (1<<4);
+ if( p[1] <= nw ) bits |= (1<<3);
+ if( p[1] >= pw ) bits |= (1<<2);
+ if( p[0] <= nw ) bits |= (1<<1);
+ if( p[0] >= pw ) bits |= (1<<0);
+ return bits;
+ case 2:
+ if( p[1] <= nw ) bits |= (1<<3);
+ if( p[1] >= pw ) bits |= (1<<2);
+ if( p[0] <= nw ) bits |= (1<<1);
+ if( p[0] >= pw ) bits |= (1<<0);
+ return bits;
+ case 1:
+ if( p[0] <= nw ) bits |= (1<<1);
+ if( p[0] >= pw ) bits |= (1<<0);
+ return bits;
+ default: {
+ int bit = 1;
+ for( int i=0; i<nc; i++ ) {
+ if( p[i] >= pw ) bits |= bit;
+ bit <<= 1;
+ if( p[i] <= nw ) bits |= bit;
+ bit <<= 1;
+ }
+ abort();
+ break;
+ }
+ }
+ }
+ return bits;
+}
+
+/*--------------------------------------------------------------------------
+ * xformRational - transform a homogeneous point
+ *--------------------------------------------------------------------------
+ */
+void
+Mapdesc::xformRational( Maxmatrix mat, REAL *d, REAL *s )
+{
+ assert( hcoords >= 0 );
+
+ if( hcoords == 3 ) {
+ REAL x = s[0];
+ REAL y = s[1];
+ REAL z = s[2];
+ d[0] = x*mat[0][0]+y*mat[1][0]+z*mat[2][0];
+ d[1] = x*mat[0][1]+y*mat[1][1]+z*mat[2][1];
+ d[2] = x*mat[0][2]+y*mat[1][2]+z*mat[2][2];
+ } else if( hcoords == 4 ) {
+ REAL x = s[0];
+ REAL y = s[1];
+ REAL z = s[2];
+ REAL w = s[3];
+ d[0] = x*mat[0][0]+y*mat[1][0]+z*mat[2][0]+w*mat[3][0];
+ d[1] = x*mat[0][1]+y*mat[1][1]+z*mat[2][1]+w*mat[3][1];
+ d[2] = x*mat[0][2]+y*mat[1][2]+z*mat[2][2]+w*mat[3][2];
+ d[3] = x*mat[0][3]+y*mat[1][3]+z*mat[2][3]+w*mat[3][3];
+ } else {
+ for( int i=0; i != hcoords; i++ ) {
+ d[i] = 0;
+ for( int j = 0; j != hcoords; j++ )
+ d[i] += s[j] * mat[j][i];
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * xformNonrational - transform a inhomogeneous point to a homogeneous point
+ *--------------------------------------------------------------------------
+ */
+void
+Mapdesc::xformNonrational( Maxmatrix mat, REAL *d, REAL *s )
+{
+ if( inhcoords == 2 ) {
+ REAL x = s[0];
+ REAL y = s[1];
+ d[0] = x*mat[0][0]+y*mat[1][0]+mat[2][0];
+ d[1] = x*mat[0][1]+y*mat[1][1]+mat[2][1];
+ d[2] = x*mat[0][2]+y*mat[1][2]+mat[2][2];
+ } else if( inhcoords == 3 ) {
+ REAL x = s[0];
+ REAL y = s[1];
+ REAL z = s[2];
+ d[0] = x*mat[0][0]+y*mat[1][0]+z*mat[2][0]+mat[3][0];
+ d[1] = x*mat[0][1]+y*mat[1][1]+z*mat[2][1]+mat[3][1];
+ d[2] = x*mat[0][2]+y*mat[1][2]+z*mat[2][2]+mat[3][2];
+ d[3] = x*mat[0][3]+y*mat[1][3]+z*mat[2][3]+mat[3][3];
+ } else {
+ assert( inhcoords >= 0 );
+ for( int i=0; i != hcoords; i++ ) {
+ d[i] = mat[inhcoords][i];
+ for( int j = 0; j < inhcoords; j++ )
+ d[i] += s[j] * mat[j][i];
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * xformAndCullCheck - transform a set of points that may be EITHER
+ * homogeneous or inhomogeneous depending on the map description and
+ * check if they are either completely inside, completely outside,
+ * or intersecting the viewing frustrum.
+ *--------------------------------------------------------------------------
+ */
+int
+Mapdesc::xformAndCullCheck(
+ REAL *pts, int uorder, int ustride, int vorder, int vstride )
+{
+ assert( uorder > 0 );
+ assert( vorder > 0 );
+
+ unsigned int inbits = mask;
+ unsigned int outbits = 0;
+
+ REAL *p = pts;
+ for( REAL *pend = p + uorder * ustride; p != pend; p += ustride ) {
+ REAL *q = p;
+ for( REAL *qend = q + vorder * vstride; q != qend; q += vstride ) {
+ REAL cpts[MAXCOORDS];
+ xformCulling( cpts, q );
+ unsigned int bits = clipbits( cpts );
+ outbits |= bits;
+ inbits &= bits;
+ if( ( outbits == (unsigned int)mask ) && ( inbits != (unsigned int)mask ) ) return CULL_ACCEPT;
+ }
+ }
+
+ if( outbits != (unsigned int)mask ) {
+ return CULL_TRIVIAL_REJECT;
+ } else if( inbits == (unsigned int)mask ) {
+ return CULL_TRIVIAL_ACCEPT;
+ } else {
+ return CULL_ACCEPT;
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * cullCheck - check if a set of homogeneous transformed points are
+ * either completely inside, completely outside,
+ * or intersecting the viewing frustrum.
+ *--------------------------------------------------------------------------
+ */
+int
+Mapdesc::cullCheck( REAL *pts, int uorder, int ustride, int vorder, int vstride )
+{
+ unsigned int inbits = mask;
+ unsigned int outbits = 0;
+
+ REAL *p = pts;
+ for( REAL *pend = p + uorder * ustride; p != pend; p += ustride ) {
+ REAL *q = p;
+ for( REAL *qend = q + vorder * vstride; q != qend; q += vstride ) {
+ unsigned int bits = clipbits( q );
+ outbits |= bits;
+ inbits &= bits;
+ if( ( outbits == (unsigned int)mask ) && ( inbits != (unsigned int)mask ) ) return CULL_ACCEPT;
+ }
+ }
+
+ if( outbits != (unsigned int)mask ) {
+ return CULL_TRIVIAL_REJECT;
+ } else if( inbits == (unsigned int)mask ) {
+ return CULL_TRIVIAL_ACCEPT;
+ } else {
+ return CULL_ACCEPT;
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * cullCheck - check if a set of homogeneous transformed points are
+ * either completely inside, completely outside,
+ * or intersecting the viewing frustrum.
+ *--------------------------------------------------------------------------
+ */
+int
+Mapdesc::cullCheck( REAL *pts, int order, int stride )
+{
+ unsigned int inbits = mask;
+ unsigned int outbits = 0;
+
+ REAL *p = pts;
+ for( REAL *pend = p + order * stride; p != pend; p += stride ) {
+ unsigned int bits = clipbits( p );
+ outbits |= bits;
+ inbits &= bits;
+ if( ( outbits == (unsigned int)mask ) && ( inbits != (unsigned int)mask ) ) return CULL_ACCEPT;
+ }
+
+ if( outbits != (unsigned int)mask ) {
+ return CULL_TRIVIAL_REJECT;
+ } else if( inbits == (unsigned int)mask ) {
+ return CULL_TRIVIAL_ACCEPT;
+ } else {
+ return CULL_ACCEPT;
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * xformSampling - transform a set of points that may be EITHER
+ * homogeneous or inhomogeneous depending on the map description
+ * into sampling space
+ *--------------------------------------------------------------------------
+ */
+void
+Mapdesc::xformSampling( REAL *pts, int order, int stride, REAL *sp, int outstride )
+{
+ xformMat( smat, pts, order, stride, sp, outstride );
+}
+
+void
+Mapdesc::xformBounding( REAL *pts, int order, int stride, REAL *sp, int outstride )
+{
+ xformMat( bmat, pts, order, stride, sp, outstride );
+}
+
+/*--------------------------------------------------------------------------
+ * xformCulling - transform a set of points that may be EITHER
+ * homogeneous or inhomogeneous depending on the map description
+ * into culling space
+ *--------------------------------------------------------------------------
+ */
+void
+Mapdesc::xformCulling( REAL *pts, int order, int stride, REAL *cp, int outstride )
+{
+ xformMat( cmat, pts, order, stride, cp, outstride );
+}
+
+/*--------------------------------------------------------------------------
+ * xformCulling - transform a set of points that may be EITHER
+ * homogeneous or inhomogeneous depending on the map description
+ * into culling space
+ *--------------------------------------------------------------------------
+ */
+void
+Mapdesc::xformCulling( REAL *pts,
+ int uorder, int ustride,
+ int vorder, int vstride,
+ REAL *cp, int outustride, int outvstride )
+{
+ xformMat( cmat, pts, uorder, ustride, vorder, vstride, cp, outustride, outvstride );
+}
+
+/*--------------------------------------------------------------------------
+ * xformSampling - transform a set of points that may be EITHER
+ * homogeneous or inhomogeneous depending on the map description
+ * into sampling space
+ *--------------------------------------------------------------------------
+ */
+void
+Mapdesc::xformSampling( REAL *pts,
+ int uorder, int ustride,
+ int vorder, int vstride,
+ REAL *sp, int outustride, int outvstride )
+{
+ xformMat( smat, pts, uorder, ustride, vorder, vstride, sp, outustride, outvstride );
+}
+
+void
+Mapdesc::xformBounding( REAL *pts,
+ int uorder, int ustride,
+ int vorder, int vstride,
+ REAL *sp, int outustride, int outvstride )
+{
+ xformMat( bmat, pts, uorder, ustride, vorder, vstride, sp, outustride, outvstride );
+}
+
+void
+Mapdesc::xformMat(
+ Maxmatrix mat,
+ REAL * pts,
+ int order,
+ int stride,
+ REAL * cp,
+ int outstride )
+{
+ if( isrational ) {
+ REAL *pend = pts + order * stride;
+ for( REAL *p = pts ; p != pend; p += stride ) {
+ xformRational( mat, cp, p );
+ cp += outstride;
+ }
+ } else {
+ REAL *pend = pts + order * stride;
+ for( REAL *p = pts ; p != pend; p += stride ) {
+ xformNonrational( mat, cp, p );
+ cp += outstride;
+ }
+ }
+}
+
+void
+Mapdesc::xformMat( Maxmatrix mat, REAL *pts,
+ int uorder, int ustride,
+ int vorder, int vstride,
+ REAL *cp, int outustride, int outvstride )
+{
+ if( isrational ) {
+ REAL *pend = pts + uorder * ustride;
+ for( REAL *p = pts ; p != pend; p += ustride ) {
+ REAL *cpts2 = cp;
+ REAL *qend = p + vorder * vstride;
+ for( REAL *q = p; q != qend; q += vstride ) {
+ xformRational( mat, cpts2, q );
+ cpts2 += outvstride;
+ }
+ cp += outustride;
+ }
+ } else {
+ REAL *pend = pts + uorder * ustride;
+ for( REAL *p = pts ; p != pend; p += ustride ) {
+ REAL *cpts2 = cp;
+ REAL *qend = p + vorder * vstride;
+ for( REAL *q = p; q != qend; q += vstride ) {
+ xformNonrational( mat, cpts2, q );
+ cpts2 += outvstride;
+ }
+ cp += outustride;
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * subdivide - subdivide a curve along an isoparametric line
+ *--------------------------------------------------------------------------
+ */
+
+void
+Mapdesc::subdivide( REAL *src, REAL *dst, REAL v, int stride, int order )
+{
+ REAL mv = 1.0 - v;
+
+ for( REAL *send=src+stride*order; src!=send; send-=stride, dst+=stride ) {
+ copyPt( dst, src );
+ REAL *qpnt = src + stride;
+ for( REAL *qp=src; qpnt!=send; qp=qpnt, qpnt+=stride )
+ sumPt( qp, qp, qpnt, mv, v );
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * subdivide - subdivide a patch along an isoparametric line
+ *--------------------------------------------------------------------------
+ */
+
+void
+Mapdesc::subdivide( REAL *src, REAL *dst, REAL v,
+ int so, int ss, int to, int ts )
+{
+ REAL mv = 1.0 - v;
+
+ for( REAL *slast = src+ss*so; src != slast; src += ss, dst += ss ) {
+ REAL *sp = src;
+ REAL *dp = dst;
+ for( REAL *send = src+ts*to; sp != send; send -= ts, dp += ts ) {
+ copyPt( dp, sp );
+ REAL *qp = sp;
+ for( REAL *qpnt = sp+ts; qpnt != send; qp = qpnt, qpnt += ts )
+ sumPt( qp, qp, qpnt, mv, v );
+ }
+ }
+}
+
+
+#define sign(x) ((x > 0) ? 1 : ((x < 0.0) ? -1 : 0))
+
+/*--------------------------------------------------------------------------
+ * project - project a set of homogeneous coordinates into inhomogeneous ones
+ *--------------------------------------------------------------------------
+ */
+int
+Mapdesc::project( REAL *src, int rstride, int cstride,
+ REAL *dest, int trstride, int tcstride,
+ int nrows, int ncols )
+{
+ int s = sign( src[inhcoords] );
+ REAL *rlast = src + nrows * rstride;
+ REAL *trptr = dest;
+ for( REAL *rptr=src; rptr != rlast; rptr+=rstride, trptr+=trstride ) {
+ REAL *clast = rptr + ncols * cstride;
+ REAL *tcptr = trptr;
+ for( REAL *cptr = rptr; cptr != clast; cptr+=cstride, tcptr+=tcstride ) {
+ REAL *coordlast = cptr + inhcoords;
+ if( sign( *coordlast ) != s ) return 0;
+ REAL *tcoord = tcptr;
+ for( REAL *coord = cptr; coord != coordlast; coord++, tcoord++ ) {
+ *tcoord = *coord / *coordlast;
+ }
+ }
+ }
+ return 1;
+}
+
+/*--------------------------------------------------------------------------
+ * project - project a set of homogeneous coordinates into inhomogeneous ones
+ *--------------------------------------------------------------------------
+ */
+int
+Mapdesc::project( REAL *src, int stride, REAL *dest, int tstride, int ncols )
+{
+ int s = sign( src[inhcoords] );
+
+ REAL *clast = src + ncols * stride;
+ for( REAL *cptr = src, *tcptr = dest; cptr != clast; cptr+=stride, tcptr+=tstride ) {
+ REAL *coordlast = cptr + inhcoords;
+ if( sign( *coordlast ) != s ) return 0;
+ for( REAL *coord = cptr, *tcoord = tcptr; coord != coordlast; coord++, tcoord++ )
+ *tcoord = *coord / *coordlast;
+ }
+
+ return 1;
+}
+
+int
+Mapdesc::bboxTooBig(
+ REAL *p,
+ int rstride,
+ int cstride,
+ int nrows,
+ int ncols,
+ REAL bb[2][MAXCOORDS] )
+{
+ REAL bbpts[MAXORDER][MAXORDER][MAXCOORDS];
+ const int trstride = sizeof(bbpts[0]) / sizeof(REAL);
+ const int tcstride = sizeof(bbpts[0][0]) / sizeof(REAL);
+
+ // points have been transformed, therefore they are homogeneous
+ // project points
+ int val = project( p, rstride, cstride,
+ &bbpts[0][0][0], trstride, tcstride, nrows, ncols );
+ if( val == 0 ) return -1;
+
+ // compute bounding box
+ bbox( bb, &bbpts[0][0][0], trstride, tcstride, nrows, ncols );
+
+ // find out if bounding box can't fit in unit cube
+ if( bbox_subdividing == N_BBOXROUND ) {
+ for( int k=0; k != inhcoords; k++ )
+ if( ceilf(bb[1][k]) - floorf(bb[0][k]) > bboxsize[k] ) return 1;
+ } else {
+ for( int k=0; k != inhcoords; k++ )
+ if( bb[1][k] - bb[0][k] > bboxsize[k] ) return 1;
+ }
+ return 0;
+}
+
+void
+Mapdesc::bbox(
+ REAL bb[2][MAXCOORDS],
+ REAL *p,
+ int rstride,
+ int cstride,
+ int nrows,
+ int ncols )
+{
+ int k;
+ for( k=0; k != inhcoords; k++ )
+ bb[0][k] = bb[1][k] = p[k];
+
+ for( int i=0; i != nrows; i++ )
+ for( int j=0; j != ncols; j++ )
+ for( k=0; k != inhcoords; k++ ) {
+ REAL x = p[i*rstride + j*cstride + k];
+ if( x < bb[0][k] ) bb[0][k] = x;
+ else if( x > bb[1][k] ) bb[1][k] = x;
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * calcVelocityRational - calculate upper bound on first partial derivative
+ * of a homogeneous set of points and bounds on each row of points.
+ *--------------------------------------------------------------------------
+ */
+REAL
+Mapdesc::calcVelocityRational( REAL *p, int stride, int ncols )
+{
+ REAL tmp[MAXORDER][MAXCOORDS];
+
+ assert( ncols <= MAXORDER );
+
+ const int tstride = sizeof(tmp[0]) / sizeof(REAL);
+
+ if( project( p, stride, &tmp[0][0], tstride, ncols ) ) {
+ return calcPartialVelocity( &tmp[0][0], tstride, ncols, 1, 1.0 );
+ } else { /* XXX */
+ return calcPartialVelocity( &tmp[0][0], tstride, ncols, 1, 1.0 );
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * calcVelocityNonrational - calculate upper bound on first partial
+ * derivative of a inhomogeneous set of points.
+ *--------------------------------------------------------------------------
+ */
+REAL
+Mapdesc::calcVelocityNonrational( REAL *pts, int stride, int ncols )
+{
+ return calcPartialVelocity( pts, stride, ncols, 1, 1.0 );
+}
+
+int
+Mapdesc::isProperty( long property )
+{
+ switch ( property ) {
+ case N_PIXEL_TOLERANCE:
+ case N_ERROR_TOLERANCE:
+ case N_CULLING:
+ case N_BBOX_SUBDIVIDING:
+ case N_S_STEPS:
+ case N_T_STEPS:
+ case N_SAMPLINGMETHOD:
+ case N_CLAMPFACTOR:
+ case N_MINSAVINGS:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+REAL
+Mapdesc::getProperty( long property )
+{
+ switch ( property ) {
+ case N_PIXEL_TOLERANCE:
+ return pixel_tolerance;
+ case N_ERROR_TOLERANCE:
+ return error_tolerance;
+ case N_CULLING:
+ return culling_method;
+ case N_BBOX_SUBDIVIDING:
+ return bbox_subdividing;
+ case N_S_STEPS:
+ return s_steps;
+ case N_T_STEPS:
+ return t_steps;
+ case N_SAMPLINGMETHOD:
+ return sampling_method;
+ case N_CLAMPFACTOR:
+ return clampfactor;
+ case N_MINSAVINGS:
+ return minsavings;
+ default:
+ abort();
+ return -1; //not necessary, needed to shut up compiler
+ }
+}
+
+void
+Mapdesc::setProperty( long property, REAL value )
+{
+
+ switch ( property ) {
+ case N_PIXEL_TOLERANCE:
+ pixel_tolerance = value;
+ break;
+ case N_ERROR_TOLERANCE:
+ error_tolerance = value;
+ break;
+ case N_CULLING:
+ culling_method = value;
+ break;
+ case N_BBOX_SUBDIVIDING:
+ if( value <= 0.0 ) value = N_NOBBOXSUBDIVISION;
+ bbox_subdividing = value;
+ break;
+ case N_S_STEPS:
+ if( value < 0.0 ) value = 0.0;
+ s_steps = value;
+ maxrate = ( value < 0.0 ) ? 0.0 : value;
+ maxsrate = ( value < 0.0 ) ? 0.0 : value;
+ break;
+ case N_T_STEPS:
+ if( value < 0.0 ) value = 0.0;
+ t_steps = value;
+ maxtrate = ( value < 0.0 ) ? 0.0 : value;
+ break;
+ case N_SAMPLINGMETHOD:
+ sampling_method = value;
+ break;
+ case N_CLAMPFACTOR:
+ if( value <= 0.0 ) value = N_NOCLAMPING;
+ clampfactor = value;
+ break;
+ case N_MINSAVINGS:
+ if( value <= 0.0 ) value = N_NOSAVINGSSUBDIVISION;
+ minsavings = value;
+ break;
+ default:
+ abort();
+ break;
+ }
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/mapdesc.h b/src/glu/sgi/libnurbs/internals/mapdesc.h
new file mode 100644
index 00000000000..ac4c476e963
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/mapdesc.h
@@ -0,0 +1,277 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * mapdesc.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/mapdesc.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __glumapdesc_h_
+#define __glumapdesc_h_
+
+#include "mystdio.h"
+#include "types.h"
+#include "defines.h"
+#include "bufpool.h"
+#include "nurbsconsts.h"
+
+typedef REAL Maxmatrix[MAXCOORDS][MAXCOORDS];
+
+class Backend;
+
+class Mapdesc : public PooledObj {
+ friend class Maplist;
+
+public:
+ Mapdesc( long, int, int, Backend & );
+ int isProperty( long );
+ REAL getProperty( long );
+ void setProperty( long, REAL );
+ int isConstantSampling( void );
+ int isDomainSampling( void );
+ int isRangeSampling( void );
+ int isSampling( void );
+ int isParametricDistanceSampling( void );
+ int isObjectSpaceParaSampling( void );
+ int isObjectSpacePathSampling( void );
+ int isSurfaceAreaSampling( void );
+ int isPathLengthSampling( void );
+ int isCulling( void );
+ int isBboxSubdividing( void );
+ long getType( void );
+
+ /* curve routines */
+ void subdivide( REAL *, REAL *, REAL, int, int );
+ int cullCheck( REAL *, int, int );
+ void xformBounding( REAL *, int, int, REAL *, int );
+ void xformCulling( REAL *, int, int, REAL *, int );
+ void xformSampling( REAL *, int, int, REAL *, int );
+ void xformMat( Maxmatrix, REAL *, int, int, REAL *, int );
+ REAL calcPartialVelocity ( REAL *, int, int, int, REAL );
+ int project( REAL *, int, REAL *, int, int );
+ REAL calcVelocityRational( REAL *, int, int );
+ REAL calcVelocityNonrational( REAL *, int, int );
+
+ /* surface routines */
+ void subdivide( REAL *, REAL *, REAL, int, int, int, int );
+ int cullCheck( REAL *, int, int, int, int );
+ void xformBounding( REAL *, int, int, int, int, REAL *, int, int );
+ void xformCulling( REAL *, int, int, int, int, REAL *, int, int );
+ void xformSampling( REAL *, int, int, int, int, REAL *, int, int );
+ void xformMat( Maxmatrix, REAL *, int, int, int, int, REAL *, int, int );
+ REAL calcPartialVelocity ( REAL *, REAL *, int, int, int, int, int, int, REAL, REAL, int );
+ int project( REAL *, int, int, REAL *, int, int, int, int);
+ void surfbbox( REAL bb[2][MAXCOORDS] );
+
+ int bboxTooBig( REAL *, int, int, int, int, REAL [2][MAXCOORDS] );
+ int xformAndCullCheck( REAL *, int, int, int, int );
+
+ void identify( REAL[MAXCOORDS][MAXCOORDS] );
+ void setBboxsize( INREAL *);
+ inline void setBmat( INREAL*, long, long );
+ inline void setCmat( INREAL*, long, long );
+ inline void setSmat( INREAL*, long, long );
+ inline int isRational( void );
+ inline int getNcoords( void );
+
+ REAL pixel_tolerance; /* pathlength sampling tolerance */
+ REAL error_tolerance; /* parametric error sampling tolerance*/
+ REAL object_space_error_tolerance; /* object space tess*/
+ REAL clampfactor;
+ REAL minsavings;
+ REAL maxrate;
+ REAL maxsrate;
+ REAL maxtrate;
+ REAL bboxsize[MAXCOORDS];
+
+private:
+ long type;
+ int isrational;
+ int ncoords;
+ int hcoords;
+ int inhcoords;
+ int mask;
+ Maxmatrix bmat;
+ Maxmatrix cmat;
+ Maxmatrix smat;
+ REAL s_steps; /* max samples in s direction */
+ REAL t_steps; /* max samples in t direction */
+ REAL sampling_method;
+ REAL culling_method; /* check for culling */
+ REAL bbox_subdividing;
+ Mapdesc * next;
+ Backend & backend;
+
+ void bbox( REAL [2][MAXCOORDS], REAL *, int, int, int, int );
+ REAL maxDifference( int, REAL *, int );
+ static void copy( Maxmatrix, long, INREAL *, long, long );
+
+ /* individual control point routines */
+ static void transform4d( float[4], float[4], float[4][4] );
+ static void multmatrix4d ( float[4][4], const float[4][4],
+ const float[4][4] );
+ void copyPt( REAL *, REAL * );
+ void sumPt( REAL *, REAL *, REAL *, REAL, REAL );
+ void xformSampling( REAL *, REAL * );
+ void xformCulling( REAL *, REAL * );
+ void xformRational( Maxmatrix, REAL *, REAL * );
+ void xformNonrational( Maxmatrix, REAL *, REAL * );
+ unsigned int clipbits( REAL * );
+};
+
+inline void
+Mapdesc::setBmat( INREAL *mat, long rstride, long cstride )
+{
+ copy( bmat, hcoords, mat, rstride, cstride );
+}
+
+inline void
+Mapdesc::setCmat( INREAL *mat, long rstride, long cstride )
+{
+ copy( cmat, hcoords, mat, rstride, cstride );
+}
+
+inline void
+Mapdesc::setSmat( INREAL *mat, long rstride, long cstride )
+{
+ copy( smat, hcoords, mat, rstride, cstride );
+}
+
+inline long
+Mapdesc::getType( void )
+{
+ return type;
+}
+
+inline void
+Mapdesc::xformCulling( REAL *d, REAL *s )
+{
+ if( isrational )
+ xformRational( cmat, d, s );
+ else
+ xformNonrational( cmat, d, s );
+}
+
+inline void
+Mapdesc::xformSampling( REAL *d, REAL *s )
+{
+ if( isrational )
+ xformRational( smat, d, s );
+ else
+ xformNonrational( smat, d, s );
+}
+
+inline int
+Mapdesc::isRational( void )
+{
+ return isrational ? 1 : 0;
+}
+
+inline int
+Mapdesc::getNcoords( void )
+{
+ return ncoords;
+}
+
+inline int
+Mapdesc::isConstantSampling( void )
+{
+ return ((sampling_method == N_FIXEDRATE) ? 1 : 0);
+}
+
+inline int
+Mapdesc::isDomainSampling( void )
+{
+ return ((sampling_method == N_DOMAINDISTANCE) ? 1 : 0);
+}
+
+inline int
+Mapdesc::isParametricDistanceSampling( void )
+{
+ return ((sampling_method == N_PARAMETRICDISTANCE) ? 1 : 0);
+}
+
+inline int
+Mapdesc::isObjectSpaceParaSampling( void )
+{
+ return ((sampling_method == N_OBJECTSPACE_PARA) ? 1 : 0);
+}
+
+inline int
+Mapdesc::isObjectSpacePathSampling( void )
+{
+ return ((sampling_method == N_OBJECTSPACE_PATH) ? 1 : 0);
+}
+
+inline int
+Mapdesc::isSurfaceAreaSampling( void )
+{
+ return ((sampling_method == N_SURFACEAREA) ? 1 : 0);
+}
+
+inline int
+Mapdesc::isPathLengthSampling( void )
+{
+ return ((sampling_method == N_PATHLENGTH) ? 1 : 0);
+}
+
+inline int
+Mapdesc::isRangeSampling( void )
+{
+ return ( isParametricDistanceSampling() || isPathLengthSampling() ||
+ isSurfaceAreaSampling() ||
+ isObjectSpaceParaSampling() ||
+ isObjectSpacePathSampling());
+}
+
+inline int
+Mapdesc::isSampling( void )
+{
+ return isRangeSampling() || isConstantSampling() || isDomainSampling();
+}
+
+inline int
+Mapdesc::isCulling( void )
+{
+ return ((culling_method != N_NOCULLING) ? 1 : 0);
+}
+
+inline int
+Mapdesc::isBboxSubdividing( void )
+{
+ return ((bbox_subdividing != N_NOBBOXSUBDIVISION) ? 1 : 0);
+}
+#endif /* __glumapdesc_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/mapdescv.cc b/src/glu/sgi/libnurbs/internals/mapdescv.cc
new file mode 100644
index 00000000000..380bcfe171f
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/mapdescv.cc
@@ -0,0 +1,245 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * mapdescv.c++
+ *
+ * $Date: 2004/05/12 15:29:36 $ $Revision: 1.3 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/mapdescv.cc,v 1.3 2004/05/12 15:29:36 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "mystring.h"
+#include "mymath.h"
+#include "nurbsconsts.h"
+#include "mapdesc.h"
+
+/*--------------------------------------------------------------------------
+ * calcPartialVelocity - calculate maximum magnitude of a given partial
+ * derivative
+ *--------------------------------------------------------------------------
+ */
+REAL
+Mapdesc::calcPartialVelocity (
+ REAL *p,
+ int stride,
+ int ncols,
+ int partial,
+ REAL range )
+{
+ REAL tmp[MAXORDER][MAXCOORDS];
+ REAL mag[MAXORDER];
+
+ assert( ncols <= MAXORDER );
+
+ int j, k, t;
+ // copy inhomogeneous control points into temporary array
+ for( j=0; j != ncols; j++ )
+ for( k=0; k != inhcoords; k++ )
+ tmp[j][k] = p[j*stride + k];
+
+ for( t=0; t != partial; t++ )
+ for( j=0; j != ncols-t-1; j++ )
+ for( k=0; k != inhcoords; k++ )
+ tmp[j][k] = tmp[j+1][k] - tmp[j][k];
+
+ // compute magnitude and store in mag array
+ for( j=0; j != ncols-partial; j++ ) {
+ mag[j] = 0.0;
+ for( k=0; k != inhcoords; k++ )
+ mag[j] += tmp[j][k] * tmp[j][k];
+ }
+
+ // compute scale factor
+ REAL fac = 1;
+ REAL invt = 1.0 / range;
+ for( t = ncols-1; t != ncols-1-partial; t-- )
+ fac *= t * invt;
+
+ // compute max magnitude of all entries in array
+ REAL max = 0.0;
+ for( j=0; j != ncols-partial; j++ )
+ if( mag[j] > max ) max = mag[j];
+ max = fac * sqrtf( (float) max );
+
+ return max;
+}
+
+/*--------------------------------------------------------------------------
+ * calcPartialVelocity - calculate maximum magnitude of a given partial
+ * derivative
+ *--------------------------------------------------------------------------
+ */
+REAL
+Mapdesc::calcPartialVelocity (
+ REAL *dist,
+ REAL *p,
+ int rstride,
+ int cstride,
+ int nrows,
+ int ncols,
+ int spartial,
+ int tpartial,
+ REAL srange,
+ REAL trange,
+ int side )
+{
+ REAL tmp[MAXORDER][MAXORDER][MAXCOORDS];
+ REAL mag[MAXORDER][MAXORDER];
+
+ assert( nrows <= MAXORDER );
+ assert( ncols <= MAXORDER );
+
+ REAL *tp = &tmp[0][0][0];
+ REAL *mp = &mag[0][0];
+ const int istride = sizeof( tmp[0]) / sizeof( tmp[0][0][0] );
+ const int jstride = sizeof( tmp[0][0]) / sizeof( tmp[0][0][0] );
+ /*
+ const int kstride = sizeof( tmp[0][0][0]) / sizeof( tmp[0][0][0] );
+ */
+ const int mistride = sizeof( mag[0]) / sizeof( mag[0][0] );
+ const int mjstride = sizeof( mag[0][0]) / sizeof( mag[0][0] );
+ const int idist = nrows * istride;
+ const int jdist = ncols * jstride;
+ /*
+ const int kdist = inhcoords * kstride;
+ */
+ const int id = idist - spartial * istride;
+ const int jd = jdist - tpartial * jstride;
+
+ {
+ // copy control points
+ REAL *ti = tp;
+ REAL *qi = p;
+ REAL *til = tp + idist;
+ for( ; ti != til; ) {
+ REAL *tj = ti;
+ REAL *qj = qi;
+ REAL *tjl = ti + jdist;
+ for( ; tj != tjl; ) {
+ for( int k=0; k != inhcoords; k++ ) {
+ tj[k] = qj[k];
+ }
+ tj += jstride;
+ qj += cstride;
+ }
+ ti += istride;
+ qi += rstride;
+ }
+ }
+
+ {
+ // compute (s)-partial derivative control points
+ REAL *til = tp + idist - istride;
+ const REAL *till = til - ( spartial * istride );
+ for( ; til != till; til -= istride )
+ for( REAL *ti = tp; ti != til; ti += istride )
+ for( REAL *tj = ti, *tjl = tj + jdist; tj != tjl; tj += jstride )
+ for( int k=0; k != inhcoords; k++ )
+ tj[k] = tj[k+istride] - tj[k];
+ }
+
+ {
+ // compute (s,t)-partial derivative control points
+ REAL *tjl = tp + jdist - jstride;
+ const REAL *tjll = tjl - ( tpartial * jstride );
+ for( ; tjl != tjll; tjl -= jstride )
+ for( REAL *tj = tp; tj != tjl; tj += jstride )
+ for( REAL *ti = tj, *til = ti + id; ti != til; ti += istride )
+ for( int k=0; k != inhcoords; k++ )
+ ti[k] = ti[k+jstride] - ti[k];
+
+ }
+
+ REAL max = 0.0;
+ {
+ // compute magnitude and store in mag array
+ memset( (void *) mp, 0, sizeof( mag ) );
+ for( REAL *ti = tp, *mi = mp, *til = tp + id; ti != til; ti += istride, mi += mistride )
+ for( REAL *tj = ti, *mj = mi, *tjl = ti + jd; tj != tjl; tj += jstride, mj += mjstride ) {
+ for( int k=0; k != inhcoords; k++ )
+ *mj += tj[k] * tj[k];
+ if( *mj > max ) max = *mj;
+ }
+
+ }
+
+ int i, j;
+
+ // compute scale factor
+ REAL fac = 1.0;
+ {
+ REAL invs = 1.0 / srange;
+ REAL invt = 1.0 / trange;
+ for( int s = nrows-1, slast = s-spartial; s != slast; s-- )
+ fac *= s * invs;
+ for( int t = ncols-1, tlast = t-tpartial; t != tlast; t-- )
+ fac *= t * invt;
+ }
+
+ if( side == 0 ) {
+ // compute max magnitude of first and last column
+ dist[0] = 0.0;
+ dist[1] = 0.0;
+ for( i=0; i != nrows-spartial; i++ ) {
+ j = 0;
+ if( mag[i][j] > dist[0] ) dist[0] = mag[i][j];
+
+ j = ncols-tpartial-1;
+ if( mag[i][j] > dist[1] ) dist[1] = mag[i][j];
+ }
+ dist[0] = fac * sqrtf( dist[0] );
+ dist[1] = fac * sqrtf( dist[1] );
+ } else if( side == 1 ) {
+ // compute max magnitude of first and last row
+ dist[0] = 0.0;
+ dist[1] = 0.0;
+ for( j=0; j != ncols-tpartial; j++ ) {
+ i = 0;
+ if( mag[i][j] > dist[0] ) dist[0] = mag[i][j];
+
+ i = nrows-spartial-1;
+ if( mag[i][j] > dist[1] ) dist[1] = mag[i][j];
+ }
+ dist[0] = fac * sqrtf( dist[0] );
+ dist[1] = fac * sqrtf( dist[1] );
+ }
+
+ max = fac * sqrtf( (float) max );
+
+ return max;
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/maplist.cc b/src/glu/sgi/libnurbs/internals/maplist.cc
new file mode 100644
index 00000000000..803044ffd3f
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/maplist.cc
@@ -0,0 +1,119 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * maplist.c++
+ *
+ * $Date: 2005/10/28 13:09:08 $ $Revision: 1.1.30.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/maplist.cc,v 1.1.30.1 2005/10/28 13:09:08 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "mymath.h"
+#include "nurbsconsts.h"
+#include "maplist.h"
+#include "mapdesc.h"
+#include "backend.h"
+
+Maplist::Maplist( Backend& b )
+ : mapdescPool( sizeof( Mapdesc ), 10, "mapdesc pool" ),
+ backend( b )
+{
+ maps = 0; lastmap = &maps;
+}
+
+void
+Maplist::initialize( void )
+{
+ freeMaps();
+ define( N_P2D, 0, 2 );
+ define( N_P2DR, 1, 3 );
+}
+
+void
+Maplist::add( long type, int israt, int ncoords )
+{
+ *lastmap = new(mapdescPool) Mapdesc( type, israt, ncoords, backend );
+ lastmap = &((*lastmap)->next);
+}
+
+void
+Maplist::define( long type, int israt, int ncoords )
+{
+#ifndef NDEBUG // to avoid warning
+ Mapdesc *m = locate( type );
+ assert( m == NULL || ( m->isrational == israt && m->ncoords == ncoords ) );
+#endif
+ add( type, israt, ncoords );
+}
+
+void
+Maplist::remove( Mapdesc *m )
+{
+ for( Mapdesc **curmap = &maps; *curmap; curmap = &((*curmap)->next) ) {
+ if( *curmap == m ) {
+ *curmap = m->next;
+ m->deleteMe( mapdescPool );
+ return;
+ }
+ }
+ abort();
+}
+
+void
+Maplist::freeMaps( void )
+{
+ mapdescPool.clear();
+ maps = 0;
+ lastmap = &maps;
+}
+
+Mapdesc *
+Maplist::find( long type )
+{
+ Mapdesc *val = locate( type );
+ assert( val != 0 );
+ return val;
+}
+
+Mapdesc *
+Maplist::locate( long type )
+{
+ Mapdesc *m;
+ for( m = maps; m; m = m->next )
+ if( m->getType() == type ) break;
+ return m;
+}
diff --git a/src/glu/sgi/libnurbs/internals/maplist.h b/src/glu/sgi/libnurbs/internals/maplist.h
new file mode 100644
index 00000000000..369120e9044
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/maplist.h
@@ -0,0 +1,87 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * maplist.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/maplist.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __glumaplist_h_
+#define __glumaplist_h_
+
+#include "types.h"
+#include "defines.h"
+#include "bufpool.h"
+
+class Backend;
+class Mapdesc;
+
+class Maplist {
+public:
+ Maplist( Backend & );
+ void define( long, int, int );
+ inline void undefine( long );
+ inline int isMap( long );
+
+ void initialize( void );
+ Mapdesc * find( long );
+ Mapdesc * locate( long );
+
+private:
+ Pool mapdescPool;
+ Mapdesc * maps;
+ Mapdesc ** lastmap;
+ Backend & backend;
+
+ void add( long, int, int );
+ void remove( Mapdesc * );
+ void freeMaps( void );
+};
+
+inline int
+Maplist::isMap( long type )
+{
+ return (locate( type ) ? 1 : 0);
+}
+
+inline void
+Maplist::undefine( long type )
+{
+ Mapdesc *m = locate( type );
+ assert( m != 0 );
+ remove( m );
+}
+#endif /* __glumaplist_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/mesher.cc b/src/glu/sgi/libnurbs/internals/mesher.cc
new file mode 100644
index 00000000000..ca0c6617127
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/mesher.cc
@@ -0,0 +1,488 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * mesher.c++
+ *
+ * $Date: 2001/11/29 16:16:55 $ $Revision: 1.3 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/mesher.cc,v 1.3 2001/11/29 16:16:55 kschultz Exp $
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "gridvertex.h"
+#include "gridtrimvertex.h"
+#include "jarcloc.h"
+#include "gridline.h"
+#include "trimline.h"
+#include "uarray.h"
+#include "backend.h"
+#include "mesher.h"
+
+
+const float Mesher::ZERO = 0.0;
+
+Mesher::Mesher( Backend& b )
+ : backend( b ),
+ p( sizeof( GridTrimVertex ), 100, "GridTrimVertexPool" )
+{
+ stacksize = 0;
+ vdata = 0;
+ lastedge = 0; //needed to prevent purify UMR
+}
+
+Mesher::~Mesher( void )
+{
+ if( vdata ) delete[] vdata;
+}
+
+void
+Mesher::init( unsigned int npts )
+{
+ p.clear();
+ if( stacksize < npts ) {
+ stacksize = 2 * npts;
+ if( vdata ) delete[] vdata;
+ vdata = new GridTrimVertex_p[stacksize];
+ }
+}
+
+inline void
+Mesher::push( GridTrimVertex *gt )
+{
+ assert( itop+1 != (int)stacksize );
+ vdata[++itop] = gt;
+}
+
+inline void
+Mesher::pop( long )
+{
+}
+
+inline void
+Mesher::openMesh()
+{
+ backend.bgntmesh( "addedge" );
+}
+
+inline void
+Mesher::closeMesh()
+{
+ backend.endtmesh();
+}
+
+inline void
+Mesher::swapMesh()
+{
+ backend.swaptmesh();
+}
+
+inline void
+Mesher::clearStack()
+{
+ itop = -1;
+ last[0] = 0;
+}
+
+void
+Mesher::finishLower( GridTrimVertex *gtlower )
+{
+ for( push(gtlower);
+ nextlower( gtlower=new(p) GridTrimVertex );
+ push(gtlower) )
+ addLower();
+ addLast();
+}
+
+void
+Mesher::finishUpper( GridTrimVertex *gtupper )
+{
+ for( push(gtupper);
+ nextupper( gtupper=new(p) GridTrimVertex );
+ push(gtupper) )
+ addUpper();
+ addLast();
+}
+
+void
+Mesher::mesh( void )
+{
+ GridTrimVertex *gtlower, *gtupper;
+
+ Hull::init( );
+ nextupper( gtupper = new(p) GridTrimVertex );
+ nextlower( gtlower = new(p) GridTrimVertex );
+
+ clearStack();
+ openMesh();
+ push(gtupper);
+
+ nextupper( gtupper = new(p) GridTrimVertex );
+ nextlower( gtlower );
+
+ assert( gtupper->t && gtlower->t );
+
+ if( gtupper->t->param[0] < gtlower->t->param[0] ) {
+ push(gtupper);
+ lastedge = 1;
+ if( nextupper( gtupper=new(p) GridTrimVertex ) == 0 ) {
+ finishLower(gtlower);
+ return;
+ }
+ } else if( gtupper->t->param[0] > gtlower->t->param[0] ) {
+ push(gtlower);
+ lastedge = 0;
+ if( nextlower( gtlower=new(p) GridTrimVertex ) == 0 ) {
+ finishUpper(gtupper);
+ return;
+ }
+ } else {
+ if( lastedge == 0 ) {
+ push(gtupper);
+ lastedge = 1;
+ if( nextupper(gtupper=new(p) GridTrimVertex) == 0 ) {
+ finishLower(gtlower);
+ return;
+ }
+ } else {
+ push(gtlower);
+ lastedge = 0;
+ if( nextlower( gtlower=new(p) GridTrimVertex ) == 0 ) {
+ finishUpper(gtupper);
+ return;
+ }
+ }
+ }
+
+ while ( 1 ) {
+ if( gtupper->t->param[0] < gtlower->t->param[0] ) {
+ push(gtupper);
+ addUpper();
+ if( nextupper( gtupper=new(p) GridTrimVertex ) == 0 ) {
+ finishLower(gtlower);
+ return;
+ }
+ } else if( gtupper->t->param[0] > gtlower->t->param[0] ) {
+ push(gtlower);
+ addLower();
+ if( nextlower( gtlower=new(p) GridTrimVertex ) == 0 ) {
+ finishUpper(gtupper);
+ return;
+ }
+ } else {
+ if( lastedge == 0 ) {
+ push(gtupper);
+ addUpper();
+ if( nextupper( gtupper=new(p) GridTrimVertex ) == 0 ) {
+ finishLower(gtlower);
+ return;
+ }
+ } else {
+ push(gtlower);
+ addLower();
+ if( nextlower( gtlower=new(p) GridTrimVertex ) == 0 ) {
+ finishUpper(gtupper);
+ return;
+ }
+ }
+ }
+ }
+}
+
+inline int
+Mesher::isCcw( int ilast )
+{
+ REAL area = det3( vdata[ilast]->t, vdata[itop-1]->t, vdata[itop-2]->t );
+ return (area < ZERO) ? 0 : 1;
+}
+
+inline int
+Mesher::isCw( int ilast )
+{
+ REAL area = det3( vdata[ilast]->t, vdata[itop-1]->t, vdata[itop-2]->t );
+ return (area > -ZERO) ? 0 : 1;
+}
+
+inline int
+Mesher::equal( int x, int y )
+{
+ return( last[0] == vdata[x] && last[1] == vdata[y] );
+}
+
+inline void
+Mesher::copy( int x, int y )
+{
+ last[0] = vdata[x]; last[1] = vdata[y];
+}
+
+inline void
+Mesher::move( int x, int y )
+{
+ vdata[x] = vdata[y];
+}
+
+inline void
+Mesher::output( int x )
+{
+ backend.tmeshvert( vdata[x] );
+}
+
+/*---------------------------------------------------------------------------
+ * addedge - addedge an edge to the triangulation
+ *
+ * This code has been re-written to generate large triangle meshes
+ * from a monotone polygon. Although smaller triangle meshes
+ * could be generated faster and with less code, larger meshes
+ * actually give better SYSTEM performance. This is because
+ * vertices are processed in the backend slower than they are
+ * generated by this code and any decrease in the number of vertices
+ * results in a decrease in the time spent in the backend.
+ *---------------------------------------------------------------------------
+ */
+
+void
+Mesher::addLast( )
+{
+ register int ilast = itop;
+
+ if( lastedge == 0 ) {
+ if( equal( 0, 1 ) ) {
+ output( ilast );
+ swapMesh();
+ for( register int i = 2; i < ilast; i++ ) {
+ swapMesh();
+ output( i );
+ }
+ copy( ilast, ilast-1 );
+ } else if( equal( ilast-2, ilast-1) ) {
+ swapMesh();
+ output( ilast );
+ for( register int i = ilast-3; i >= 0; i-- ) {
+ output( i );
+ swapMesh();
+ }
+ copy( 0, ilast );
+ } else {
+ closeMesh(); openMesh();
+ output( ilast );
+ output( 0 );
+ for( register int i = 1; i < ilast; i++ ) {
+ swapMesh();
+ output( i );
+ }
+ copy( ilast, ilast-1 );
+ }
+ } else {
+ if( equal( 1, 0) ) {
+ swapMesh();
+ output( ilast );
+ for( register int i = 2; i < ilast; i++ ) {
+ output( i );
+ swapMesh();
+ }
+ copy( ilast-1, ilast );
+ } else if( equal( ilast-1, ilast-2) ) {
+ output( ilast );
+ swapMesh();
+ for( register int i = ilast-3; i >= 0; i-- ) {
+ swapMesh();
+ output( i );
+ }
+ copy( ilast, 0 );
+ } else {
+ closeMesh(); openMesh();
+ output( 0 );
+ output( ilast );
+ for( register int i = 1; i < ilast; i++ ) {
+ output( i );
+ swapMesh();
+ }
+ copy( ilast-1, ilast );
+ }
+ }
+ closeMesh();
+ //for( register long k=0; k<=ilast; k++ ) pop( k );
+}
+
+void
+Mesher::addUpper( )
+{
+ register int ilast = itop;
+
+ if( lastedge == 0 ) {
+ if( equal( 0, 1 ) ) {
+ output( ilast );
+ swapMesh();
+ for( register int i = 2; i < ilast; i++ ) {
+ swapMesh();
+ output( i );
+ }
+ copy( ilast, ilast-1 );
+ } else if( equal( ilast-2, ilast-1) ) {
+ swapMesh();
+ output( ilast );
+ for( register int i = ilast-3; i >= 0; i-- ) {
+ output( i );
+ swapMesh();
+ }
+ copy( 0, ilast );
+ } else {
+ closeMesh(); openMesh();
+ output( ilast );
+ output( 0 );
+ for( register int i = 1; i < ilast; i++ ) {
+ swapMesh();
+ output( i );
+ }
+ copy( ilast, ilast-1 );
+ }
+ lastedge = 1;
+ //for( register long k=0; k<ilast-1; k++ ) pop( k );
+ move( 0, ilast-1 );
+ move( 1, ilast );
+ itop = 1;
+ } else {
+ if( ! isCcw( ilast ) ) return;
+ do {
+ itop--;
+ } while( (itop > 1) && isCcw( ilast ) );
+
+ if( equal( ilast-1, ilast-2 ) ) {
+ output( ilast );
+ swapMesh();
+ for( register int i=ilast-3; i>=itop-1; i-- ) {
+ swapMesh();
+ output( i );
+ }
+ copy( ilast, itop-1 );
+ } else if( equal( itop, itop-1 ) ) {
+ swapMesh();
+ output( ilast );
+ for( register int i = itop+1; i < ilast; i++ ) {
+ output( i );
+ swapMesh();
+ }
+ copy( ilast-1, ilast );
+ } else {
+ closeMesh(); openMesh();
+ output( ilast );
+ output( ilast-1 );
+ for( register int i=ilast-2; i>=itop-1; i-- ) {
+ swapMesh();
+ output( i );
+ }
+ copy( ilast, itop-1 );
+ }
+ //for( register int k=itop; k<ilast; k++ ) pop( k );
+ move( itop, ilast );
+ }
+}
+
+void
+Mesher::addLower()
+{
+ register int ilast = itop;
+
+ if( lastedge == 1 ) {
+ if( equal( 1, 0) ) {
+ swapMesh();
+ output( ilast );
+ for( register int i = 2; i < ilast; i++ ) {
+ output( i );
+ swapMesh();
+ }
+ copy( ilast-1, ilast );
+ } else if( equal( ilast-1, ilast-2) ) {
+ output( ilast );
+ swapMesh();
+ for( register int i = ilast-3; i >= 0; i-- ) {
+ swapMesh();
+ output( i );
+ }
+ copy( ilast, 0 );
+ } else {
+ closeMesh(); openMesh();
+ output( 0 );
+ output( ilast );
+ for( register int i = 1; i < ilast; i++ ) {
+ output( i );
+ swapMesh();
+ }
+ copy( ilast-1, ilast );
+ }
+
+ lastedge = 0;
+ //for( register long k=0; k<ilast-1; k++ ) pop( k );
+ move( 0, ilast-1 );
+ move( 1, ilast );
+ itop = 1;
+ } else {
+ if( ! isCw( ilast ) ) return;
+ do {
+ itop--;
+ } while( (itop > 1) && isCw( ilast ) );
+
+ if( equal( ilast-2, ilast-1) ) {
+ swapMesh();
+ output( ilast );
+ for( register int i=ilast-3; i>=itop-1; i--) {
+ output( i );
+ swapMesh( );
+ }
+ copy( itop-1, ilast );
+ } else if( equal( itop-1, itop) ) {
+ output( ilast );
+ swapMesh();
+ for( register int i=itop+1; i<ilast; i++ ) {
+ swapMesh( );
+ output( i );
+ }
+ copy( ilast, ilast-1 );
+ } else {
+ closeMesh(); openMesh();
+ output( ilast-1 );
+ output( ilast );
+ for( register int i=ilast-2; i>=itop-1; i-- ) {
+ output( i );
+ swapMesh( );
+ }
+ copy( itop-1, ilast );
+ }
+ //for( register int k=itop; k<ilast; k++ ) pop( k );
+ move( itop, ilast );
+ }
+}
+
+
diff --git a/src/glu/sgi/libnurbs/internals/mesher.h b/src/glu/sgi/libnurbs/internals/mesher.h
new file mode 100644
index 00000000000..c96db73b4aa
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/mesher.h
@@ -0,0 +1,89 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * mesher.h
+ *
+ * $Date: 2001/08/07 17:34:11 $ $Revision: 1.2 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/mesher.h,v 1.2 2001/08/07 17:34:11 brianp Exp $
+ */
+
+#ifndef __glumesher_h_
+#define __glumesher_h_
+
+#include "hull.h"
+
+class TrimRegion;
+class Backend;
+class Pool;
+// struct GridTrimVertex;
+
+
+class Mesher : virtual public TrimRegion, public Hull {
+public:
+ Mesher( Backend & );
+ ~Mesher( void );
+ void init( unsigned int );
+ void mesh( void );
+
+private:
+ static const float ZERO;
+ Backend& backend;
+
+ Pool p;
+ unsigned int stacksize;
+ GridTrimVertex ** vdata;
+ GridTrimVertex * last[2];
+ int itop;
+ int lastedge;
+
+ inline void openMesh( void );
+ inline void swapMesh( void );
+ inline void closeMesh( void );
+ inline int isCcw( int );
+ inline int isCw( int );
+ inline void clearStack( void );
+ inline void push( GridTrimVertex * );
+ inline void pop( long );
+ inline void move( int, int );
+ inline int equal( int, int );
+ inline void copy( int, int );
+ inline void output( int );
+ void addUpper( void );
+ void addLower( void );
+ void addLast( void );
+ void finishUpper( GridTrimVertex * );
+ void finishLower( GridTrimVertex * );
+};
+#endif /* __glumesher_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/monoTriangulationBackend.cc b/src/glu/sgi/libnurbs/internals/monoTriangulationBackend.cc
new file mode 100644
index 00000000000..19e87b99db3
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/monoTriangulationBackend.cc
@@ -0,0 +1,399 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2005/10/28 13:09:08 $ $Revision: 1.2.8.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/monoTriangulationBackend.cc,v 1.2.8.1 2005/10/28 13:09:08 brianp Exp $
+*/
+
+#include "monoTriangulation.h"
+#include "polyUtil.h"
+#include "backend.h"
+#include "arc.h"
+
+void reflexChain::outputFan(Real v[2], Backend* backend)
+{
+ Int i;
+ /*
+ TrimVertex trimVert;
+ */
+ backend->bgntfan();
+
+ /*
+ trimVert.param[0]=v[0];
+ trimVert.param[1]=v[1];
+ backend->tmeshvert(&trimVert);
+ */
+ backend->tmeshvert(v[0], v[1]);
+
+ if(isIncreasing) {
+ for(i=0; i<index_queue; i++)
+ {
+ /*
+ trimVert.param[0]=queue[i][0];
+ trimVert.param[1]=queue[i][1];
+ backend->tmeshvert(&trimVert);
+ */
+ backend->tmeshvert(queue[i][0], queue[i][1]);
+ }
+ }
+ else {
+ for(i=index_queue-1; i>=0; i--)
+ {
+ /*
+ trimVert.param[0]=queue[i][0];
+ trimVert.param[1]=queue[i][1];
+ backend->tmeshvert(&trimVert);
+ */
+ backend->tmeshvert(queue[i][0], queue[i][1]);
+ }
+ }
+ backend->endtfan();
+}
+
+void reflexChain::processNewVertex(Real v[2], Backend* backend)
+{
+ Int i,j,k;
+ Int isReflex;
+ /*TrimVertex trimVert;*/
+ /*if there are at most one vertex in the queue, then simply insert
+ */
+ if(index_queue <=1){
+ insert(v);
+ return;
+ }
+
+ /*there are at least two vertices in the queue*/
+ j=index_queue-1;
+
+ for(i=j; i>=1; i--) {
+ if(isIncreasing) {
+ isReflex = (area(queue[i-1], queue[i], v) <= 0.0);
+ }
+ else /*decreasing*/{
+ isReflex = (area(v, queue[i], queue[i-1]) <= 0.0);
+ }
+ if(isReflex) {
+ break;
+ }
+ }
+
+ /*
+ *if i<j then vertices: i+1--j are convex
+ * output triangle fan:
+ * v, and queue[i], i+1, ..., j
+ */
+ if(i<j)
+ {
+ backend->bgntfan();
+ /*
+ trimVert.param[0]=v[0];
+ trimVert.param[1]=v[1];
+ backend->tmeshvert(& trimVert);
+ */
+ backend->tmeshvert(v[0], v[1]);
+
+ if(isIncreasing) {
+ for(k=i; k<=j; k++)
+ {
+ /*
+ trimVert.param[0]=queue[k][0];
+ trimVert.param[1]=queue[k][1];
+ backend->tmeshvert(& trimVert);
+ */
+ backend->tmeshvert(queue[k][0], queue[k][1]);
+ }
+ }
+ else {
+ for(k=j; k>=i; k--)
+ {
+ /*
+ trimVert.param[0]=queue[k][0];
+ trimVert.param[1]=queue[k][1];
+ backend->tmeshvert(& trimVert);
+ */
+ backend->tmeshvert(queue[k][0], queue[k][1]);
+ }
+ }
+
+ backend->endtfan();
+ }
+
+ /*delete vertices i+1--j from the queue*/
+ index_queue = i+1;
+ /*finally insert v at the end of the queue*/
+ insert(v);
+
+}
+
+
+void monoTriangulationRec(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ Backend* backend)
+{
+ assert( inc_chain != NULL && dec_chain != NULL);
+ assert( ! (inc_current>=inc_chain->getNumElements() &&
+ dec_current>=dec_chain->getNumElements()));
+ Int inc_nVertices;
+ Int dec_nVertices;
+ Real** inc_array ;
+ Real** dec_array ;
+ Int i;
+ assert( ! ( (inc_chain==NULL) && (dec_chain==NULL)));
+
+ if(inc_current>=inc_chain->getNumElements()) /*no more vertices on inc_chain*/
+ {
+
+ dec_array = dec_chain->getArray();
+ dec_nVertices = dec_chain->getNumElements();
+ reflexChain rChain(20,0);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, backend);
+ /*process all the vertices on the dec_chain*/
+ for(i=dec_current; i<dec_nVertices; i++){
+ rChain.processNewVertex(dec_array[i], backend);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, backend);
+
+ }
+ else if(dec_current>= dec_chain->getNumElements()) /*no more vertices on dec_chain*/
+ {
+ inc_array = inc_chain->getArray();
+ inc_nVertices= inc_chain->getNumElements();
+ reflexChain rChain(20,1);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, backend);
+ /*process all the vertices on the inc_chain*/
+ for(i=inc_current; i<inc_nVertices; i++){
+ rChain.processNewVertex(inc_array[i], backend);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, backend);
+ }
+ else /*neither chain is empty*/
+ {
+ inc_array = inc_chain -> getArray();
+ dec_array = dec_chain -> getArray();
+ inc_nVertices= inc_chain->getNumElements();
+ dec_nVertices= dec_chain->getNumElements();
+ /*if top of inc_chain is 'lower' than top of dec_chain, process all the
+ *vertices on the dec_chain which are higher than top of inc_chain
+ */
+ if(compV2InY(inc_array[inc_current], dec_array[dec_current]) <= 0)
+ {
+
+ reflexChain rChain(20, 0);
+ rChain.processNewVertex(topVertex, backend);
+ for(i=dec_current; i<dec_nVertices; i++)
+ {
+ if(compV2InY(inc_array[inc_current], dec_array[i]) <= 0)
+ rChain.processNewVertex(dec_array[i], backend);
+ else
+ break;
+ }
+ rChain.outputFan(inc_array[inc_current], backend);
+ monoTriangulationRec(dec_array[i-1], botVertex,
+ inc_chain, inc_current,
+ dec_chain, i,
+ backend);
+ }
+ else /*compV2InY(inc_array[inc_current], dec_array[dec_current]) > 0*/
+ {
+
+ reflexChain rChain(20, 1);
+ rChain.processNewVertex(topVertex, backend);
+ for(i=inc_current; i<inc_nVertices; i++)
+ {
+ if(compV2InY(inc_array[i], dec_array[dec_current]) >0)
+ rChain.processNewVertex(inc_array[i], backend);
+ else
+ break;
+ }
+ rChain.outputFan(dec_array[dec_current], backend);
+ monoTriangulationRec(inc_array[i-1], botVertex,
+ inc_chain, i,
+ dec_chain, dec_current,
+ backend);
+ }
+ }/*end case neither is empty*/
+}
+
+
+void monoTriangulationFunBackend(Arc_ptr loop, Int (*compFun)(Real*, Real*), Backend* backend)
+{
+ Int i;
+ /*find the top vertex, bottom vertex, inccreasing chain, and decreasing chain,
+ *then call monoTriangulationRec
+ */
+ Arc_ptr tempV;
+ Arc_ptr topV;
+ Arc_ptr botV;
+ topV = botV = loop;
+ for(tempV = loop->next; tempV != loop; tempV = tempV->next)
+ {
+ if(compFun(topV->tail(), tempV->tail())<0) {
+ topV = tempV;
+ }
+ if(compFun(botV->tail(), tempV->tail())>0) {
+ botV = tempV;
+ }
+ }
+
+ /*creat increase and decrease chains*/
+ vertexArray inc_chain(20); /*this is a dynamic array*/
+ for(i=1; i<=topV->pwlArc->npts-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
+ inc_chain.appendVertex(topV->pwlArc->pts[i].param);
+ }
+ for(tempV = topV->next; tempV != botV; tempV = tempV->next)
+ {
+ for(i=0; i<=tempV->pwlArc->npts-2; i++){
+ inc_chain.appendVertex(tempV->pwlArc->pts[i].param);
+ }
+ }
+
+ vertexArray dec_chain(20);
+ for(tempV = topV->prev; tempV != botV; tempV = tempV->prev)
+ {
+ for(i=tempV->pwlArc->npts-2; i>=0; i--){
+ dec_chain.appendVertex(tempV->pwlArc->pts[i].param);
+ }
+ }
+ for(i=botV->pwlArc->npts-2; i>=1; i--){
+ dec_chain.appendVertex(tempV->pwlArc->pts[i].param);
+ }
+
+ monoTriangulationRecFunBackend(topV->tail(), botV->tail(), &inc_chain, 0, &dec_chain, 0, compFun, backend);
+
+}
+
+/*if compFun == compV2InY, top to bottom: V-monotone
+ *if compFun == compV2InX, right to left: U-monotone
+ */
+void monoTriangulationRecFunBackend(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ Int (*compFun)(Real*, Real*),
+ Backend* backend)
+{
+ assert( inc_chain != NULL && dec_chain != NULL);
+ assert( ! (inc_current>=inc_chain->getNumElements() &&
+ dec_current>=dec_chain->getNumElements()));
+ Int inc_nVertices;
+ Int dec_nVertices;
+ Real** inc_array ;
+ Real** dec_array ;
+ Int i;
+ assert( ! ( (inc_chain==NULL) && (dec_chain==NULL)));
+
+ if(inc_current>=inc_chain->getNumElements()) /*no more vertices on inc_chain*/
+ {
+
+ dec_array = dec_chain->getArray();
+ dec_nVertices = dec_chain->getNumElements();
+ reflexChain rChain(20,0);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, backend);
+ /*process all the vertices on the dec_chain*/
+ for(i=dec_current; i<dec_nVertices; i++){
+ rChain.processNewVertex(dec_array[i], backend);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, backend);
+
+ }
+ else if(dec_current>= dec_chain->getNumElements()) /*no more vertices on dec_chain*/
+ {
+ inc_array = inc_chain->getArray();
+ inc_nVertices= inc_chain->getNumElements();
+ reflexChain rChain(20,1);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, backend);
+ /*process all the vertices on the inc_chain*/
+ for(i=inc_current; i<inc_nVertices; i++){
+ rChain.processNewVertex(inc_array[i], backend);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, backend);
+ }
+ else /*neither chain is empty*/
+ {
+ inc_array = inc_chain -> getArray();
+ dec_array = dec_chain -> getArray();
+ inc_nVertices= inc_chain->getNumElements();
+ dec_nVertices= dec_chain->getNumElements();
+ /*if top of inc_chain is 'lower' than top of dec_chain, process all the
+ *vertices on the dec_chain which are higher than top of inc_chain
+ */
+ if(compFun(inc_array[inc_current], dec_array[dec_current]) <= 0)
+ {
+
+ reflexChain rChain(20, 0);
+ rChain.processNewVertex(topVertex, backend);
+ for(i=dec_current; i<dec_nVertices; i++)
+ {
+ if(compFun(inc_array[inc_current], dec_array[i]) <= 0)
+ rChain.processNewVertex(dec_array[i], backend);
+ else
+ break;
+ }
+ rChain.outputFan(inc_array[inc_current], backend);
+ monoTriangulationRecFunBackend(dec_array[i-1], botVertex,
+ inc_chain, inc_current,
+ dec_chain, i,
+ compFun,
+ backend);
+ }
+ else /*compFun(inc_array[inc_current], dec_array[dec_current]) > 0*/
+ {
+
+ reflexChain rChain(20, 1);
+ rChain.processNewVertex(topVertex, backend);
+ for(i=inc_current; i<inc_nVertices; i++)
+ {
+ if(compFun(inc_array[i], dec_array[dec_current]) >0)
+ rChain.processNewVertex(inc_array[i], backend);
+ else
+ break;
+ }
+ rChain.outputFan(dec_array[dec_current], backend);
+ monoTriangulationRecFunBackend(inc_array[i-1], botVertex,
+ inc_chain, i,
+ dec_chain, dec_current,
+ compFun,
+ backend);
+ }
+ }/*end case neither is empty*/
+}
diff --git a/src/glu/sgi/libnurbs/internals/monotonizer.cc b/src/glu/sgi/libnurbs/internals/monotonizer.cc
new file mode 100644
index 00000000000..b3bb61758d7
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/monotonizer.cc
@@ -0,0 +1,262 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * monotonizer.c++
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/monotonizer.cc,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "arc.h"
+#include "arctess.h"
+#include "bezierarc.h"
+#include "bin.h"
+#include "mapdesc.h"
+#include "nurbsconsts.h"
+#include "subdivider.h"
+
+/*-----------------------------------------------------------------------------
+ * Subdivider::decompose - break all curves into monotone arcs
+ *-----------------------------------------------------------------------------
+ */
+int
+Subdivider::decompose( Bin& bin, REAL geo_stepsize )
+{
+ Arc_ptr jarc;
+ for( jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
+ if( ! jarc->isTessellated() ) {
+ /* points have not been transformed, therefore they may be either
+ homogeneous or inhomogeneous */
+ tessellate( jarc, geo_stepsize );
+ if( jarc->isDisconnected() || jarc->next->isDisconnected() )
+ return 1;
+ }
+ }
+
+ for( jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
+ monotonize( jarc, bin );
+ }
+
+#ifndef NDEBUG
+ for( jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
+ assert( isMonotone( jarc ) != 0 );
+ }
+#endif
+
+ return 0;
+}
+
+void
+Subdivider::tessellate( Arc_ptr jarc, REAL geo_stepsize )
+{
+ BezierArc *b = jarc->bezierArc;
+ Mapdesc *mapdesc = b->mapdesc;
+
+ if( mapdesc->isRational() ) {
+ REAL max = mapdesc->calcVelocityRational( b->cpts, b->stride, b->order );
+ REAL arc_stepsize = (max > 1.0) ? (1.0/max) : 1.0;
+ if( jarc->bezierArc->order != 2 )
+ arctessellator.tessellateNonlinear( jarc, geo_stepsize, arc_stepsize, 1 );
+ else {
+ arctessellator.tessellateLinear( jarc, geo_stepsize, arc_stepsize, 1 );
+ }
+ } else {
+ REAL max = mapdesc->calcVelocityNonrational( b->cpts, b->stride, b->order );
+ REAL arc_stepsize = (max > 1.0) ? (1.0/max) : 1.0;
+ if( jarc->bezierArc->order != 2 )
+ arctessellator.tessellateNonlinear( jarc, geo_stepsize, arc_stepsize, 0 );
+ else {
+ arctessellator.tessellateLinear( jarc, geo_stepsize, arc_stepsize, 0 );
+ }
+ }
+}
+
+/*-------------------------------------------------------------------------
+ * Subdivider::monotonize - break up a jordan arc into s,t-monotone
+ * components. This code will remove degenerate segments, including
+ * arcs of only a single point.
+ *-------------------------------------------------------------------------
+ */
+void
+Subdivider::monotonize( Arc_ptr jarc, Bin& bin )
+{
+ TrimVertex *firstvert = jarc->pwlArc->pts;
+ TrimVertex *lastvert = firstvert + (jarc->pwlArc->npts - 1);
+ long uid = jarc->nuid;
+ arc_side side = jarc->getside();
+ dir sdir = none;
+ dir tdir = none;
+ int degenerate = 1;
+
+ int nudegenerate;
+ int change;
+
+ TrimVertex *vert;
+ for( vert = firstvert; vert != lastvert; vert++ ) {
+
+ nudegenerate = 1;
+ change = 0;
+
+ /* check change relative to s axis, clear degenerate bit if needed */
+ REAL sdiff = vert[1].param[0] - vert[0].param[0];
+ if( sdiff == 0 ) {
+ if( sdir != same ) {
+ sdir = same;
+ change = 1;
+ }
+ } else if( sdiff < 0.0 ) {
+ if( sdir != down ) {
+ sdir = down;
+ change = 1;
+ }
+ nudegenerate = 0;
+ } else {
+ if( sdir != up ) {
+ sdir = up;
+ change = 1;
+ }
+ nudegenerate = 0;
+ }
+
+ /* check change relative to t axis, clear degenerate bit if needed */
+ REAL tdiff = vert[1].param[1] - vert[0].param[1];
+ if( tdiff == 0 ) {
+ if( tdir != same ) {
+ tdir = same;
+ change = 1;
+ }
+ } else if( tdiff < 0.0 ) {
+ if( tdir != down ) {
+ tdir = down;
+ change = 1;
+ }
+ nudegenerate = 0;
+ } else {
+ if( tdir != up ) {
+ tdir = up;
+ change = 1;
+ }
+ nudegenerate = 0;
+ }
+
+ if( change ) {
+ if( ! degenerate ) {
+ /* make last segment into separate pwl curve */
+ jarc->pwlArc->npts = vert - firstvert + 1;
+ jarc = (new(arcpool) Arc( side, uid ))->append( jarc );
+ jarc->pwlArc = new(pwlarcpool) PwlArc();
+ bin.addarc( jarc );
+ }
+ firstvert = jarc->pwlArc->pts = vert;
+ degenerate = nudegenerate;
+ }
+ }
+ jarc->pwlArc->npts = vert - firstvert + 1;
+
+ if( degenerate ) {
+ /* remove jarc from circularly linked list */
+ jarc->prev->next = jarc->next;
+ jarc->next->prev = jarc->prev;
+
+ assert( jarc->prev->check( ) != 0 );
+ assert( jarc->next->check( ) != 0 );
+
+ /* remove jarc from bin */
+ bin.remove_this_arc( jarc );
+
+ jarc->pwlArc->deleteMe( pwlarcpool ); jarc->pwlArc = 0;
+ jarc->deleteMe( arcpool );
+ }
+}
+
+/*-------------------------------------------------------------------------
+ * Subdivider::isMonotone - return true if arc is monotone AND non-degenerate
+ *-------------------------------------------------------------------------
+ */
+int
+Subdivider::isMonotone( Arc_ptr jarc )
+{
+ TrimVertex *firstvert = jarc->pwlArc->pts;
+ TrimVertex *lastvert = firstvert + (jarc->pwlArc->npts - 1);
+
+ if( firstvert == lastvert ) return 1;
+
+ TrimVertex *vert = firstvert;
+ enum dir sdir;
+ enum dir tdir;
+
+ REAL diff = vert[1].param[0] - vert[0].param[0];
+ if( diff == 0.0 )
+ sdir = same;
+ else if( diff < 0.0 )
+ sdir = down;
+ else
+ sdir = up;
+
+ diff = vert[1].param[1] - vert[0].param[1];
+ if( diff == 0.0 )
+ tdir = same;
+ else if( diff < 0.0 )
+ tdir = down;
+ else
+ tdir = up;
+
+ if( (sdir == same) && (tdir == same) ) return 0;
+
+ for( ++vert ; vert != lastvert; vert++ ) {
+ diff = vert[1].param[0] - vert[0].param[0];
+ if( diff == 0.0 ) {
+ if( sdir != same ) return 0;
+ } else if( diff < 0.0 ) {
+ if( sdir != down ) return 0;
+ } else {
+ if( sdir != up ) return 0;
+ }
+
+ diff = vert[1].param[1] - vert[0].param[1];
+ if( diff == 0.0 ) {
+ if( tdir != same ) return 0;
+ } else if( diff < 0.0 ) {
+ if( tdir != down ) return 0;
+ } else {
+ if( tdir != up ) return 0;
+ }
+ }
+ return 1;
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/monotonizer.h b/src/glu/sgi/libnurbs/internals/monotonizer.h
new file mode 100644
index 00000000000..f26c50e16ff
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/monotonizer.h
@@ -0,0 +1,47 @@
+/**************************************************************************
+ * *
+ * Copyright (C) 1999, Silicon Graphics, Inc. *
+ * *
+ * These coded instructions, statements, and computer programs contain *
+ * unpublished proprietary information of Silicon Graphics, Inc., and *
+ * are protected by Federal copyright law. They may not be disclosed *
+ * to third parties or copied or duplicated in any form, in whole or *
+ * in part, without the prior written consent of Silicon Graphics, Inc. *
+ * *
+ **************************************************************************/
+
+/*
+ * monotonizer.h
+ *
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/monotonizer.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __glumonotonizer_h_
+#define __glumonotonizer_h_
+
+#include "mysetjmp.h"
+#include "types.h"
+
+class Arc;
+class ArcTessellator;
+class Pool;
+class Bin;
+class PwlArcPool;
+class Mapdesc;
+
+class Monotonizer {
+ ArcTessellator& arctessellator;
+ Pool& arcpool;
+ Pool& pwlarcpool;
+ jmp_buf& nurbsJmpBuf;
+
+ enum dir { down, same, up, none };
+ void tessellate( Arc *, REAL );
+ void monotonize( Arc *, Bin & );
+ int isMonotone( Arc * );
+public:
+ Monotonizer( ArcTessellator& at, Pool& ap, Pool& p, jmp_buf& j )
+ : arctessellator(at), arcpool(ap), pwlarcpool(p), nurbsJmpBuf(j) {}
+ int decompose( Bin &, REAL );
+};
+#endif /* __glumonotonizer_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/myassert.h b/src/glu/sgi/libnurbs/internals/myassert.h
new file mode 100644
index 00000000000..befc7fd8ade
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/myassert.h
@@ -0,0 +1,57 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * myassert.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/myassert.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __glumyassert_h_
+#define __glumyassert_h_
+
+#ifdef STANDALONE
+#define assert(EX) ((void)0)
+#endif
+
+#ifdef LIBRARYBUILD
+#include <assert.h>
+#endif
+
+#ifdef GLBUILD
+#define assert(EX) ((void)0)
+#endif
+
+#endif /* __glumyassert_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/mycode.cc b/src/glu/sgi/libnurbs/internals/mycode.cc
new file mode 100644
index 00000000000..6d00c6d53a3
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/mycode.cc
@@ -0,0 +1,69 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/mycode.cc,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#include "mymath.h"
+
+#ifdef NEEDCEILF
+
+float ceilf( float x )
+{
+ if( x < 0 ) {
+ float nx = -x;
+ int ix = (int) nx;
+ return (float) -ix;
+ } else {
+ int ix = (int) x;
+ if( x == (float) ix ) return x;
+ return (float) (ix+1);
+ }
+}
+
+float floorf( float x )
+{
+ if( x < 0 ) {
+ float nx = -x;
+ int ix = (int) nx;
+ if( nx == (float) ix ) return x;
+ return (float) -(ix+1);
+ } else {
+ int ix = (int) x;
+ return (float) ix;
+ }
+}
+#endif
diff --git a/src/glu/sgi/libnurbs/internals/mymath.h b/src/glu/sgi/libnurbs/internals/mymath.h
new file mode 100644
index 00000000000..73078251dda
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/mymath.h
@@ -0,0 +1,72 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * mymath.h
+ *
+ */
+
+#ifndef __glumymath_h_
+#define __glumymath_h_
+
+#ifdef GLBUILD
+#define sqrtf gl_fsqrt
+#endif
+
+#if defined(GLBUILD) || defined(STANDALONE)
+#define M_SQRT2 1.41421356237309504880
+#define ceilf myceilf
+#define floorf myfloorf
+#define sqrtf sqrt
+extern "C" double sqrt(double);
+extern "C" float ceilf(float);
+extern "C" float floorf(float);
+#define NEEDCEILF
+#endif
+
+#ifdef LIBRARYBUILD
+#include <math.h>
+#endif
+
+#if !defined sqrtf
+# define sqrtf(x) ((float)sqrt(x))
+#endif
+#if !defined ceilf
+# define ceilf(x) ((float)ceil(x))
+#endif
+#if !defined floorf
+# define floorf(x) ((float)floor(x))
+#endif
+
+#endif /* __glumymath_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/mysetjmp.h b/src/glu/sgi/libnurbs/internals/mysetjmp.h
new file mode 100644
index 00000000000..bfb9cea98ba
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/mysetjmp.h
@@ -0,0 +1,89 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * mysetjmp.h
+ *
+ */
+
+#ifndef __glumysetjmp_h_
+#define __glumysetjmp_h_
+
+#ifdef STANDALONE
+struct JumpBuffer;
+extern "C" JumpBuffer *newJumpbuffer( void );
+extern "C" void deleteJumpbuffer(JumpBuffer *);
+extern "C" void mylongjmp( JumpBuffer *, int );
+extern "C" int mysetjmp( JumpBuffer * );
+#endif
+
+#ifdef GLBUILD
+#define setjmp gl_setjmp
+#define longjmp gl_longjmp
+#endif
+
+#if defined(LIBRARYBUILD) || defined(GLBUILD)
+#include <setjmp.h>
+#include <stdlib.h>
+
+struct JumpBuffer {
+ jmp_buf buf;
+};
+
+inline JumpBuffer *
+newJumpbuffer( void )
+{
+ return (JumpBuffer *) malloc( sizeof( JumpBuffer ) );
+}
+
+inline void
+deleteJumpbuffer(JumpBuffer *jb)
+{
+ free( (void *) jb);
+}
+
+inline void
+mylongjmp( JumpBuffer *j, int code )
+{
+ ::longjmp( j->buf, code );
+}
+
+inline int
+mysetjmp( JumpBuffer *j )
+{
+ return setjmp( j->buf );
+}
+#endif
+
+#endif /* __glumysetjmp_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/mystring.h b/src/glu/sgi/libnurbs/internals/mystring.h
new file mode 100644
index 00000000000..7b451c6e69e
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/mystring.h
@@ -0,0 +1,62 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * mystring.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/mystring.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __glumystring_h_
+#define __glumystring_h_
+
+#ifdef STANDALONE
+typedef unsigned int size_t;
+extern "C" void * memcpy(void *, const void *, size_t);
+extern "C" void * memset(void *, int, size_t);
+#endif
+
+#ifdef GLBUILD
+#define memcpy(a,b,c) bcopy(b,a,c)
+#define memset(a,b,c) bzero(a,c)
+extern "C" void bcopy(const void *, void *, int);
+extern "C" void bzero(void *, int);
+#endif
+
+#ifdef LIBRARYBUILD
+#include <string.h>
+#endif
+
+#endif /* __glumystring_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/nurbsconsts.h b/src/glu/sgi/libnurbs/internals/nurbsconsts.h
new file mode 100644
index 00000000000..35d3d99a1e8
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/nurbsconsts.h
@@ -0,0 +1,126 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * nurbsconsts.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/nurbsconsts.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __glunurbsconsts_h_
+#define __glunurbsconsts_h_
+
+/* NURBS Properties - one set per map,
+ each takes a single INREAL arg */
+#define N_SAMPLING_TOLERANCE 1
+#define N_S_RATE 6
+#define N_T_RATE 7
+#define N_CLAMPFACTOR 13
+#define N_NOCLAMPING 0.0
+#define N_MINSAVINGS 14
+#define N_NOSAVINGSSUBDIVISION 0.0
+
+/* NURBS Properties - one set per map,
+ each takes an enumerated value */
+#define N_CULLING 2
+#define N_NOCULLING 0.0
+#define N_CULLINGON 1.0
+#define N_SAMPLINGMETHOD 10
+#define N_NOSAMPLING 0.0
+#define N_FIXEDRATE 3.0
+#define N_DOMAINDISTANCE 2.0
+#define N_PARAMETRICDISTANCE 5.0
+#define N_PATHLENGTH 6.0
+#define N_SURFACEAREA 7.0
+#define N_OBJECTSPACE_PARA 8.0
+#define N_OBJECTSPACE_PATH 9.0
+#define N_BBOX_SUBDIVIDING 17
+#define N_NOBBOXSUBDIVISION 0.0
+#define N_BBOXTIGHT 1.0
+#define N_BBOXROUND 2.0
+
+/* NURBS Rendering Properties - one set per renderer
+ each takes an enumerated value */
+#define N_DISPLAY 3
+#define N_FILL 1.0
+#define N_OUTLINE_POLY 2.0
+#define N_OUTLINE_TRI 3.0
+#define N_OUTLINE_QUAD 4.0
+#define N_OUTLINE_PATCH 5.0
+#define N_OUTLINE_PARAM 6.0
+#define N_OUTLINE_PARAM_S 7.0
+#define N_OUTLINE_PARAM_ST 8.0
+#define N_OUTLINE_SUBDIV 9.0
+#define N_OUTLINE_SUBDIV_S 10.0
+#define N_OUTLINE_SUBDIV_ST 11.0
+#define N_ISOLINE_S 12.0
+#define N_ERRORCHECKING 4
+#define N_NOMSG 0.0
+#define N_MSG 1.0
+
+/* GL 4.0 propeties not defined above */
+#ifndef N_PIXEL_TOLERANCE
+#define N_PIXEL_TOLERANCE N_SAMPLING_TOLERANCE
+#define N_ERROR_TOLERANCE 20
+#define N_SUBDIVISIONS 5
+#define N_TILES 8
+#define N_TMP1 9
+#define N_TMP2 N_SAMPLINGMETHOD
+#define N_TMP3 11
+#define N_TMP4 12
+#define N_TMP5 N_CLAMPFACTOR
+#define N_TMP6 N_MINSAVINGS
+#define N_S_STEPS N_S_RATE
+#define N_T_STEPS N_T_RATE
+#endif
+
+/* NURBS Rendering Properties - one set per map,
+ each takes an INREAL matrix argument */
+#define N_CULLINGMATRIX 1
+#define N_SAMPLINGMATRIX 2
+#define N_BBOXMATRIX 3
+
+
+/* NURBS Rendering Properties - one set per map,
+ each takes an INREAL vector argument */
+#define N_BBOXSIZE 4
+
+/* type argument for trimming curves */
+#ifndef N_P2D
+#define N_P2D 0x8
+#define N_P2DR 0xd
+#endif
+
+#endif /* __glunurbsconsts_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/nurbsinterfac.cc b/src/glu/sgi/libnurbs/internals/nurbsinterfac.cc
new file mode 100644
index 00000000000..1a68ca51d91
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/nurbsinterfac.cc
@@ -0,0 +1,537 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * nurbsinterfac.c++
+ *
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "nurbsconsts.h"
+#include "nurbstess.h"
+#include "bufpool.h"
+#include "quilt.h"
+#include "displaylist.h"
+#include "knotvector.h"
+#include "mapdesc.h"
+
+#define THREAD( work, arg, cleanup ) \
+ if( dl ) {\
+ arg->save = 1;\
+ dl->append( (PFVS)&NurbsTessellator::work, (void *) arg, (PFVS)&NurbsTessellator::cleanup );\
+ } else {\
+ arg->save = 0;\
+ work( arg );\
+ }
+
+#define THREAD2( work ) \
+ if( dl ) {\
+ dl->append( (PFVS)&NurbsTessellator::work, 0, 0 );\
+ } else {\
+ work( );\
+ }
+
+NurbsTessellator::NurbsTessellator( BasicCurveEvaluator &c, BasicSurfaceEvaluator& e)
+ : maplist( backend ),
+ backend( c, e ),
+ subdivider( renderhints, backend ),
+ o_pwlcurvePool( sizeof( O_pwlcurve ), 32, "o_pwlcurvePool" ),
+ o_nurbscurvePool( sizeof( O_nurbscurve ), 32, "o_nurbscurvePool"),
+ o_curvePool( sizeof( O_curve ), 32, "o_curvePool" ),
+ o_trimPool( sizeof( O_trim ), 32, "o_trimPool" ),
+ o_surfacePool( sizeof( O_surface ), 1, "o_surfacePool" ),
+ o_nurbssurfacePool( sizeof( O_nurbssurface ), 4, "o_nurbssurfacePool" ),
+ propertyPool( sizeof( Property ), 32, "propertyPool" ),
+ quiltPool( sizeof( Quilt ), 32, "quiltPool" )
+{
+ dl = 0;
+ inSurface = 0;
+ inCurve = 0;
+ inTrim = 0;
+ playBack = 0;
+ jumpbuffer = newJumpbuffer();
+ subdivider.setJumpbuffer( jumpbuffer );
+}
+
+NurbsTessellator::~NurbsTessellator( void )
+{
+ if( inTrim ) {
+ do_nurbserror( 12 );
+ endtrim();
+ }
+
+ if( inSurface ) {
+ *nextNurbssurface = 0;
+ do_freeall();
+ }
+
+ if (jumpbuffer) {
+ deleteJumpbuffer(jumpbuffer);
+ jumpbuffer= 0;
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * bgnsurface - allocate and initialize an o_surface structure
+ *
+ * Client: GL user
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::bgnsurface( long nuid )
+{
+ O_surface *o_surface = new(o_surfacePool) O_surface;
+ o_surface->nuid = nuid;
+ THREAD( do_bgnsurface, o_surface, do_freebgnsurface );
+}
+
+/*-----------------------------------------------------------------------------
+ * bgncurve - allocate an initialize an o_curve structure
+ *
+ * Client: GL user
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::bgncurve( long nuid )
+{
+ O_curve *o_curve = new(o_curvePool) O_curve;
+ o_curve->nuid = nuid;
+ THREAD( do_bgncurve, o_curve, do_freebgncurve );
+}
+/*-----------------------------------------------------------------------------
+ * endcurve -
+ *
+ * Client:
+ *-----------------------------------------------------------------------------
+ */
+
+void
+NurbsTessellator::endcurve( void )
+{
+ THREAD2( do_endcurve );
+}
+
+/*-----------------------------------------------------------------------------
+ * endsurface - user level end of surface call
+ *
+ * Client: GL user
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::endsurface( void )
+{
+ THREAD2( do_endsurface );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * bgntrim - allocate and initialize a new trim loop structure (o_trim )
+ *
+ * Client: GL user
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::bgntrim( void )
+{
+ O_trim *o_trim = new(o_trimPool) O_trim;
+ THREAD( do_bgntrim, o_trim, do_freebgntrim );
+}
+
+/*-----------------------------------------------------------------------------
+ * endtrim -
+ *
+ * Client: GL user
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::endtrim( void )
+{
+ THREAD2( do_endtrim );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * pwlcurve -
+ *
+ * count - number of points on curve
+ * array - array of points on curve
+ * byte_stride - distance between points in bytes
+ * type - valid data flag
+ *
+ * Client: Gl user
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::pwlcurve( long count, INREAL array[], long byte_stride, long type )
+{
+ Mapdesc *mapdesc = maplist.locate( type );
+
+ if( mapdesc == 0 ) {
+ do_nurbserror( 35 );
+ isDataValid = 0;
+ return;
+ }
+
+ if ( (type != N_P2D) && (type != N_P2DR) ) {
+ do_nurbserror( 22 );
+ isDataValid = 0;
+ return;
+ }
+ if( count < 0 ) {
+ do_nurbserror( 33 );
+ isDataValid = 0;
+ return;
+ }
+ if( byte_stride < 0 ) {
+ do_nurbserror( 34 );
+ isDataValid = 0;
+ return;
+ }
+
+#ifdef NOTDEF
+ if( mapdesc->isRational() ) {
+ INREAL *p = array;
+ INREAL x = p[0]; INREAL y = p[1]; INREAL w = p[2];
+ p = (INREAL *) (((char *) p) + byte_stride);
+ for( long i = 1; i != count; i++ ) {
+ if( p[0] == x && p[1] == y && p[2] == w ) break;
+ x = p[0]; y = p[1]; w = p[2];
+ p = (INREAL *) (((char *) p) + byte_stride);
+ }
+ if( i != count ) {
+ do_nurbserror( 37 );
+ dprintf( "point %d (%f,%f)\n", i, x, y );
+ isDataValid = 0;
+ return;
+ }
+ } else {
+ INREAL *p = array;
+ INREAL x = p[0]; INREAL y = p[1];
+ p = (INREAL *) (((char *) p) + byte_stride);
+ for( long i = 1; i != count; i++ ) {
+ if( p[0] == x && p[1] == y ) break;
+ x = p[0]; y = p[1];
+ p = (INREAL *) (((char *) p) + byte_stride);
+ }
+ if( i != count ) {
+ do_nurbserror( 37 );
+ dprintf( "point %d (%f,%f)\n", i, x, y );
+ isDataValid = 0;
+ return;
+ }
+ }
+#endif
+
+ O_pwlcurve *o_pwlcurve = new(o_pwlcurvePool) O_pwlcurve( type, count, array, byte_stride, extTrimVertexPool.get((int)count) );
+ THREAD( do_pwlcurve, o_pwlcurve, do_freepwlcurve );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * nurbscurve -
+ *
+ * Client: GL user
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::nurbscurve(
+ long nknots, /* number of p knots */
+ INREAL knot[], /* nondecreasing knot values in p */
+ long byte_stride, /* distance in bytes between control points */
+ INREAL ctlarray[], /* pointer to first control point */
+ long order, /* order of spline */
+ long type ) /* description of range space */
+{
+
+ Mapdesc *mapdesc = maplist.locate( type );
+
+ if( mapdesc == 0 ) {
+ do_nurbserror( 35 );
+ isDataValid = 0;
+ return;
+ }
+
+ if( ctlarray == 0 ) {
+ do_nurbserror( 36 );
+ isDataValid = 0;
+ return;
+ }
+
+ if( byte_stride < 0 ) {
+ do_nurbserror( 34 );
+ isDataValid = 0;
+ return;
+ }
+
+ Knotvector knots;
+
+ knots.init( nknots, byte_stride, order, knot );
+ if( do_check_knots( &knots, "curve" ) ) return;
+
+ O_nurbscurve *o_nurbscurve = new(o_nurbscurvePool) O_nurbscurve(type);
+ o_nurbscurve->bezier_curves = new(quiltPool) Quilt(mapdesc);
+ o_nurbscurve->bezier_curves->toBezier( knots,ctlarray, mapdesc->getNcoords() );
+
+ THREAD( do_nurbscurve, o_nurbscurve, do_freenurbscurve );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * nurbssurface -
+ *
+ * Client: User routine
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::nurbssurface(
+ long sknot_count, /* number of s knots */
+ INREAL sknot[], /* nondecreasing knot values in s */
+ long tknot_count, /* number of t knots */
+ INREAL tknot[], /* nondecreasing knot values in t */
+ long s_byte_stride, /* s step size in memory bytes */
+ long t_byte_stride, /* t step size in memory bytes */
+ INREAL ctlarray[], /* pointer to first control point */
+ long sorder, /* order of the spline in s parameter */
+ long torder, /* order of the spline in t parameter */
+ long type) /* description of range space */
+{
+ Mapdesc *mapdesc = maplist.locate( type );
+
+ if( mapdesc == 0 ) {
+ do_nurbserror( 35 );
+ isDataValid = 0;
+ return;
+ }
+
+ if( s_byte_stride < 0 ) {
+ do_nurbserror( 34 );
+ isDataValid = 0;
+ return;
+ }
+
+ if( t_byte_stride < 0 ) {
+ do_nurbserror( 34 );
+ isDataValid = 0;
+ return;
+ }
+
+ Knotvector sknotvector, tknotvector;
+
+ sknotvector.init( sknot_count, s_byte_stride, sorder, sknot );
+ if( do_check_knots( &sknotvector, "surface" ) ) return;
+
+ tknotvector.init( tknot_count, t_byte_stride, torder, tknot );
+ if( do_check_knots( &tknotvector, "surface" ) ) return;
+
+ O_nurbssurface *o_nurbssurface = new(o_nurbssurfacePool) O_nurbssurface(type);
+ o_nurbssurface->bezier_patches = new(quiltPool) Quilt(mapdesc);
+
+ o_nurbssurface->bezier_patches->toBezier( sknotvector, tknotvector,
+ ctlarray, mapdesc->getNcoords() );
+ THREAD( do_nurbssurface, o_nurbssurface, do_freenurbssurface );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * setnurbsproperty -
+ *
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::setnurbsproperty( long tag, INREAL value )
+{
+ if( ! renderhints.isProperty( tag ) ) {
+ do_nurbserror( 26 );
+ } else {
+ Property *prop = new(propertyPool) Property( tag, value );
+ THREAD( do_setnurbsproperty, prop, do_freenurbsproperty );
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * setnurbsproperty -
+ *
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::setnurbsproperty( long type, long tag, INREAL value )
+{
+ Mapdesc *mapdesc = maplist.locate( type );
+
+ if( mapdesc == 0 ) {
+ do_nurbserror( 35 );
+ return;
+ }
+
+ if( ! mapdesc->isProperty( tag ) ) {
+ do_nurbserror( 26 );
+ return;
+ }
+
+ Property *prop = new(propertyPool) Property( type, tag, value );
+ THREAD( do_setnurbsproperty2, prop, do_freenurbsproperty );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * getnurbsproperty -
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+NurbsTessellator::getnurbsproperty( long tag, INREAL *value )
+{
+ if( renderhints.isProperty( tag ) ) {
+ *value = renderhints.getProperty( tag );
+ } else {
+ do_nurbserror( 26 );
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * getnurbsproperty -
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+NurbsTessellator::getnurbsproperty( long type, long tag, INREAL *value )
+{
+ Mapdesc *mapdesc = maplist.locate( type );
+
+ if( mapdesc == 0 )
+ do_nurbserror( 35 );
+
+ if( mapdesc->isProperty( tag ) ) {
+ *value = mapdesc->getProperty( tag );
+ } else {
+ do_nurbserror( 26 );
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * setnurbsproperty - accept a user supplied matrix as culling or sampling mat
+ *--------------------------------------------------------------------------
+ */
+
+void
+NurbsTessellator::setnurbsproperty( long type, long purpose, INREAL *mat )
+{
+ // XXX - cannot be put in display list
+ Mapdesc *mapdesc = maplist.locate( type );
+
+ if( mapdesc == 0 ) {
+ do_nurbserror( 35 );
+ isDataValid = 0;
+ } else if( purpose == N_BBOXSIZE ) {
+ mapdesc->setBboxsize( mat );
+ } else {
+#ifndef NDEBUG
+ dprintf( "ERRORRORRORR!!!\n");
+#endif
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * setnurbsproperty - accept a user supplied matrix as culling or sampling mat
+ *--------------------------------------------------------------------------
+ */
+
+void
+NurbsTessellator::setnurbsproperty( long type, long purpose, INREAL *mat,
+ long rstride, long cstride )
+{
+ // XXX - cannot be put in display list
+ Mapdesc *mapdesc = maplist.locate( type );
+
+ if( mapdesc == 0 ) {
+ do_nurbserror( 35 );
+ isDataValid = 0;
+ } else if( purpose == N_CULLINGMATRIX ) {
+ mapdesc->setCmat( mat, rstride, cstride );
+ } else if( purpose == N_SAMPLINGMATRIX ) {
+ mapdesc->setSmat( mat, rstride, cstride );
+ } else if( purpose == N_BBOXMATRIX ) {
+ mapdesc->setBmat( mat, rstride, cstride );
+ } else {
+#ifndef NDEBUG
+ dprintf( "ERRORRORRORR!!!\n");
+#endif
+ }
+}
+
+void
+NurbsTessellator::redefineMaps( void )
+{
+ maplist.initialize();
+}
+
+void
+NurbsTessellator::defineMap( long type, long rational, long ncoords )
+{
+ maplist.define( type, (int) rational, (int) ncoords );
+}
+
+void
+NurbsTessellator::discardRecording( void *_dl )
+{
+ delete (DisplayList *) _dl;
+}
+
+void *
+NurbsTessellator::beginRecording( void )
+{
+ dl = new DisplayList( this );
+ return (void *) dl;
+}
+
+void
+NurbsTessellator::endRecording( void )
+{
+ dl->endList();
+ dl = 0;
+}
+
+void
+NurbsTessellator::playRecording( void *_dl )
+{
+ playBack = 1;
+ bgnrender();
+ ((DisplayList *)_dl)->play();
+ endrender();
+ playBack = 0;
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/nurbstess.cc b/src/glu/sgi/libnurbs/internals/nurbstess.cc
new file mode 100644
index 00000000000..678f067b6f3
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/nurbstess.cc
@@ -0,0 +1,693 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * nurbstess.c++
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/nurbstess.cc,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mysetjmp.h"
+#include "mystdio.h"
+#include "nurbsconsts.h"
+#include "nurbstess.h"
+#include "bufpool.h"
+#include "quilt.h"
+#include "knotvector.h"
+#include "mapdesc.h"
+#include "maplist.h"
+
+void
+NurbsTessellator::set_domain_distance_u_rate(REAL u_rate)
+{
+ subdivider.set_domain_distance_u_rate(u_rate);
+}
+
+void
+NurbsTessellator::set_domain_distance_v_rate(REAL v_rate)
+{
+ subdivider.set_domain_distance_v_rate(v_rate);
+}
+
+void
+NurbsTessellator::set_is_domain_distance_sampling(int flag)
+{
+ subdivider.set_is_domain_distance_sampling(flag);
+}
+
+void
+NurbsTessellator::resetObjects( void )
+{
+ subdivider.clear();
+}
+
+void
+NurbsTessellator::makeobj( int )
+{
+#ifndef NDEBUG
+ dprintf( "makeobj\n" );
+#endif
+}
+
+void
+NurbsTessellator::closeobj( void )
+{
+#ifndef NDEBUG
+ dprintf( "closeobj\n" );
+#endif
+}
+
+void
+NurbsTessellator::bgnrender( void )
+{
+#ifndef NDEBUG
+ dprintf( "bgnrender\n" );
+#endif
+}
+
+void
+NurbsTessellator::endrender( void )
+{
+#ifndef NDEBUG
+ dprintf( "endrender\n" );
+#endif
+}
+
+/*-----------------------------------------------------------------------------
+ * do_freebgnsurface - free o_surface structure
+ *
+ * Client: do_freeall(), bgnsurface()
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_freebgnsurface( O_surface *o_surface )
+{
+ o_surface->deleteMe( o_surfacePool );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * do_bgnsurface - begin the display of a surface
+ *
+ * Client: bgnsurface()
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_bgnsurface( O_surface *o_surface )
+{
+ if( inSurface ) {
+ do_nurbserror( 27 );
+ endsurface();
+ }
+ inSurface = 1;
+
+ if( ! playBack ) bgnrender();
+
+ isTrimModified = 0;
+ isSurfaceModified = 0;
+ isDataValid = 1;
+ numTrims = 0;
+ currentSurface = o_surface;
+ nextTrim = &( currentSurface->o_trim );
+ nextNurbssurface = &( currentSurface->o_nurbssurface );
+}
+
+/*-----------------------------------------------------------------------------
+ * do_bgncurve - begin the display of a curve
+ *
+ * Client: bgncurve()
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_bgncurve( O_curve *o_curve )
+{
+ if ( inCurve ) {
+ do_nurbserror( 6 );
+ endcurve();
+ }
+
+ inCurve = 1;
+ currentCurve = o_curve;
+ currentCurve->curvetype = ct_none;
+
+ if( inTrim ) {
+ if( *nextCurve != o_curve ) {
+ isCurveModified = 1;
+ *nextCurve = o_curve;
+ }
+ } else {
+ if( ! playBack ) bgnrender();
+ isDataValid = 1;
+ }
+ nextCurve = &(o_curve->next);
+ nextPwlcurve = &(o_curve->curve.o_pwlcurve);
+ nextNurbscurve = &(o_curve->curve.o_nurbscurve);
+}
+
+/*-----------------------------------------------------------------------------
+ * do_endcurve -
+ *
+ * Client: endcurve()
+ *-----------------------------------------------------------------------------
+ */
+
+void
+NurbsTessellator::do_endcurve( void )
+{
+ if( ! inCurve ) {
+ do_nurbserror( 7 );
+ return;
+ }
+ inCurve = 0;
+
+ *nextCurve = 0;
+ if (currentCurve->curvetype == ct_nurbscurve)
+ *nextNurbscurve = 0;
+ else
+ *nextPwlcurve = 0;
+
+ if ( ! inTrim ) {
+ if( ! isDataValid ) {
+ do_freecurveall( currentCurve );
+ return;
+ }
+
+ int errval;
+ errval = ::mysetjmp( jumpbuffer );
+ if( errval == 0 ) {
+ if( currentCurve->curvetype == ct_nurbscurve ) {
+ subdivider.beginQuilts();
+ for( O_nurbscurve *n = currentCurve->curve.o_nurbscurve; n != 0; n = n->next )
+ subdivider.addQuilt( n->bezier_curves );
+ subdivider.endQuilts();
+ subdivider.drawCurves();
+ if( ! playBack ) endrender();
+ } else {
+ /* XXX */
+ if( ! playBack ) endrender();
+ /*do_draw_pwlcurve( currentCurve->curve.o_pwlcurve ) */;
+ do_nurbserror( 9 );
+ }
+ } else {
+ if( ! playBack ) endrender();
+ do_nurbserror( errval );
+ }
+ do_freecurveall( currentCurve );
+ resetObjects();
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * do_endsurface - mark end of surface, display surface, free immediate data
+ *
+ * Client:
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_endsurface( void )
+{
+ if( inTrim ) {
+ do_nurbserror( 12 );
+ endtrim();
+ }
+
+ if( ! inSurface ) {
+ do_nurbserror( 13 );
+ return;
+ }
+ inSurface = 0;
+
+ *nextNurbssurface = 0;
+
+ if( ! isDataValid ) {
+ do_freeall( );
+ return;
+ }
+
+ if( *nextTrim != 0 ) {
+ isTrimModified = 1;
+ *nextTrim = 0;
+ }
+
+ int errval;
+
+ errval = ::mysetjmp( jumpbuffer );
+ if( errval == 0 ) {
+ if( numTrims > 0 ) {
+
+ subdivider.beginTrims();
+ for( O_trim *trim = currentSurface->o_trim; trim; trim = trim->next ) {
+ subdivider.beginLoop();
+ for( O_curve *curve = trim->o_curve; curve; curve = curve->next ) {
+ curve->used = 0;
+ assert( curve->curvetype != ct_none );
+ if (curve->curvetype == ct_pwlcurve) {
+ O_pwlcurve *c = curve->curve.o_pwlcurve;
+ subdivider.addArc( c->npts, c->pts, curve->nuid );
+ } else {
+ Quilt *quilt = curve->curve.o_nurbscurve->bezier_curves;
+ Quiltspec *qspec = quilt->qspec;
+ REAL *cpts = quilt->cpts + qspec->offset;
+ REAL *cptsend = cpts + (qspec->width * qspec->order * qspec->stride);
+ for( ; cpts != cptsend; cpts += qspec->order*qspec->stride )
+ subdivider.addArc( cpts, quilt, curve->nuid );
+ }
+ }
+ subdivider.endLoop();
+ }
+ subdivider.endTrims();
+ }
+
+ subdivider.beginQuilts();
+ for( O_nurbssurface *n = currentSurface->o_nurbssurface; n; n = n->next )
+ subdivider.addQuilt( n->bezier_patches );
+ subdivider.endQuilts();
+ subdivider.drawSurfaces( currentSurface->nuid );
+ if( ! playBack ) endrender();
+ } else {
+ if( ! playBack ) endrender();
+ do_nurbserror( errval );
+ }
+
+ do_freeall( );
+ resetObjects();
+}
+
+/*-----------------------------------------------------------------------------
+ * do_freeall - free all data allocated in immediate mode
+ *
+ * Client:
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_freeall( void )
+{
+ for( O_trim *o_trim = currentSurface->o_trim; o_trim; ) {
+ O_trim *next_o_trim = o_trim->next;
+ for( O_curve *curve = o_trim->o_curve; curve; ) {
+ O_curve *next_o_curve = curve->next;
+ do_freecurveall( curve );
+ curve = next_o_curve;
+ }
+ if( o_trim->save == 0 ) do_freebgntrim( o_trim );
+ o_trim = next_o_trim;
+ }
+
+ O_nurbssurface *nurbss, *next_nurbss;
+ for( nurbss= currentSurface->o_nurbssurface; nurbss; nurbss = next_nurbss) {
+ next_nurbss = nurbss->next;
+ if( nurbss->save == 0 )
+ do_freenurbssurface( nurbss );
+ else
+ nurbss->used = 0;
+ }
+
+ if( currentSurface->save == 0 ) do_freebgnsurface( currentSurface );
+}
+
+void
+NurbsTessellator::do_freecurveall( O_curve *curve )
+{
+ assert( curve->curvetype != ct_none );
+
+ if( curve->curvetype == ct_nurbscurve ) {
+ O_nurbscurve *ncurve, *next_ncurve;
+ for( ncurve=curve->curve.o_nurbscurve; ncurve; ncurve=next_ncurve ) {
+ next_ncurve = ncurve->next;
+ if( ncurve->save == 0 )
+ do_freenurbscurve( ncurve );
+ else
+ ncurve->used = 0;
+ }
+ } else {
+ O_pwlcurve *pcurve, *next_pcurve;
+ for( pcurve=curve->curve.o_pwlcurve; pcurve; pcurve=next_pcurve ) {
+ next_pcurve = pcurve->next;
+ if( pcurve->save == 0 )
+ do_freepwlcurve( pcurve );
+ else
+ pcurve->used = 0;
+ }
+ }
+ if( curve->save == 0 )
+ do_freebgncurve( curve );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * do_freebgntrim - free the space allocated for a trim loop
+ *
+ * Client:
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_freebgntrim( O_trim *o_trim )
+{
+ o_trim->deleteMe( o_trimPool );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * do_bgntrim - link in a trim loop to the current trimmed surface description
+ *
+ * Client: bgntrim()
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_bgntrim( O_trim *o_trim )
+{
+
+ if( ! inSurface ) {
+ do_nurbserror( 15 );
+ bgnsurface( 0 );
+ inSurface = 2;
+ }
+
+ if( inTrim ) {
+ do_nurbserror( 16 );
+ endtrim();
+ }
+ inTrim = 1;
+
+ if( *nextTrim != o_trim ) {
+ isTrimModified = 1;
+ *nextTrim = o_trim;
+ }
+
+ currentTrim = o_trim;
+ nextTrim = &(o_trim->next);
+ nextCurve = &(o_trim->o_curve);
+}
+
+
+/*-----------------------------------------------------------------------------
+ * do_endtrim - mark the end of the current trim loop
+ *
+ * Client: endtrim()
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_endtrim( void )
+{
+ if( ! inTrim ) {
+ do_nurbserror( 17 );
+ return;
+ }
+ inTrim = 0;
+
+ if( currentTrim->o_curve == 0 ) {
+ do_nurbserror( 18 );
+ isDataValid = 0;
+ }
+
+ numTrims++;
+
+ if( *nextCurve != 0 ) {
+ isTrimModified = 1;
+ *nextCurve = 0;
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * do_freepwlcurve -
+ *
+ * Client:
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_freepwlcurve( O_pwlcurve *o_pwlcurve )
+{
+ o_pwlcurve->deleteMe( o_pwlcurvePool );
+}
+
+void
+NurbsTessellator::do_freebgncurve( O_curve *o_curve )
+{
+ o_curve->deleteMe( o_curvePool );
+}
+
+/*-----------------------------------------------------------------------------
+ * do_pwlcurve - link in pwl trim loop to the current surface description
+ *
+ * Client: pwlcurve()
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_pwlcurve( O_pwlcurve *o_pwlcurve )
+{
+ if( ! inTrim ) {
+ do_nurbserror( 19 );
+ if( o_pwlcurve->save == 0 )
+ do_freepwlcurve(o_pwlcurve );
+ return;
+ }
+
+ if( ! inCurve ) {
+ bgncurve( 0 );
+ inCurve = 2;
+ }
+
+ if( o_pwlcurve->used ) {
+ do_nurbserror( 20 );
+ isDataValid = 0;
+ return;
+ } else
+ o_pwlcurve->used = 1;
+
+ if( currentCurve->curvetype == ct_none ) {
+ currentCurve->curvetype = ct_pwlcurve;
+ } else if( currentCurve->curvetype != ct_pwlcurve ) {
+ do_nurbserror( 21 );
+ isDataValid = 0;
+ return;
+ }
+
+ if( *nextPwlcurve != o_pwlcurve ) {
+ isCurveModified = 1;
+ *nextPwlcurve = o_pwlcurve;
+ }
+ nextPwlcurve = &(o_pwlcurve->next);
+
+ if( o_pwlcurve->owner != currentCurve ) {
+ isCurveModified = 1;
+ o_pwlcurve->owner = currentCurve;
+ }
+
+ if( (inCurve == 2) )
+ endcurve();
+}
+
+
+/*-----------------------------------------------------------------------------
+ * do_freenurbscurve -
+ *
+ * Client:
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_freenurbscurve( O_nurbscurve *o_nurbscurve )
+{
+ o_nurbscurve->bezier_curves->deleteMe( quiltPool );
+ o_nurbscurve->deleteMe( o_nurbscurvePool );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * do_nurbscurve -
+ *
+ * Client: nurbscurve()
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_nurbscurve( O_nurbscurve *o_nurbscurve )
+{
+ if ( ! inCurve ) {
+ bgncurve( 0 );
+ inCurve = 2;
+ }
+
+ if( o_nurbscurve->used ) {
+ /* error - curve was already called in current surface */
+ do_nurbserror( 23 );
+ isDataValid = 0;
+ return;
+ } else
+ o_nurbscurve->used = 1;
+
+ if( currentCurve->curvetype == ct_none ) {
+ currentCurve->curvetype = ct_nurbscurve;
+ } else if( currentCurve->curvetype != ct_nurbscurve ) {
+ do_nurbserror( 24 );
+ isDataValid = 0;
+ return;
+ }
+
+ if( *nextNurbscurve != o_nurbscurve ) {
+ isCurveModified = 1;
+ *nextNurbscurve = o_nurbscurve;
+ }
+
+ nextNurbscurve = &(o_nurbscurve->next);
+
+ if( o_nurbscurve->owner != currentCurve ) {
+ isCurveModified = 1;
+ o_nurbscurve->owner = currentCurve;
+ }
+
+ if( o_nurbscurve->owner == 0 )
+ isCurveModified = 1;
+
+ if( inCurve == 2 )
+ endcurve();
+}
+
+
+/*-----------------------------------------------------------------------------
+ * do_freenurbssurface -
+ *
+ * Client:
+ *-----------------------------------------------------------------------------
+ */
+
+void
+NurbsTessellator::do_freenurbssurface( O_nurbssurface *o_nurbssurface )
+{
+ o_nurbssurface->bezier_patches->deleteMe( quiltPool );
+ o_nurbssurface->deleteMe( o_nurbssurfacePool );
+}
+
+/*-----------------------------------------------------------------------------
+ * do_nurbssurface -
+ *
+ * Client: nurbssurface()
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_nurbssurface( O_nurbssurface *o_nurbssurface )
+{
+ if( ! inSurface ) {
+ bgnsurface( 0 );
+ inSurface = 2;
+ }
+
+ if( o_nurbssurface->used ) {
+ /* error - surface was already called in current block */
+ do_nurbserror( 25 );
+ isDataValid = 0;
+ return;
+ } else
+ o_nurbssurface->used = 1;
+
+ if( *nextNurbssurface != o_nurbssurface ) {
+ isSurfaceModified = 1;
+ *nextNurbssurface = o_nurbssurface;
+ }
+
+ if( o_nurbssurface->owner != currentSurface ) {
+ isSurfaceModified = 1;
+ o_nurbssurface->owner = currentSurface;
+ }
+ nextNurbssurface = &(o_nurbssurface->next);
+
+ if( inSurface == 2 )
+ endsurface();
+}
+
+
+/*-----------------------------------------------------------------------------
+ * do_freenurbsproperty
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+NurbsTessellator::do_freenurbsproperty( Property *prop )
+{
+ prop->deleteMe( propertyPool );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * do_setnurbsproperty -
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+NurbsTessellator::do_setnurbsproperty( Property *prop )
+{
+ renderhints.setProperty( prop->tag, prop->value );
+ if( prop->save == 0 )
+ do_freenurbsproperty( prop );
+}
+
+void
+NurbsTessellator::do_setnurbsproperty2( Property *prop )
+{
+ Mapdesc *mapdesc = maplist.find( prop->type );
+
+ mapdesc->setProperty( prop->tag, prop->value );
+ if( prop->save == 0 )
+ do_freenurbsproperty( prop );
+}
+
+void
+NurbsTessellator::errorHandler( int )
+{
+}
+
+void
+NurbsTessellator::do_nurbserror( int msg )
+{
+ errorHandler( msg );
+}
+
+int
+NurbsTessellator::do_check_knots( Knotvector *knots, char *msg )
+{
+ int status = knots->validate();
+ if( status ) {
+ do_nurbserror( status );
+ if( renderhints.errorchecking != N_NOMSG ) knots->show( msg );
+ }
+ return status;
+}
+
+
+
+
+
diff --git a/src/glu/sgi/libnurbs/internals/nurbstess.h b/src/glu/sgi/libnurbs/internals/nurbstess.h
new file mode 100644
index 00000000000..3577088a9c2
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/nurbstess.h
@@ -0,0 +1,176 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * nurbstess.h
+ *
+ */
+
+#ifndef __glunurbstess_h_
+#define __glunurbstess_h_
+
+#include "mysetjmp.h"
+#include "subdivider.h"
+#include "renderhints.h"
+#include "backend.h"
+#include "maplist.h"
+#include "reader.h"
+#include "nurbsconsts.h"
+
+struct Knotvector;
+class Quilt;
+class DisplayList;
+class BasicCurveEvaluator;
+class BasicSurfaceEvaluator;
+
+class NurbsTessellator {
+public:
+ NurbsTessellator( BasicCurveEvaluator &c,
+ BasicSurfaceEvaluator &e );
+ virtual ~NurbsTessellator( void );
+
+ void getnurbsproperty( long, INREAL * );
+ void getnurbsproperty( long, long, INREAL * );
+ void setnurbsproperty( long, INREAL );
+ void setnurbsproperty( long, long, INREAL );
+ void setnurbsproperty( long, long, INREAL * );
+ void setnurbsproperty( long, long, INREAL *, long, long );
+
+ // called before a tessellation begins/ends
+ virtual void bgnrender( void );
+ virtual void endrender( void );
+
+ // called to make a display list of the output vertices
+ virtual void makeobj( int n );
+ virtual void closeobj( void );
+
+ // called when a error occurs
+ virtual void errorHandler( int );
+
+ void bgnsurface( long );
+ void endsurface( void );
+ void bgntrim( void );
+ void endtrim( void );
+ void bgncurve( long );
+ void endcurve( void );
+ void pwlcurve( long, INREAL[], long, long );
+ void nurbscurve( long, INREAL[], long, INREAL[], long, long );
+ void nurbssurface( long, INREAL[], long, INREAL[], long, long,
+ INREAL[], long, long, long );
+
+ void defineMap( long, long, long );
+ void redefineMaps( void );
+
+ // recording of input description
+ void discardRecording( void * );
+ void * beginRecording( void );
+ void endRecording( void );
+ void playRecording( void * );
+
+ //for optimizing untrimmed nurbs in the case of domain distance sampling
+ void set_domain_distance_u_rate(REAL u_rate);
+ void set_domain_distance_v_rate(REAL v_rate);
+ void set_is_domain_distance_sampling(int flag);
+
+
+protected:
+ Renderhints renderhints;
+ Maplist maplist;
+ Backend backend;
+
+private:
+
+ void resetObjects( void );
+ int do_check_knots( Knotvector *, char * );
+ void do_nurbserror( int );
+ void do_bgncurve( O_curve * );
+ void do_endcurve( void );
+ void do_freeall( void );
+ void do_freecurveall( O_curve * );
+ void do_freebgntrim( O_trim * );
+ void do_freebgncurve( O_curve * );
+ void do_freepwlcurve( O_pwlcurve * );
+ void do_freenurbscurve( O_nurbscurve * );
+ void do_freenurbssurface( O_nurbssurface * );
+ void do_freebgnsurface( O_surface * );
+ void do_bgnsurface( O_surface * );
+ void do_endsurface( void );
+ void do_bgntrim( O_trim * );
+ void do_endtrim( void );
+ void do_pwlcurve( O_pwlcurve * );
+ void do_nurbscurve( O_nurbscurve * );
+ void do_nurbssurface( O_nurbssurface * );
+ void do_freenurbsproperty( Property * );
+ void do_setnurbsproperty( Property * );
+ void do_setnurbsproperty2( Property * );
+
+ Subdivider subdivider;
+ JumpBuffer* jumpbuffer;
+ Pool o_pwlcurvePool;
+ Pool o_nurbscurvePool;
+ Pool o_curvePool;
+ Pool o_trimPool;
+ Pool o_surfacePool;
+ Pool o_nurbssurfacePool;
+ Pool propertyPool;
+public:
+ Pool quiltPool;
+private:
+ TrimVertexPool extTrimVertexPool;
+
+ int inSurface; /* bgnsurface seen */
+ int inCurve; /* bgncurve seen */
+ int inTrim; /* bgntrim seen */
+ int isCurveModified; /* curve changed */
+ int isTrimModified; /* trim curves changed */
+ int isSurfaceModified; /* surface changed */
+ int isDataValid; /* all data is good */
+ int numTrims; /* valid trim regions */
+ int playBack;
+
+ O_trim** nextTrim; /* place to link o_trim */
+ O_curve** nextCurve; /* place to link o_curve */
+ O_nurbscurve** nextNurbscurve; /* place to link o_nurbscurve */
+ O_pwlcurve** nextPwlcurve; /* place to link o_pwlcurve */
+ O_nurbssurface** nextNurbssurface; /* place to link o_nurbssurface */
+
+ O_surface* currentSurface;
+ O_trim* currentTrim;
+ O_curve* currentCurve;
+
+ DisplayList *dl;
+
+};
+
+#endif /* __glunurbstess_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/patch.cc b/src/glu/sgi/libnurbs/internals/patch.cc
new file mode 100644
index 00000000000..664819cae77
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/patch.cc
@@ -0,0 +1,506 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * patch.c++
+ *
+ * $Date: 2002/11/01 23:35:07 $ $Revision: 1.3 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/patch.cc,v 1.3 2002/11/01 23:35:07 brianp Exp $
+ */
+
+#include <stdio.h>
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "mymath.h"
+#include "mystring.h"
+#include "patch.h"
+#include "mapdesc.h"
+#include "quilt.h"
+#include "nurbsconsts.h"
+#include "simplemath.h" //for glu_abs function in ::singleStep();
+
+
+/*--------------------------------------------------------------------------
+ * Patch - copy patch from quilt and transform control points
+ *--------------------------------------------------------------------------
+ */
+
+Patch::Patch( Quilt_ptr geo, REAL *pta, REAL *ptb, Patch *n )
+{
+/* pspec[i].range is uninit here */
+ mapdesc = geo->mapdesc;
+ cullval = mapdesc->isCulling() ? CULL_ACCEPT : CULL_TRIVIAL_ACCEPT;
+ notInBbox = mapdesc->isBboxSubdividing() ? 1 : 0;
+ needsSampling = mapdesc->isRangeSampling() ? 1 : 0;
+ pspec[0].order = geo->qspec[0].order;
+ pspec[1].order = geo->qspec[1].order;
+ pspec[0].stride = pspec[1].order * MAXCOORDS;
+ pspec[1].stride = MAXCOORDS;
+
+ /* transform control points to sampling and culling spaces */
+ REAL *ps = geo->cpts;
+ geo->select( pta, ptb );
+ ps += geo->qspec[0].offset;
+ ps += geo->qspec[1].offset;
+ ps += geo->qspec[0].index * geo->qspec[0].order * geo->qspec[0].stride;
+ ps += geo->qspec[1].index * geo->qspec[1].order * geo->qspec[1].stride;
+
+ if( needsSampling ) {
+ mapdesc->xformSampling( ps, geo->qspec[0].order, geo->qspec[0].stride,
+ geo->qspec[1].order, geo->qspec[1].stride,
+ spts, pspec[0].stride, pspec[1].stride );
+ }
+
+ if( cullval == CULL_ACCEPT ) {
+ mapdesc->xformCulling( ps, geo->qspec[0].order, geo->qspec[0].stride,
+ geo->qspec[1].order, geo->qspec[1].stride,
+ cpts, pspec[0].stride, pspec[1].stride );
+ }
+
+ if( notInBbox ) {
+ mapdesc->xformBounding( ps, geo->qspec[0].order, geo->qspec[0].stride,
+ geo->qspec[1].order, geo->qspec[1].stride,
+ bpts, pspec[0].stride, pspec[1].stride );
+ }
+
+ /* set scale range */
+ pspec[0].range[0] = geo->qspec[0].breakpoints[geo->qspec[0].index];
+ pspec[0].range[1] = geo->qspec[0].breakpoints[geo->qspec[0].index+1];
+ pspec[0].range[2] = pspec[0].range[1] - pspec[0].range[0];
+
+ pspec[1].range[0] = geo->qspec[1].breakpoints[geo->qspec[1].index];
+ pspec[1].range[1] = geo->qspec[1].breakpoints[geo->qspec[1].index+1];
+ pspec[1].range[2] = pspec[1].range[1] - pspec[1].range[0];
+
+ // may need to subdivide to match range of sub-patch
+ if( pspec[0].range[0] != pta[0] ) {
+ assert( pspec[0].range[0] < pta[0] );
+ Patch lower( *this, 0, pta[0], 0 );
+ *this = lower;
+ }
+
+ if( pspec[0].range[1] != ptb[0] ) {
+ assert( pspec[0].range[1] > ptb[0] );
+ Patch upper( *this, 0, ptb[0], 0 );
+ }
+
+ if( pspec[1].range[0] != pta[1] ) {
+ assert( pspec[1].range[0] < pta[1] );
+ Patch lower( *this, 1, pta[1], 0 );
+ *this = lower;
+ }
+
+ if( pspec[1].range[1] != ptb[1] ) {
+ assert( pspec[1].range[1] > ptb[1] );
+ Patch upper( *this, 1, ptb[1], 0 );
+ }
+ checkBboxConstraint();
+ next = n;
+}
+
+/*--------------------------------------------------------------------------
+ * Patch - subdivide a patch along an isoparametric line
+ *--------------------------------------------------------------------------
+ */
+
+Patch::Patch( Patch& upper, int param, REAL value, Patch *n )
+{
+ Patch& lower = *this;
+
+ lower.cullval = upper.cullval;
+ lower.mapdesc = upper.mapdesc;
+ lower.notInBbox = upper.notInBbox;
+ lower.needsSampling = upper.needsSampling;
+ lower.pspec[0].order = upper.pspec[0].order;
+ lower.pspec[1].order = upper.pspec[1].order;
+ lower.pspec[0].stride = upper.pspec[0].stride;
+ lower.pspec[1].stride = upper.pspec[1].stride;
+ lower.next = n;
+
+ /* reset scale range */
+ switch( param ) {
+ case 0: {
+ REAL d = (value-upper.pspec[0].range[0]) / upper.pspec[0].range[2];
+ if( needsSampling )
+ mapdesc->subdivide( upper.spts, lower.spts, d, pspec[1].order,
+ pspec[1].stride, pspec[0].order, pspec[0].stride );
+
+ if( cullval == CULL_ACCEPT )
+ mapdesc->subdivide( upper.cpts, lower.cpts, d, pspec[1].order,
+ pspec[1].stride, pspec[0].order, pspec[0].stride );
+
+ if( notInBbox )
+ mapdesc->subdivide( upper.bpts, lower.bpts, d, pspec[1].order,
+ pspec[1].stride, pspec[0].order, pspec[0].stride );
+
+ lower.pspec[0].range[0] = upper.pspec[0].range[0];
+ lower.pspec[0].range[1] = value;
+ lower.pspec[0].range[2] = value - upper.pspec[0].range[0];
+ upper.pspec[0].range[0] = value;
+ upper.pspec[0].range[2] = upper.pspec[0].range[1] - value;
+
+ lower.pspec[1].range[0] = upper.pspec[1].range[0];
+ lower.pspec[1].range[1] = upper.pspec[1].range[1];
+ lower.pspec[1].range[2] = upper.pspec[1].range[2];
+ break;
+ }
+ case 1: {
+ REAL d = (value-upper.pspec[1].range[0]) / upper.pspec[1].range[2];
+ if( needsSampling )
+ mapdesc->subdivide( upper.spts, lower.spts, d, pspec[0].order,
+ pspec[0].stride, pspec[1].order, pspec[1].stride );
+ if( cullval == CULL_ACCEPT )
+ mapdesc->subdivide( upper.cpts, lower.cpts, d, pspec[0].order,
+ pspec[0].stride, pspec[1].order, pspec[1].stride );
+ if( notInBbox )
+ mapdesc->subdivide( upper.bpts, lower.bpts, d, pspec[0].order,
+ pspec[0].stride, pspec[1].order, pspec[1].stride );
+ lower.pspec[0].range[0] = upper.pspec[0].range[0];
+ lower.pspec[0].range[1] = upper.pspec[0].range[1];
+ lower.pspec[0].range[2] = upper.pspec[0].range[2];
+
+ lower.pspec[1].range[0] = upper.pspec[1].range[0];
+ lower.pspec[1].range[1] = value;
+ lower.pspec[1].range[2] = value - upper.pspec[1].range[0];
+ upper.pspec[1].range[0] = value;
+ upper.pspec[1].range[2] = upper.pspec[1].range[1] - value;
+ break;
+ }
+ }
+
+ // inherit bounding box
+ if( mapdesc->isBboxSubdividing() && ! notInBbox )
+ memcpy( lower.bb, upper.bb, sizeof( bb ) );
+
+ lower.checkBboxConstraint();
+ upper.checkBboxConstraint();
+}
+
+/*--------------------------------------------------------------------------
+ * clamp - clamp the sampling rate to a given maximum
+ *--------------------------------------------------------------------------
+ */
+
+void
+Patch::clamp( void )
+{
+ if( mapdesc->clampfactor != N_NOCLAMPING ) {
+ pspec[0].clamp( mapdesc->clampfactor );
+ pspec[1].clamp( mapdesc->clampfactor );
+ }
+}
+
+void
+Patchspec::clamp( REAL clampfactor )
+{
+ if( sidestep[0] < minstepsize )
+ sidestep[0] = clampfactor * minstepsize;
+ if( sidestep[1] < minstepsize )
+ sidestep[1] = clampfactor * minstepsize;
+ if( stepsize < minstepsize )
+ stepsize = clampfactor * minstepsize;
+}
+
+void
+Patch::checkBboxConstraint( void )
+{
+ if( notInBbox &&
+ mapdesc->bboxTooBig( bpts, pspec[0].stride, pspec[1].stride,
+ pspec[0].order, pspec[1].order, bb ) != 1 ) {
+ notInBbox = 0;
+ }
+}
+
+void
+Patch::bbox( void )
+{
+ if( mapdesc->isBboxSubdividing() )
+ mapdesc->surfbbox( bb );
+}
+
+/*--------------------------------------------------------------------------
+ * getstepsize - compute the sampling density across the patch
+ * and determine if patch needs to be subdivided
+ *--------------------------------------------------------------------------
+ */
+
+void
+Patch::getstepsize( void )
+{
+ pspec[0].minstepsize = pspec[1].minstepsize = 0;
+ pspec[0].needsSubdivision = pspec[1].needsSubdivision = 0;
+
+ if( mapdesc->isConstantSampling() ) {
+ // fixed number of samples per patch in each direction
+ // maxsrate is number of s samples per patch
+ // maxtrate is number of t samples per patch
+ pspec[0].getstepsize( mapdesc->maxsrate );
+ pspec[1].getstepsize( mapdesc->maxtrate );
+
+ } else if( mapdesc->isDomainSampling() ) {
+ // maxsrate is number of s samples per unit s length of domain
+ // maxtrate is number of t samples per unit t length of domain
+ pspec[0].getstepsize( mapdesc->maxsrate * pspec[0].range[2] );
+ pspec[1].getstepsize( mapdesc->maxtrate * pspec[1].range[2] );
+
+ } else if( ! needsSampling ) {
+ pspec[0].singleStep();
+ pspec[1].singleStep();
+ } else {
+ // upper bound on path length between sample points
+ REAL tmp[MAXORDER][MAXORDER][MAXCOORDS];
+ const int trstride = sizeof(tmp[0]) / sizeof(REAL);
+ const int tcstride = sizeof(tmp[0][0]) / sizeof(REAL);
+
+ assert( pspec[0].order <= MAXORDER );
+
+ /* points have been transformed, therefore they are homogeneous */
+
+ int val = mapdesc->project( spts, pspec[0].stride, pspec[1].stride,
+ &tmp[0][0][0], trstride, tcstride,
+ pspec[0].order, pspec[1].order );
+ if( val == 0 ) {
+ // control points cross infinity, therefore partials are undefined
+ pspec[0].getstepsize( mapdesc->maxsrate );
+ pspec[1].getstepsize( mapdesc->maxtrate );
+ } else {
+ REAL t1 = mapdesc->getProperty( N_PIXEL_TOLERANCE );
+// REAL t2 = mapdesc->getProperty( N_ERROR_TOLERANCE );
+ pspec[0].minstepsize = ( mapdesc->maxsrate > 0.0 ) ?
+ (pspec[0].range[2] / mapdesc->maxsrate) : 0.0;
+ pspec[1].minstepsize = ( mapdesc->maxtrate > 0.0 ) ?
+ (pspec[1].range[2] / mapdesc->maxtrate) : 0.0;
+ if( mapdesc->isParametricDistanceSampling() ||
+ mapdesc->isObjectSpaceParaSampling() ) {
+
+ REAL t2;
+ t2 = mapdesc->getProperty( N_ERROR_TOLERANCE );
+
+ // t2 is upper bound on the distance between surface and tessellant
+ REAL ssv[2], ttv[2];
+ REAL ss = mapdesc->calcPartialVelocity( ssv, &tmp[0][0][0], trstride, tcstride, pspec[0].order, pspec[1].order, 2, 0, pspec[0].range[2], pspec[1].range[2], 0 );
+ REAL st = mapdesc->calcPartialVelocity( 0, &tmp[0][0][0], trstride, tcstride, pspec[0].order, pspec[1].order, 1, 1, pspec[0].range[2], pspec[1].range[2], -1 );
+ REAL tt = mapdesc->calcPartialVelocity( ttv, &tmp[0][0][0], trstride, tcstride, pspec[0].order, pspec[1].order, 0, 2, pspec[0].range[2], pspec[1].range[2], 1 );
+ //make sure that ss st and tt are nonnegative:
+ if(ss <0) ss = -ss;
+ if(st <0) st = -st;
+ if(tt <0) tt = -tt;
+
+ if( ss != 0.0 && tt != 0.0 ) {
+ /* printf( "ssv[0] %g ssv[1] %g ttv[0] %g ttv[1] %g\n",
+ ssv[0], ssv[1], ttv[0], ttv[1] ); */
+ REAL ttq = sqrtf( (float) ss );
+ REAL ssq = sqrtf( (float) tt );
+ REAL ds = sqrtf( 4 * t2 * ttq / ( ss * ttq + st * ssq ) );
+ REAL dt = sqrtf( 4 * t2 * ssq / ( tt * ssq + st * ttq ) );
+ pspec[0].stepsize = ( ds < pspec[0].range[2] ) ? ds : pspec[0].range[2];
+ REAL scutoff = 2.0 * t2 / ( pspec[0].range[2] * pspec[0].range[2]);
+ pspec[0].sidestep[0] = (ssv[0] > scutoff) ? sqrtf( 2.0 * t2 / ssv[0] ) : pspec[0].range[2];
+ pspec[0].sidestep[1] = (ssv[1] > scutoff) ? sqrtf( 2.0 * t2 / ssv[1] ) : pspec[0].range[2];
+
+ pspec[1].stepsize = ( dt < pspec[1].range[2] ) ? dt : pspec[1].range[2];
+ REAL tcutoff = 2.0 * t2 / ( pspec[1].range[2] * pspec[1].range[2]);
+ pspec[1].sidestep[0] = (ttv[0] > tcutoff) ? sqrtf( 2.0 * t2 / ttv[0] ) : pspec[1].range[2];
+ pspec[1].sidestep[1] = (ttv[1] > tcutoff) ? sqrtf( 2.0 * t2 / ttv[1] ) : pspec[1].range[2];
+ } else if( ss != 0.0 ) {
+ REAL x = pspec[1].range[2] * st;
+ REAL ds = ( sqrtf( x * x + 8.0 * t2 * ss ) - x ) / ss;
+ pspec[0].stepsize = ( ds < pspec[0].range[2] ) ? ds : pspec[0].range[2];
+ REAL scutoff = 2.0 * t2 / ( pspec[0].range[2] * pspec[0].range[2]);
+ pspec[0].sidestep[0] = (ssv[0] > scutoff) ? sqrtf( 2.0 * t2 / ssv[0] ) : pspec[0].range[2];
+ pspec[0].sidestep[1] = (ssv[1] > scutoff) ? sqrtf( 2.0 * t2 / ssv[1] ) : pspec[0].range[2];
+ pspec[1].singleStep();
+ } else if( tt != 0.0 ) {
+ REAL x = pspec[0].range[2] * st;
+ REAL dt = ( sqrtf( x * x + 8.0 * t2 * tt ) - x ) / tt;
+ pspec[0].singleStep();
+ REAL tcutoff = 2.0 * t2 / ( pspec[1].range[2] * pspec[1].range[2]);
+ pspec[1].stepsize = ( dt < pspec[1].range[2] ) ? dt : pspec[1].range[2];
+ pspec[1].sidestep[0] = (ttv[0] > tcutoff) ? sqrtf( 2.0 * t2 / ttv[0] ) : pspec[1].range[2];
+ pspec[1].sidestep[1] = (ttv[1] > tcutoff) ? sqrtf( 2.0 * t2 / ttv[1] ) : pspec[1].range[2];
+ } else {
+ if( 4.0 * t2 > st * pspec[0].range[2] * pspec[1].range[2] ) {
+ pspec[0].singleStep();
+ pspec[1].singleStep();
+ } else {
+ REAL area = 4.0 * t2 / st;
+ REAL ds = sqrtf( area * pspec[0].range[2] / pspec[1].range[2] );
+ REAL dt = sqrtf( area * pspec[1].range[2] / pspec[0].range[2] );
+ pspec[0].stepsize = ( ds < pspec[0].range[2] ) ? ds : pspec[0].range[2];
+ pspec[0].sidestep[0] = pspec[0].range[2];
+ pspec[0].sidestep[1] = pspec[0].range[2];
+
+ pspec[1].stepsize = ( dt < pspec[1].range[2] ) ? dt : pspec[1].range[2];
+ pspec[1].sidestep[0] = pspec[1].range[2];
+ pspec[1].sidestep[1] = pspec[1].range[2];
+ }
+ }
+ } else if( mapdesc->isPathLengthSampling() ||
+ mapdesc->isObjectSpacePathSampling()) {
+ // t1 is upper bound on path length
+ REAL msv[2], mtv[2];
+ REAL ms = mapdesc->calcPartialVelocity( msv, &tmp[0][0][0], trstride, tcstride, pspec[0].order, pspec[1].order, 1, 0, pspec[0].range[2], pspec[1].range[2], 0 );
+ REAL mt = mapdesc->calcPartialVelocity( mtv, &tmp[0][0][0], trstride, tcstride, pspec[0].order, pspec[1].order, 0, 1, pspec[0].range[2], pspec[1].range[2], 1 );
+ REAL side_scale = 1.0;
+
+ if( ms != 0.0 ) {
+ if( mt != 0.0 ) {
+/* REAL d = t1 / ( ms * ms + mt * mt );*/
+/* REAL ds = mt * d;*/
+ REAL ds = t1 / (2.0*ms);
+/* REAL dt = ms * d;*/
+ REAL dt = t1 / (2.0*mt);
+ pspec[0].stepsize = ( ds < pspec[0].range[2] ) ? ds : pspec[0].range[2];
+ pspec[0].sidestep[0] = ( msv[0] * pspec[0].range[2] > t1 ) ? (side_scale* t1 / msv[0]) : pspec[0].range[2];
+ pspec[0].sidestep[1] = ( msv[1] * pspec[0].range[2] > t1 ) ? (side_scale* t1 / msv[1]) : pspec[0].range[2];
+
+ pspec[1].stepsize = ( dt < pspec[1].range[2] ) ? dt : pspec[1].range[2];
+ pspec[1].sidestep[0] = ( mtv[0] * pspec[1].range[2] > t1 ) ? (side_scale*t1 / mtv[0]) : pspec[1].range[2];
+ pspec[1].sidestep[1] = ( mtv[1] * pspec[1].range[2] > t1 ) ? (side_scale*t1 / mtv[1]) : pspec[1].range[2];
+ } else {
+ pspec[0].stepsize = ( t1 < ms * pspec[0].range[2] ) ? (t1 / ms) : pspec[0].range[2];
+ pspec[0].sidestep[0] = ( msv[0] * pspec[0].range[2] > t1 ) ? (t1 / msv[0]) : pspec[0].range[2];
+ pspec[0].sidestep[1] = ( msv[1] * pspec[0].range[2] > t1 ) ? (t1 / msv[1]) : pspec[0].range[2];
+
+ pspec[1].singleStep();
+ }
+ } else {
+ if( mt != 0.0 ) {
+ pspec[0].singleStep();
+
+ pspec[1].stepsize = ( t1 < mt * pspec[1].range[2] ) ? (t1 / mt) : pspec[1].range[2];
+ pspec[1].sidestep[0] = ( mtv[0] * pspec[1].range[2] > t1 ) ? (t1 / mtv[0]) : pspec[1].range[2];
+ pspec[1].sidestep[1] = ( mtv[1] * pspec[1].range[2] > t1 ) ? (t1 / mtv[1]) : pspec[1].range[2];
+ } else {
+ pspec[0].singleStep();
+ pspec[1].singleStep();
+ }
+ }
+ } else if( mapdesc->isSurfaceAreaSampling() ) {
+ // t is the square root of area
+/*
+ REAL msv[2], mtv[2];
+ REAL ms = mapdesc->calcPartialVelocity( msv, &tmp[0][0][0], trstride, tcstride, pspec[0].order, pspec[1].order, 1, 0, pspec[0].range[2], pspec[1].range[2], 0 );
+ REAL mt = mapdesc->calcPartialVelocity( mtv, &tmp[0][0][0], trstride, tcstride, pspec[0].order, pspec[1].order, 0, 1, pspec[0].range[2], pspec[1].range[2], 1 );
+ if( ms != 0.0 && mt != 0.0 ) {
+ REAL d = 1.0 / (ms * mt);
+ t *= M_SQRT2;
+ REAL ds = t * sqrtf( d * pspec[0].range[2] / pspec[1].range[2] );
+ REAL dt = t * sqrtf( d * pspec[1].range[2] / pspec[0].range[2] );
+ pspec[0].stepsize = ( ds < pspec[0].range[2] ) ? ds : pspec[0].range[2];
+ pspec[0].sidestep[0] = ( msv[0] * pspec[0].range[2] > t ) ? (t / msv[0]) : pspec[0].range[2];
+ pspec[0].sidestep[1] = ( msv[1] * pspec[0].range[2] > t ) ? (t / msv[1]) : pspec[0].range[2];
+
+ pspec[1].stepsize = ( dt < pspec[1].range[2] ) ? dt : pspec[1].range[2];
+ pspec[1].sidestep[0] = ( mtv[0] * pspec[1].range[2] > t ) ? (t / mtv[0]) : pspec[1].range[2];
+ pspec[1].sidestep[1] = ( mtv[1] * pspec[1].range[2] > t ) ? (t / mtv[1]) : pspec[1].range[2];
+ } else {
+ pspec[0].singleStep();
+ pspec[1].singleStep();
+ }
+*/
+ } else {
+ pspec[0].singleStep();
+ pspec[1].singleStep();
+ }
+ }
+ }
+
+#ifdef DEBUG
+ dprintf( "sidesteps %g %g %g %g, stepsize %g %g\n",
+ pspec[0].sidestep[0], pspec[0].sidestep[1],
+ pspec[1].sidestep[0], pspec[1].sidestep[1],
+ pspec[0].stepsize, pspec[1].stepsize );
+#endif
+
+ if( mapdesc->minsavings != N_NOSAVINGSSUBDIVISION ) {
+ REAL savings = 1./(pspec[0].stepsize * pspec[1].stepsize) ;
+ savings-= (2./( pspec[0].sidestep[0] + pspec[0].sidestep[1] )) *
+ (2./( pspec[1].sidestep[0] + pspec[1].sidestep[1] ));
+
+ savings *= pspec[0].range[2] * pspec[1].range[2];
+ if( savings > mapdesc->minsavings ) {
+ pspec[0].needsSubdivision = pspec[1].needsSubdivision = 1;
+ }
+ }
+
+ if( pspec[0].stepsize < pspec[0].minstepsize ) pspec[0].needsSubdivision = 1;
+ if( pspec[1].stepsize < pspec[1].minstepsize ) pspec[1].needsSubdivision = 1;
+ needsSampling = (needsSampling ? needsSamplingSubdivision() : 0);
+}
+
+void
+Patchspec::singleStep()
+{
+ stepsize = sidestep[0] = sidestep[1] = glu_abs(range[2]);
+}
+
+void
+Patchspec::getstepsize( REAL max ) // max is number of samples for entire patch
+{
+ stepsize = ( max >= 1.0 ) ? range[2] / max : range[2];
+ if (stepsize < 0.0) {
+ stepsize = -stepsize;
+ }
+ sidestep[0] = sidestep[1] = minstepsize = stepsize;
+}
+
+int
+Patch::needsSamplingSubdivision( void )
+{
+ return (pspec[0].needsSubdivision || pspec[1].needsSubdivision) ? 1 : 0;
+}
+
+int
+Patch::needsNonSamplingSubdivision( void )
+{
+ return notInBbox;
+}
+
+int
+Patch::needsSubdivision( int param )
+{
+ return pspec[param].needsSubdivision;
+}
+
+int
+Patch::cullCheck( void )
+{
+ if( cullval == CULL_ACCEPT )
+ cullval = mapdesc->cullCheck( cpts, pspec[0].order, pspec[0].stride,
+ pspec[1].order, pspec[1].stride );
+ return cullval;
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/patch.h b/src/glu/sgi/libnurbs/internals/patch.h
new file mode 100644
index 00000000000..74d80dc24a3
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/patch.h
@@ -0,0 +1,100 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * patch.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/patch.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __glupatch_h_
+#define __glupatch_h_
+
+#include "types.h"
+#include "defines.h"
+
+class Quilt;
+class Mapdesc;
+
+
+struct Pspec {
+ REAL range[3];
+ REAL sidestep[2];
+ REAL stepsize;
+ REAL minstepsize;
+ int needsSubdivision;
+};
+
+struct Patchspec : public Pspec {
+ int order;
+ int stride;
+ void clamp( REAL );
+ void getstepsize( REAL );
+ void singleStep( void );
+};
+
+class Patch {
+public:
+friend class Subdivider;
+friend class Quilt;
+friend class Patchlist;
+ Patch( Quilt *, REAL*, REAL *, Patch * );
+ Patch( Patch &, int, REAL, Patch * );
+ void bbox( void );
+ void clamp( void );
+ void getstepsize( void );
+ int cullCheck( void );
+ int needsSubdivision( int );
+ int needsSamplingSubdivision( void );
+ int needsNonSamplingSubdivision( void );
+
+ int get_uorder() {return pspec[0].order;}
+ int get_vorder() {return pspec[1].order;}
+
+private:
+
+ Mapdesc* mapdesc;
+ Patch* next;
+ int cullval;
+ int notInBbox;
+ int needsSampling;
+ REAL cpts[MAXORDER*MAXORDER*MAXCOORDS]; //culling pts
+ REAL spts[MAXORDER*MAXORDER*MAXCOORDS]; //sampling pts
+ REAL bpts[MAXORDER*MAXORDER*MAXCOORDS]; //bbox pts
+ Patchspec pspec[2];
+ void checkBboxConstraint( void );
+ REAL bb[2][MAXCOORDS];
+};
+#endif /* __glupatch_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/patchlist.cc b/src/glu/sgi/libnurbs/internals/patchlist.cc
new file mode 100644
index 00000000000..d238bc501fd
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/patchlist.cc
@@ -0,0 +1,172 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * patchlist.c++
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/patchlist.cc,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#include <stdio.h>
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "quilt.h"
+#include "patchlist.h"
+#include "patch.h"
+#include "nurbsconsts.h"
+
+Patchlist::Patchlist( Quilt *quilts, REAL *pta, REAL *ptb )
+{
+ patch = 0;
+ for( Quilt *q = quilts; q; q = q->next )
+ patch = new Patch( q, pta, ptb, patch );
+ pspec[0].range[0] = pta[0];
+ pspec[0].range[1] = ptb[0];
+ pspec[0].range[2] = ptb[0] - pta[0];
+
+ pspec[1].range[0] = pta[1];
+ pspec[1].range[1] = ptb[1];
+ pspec[1].range[2] = ptb[1] - pta[1];
+}
+
+Patchlist::Patchlist( Patchlist &upper, int param, REAL value)
+{
+ Patchlist &lower = *this;
+ patch = 0;
+ for( Patch *p = upper.patch; p; p = p->next )
+ patch = new Patch( *p, param, value, patch );
+
+ if( param == 0 ) {
+ lower.pspec[0].range[0] = upper.pspec[0].range[0];
+ lower.pspec[0].range[1] = value;
+ lower.pspec[0].range[2] = value - upper.pspec[0].range[0];
+ upper.pspec[0].range[0] = value;
+ upper.pspec[0].range[2] = upper.pspec[0].range[1] - value;
+ lower.pspec[1] = upper.pspec[1];
+ } else {
+ lower.pspec[0] = upper.pspec[0];
+ lower.pspec[1].range[0] = upper.pspec[1].range[0];
+ lower.pspec[1].range[1] = value;
+ lower.pspec[1].range[2] = value - upper.pspec[1].range[0];
+ upper.pspec[1].range[0] = value;
+ upper.pspec[1].range[2] = upper.pspec[1].range[1] - value;
+ }
+}
+
+Patchlist::~Patchlist()
+{
+ while( patch ) {
+ Patch *p = patch;
+ patch = patch->next;
+ delete p;
+ }
+}
+
+int
+Patchlist::cullCheck( void )
+{
+ for( Patch *p = patch; p; p = p->next )
+ if( p->cullCheck() == CULL_TRIVIAL_REJECT )
+ return CULL_TRIVIAL_REJECT;
+ return CULL_ACCEPT;
+}
+
+void
+Patchlist::getRanges(REAL ranges[4])
+{
+ ranges[0] = pspec[0].range[0];
+ ranges[1] = pspec[0].range[1];
+ ranges[2] = pspec[1].range[0];
+ ranges[3] = pspec[1].range[1];
+}
+
+void
+Patchlist::getstepsize( void )
+{
+ pspec[0].stepsize = pspec[0].range[2];
+ pspec[0].sidestep[0] = pspec[0].range[2];
+ pspec[0].sidestep[1] = pspec[0].range[2];
+
+ pspec[1].stepsize = pspec[1].range[2];
+ pspec[1].sidestep[0] = pspec[1].range[2];
+ pspec[1].sidestep[1] = pspec[1].range[2];
+
+ for( Patch *p = patch; p; p = p->next ) {
+ p->getstepsize();
+ p->clamp();
+ pspec[0].stepsize = ((p->pspec[0].stepsize < pspec[0].stepsize) ? p->pspec[0].stepsize : pspec[0].stepsize);
+ pspec[0].sidestep[0] = ((p->pspec[0].sidestep[0] < pspec[0].sidestep[0]) ? p->pspec[0].sidestep[0] : pspec[0].sidestep[0]);
+ pspec[0].sidestep[1] = ((p->pspec[0].sidestep[1] < pspec[0].sidestep[1]) ? p->pspec[0].sidestep[1] : pspec[0].sidestep[1]);
+ pspec[1].stepsize = ((p->pspec[1].stepsize < pspec[1].stepsize) ? p->pspec[1].stepsize : pspec[1].stepsize);
+ pspec[1].sidestep[0] = ((p->pspec[1].sidestep[0] < pspec[1].sidestep[0]) ? p->pspec[1].sidestep[0] : pspec[1].sidestep[0]);
+ pspec[1].sidestep[1] = ((p->pspec[1].sidestep[1] < pspec[1].sidestep[1]) ? p->pspec[1].sidestep[1] : pspec[1].sidestep[1]);
+ }
+}
+
+void
+Patchlist::bbox( void )
+{
+ for( Patch *p = patch; p; p = p->next )
+ p->bbox();
+}
+
+int
+Patchlist::needsNonSamplingSubdivision( void )
+{
+ notInBbox = 0;
+ for( Patch *p = patch; p; p = p->next )
+ notInBbox |= p->needsNonSamplingSubdivision();
+ return notInBbox;
+}
+
+int
+Patchlist::needsSamplingSubdivision( void )
+{
+ pspec[0].needsSubdivision = 0;
+ pspec[1].needsSubdivision = 0;
+
+ for( Patch *p = patch; p; p = p->next ) {
+ pspec[0].needsSubdivision |= p->pspec[0].needsSubdivision;
+ pspec[1].needsSubdivision |= p->pspec[0].needsSubdivision;
+ }
+ return (pspec[0].needsSubdivision || pspec[1].needsSubdivision) ? 1 : 0;
+}
+
+int
+Patchlist::needsSubdivision( int param )
+{
+ return pspec[param].needsSubdivision;
+}
diff --git a/src/glu/sgi/libnurbs/internals/patchlist.h b/src/glu/sgi/libnurbs/internals/patchlist.h
new file mode 100644
index 00000000000..6e14042cddc
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/patchlist.h
@@ -0,0 +1,98 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * patchlist.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/patchlist.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __glupatchlist_h_
+#define __glupatchlist_h_
+
+#include "types.h"
+#include "defines.h"
+#include "patch.h"
+
+class Quilt;
+
+class Patchlist {
+friend class Subdivider;
+public:
+ Patchlist( Quilt *, REAL *, REAL * );
+ Patchlist( Patchlist &, int , REAL );
+ ~Patchlist();
+ void bbox();
+ int cullCheck( void );
+ void getstepsize( void );
+ int needsNonSamplingSubdivision( void );
+ int needsSamplingSubdivision( void );
+ int needsSubdivision( int );
+ REAL getStepsize( int );
+ void getRanges(REAL ranges[4]);
+
+ int get_uorder();
+ int get_vorder();
+private:
+ Patch *patch;
+ int notInBbox;
+ int needsSampling;
+ Pspec pspec[2];
+};
+
+inline REAL
+Patchlist::getStepsize( int param )
+{
+ return pspec[param].stepsize;
+}
+
+inline int
+Patchlist::get_uorder()
+{
+ return patch->get_uorder();
+
+}
+
+inline int
+ Patchlist::get_vorder()
+{
+ return patch->get_vorder();
+}
+
+
+
+
+
+#endif /* __glupatchlist_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/pwlarc.h b/src/glu/sgi/libnurbs/internals/pwlarc.h
new file mode 100644
index 00000000000..172472a1a6d
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/pwlarc.h
@@ -0,0 +1,84 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * pwlarc.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/pwlarc.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __glupwlarc_h_
+#define __glupwlarc_h_
+
+#include "myassert.h"
+#include "nurbsconsts.h"
+
+class TrimVertex;
+
+class PwlArc : public PooledObj { /* a piecewise-linear arc */
+public:
+ TrimVertex * pts; /* sample points */
+ int npts; /* number of sample points */
+ long type; /* curve type */
+ inline PwlArc( void );
+ inline PwlArc( int, TrimVertex * );
+ inline PwlArc( int, TrimVertex *, long );
+};
+
+inline
+PwlArc::PwlArc( void )
+{
+ type = N_P2D;
+ pts = 0;
+ npts = -1;
+}
+
+inline
+PwlArc::PwlArc( int _npts, TrimVertex *_pts )
+{
+ pts = _pts;
+ npts = _npts;
+ type = N_P2D;
+}
+
+inline
+PwlArc::PwlArc( int _npts, TrimVertex *_pts, long _type )
+{
+ pts = _pts;
+ npts = _npts;
+ type = _type;
+}
+
+#endif /* __glupwlarc_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/quilt.cc b/src/glu/sgi/libnurbs/internals/quilt.cc
new file mode 100644
index 00000000000..0e13eeb72d6
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/quilt.cc
@@ -0,0 +1,278 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * quilt.c++
+ *
+ * $Date: 2002/11/01 23:35:07 $ $Revision: 1.2 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/quilt.cc,v 1.2 2002/11/01 23:35:07 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "quilt.h"
+#include "backend.h"
+#include "mapdesc.h"
+#include "flist.h"
+#include "knotvector.h"
+#include "patchlist.h"
+#include "math.h" //fglu_abs()
+#include "simplemath.h" //min()
+
+/* local preprocessor definitions */
+#define DEF_PATCH_STEPSIZE .4
+#define fsizeof(x) (sizeof(x)/sizeof(REAL))
+
+
+Quilt::Quilt( Mapdesc *_mapdesc )
+{
+ mapdesc = _mapdesc;
+}
+
+void
+Quilt::deleteMe( Pool& p )
+{
+ for( Quiltspec *q=qspec; q != eqspec; q++ ) {
+#if 1
+ if( q->breakpoints) delete[] q->breakpoints; q->breakpoints = 0;
+#else
+ if( q->breakpoints) {
+ delete[] q->breakpoints;
+ q->breakpoints = 0;
+printf("in here\n");
+ }
+#endif
+ }
+ if( cpts ) delete[] cpts;
+ cpts = 0;
+ PooledObj::deleteMe( p );
+}
+
+void
+Quilt::show( void )
+{
+#ifndef NDEBUG
+ int nc = mapdesc->getNcoords();
+ REAL *ps = cpts;
+ ps += qspec[0].offset;
+ ps += qspec[1].offset;
+ for( int i=0; i!= qspec[0].order * qspec[0].width; i++ ) {
+ for( int j = 0; j!= qspec[1].order * qspec[1].width; j++ ) {
+ for( int k=0; k < nc; k++ )
+ dprintf( "%g ", ps[i*qspec[0].stride + j*qspec[1].stride + k] );
+ dprintf( "\n" );
+ }
+ dprintf( "\n" );
+ }
+ dprintf( "\n" );
+#endif
+}
+
+/*--------------------------------------------------------------------------
+ * Quilt::select - find which map in each quilt contains the points
+ * pta and ptb with pta[i] < ptb[i]
+ *--------------------------------------------------------------------------
+ */
+
+void
+Quilt::select( REAL *pta, REAL *ptb )
+{
+ int dim = eqspec - qspec;
+ int i, j;
+ for( i=0; i<dim; i++) {
+ for( j=qspec[i].width-1; j>=0; j-- )
+ if( (qspec[i].breakpoints[j] <= pta[i] ) &&
+ (ptb[i] <= qspec[i].breakpoints[j+1] ) )
+ break;
+ assert( j != -1 );
+ qspec[i].index = j;
+ }
+}
+
+void
+Quilt::download( Backend &backend )
+{
+ if( getDimension() == 2 ) {
+ REAL *ps = cpts;
+ ps += qspec[0].offset;
+ ps += qspec[1].offset;
+ ps += qspec[0].index * qspec[0].order * qspec[0].stride;
+ ps += qspec[1].index * qspec[1].order * qspec[1].stride;
+ backend.surfpts( mapdesc->getType(), ps,
+ qspec[0].stride,
+ qspec[1].stride,
+ qspec[0].order,
+ qspec[1].order,
+ qspec[0].breakpoints[qspec[0].index],
+ qspec[0].breakpoints[qspec[0].index+1],
+ qspec[1].breakpoints[qspec[1].index],
+ qspec[1].breakpoints[qspec[1].index+1] );
+ } else {
+ REAL *ps = cpts;
+ ps += qspec[0].offset;
+ ps += qspec[0].index * qspec[0].order * qspec[0].stride;
+ backend.curvpts( mapdesc->getType(), ps,
+ qspec[0].stride,
+ qspec[0].order,
+ qspec[0].breakpoints[qspec[0].index],
+ qspec[0].breakpoints[qspec[0].index+1] );
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Quilt::downloadAll - download each map that contains the current patch
+ *--------------------------------------------------------------------------
+ */
+
+void
+Quilt::downloadAll( REAL *pta, REAL *ptb, Backend &backend )
+{
+ for( Quilt *m = this; m; m=m->next ) {
+ m->select( pta, ptb );
+ m->download( backend );
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Quilt::isCulled - determine if an entire quilt is trivially rejected.
+ *--------------------------------------------------------------------------
+ */
+
+int
+Quilt::isCulled( void )
+{
+ if( mapdesc->isCulling() )
+ return mapdesc->xformAndCullCheck( cpts + qspec[0].offset + qspec[1].offset,
+ qspec[0].order * qspec[0].width, qspec[0].stride,
+ qspec[1].order * qspec[1].width, qspec[1].stride );
+ else
+ return CULL_ACCEPT;
+}
+
+/*---------------------------------------------------------------------------
+ * Quilt::getRange - retrieve the valid paramater range of a set of quilts
+ *---------------------------------------------------------------------------
+ */
+void
+Quilt::getRange( REAL *from, REAL *to, Flist& slist, Flist &tlist )
+{
+ getRange( from, to, 0, slist );
+ getRange( from, to, 1, tlist );
+}
+
+/*---------------------------------------------------------------------------
+ * Quilt::getRange - retrieve the valid paramater range of a set of quilts
+ *---------------------------------------------------------------------------
+ */
+void
+Quilt::getRange( REAL *from, REAL *to, int i, Flist &list )
+{
+ Quilt *maps = this;
+ from[i] = maps->qspec[i].breakpoints[0];
+ to[i] = maps->qspec[i].breakpoints[maps->qspec[i].width];
+ int maxpts = 0;
+ Quilt_ptr m;
+ for( m=maps; m; m=m->next ) {
+ if( m->qspec[i].breakpoints[0] > from[i] )
+ from[i] = m->qspec[i].breakpoints[0];
+ if( m->qspec[i].breakpoints[m->qspec[i].width] < to[i] )
+ to[i] = m->qspec[i].breakpoints[m->qspec[i].width];
+ maxpts += m->qspec[i].width + 1;
+ }
+
+ list.grow( maxpts );
+
+ for( m=maps; m; m=m->next )
+ for( int j=0; j<=m->qspec[i].width; j++ ) {
+ list.add( m->qspec[i].breakpoints[j] );
+ }
+
+ list.filter( );
+ list.taper( from[i], to[i] );
+}
+
+void
+Quilt::getRange( REAL *from, REAL *to, Flist& slist )
+{
+ getRange( from, to, 0, slist );
+}
+
+void
+Quilt::findRates( Flist& slist, Flist& tlist, REAL rate[2] )
+{
+ findSampleRates( slist, tlist );
+ rate[0] = qspec[0].step_size;
+ rate[1] = qspec[1].step_size;
+
+ for( Quilt *q = next; q; q = q->next ) {
+ q->findSampleRates( slist, tlist );
+ if( q->qspec[0].step_size < rate[0] )
+ rate[0] = q->qspec[0].step_size;
+ if( q->qspec[1].step_size < rate[1] )
+ rate[1] = q->qspec[1].step_size;
+ }
+}
+
+void
+Quilt::findSampleRates( Flist& slist, Flist& tlist )
+{
+ qspec[0].step_size = DEF_PATCH_STEPSIZE *
+ (qspec[0].breakpoints[qspec[0].width] - qspec[0].breakpoints[0]);
+ qspec[1].step_size = DEF_PATCH_STEPSIZE *
+ (qspec[1].breakpoints[qspec[1].width] - qspec[1].breakpoints[0]);
+
+ for( int i = slist.start; i < slist.end-1; i++ ) {
+ for( int j = tlist.start; j < tlist.end-1; j++ ) {
+
+ REAL pta[2], ptb[2];
+ pta[0] = slist.pts[i];
+ ptb[0] = slist.pts[i+1];
+ pta[1] = tlist.pts[j];
+ ptb[1] = tlist.pts[j+1];
+ Patchlist patchlist( this, pta, ptb );
+ patchlist.getstepsize();
+
+ {
+ float edge_len_s = min(glu_abs(ptb[0]-pta[0]),1.0);
+ float edge_len_t = min(glu_abs(ptb[1]-pta[1]),1.0);
+
+ if( patchlist.getStepsize(0)/edge_len_s < qspec[0].step_size )
+ qspec[0].step_size = patchlist.getStepsize(0)/edge_len_s;
+ if( patchlist.getStepsize(1)/edge_len_t < qspec[1].step_size )
+ qspec[1].step_size = patchlist.getStepsize(1)/edge_len_t;
+ }
+ }
+ }
+}
diff --git a/src/glu/sgi/libnurbs/internals/quilt.h b/src/glu/sgi/libnurbs/internals/quilt.h
new file mode 100644
index 00000000000..64a4c2ed107
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/quilt.h
@@ -0,0 +1,98 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * quilt.h
+ *
+ * $Date: 2001/08/07 17:34:11 $ $Revision: 1.2 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/quilt.h,v 1.2 2001/08/07 17:34:11 brianp Exp $
+ */
+
+#ifndef __gluquilt_h_
+#define __gluquilt_h_
+
+#include "defines.h"
+#include "bufpool.h"
+#include "types.h"
+
+class Backend;
+class Mapdesc;
+class Flist;
+struct Knotvector;
+
+/* constants for memory allocation of NURBS to Bezier conversion */
+#define MAXDIM 2
+
+struct Quiltspec { /* a specification for a dimension of a quilt */
+ int stride; /* words between points */
+ int width; /* number of segments */
+ int offset; /* words to first point */
+ int order; /* order */
+ int index; /* current segment number */
+ int bdry[2]; /* boundary edge flag */
+ REAL step_size;
+ Knot * breakpoints;
+};
+
+typedef Quiltspec *Quiltspec_ptr;
+
+class Quilt : public PooledObj { /* an array of bezier patches */
+public:
+ Quilt( Mapdesc * );
+ Mapdesc * mapdesc; /* map descriptor */
+ REAL * cpts; /* control points */
+ Quiltspec qspec[MAXDIM]; /* the dimensional data */
+ Quiltspec_ptr eqspec; /* qspec trailer */
+ Quilt *next; /* next quilt in linked list */
+
+public:
+ void deleteMe( Pool& );
+ void toBezier( Knotvector &, INREAL *, long );
+ void toBezier( Knotvector &, Knotvector &, INREAL *, long );
+ void select( REAL *, REAL * );
+ int getDimension( void ) { return eqspec - qspec; }
+ void download( Backend & );
+ void downloadAll( REAL *, REAL *, Backend & );
+ int isCulled( void );
+ void getRange( REAL *, REAL *, Flist&, Flist & );
+ void getRange( REAL *, REAL *, int, Flist & );
+ void getRange( REAL *, REAL *, Flist& );
+ void findRates( Flist& slist, Flist& tlist, REAL[2] );
+ void findSampleRates( Flist& slist, Flist& tlist );
+ void show();
+};
+
+typedef class Quilt *Quilt_ptr;
+
+#endif /* __gluquilt_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/reader.cc b/src/glu/sgi/libnurbs/internals/reader.cc
new file mode 100644
index 00000000000..85d60ebf67e
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/reader.cc
@@ -0,0 +1,148 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * reader.c++
+ *
+ * $Date: 2002/11/01 23:35:07 $ $Revision: 1.2 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/reader.cc,v 1.2 2002/11/01 23:35:07 brianp Exp $
+ */
+
+#include <stdio.h>
+#include "glimports.h"
+#include "nurbsconsts.h"
+#include "reader.h"
+#include "trimvertex.h"
+#include "simplemath.h"
+
+//when read a pwlCurve, if two consecutive points are the same, then
+//eliminate one of them. This makes the tessellator more robust. The spec
+//assumes the application makes sure there are no redundant points.
+//but in Inspector, the trim curves seem to have redundant points a lot.
+//I guess other similar users may have the same problem.
+
+#define ELIMINATE_REDUNDANT_POINTS
+
+#ifdef ELIMINATE_REDUNDANT_POINTS
+#define equal(x,y) ( glu_abs(x-y) <= 0.00001)
+#endif
+
+#ifdef ELIMINATE_REDUNDANT_POINTS
+O_pwlcurve::O_pwlcurve( long _type, long count, INREAL *array, long byte_stride, TrimVertex *trimpts )
+{
+ next = 0;
+ used = 0;
+ owner = 0;
+ pts = trimpts;
+ npts = (int) count;
+ int i;
+
+ /* copy user data into internal trimming data structures */
+ switch( _type ) {
+ case N_P2D: {
+ TrimVertex *v = pts;
+ TrimVertex *prev = NULL;
+ int num = 0;
+ int doit;
+ for(i=0; i<count; i++) {
+ doit = 1;
+ if(prev != NULL)
+ {
+ if(equal(prev->param[0], array[0]) && equal(prev->param[1], array[1]))
+ {
+ doit = 0;
+ }
+ }
+
+ if(doit)
+ {
+ v->param[0] = (REAL) array[0];
+ v->param[1] = (REAL) array[1];
+ prev = v;
+ v++;
+ num++;
+ }
+ array = (INREAL *) (((char *) array) + byte_stride);
+ }
+ npts = num;
+ break;
+ }
+ case N_P2DR: {
+ TrimVertex *v = pts;
+ for( TrimVertex *lastv = v + count; v != lastv; v++ ) {
+ v->param[0] = (REAL) array[0] / (REAL) array[2];
+ v->param[1] = (REAL) array[1] / (REAL) array[2];
+ array = (INREAL *) (((char *) array) + byte_stride);
+ }
+ break;
+ }
+ }
+}
+#else
+O_pwlcurve::O_pwlcurve( long _type, long count, INREAL *array, long byte_stride, TrimVertex *trimpts )
+{
+ next = 0;
+ used = 0;
+ owner = 0;
+ pts = trimpts;
+ npts = (int) count;
+
+ /* copy user data into internal trimming data structures */
+ switch( _type ) {
+ case N_P2D: {
+ TrimVertex *v = pts;
+ for( TrimVertex *lastv = v + count; v != lastv; v++ ) {
+ v->param[0] = (REAL) array[0];
+ v->param[1] = (REAL) array[1];
+ array = (INREAL *) (((char *) array) + byte_stride);
+ }
+ break;
+ }
+ case N_P2DR: {
+ TrimVertex *v = pts;
+ for( TrimVertex *lastv = v + count; v != lastv; v++ ) {
+ v->param[0] = (REAL) array[0] / (REAL) array[2];
+ v->param[1] = (REAL) array[1] / (REAL) array[2];
+ array = (INREAL *) (((char *) array) + byte_stride);
+ }
+ break;
+ }
+ }
+}
+#endif
+
+
+
+
+
diff --git a/src/glu/sgi/libnurbs/internals/reader.h b/src/glu/sgi/libnurbs/internals/reader.h
new file mode 100644
index 00000000000..8ba8331e861
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/reader.h
@@ -0,0 +1,138 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * reader.h
+ *
+ * $Date: 2001/08/07 17:34:11 $ $Revision: 1.2 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/reader.h,v 1.2 2001/08/07 17:34:11 brianp Exp $
+ */
+
+#ifndef __glureader_h_
+#define __glureader_h_
+
+#include "bufpool.h"
+#include "types.h"
+
+enum Curvetype { ct_nurbscurve, ct_pwlcurve, ct_none };
+
+struct Property;
+struct O_surface;
+struct O_nurbssurface;
+struct O_trim;
+class O_pwlcurve;
+struct O_nurbscurve;
+struct O_curve;
+class Quilt;
+class TrimVertex;
+
+
+struct O_curve : public PooledObj {
+ union {
+ O_nurbscurve *o_nurbscurve;
+ O_pwlcurve *o_pwlcurve;
+ } curve;
+ Curvetype curvetype; /* arc type: pwl or nurbs */
+ O_curve * next; /* next arc in loop */
+ O_surface * owner; /* owning surface */
+ int used; /* curve called in cur surf */
+ int save; /* 1 if in display list */
+ long nuid;
+ O_curve() { next = 0; used = 0; owner = 0;
+ curve.o_pwlcurve = 0; }
+ };
+
+struct O_nurbscurve : public PooledObj {
+ Quilt *bezier_curves; /* array of bezier curves */
+ long type; /* range descriptor */
+ REAL tesselation; /* tesselation tolerance */
+ int method; /* tesselation method */
+ O_nurbscurve * next; /* next curve in list */
+ int used; /* curve called in cur surf */
+ int save; /* 1 if in display list */
+ O_curve * owner; /* owning curve */
+ O_nurbscurve( long _type )
+ { type = _type; owner = 0; next = 0; used = 0; }
+ };
+
+class O_pwlcurve : public PooledObj {
+public:
+ TrimVertex *pts; /* array of trim vertices */
+ int npts; /* number of trim vertices */
+ O_pwlcurve * next; /* next curve in list */
+ int used; /* curve called in cur surf */
+ int save; /* 1 if in display list */
+ O_curve * owner; /* owning curve */
+ O_pwlcurve( long, long, INREAL *, long, TrimVertex * );
+ };
+
+struct O_trim : public PooledObj {
+ O_curve *o_curve; /* closed trim loop */
+ O_trim * next; /* next loop along trim */
+ int save; /* 1 if in display list */
+ O_trim() { next = 0; o_curve = 0; }
+ };
+
+struct O_nurbssurface : public PooledObj {
+ Quilt * bezier_patches;/* array of bezier patches */
+ long type; /* range descriptor */
+ O_surface * owner; /* owning surface */
+ O_nurbssurface * next; /* next surface in chain */
+ int save; /* 1 if in display list */
+ int used; /* 1 if prev called in block */
+ O_nurbssurface( long _type )
+ { type = _type; owner = 0; next = 0; used = 0; }
+ };
+
+struct O_surface : public PooledObj {
+ O_nurbssurface * o_nurbssurface; /* linked list of surfaces */
+ O_trim * o_trim; /* list of trim loops */
+ int save; /* 1 if in display list */
+ long nuid;
+ O_surface() { o_trim = 0; o_nurbssurface = 0; }
+ };
+
+struct Property : public PooledObj {
+ long type;
+ long tag;
+ REAL value;
+ int save; /* 1 if in display list */
+ Property( long _type, long _tag, INREAL _value )
+ { type = _type; tag = _tag; value = (REAL) _value; }
+ Property( long _tag, INREAL _value )
+ { type = 0; tag = _tag; value = (REAL) _value; }
+ };
+
+class NurbsTessellator;
+#endif /* __glureader_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/renderhints.cc b/src/glu/sgi/libnurbs/internals/renderhints.cc
new file mode 100644
index 00000000000..3349b27d3f7
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/renderhints.cc
@@ -0,0 +1,135 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * renderhints.c++
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/renderhints.cc,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "renderhints.h"
+#include "defines.h"
+#include "nurbsconsts.h"
+
+
+/*--------------------------------------------------------------------------
+ * Renderhints::Renderhints - set all window specific options
+ *--------------------------------------------------------------------------
+ */
+Renderhints::Renderhints()
+{
+ display_method = N_FILL;
+ errorchecking = N_MSG;
+ subdivisions = 6.0;
+ tmp1 = 0.0;
+}
+
+void
+Renderhints::init( void )
+{
+ maxsubdivisions = (int) subdivisions;
+ if( maxsubdivisions < 0 ) maxsubdivisions = 0;
+
+
+ if( display_method == N_FILL ) {
+ wiretris = 0;
+ wirequads = 0;
+ } else if( display_method == N_OUTLINE_TRI ) {
+ wiretris = 1;
+ wirequads = 0;
+ } else if( display_method == N_OUTLINE_QUAD ) {
+ wiretris = 0;
+ wirequads = 1;
+ } else {
+ wiretris = 1;
+ wirequads = 1;
+ }
+}
+
+int
+Renderhints::isProperty( long property )
+{
+ switch ( property ) {
+ case N_DISPLAY:
+ case N_ERRORCHECKING:
+ case N_SUBDIVISIONS:
+ case N_TMP1:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+REAL
+Renderhints::getProperty( long property )
+{
+ switch ( property ) {
+ case N_DISPLAY:
+ return display_method;
+ case N_ERRORCHECKING:
+ return errorchecking;
+ case N_SUBDIVISIONS:
+ return subdivisions;
+ case N_TMP1:
+ return tmp1;
+ default:
+ abort();
+ return -1; //not necessary, needed to shut up compiler
+ }
+}
+
+void
+Renderhints::setProperty( long property, REAL value )
+{
+ switch ( property ) {
+ case N_DISPLAY:
+ display_method = value;
+ break;
+ case N_ERRORCHECKING:
+ errorchecking = value;
+ break;
+ case N_SUBDIVISIONS:
+ subdivisions = value;
+ break;
+ case N_TMP1: /* unused */
+ tmp1 = value;
+ break;
+ default:
+ abort();
+ break;
+ }
+}
diff --git a/src/glu/sgi/libnurbs/internals/renderhints.h b/src/glu/sgi/libnurbs/internals/renderhints.h
new file mode 100644
index 00000000000..ee526be04e7
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/renderhints.h
@@ -0,0 +1,66 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * renderhints.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/renderhints.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __glurenderhints_h_
+#define __glurenderhints_h_
+
+#include "types.h"
+
+class Renderhints {
+public:
+ Renderhints( void );
+ void init( void );
+ int isProperty( long );
+ REAL getProperty( long );
+ void setProperty( long, REAL );
+
+ REAL display_method; /* display mode */
+ REAL errorchecking; /* activate error checking */
+ REAL subdivisions; /* maximum number of subdivisions per patch */
+ REAL tmp1; /* unused */
+
+ int displaydomain;
+ int maxsubdivisions;
+ int wiretris;
+ int wirequads;
+};
+
+#endif /* __glurenderhints_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/simplemath.h b/src/glu/sgi/libnurbs/internals/simplemath.h
new file mode 100644
index 00000000000..4948aec58bf
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/simplemath.h
@@ -0,0 +1,56 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * simplemath.h
+ *
+ * $Date: 2002/11/01 23:35:07 $ $Revision: 1.2 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/simplemath.h,v 1.2 2002/11/01 23:35:07 brianp Exp $
+ */
+
+#ifndef __glusimplemath_h_
+#define __glusimplemath_h_
+
+/* simple inline routines */
+
+inline int
+max( int x, int y ) { return ( x < y ) ? y : x; }
+
+inline REAL
+min( REAL x, REAL y ) { return ( x > y ) ? y : x; }
+
+inline REAL
+glu_abs( REAL x ) { return ( x < 0.0 ) ? -x : x; }
+
+#endif /* __glusimplemath_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/slicer.cc b/src/glu/sgi/libnurbs/internals/slicer.cc
new file mode 100644
index 00000000000..9b72f0a6b28
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/slicer.cc
@@ -0,0 +1,1302 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * slicer.c++
+ *
+ * $Date: 2005/10/28 13:09:08 $ $Revision: 1.4.26.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/slicer.cc,v 1.4.26.1 2005/10/28 13:09:08 brianp Exp $
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "bufpool.h"
+#include "slicer.h"
+#include "backend.h"
+#include "arc.h"
+#include "gridtrimvertex.h"
+#include "simplemath.h"
+#include "trimvertex.h"
+#include "varray.h"
+
+#include "polyUtil.h" //for area()
+
+//static int count=0;
+
+/*USE_OPTTT is initiated in trimvertex.h*/
+
+#ifdef USE_OPTTT
+ #include <GL/gl.h>
+#endif
+
+//#define USE_READ_FLAG //whether to use new or old tesselator
+ //if defined, it reads "flagFile",
+ // if the number is 1, then use new tess
+ // otherwise, use the old tess.
+ //if not defined, then use new tess.
+#ifdef USE_READ_FLAG
+static Int read_flag(char* name);
+Int newtess_flag = read_flag("flagFile");
+#endif
+
+//#define COUNT_TRIANGLES
+#ifdef COUNT_TRIANGLES
+Int num_triangles = 0;
+Int num_quads = 0;
+#endif
+
+#define max(a,b) ((a>b)? a:b)
+#define ZERO 0.00001 /*determing whether a loop is a rectngle or not*/
+#define equalRect(a,b) ((glu_abs(a-b) <= ZERO)? 1:0) //only used in tessellating a rectangle
+
+#if 0 // UNUSED
+static Int is_Convex(Arc_ptr loop)
+{
+ if(area(loop->tail(), loop->head(), loop->next->head()) <0 )
+ return 0;
+ for(Arc_ptr jarc = loop->next; jarc != loop; jarc = jarc->next)
+ {
+ if(area(jarc->tail(), jarc->head(), jarc->next->head()) < 0)
+ return 0;
+ }
+ return 1;
+}
+#endif
+
+/******triangulate a monotone polygon**************/
+#include "monoTriangulation.h"
+#if 0 // UNUSED
+static int is_U_monotone(Arc_ptr loop)
+{
+ int n_changes=0;
+ int prev_sign;
+ int cur_sign;
+ Arc_ptr temp;
+
+ cur_sign = compV2InX(loop->head(), loop->tail());
+
+ n_changes = (compV2InX(loop->prev->head(), loop->prev->tail())
+ != cur_sign);
+
+ for(temp=loop->next; temp != loop; temp = temp->next)
+ {
+ prev_sign = cur_sign;
+ cur_sign = compV2InX(temp->head(), temp->tail());
+ if(cur_sign != prev_sign)
+ {
+#ifdef DEBUG
+ printf("***change signe\n");
+#endif
+ n_changes++;
+ }
+ }
+ if(n_changes == 2) return 1;
+ else
+ return 0;
+}
+#endif
+
+inline int compInY(REAL a[2], REAL b[2])
+{
+ if(a[1] < b[1])
+ return -1;
+ else if (a[1] > b[1])
+ return 1;
+ else if(a[0] > b[0])
+ return 1;
+ else return -1;
+}
+
+void monoTriangulationLoop(Arc_ptr loop, Backend& backend, primStream* pStream)
+{
+ int i;
+ //find the top, bottom, increasing and decreasing chain
+ //then call monoTrianulation
+ Arc_ptr jarc, temp;
+ Arc_ptr top;
+ Arc_ptr bot;
+ top = bot = loop;
+ if(compInY(loop->tail(), loop->prev->tail()) < 0)
+ {
+ //first find bot
+ for(temp = loop->next; temp != loop; temp = temp->next)
+ {
+ if(compInY(temp->tail(), temp->prev->tail()) > 0)
+ break;
+ }
+ bot = temp->prev;
+ //then find top
+ for(temp=loop->prev; temp != loop; temp = temp->prev)
+ {
+ if(compInY(temp->tail(), temp->prev->tail()) > 0)
+ break;
+ }
+ top = temp;
+ }
+ else //loop > loop->prev
+ {
+ for(temp=loop->next; temp != loop; temp = temp->next)
+ {
+ if(compInY(temp->tail(), temp->prev->tail()) < 0)
+ break;
+ }
+ top = temp->prev;
+ for(temp=loop->prev; temp != loop; temp = temp->prev)
+ {
+ if(compInY(temp->tail(), temp->prev->tail()) < 0)
+ break;
+ }
+ bot = temp;
+ }
+ //creat increase and decrease chains
+ vertexArray inc_chain(50); //this is a dynamci array
+ for(i=1; i<=top->pwlArc->npts-2; i++)
+ {
+ //the first vertex is the top which doesn't below to inc_chain
+ inc_chain.appendVertex(top->pwlArc->pts[i].param);
+ }
+ for(jarc=top->next; jarc != bot; jarc = jarc->next)
+ {
+ for(i=0; i<=jarc->pwlArc->npts-2; i++)
+ {
+ inc_chain.appendVertex(jarc->pwlArc->pts[i].param);
+ }
+
+ }
+ vertexArray dec_chain(50);
+ for(jarc = top->prev; jarc != bot; jarc = jarc->prev)
+ {
+ for(i=jarc->pwlArc->npts-2; i>=0; i--)
+ {
+ dec_chain.appendVertex(jarc->pwlArc->pts[i].param);
+ }
+ }
+ for(i=bot->pwlArc->npts-2; i>=1; i--)
+ {
+ dec_chain.appendVertex(jarc->pwlArc->pts[i].param);
+ }
+
+ monoTriangulationRec(top->tail(), bot->tail(), &inc_chain, 0,
+ &dec_chain, 0, &backend);
+
+}
+
+/********tesselate a rectanlge (OPTIMIZATION**************/
+static void triangulateRectGen(Arc_ptr loop, int n_ulines, int n_vlines, Backend& backend);
+
+static Int is_rect(Arc_ptr loop)
+{
+ Int nlines =1;
+ for(Arc_ptr jarc = loop->next; jarc != loop; jarc = jarc->next)
+ {
+ nlines++;
+ if(nlines == 5)
+ break;
+ }
+ if(nlines != 4)
+ return 0;
+
+
+/*
+printf("here1\n");
+printf("loop->tail=(%f,%f)\n", loop->tail()[0], loop->tail()[1]);
+printf("loop->head=(%f,%f)\n", loop->head()[0], loop->head()[1]);
+printf("loop->next->tail=(%f,%f)\n", loop->next->tail()[0], loop->next->tail()[1]);
+printf("loop->next->head=(%f,%f)\n", loop->next->head()[0], loop->next->head()[1]);
+if(fglu_abs(loop->tail()[0] - loop->head()[0])<0.000001)
+ printf("equal 1\n");
+if(loop->next->tail()[1] == loop->next->head()[1])
+ printf("equal 2\n");
+*/
+
+ if( (glu_abs(loop->tail()[0] - loop->head()[0])<=ZERO) &&
+ (glu_abs(loop->next->tail()[1] - loop->next->head()[1])<=ZERO) &&
+ (glu_abs(loop->prev->tail()[1] - loop->prev->head()[1])<=ZERO) &&
+ (glu_abs(loop->prev->prev->tail()[0] - loop->prev->prev->head()[0])<=ZERO)
+ )
+ return 1;
+ else if
+ ( (glu_abs(loop->tail()[1] - loop->head()[1]) <= ZERO) &&
+ (glu_abs(loop->next->tail()[0] - loop->next->head()[0]) <= ZERO) &&
+ (glu_abs(loop->prev->tail()[0] - loop->prev->head()[0]) <= ZERO) &&
+ (glu_abs(loop->prev->prev->tail()[1] - loop->prev->prev->head()[1]) <= ZERO)
+ )
+ return 1;
+ else
+ return 0;
+}
+
+
+//a line with the same u for opt
+#ifdef USE_OPTTT
+static void evalLineNOGE_BU(TrimVertex *verts, int n, Backend& backend)
+{
+ int i;
+ backend.preEvaluateBU(verts[0].param[0]);
+ for(i=0; i<n; i++)
+ backend.tmeshvertNOGE_BU(&verts[i]);
+}
+#endif
+
+//a line with the same v for opt
+#ifdef USE_OPTTT
+static void evalLineNOGE_BV(TrimVertex *verts, int n, Backend& backend)
+{
+ int i;
+ backend.preEvaluateBV(verts[0].param[1]);
+
+ for(i=0; i<n; i++)
+ backend.tmeshvertNOGE_BV(&verts[i]);
+}
+#endif
+
+#ifdef USE_OPTTT
+static void evalLineNOGE(TrimVertex *verts, int n, Backend& backend)
+{
+
+ if(verts[0].param[0] == verts[n-1].param[0]) //all u;s are equal
+ evalLineNOGE_BU(verts, n, backend);
+ else if(verts[0].param[1] == verts[n-1].param[1]) //all v's are equal
+ evalLineNOGE_BV(verts, n, backend);
+ else
+ {
+ int i;
+ for(i=0; i<n; i++)
+ backend.tmeshvertNOGE(&verts[i]);
+ }
+}
+#endif
+
+inline void OPT_OUTVERT(TrimVertex& vv, Backend& backend)
+{
+
+#ifdef USE_OPTTT
+ glNormal3fv(vv.cache_normal);
+ glVertex3fv(vv.cache_point);
+#else
+
+ backend.tmeshvert(&vv);
+
+#endif
+
+}
+
+static void triangulateRectAux(PwlArc* top, PwlArc* bot, PwlArc* left, PwlArc* right, Backend& backend);
+
+static void triangulateRect(Arc_ptr loop, Backend& backend, int TB_or_LR, int ulinear, int vlinear)
+{
+ //we know the loop is a rectangle, but not sure which is top
+ Arc_ptr top, bot, left, right;
+ if(loop->tail()[1] == loop->head()[1])
+ {
+ if(loop->tail()[1] > loop->prev->prev->tail()[1])
+ {
+
+ top = loop;
+ }
+ else{
+
+ top = loop->prev->prev;
+ }
+ }
+ else
+ {
+ if(loop->tail()[0] > loop->prev->prev->tail()[0])
+ {
+ //loop is the right arc
+
+ top = loop->next;
+ }
+ else
+ {
+
+ top = loop->prev;
+ }
+ }
+ left = top->next;
+ bot = left->next;
+ right= bot->next;
+
+ //if u, v are both nonlinear, then if the
+ //boundary is tessellated dense, we also
+ //sample the inside to get a better tesslletant.
+ if( (!ulinear) && (!vlinear))
+ {
+ int nu = top->pwlArc->npts;
+ if(nu < bot->pwlArc->npts)
+ nu = bot->pwlArc->npts;
+ int nv = left->pwlArc->npts;
+ if(nv < right->pwlArc->npts)
+ nv = right->pwlArc->npts;
+/*
+ if(nu > 2 && nv > 2)
+ {
+ triangulateRectGen(top, nu-2, nv-2, backend);
+ return;
+ }
+*/
+ }
+
+ if(TB_or_LR == 1)
+ triangulateRectAux(top->pwlArc, bot->pwlArc, left->pwlArc, right->pwlArc, backend);
+ else if(TB_or_LR == -1)
+ triangulateRectAux(left->pwlArc, right->pwlArc, bot->pwlArc, top->pwlArc, backend);
+ else
+ {
+ Int maxPointsTB = top->pwlArc->npts + bot->pwlArc->npts;
+ Int maxPointsLR = left->pwlArc->npts + right->pwlArc->npts;
+
+ if(maxPointsTB < maxPointsLR)
+ triangulateRectAux(left->pwlArc, right->pwlArc, bot->pwlArc, top->pwlArc, backend);
+ else
+ triangulateRectAux(top->pwlArc, bot->pwlArc, left->pwlArc, right->pwlArc, backend);
+ }
+}
+
+static void triangulateRectAux(PwlArc* top, PwlArc* bot, PwlArc* left, PwlArc* right, Backend& backend)
+{ //if(maxPointsTB >= maxPointsLR)
+ {
+
+ Int d, topd_left, topd_right, botd_left, botd_right, i,j;
+ d = left->npts /2;
+
+#ifdef USE_OPTTT
+ evalLineNOGE(top->pts, top->npts, backend);
+ evalLineNOGE(bot->pts, bot->npts, backend);
+ evalLineNOGE(left->pts, left->npts, backend);
+ evalLineNOGE(right->pts, right->npts, backend);
+#endif
+
+ if(top->npts == 2) {
+ backend.bgntfan();
+ OPT_OUTVERT(top->pts[0], backend);//the root
+ for(i=0; i<left->npts; i++){
+ OPT_OUTVERT(left->pts[i], backend);
+ }
+ for(i=1; i<= bot->npts-2; i++){
+ OPT_OUTVERT(bot->pts[i], backend);
+ }
+ backend.endtfan();
+
+ backend.bgntfan();
+ OPT_OUTVERT(bot->pts[bot->npts-2], backend);
+ for(i=0; i<right->npts; i++){
+ OPT_OUTVERT(right->pts[i], backend);
+ }
+ backend.endtfan();
+ }
+ else if(bot->npts == 2) {
+ backend.bgntfan();
+ OPT_OUTVERT(bot->pts[0], backend);//the root
+ for(i=0; i<right->npts; i++){
+ OPT_OUTVERT(right->pts[i], backend);
+ }
+ for(i=1; i<= top->npts-2; i++){
+ OPT_OUTVERT(top->pts[i], backend);
+ }
+ backend.endtfan();
+
+ backend.bgntfan();
+ OPT_OUTVERT(top->pts[top->npts-2], backend);
+ for(i=0; i<left->npts; i++){
+ OPT_OUTVERT(left->pts[i], backend);
+ }
+ backend.endtfan();
+ }
+ else { //both top and bot have >=3 points
+
+ backend.bgntfan();
+
+ OPT_OUTVERT(top->pts[top->npts-2], backend);
+
+ for(i=0; i<=d; i++)
+ {
+ OPT_OUTVERT(left->pts[i], backend);
+ }
+ backend.endtfan();
+
+ backend.bgntfan();
+
+ OPT_OUTVERT(bot->pts[1], backend);
+
+ OPT_OUTVERT(top->pts[top->npts-2], backend);
+
+ for(i=d; i< left->npts; i++)
+ {
+ OPT_OUTVERT(left->pts[i], backend);
+ }
+ backend.endtfan();
+
+ d = right->npts/2;
+ //output only when d<right->npts-1 and
+ //
+ if(d<right->npts-1)
+ {
+ backend.bgntfan();
+ // backend.tmeshvert(& top->pts[1]);
+ OPT_OUTVERT(top->pts[1], backend);
+ for(i=d; i< right->npts; i++)
+ {
+ // backend.tmeshvert(& right->pts[i]);
+
+ OPT_OUTVERT(right->pts[i], backend);
+
+ }
+ backend.endtfan();
+ }
+
+ backend.bgntfan();
+ // backend.tmeshvert(& bot->pts[bot->npts-2]);
+ OPT_OUTVERT( bot->pts[bot->npts-2], backend);
+ for(i=0; i<=d; i++)
+ {
+ // backend.tmeshvert(& right->pts[i]);
+ OPT_OUTVERT(right->pts[i], backend);
+
+ }
+
+ // backend.tmeshvert(& top->pts[1]);
+ OPT_OUTVERT(top->pts[1], backend);
+
+ backend.endtfan();
+
+
+ topd_left = top->npts-2;
+ topd_right = 1; //topd_left>= topd_right
+
+ botd_left = 1;
+ botd_right = bot->npts-2; //botd_left<= bot_dright
+
+
+ if(top->npts < bot->npts)
+ {
+ int delta=bot->npts - top->npts;
+ int u = delta/2;
+ botd_left = 1+ u;
+ botd_right = bot->npts-2-( delta-u);
+
+ if(botd_left >1)
+ {
+ backend.bgntfan();
+ // backend.tmeshvert(& top->pts[top->npts-2]);
+ OPT_OUTVERT(top->pts[top->npts-2], backend);
+ for(i=1; i<= botd_left; i++)
+ {
+ // backend.tmeshvert(& bot->pts[i]);
+ OPT_OUTVERT(bot->pts[i] , backend);
+ }
+ backend.endtfan();
+ }
+ if(botd_right < bot->npts-2)
+ {
+ backend.bgntfan();
+ OPT_OUTVERT(top->pts[1], backend);
+ for(i=botd_right; i<= bot->npts-2; i++)
+ OPT_OUTVERT(bot->pts[i], backend);
+ backend.endtfan();
+ }
+ }
+ else if(top->npts> bot->npts)
+ {
+ int delta=top->npts-bot->npts;
+ int u = delta/2;
+ topd_left = top->npts-2 - u;
+ topd_right = 1+delta-u;
+
+ if(topd_left < top->npts-2)
+ {
+ backend.bgntfan();
+ // backend.tmeshvert(& bot->pts[1]);
+ OPT_OUTVERT(bot->pts[1], backend);
+ for(i=topd_left; i<= top->npts-2; i++)
+ {
+ // backend.tmeshvert(& top->pts[i]);
+ OPT_OUTVERT(top->pts[i], backend);
+ }
+ backend.endtfan();
+ }
+ if(topd_right > 1)
+ {
+ backend.bgntfan();
+ OPT_OUTVERT(bot->pts[bot->npts-2], backend);
+ for(i=1; i<= topd_right; i++)
+ OPT_OUTVERT(top->pts[i], backend);
+ backend.endtfan();
+ }
+ }
+
+ if(topd_left <= topd_right)
+ return;
+
+ backend.bgnqstrip();
+ for(j=botd_left, i=topd_left; i>=topd_right; i--,j++)
+ {
+ // backend.tmeshvert(& top->pts[i]);
+ // backend.tmeshvert(& bot->pts[j]);
+ OPT_OUTVERT(top->pts[i], backend);
+ OPT_OUTVERT(bot->pts[j], backend);
+ }
+ backend.endqstrip();
+
+ }
+ }
+}
+
+
+static void triangulateRectCenter(int n_ulines, REAL* u_val,
+ int n_vlines, REAL* v_val,
+ Backend& backend)
+{
+
+ // XXX this code was patched by Diego Santa Cruz <[email protected]>
+ // to fix a problem in which glMapGrid2f() was called with bad parameters.
+ // This has beens submitted to SGI but not integrated as of May 1, 2001.
+ if(n_ulines>1 && n_vlines>1) {
+ backend.surfgrid(u_val[0], u_val[n_ulines-1], n_ulines-1,
+ v_val[n_vlines-1], v_val[0], n_vlines-1);
+ backend.surfmesh(0,0,n_ulines-1,n_vlines-1);
+ }
+
+ return;
+
+ /*
+ for(i=0; i<n_vlines-1; i++)
+ {
+
+ backend.bgnqstrip();
+ for(j=0; j<n_ulines; j++)
+ {
+ trimVert.param[0] = u_val[j];
+ trimVert.param[1] = v_val[i+1];
+ backend.tmeshvert(& trimVert);
+
+ trimVert.param[1] = v_val[i];
+ backend.tmeshvert(& trimVert);
+ }
+ backend.endqstrip();
+
+ }
+ */
+}
+
+//it works for top, bot, left ad right, you need ot select correct arguments
+static void triangulateRectTopGen(Arc_ptr arc, int n_ulines, REAL* u_val, Real v, int dir, int is_u, Backend& backend)
+{
+
+ if(is_u)
+ {
+ int i,k;
+ REAL* upper_val = (REAL*) malloc(sizeof(REAL) * arc->pwlArc->npts);
+ assert(upper_val);
+ if(dir)
+ {
+ for(k=0,i=arc->pwlArc->npts-1; i>=0; i--,k++)
+ {
+ upper_val[k] = arc->pwlArc->pts[i].param[0];
+ }
+ backend.evalUStrip(arc->pwlArc->npts, arc->pwlArc->pts[0].param[1],
+ upper_val,
+ n_ulines, v, u_val);
+ }
+ else
+ {
+ for(k=0,i=0; i<arc->pwlArc->npts; i++,k++)
+ {
+ upper_val[k] = arc->pwlArc->pts[i].param[0];
+
+ }
+
+ backend.evalUStrip(
+ n_ulines, v, u_val,
+ arc->pwlArc->npts, arc->pwlArc->pts[0].param[1], upper_val
+ );
+ }
+
+ free(upper_val);
+ return;
+ }
+ else //is_v
+ {
+ int i,k;
+ REAL* left_val = (REAL*) malloc(sizeof(REAL) * arc->pwlArc->npts);
+ assert(left_val);
+ if(dir)
+ {
+ for(k=0,i=arc->pwlArc->npts-1; i>=0; i--,k++)
+ {
+ left_val[k] = arc->pwlArc->pts[i].param[1];
+ }
+ backend.evalVStrip(arc->pwlArc->npts, arc->pwlArc->pts[0].param[0],
+ left_val,
+ n_ulines, v, u_val);
+ }
+ else
+ {
+ for(k=0,i=0; i<arc->pwlArc->npts; i++,k++)
+ {
+ left_val[k] = arc->pwlArc->pts[i].param[1];
+ }
+ backend.evalVStrip(
+ n_ulines, v, u_val,
+ arc->pwlArc->npts, arc->pwlArc->pts[0].param[0], left_val
+ );
+ }
+ free(left_val);
+ return;
+ }
+
+ //the following is a different version of the above code. If you comment
+ //the above code, the following code will still work. The reason to leave
+ //the folliwng code here is purely for testing purpose.
+ /*
+ int i,j;
+ PwlArc* parc = arc->pwlArc;
+ int d1 = parc->npts-1;
+ int d2 = 0;
+ TrimVertex trimVert;
+ trimVert.nuid = 0;//????
+ REAL* temp_u_val = u_val;
+ if(dir ==0) //have to reverse u_val
+ {
+ temp_u_val = (REAL*) malloc(sizeof(REAL) * n_ulines);
+ assert(temp_u_val);
+ for(i=0; i<n_ulines; i++)
+ temp_u_val[i] = u_val[n_ulines-1-i];
+ }
+ u_val = temp_u_val;
+
+ if(parc->npts > n_ulines)
+ {
+ d1 = n_ulines-1;
+
+ backend.bgntfan();
+ if(is_u){
+ trimVert.param[0] = u_val[0];
+ trimVert.param[1] = v;
+ }
+ else
+ {
+ trimVert.param[1] = u_val[0];
+ trimVert.param[0] = v;
+ }
+
+ backend.tmeshvert(& trimVert);
+ for(i=d1; i< parc->npts; i++)
+ backend.tmeshvert(& parc->pts[i]);
+ backend.endtfan();
+
+
+ }
+ else if(parc->npts < n_ulines)
+ {
+ d2 = n_ulines-parc->npts;
+
+
+ backend.bgntfan();
+ backend.tmeshvert(& parc->pts[parc->npts-1]);
+ for(i=0; i<= d2; i++)
+ {
+ if(is_u){
+ trimVert.param[0] = u_val[i];
+ trimVert.param[1] = v;
+ }
+ else
+ {
+ trimVert.param[1] = u_val[i];
+ trimVert.param[0] = v;
+ }
+ backend.tmeshvert(&trimVert);
+ }
+ backend.endtfan();
+
+ }
+ if(d1>0){
+
+
+ backend.bgnqstrip();
+ for(i=d1, j=d2; i>=0; i--, j++)
+ {
+ backend.tmeshvert(& parc->pts[i]);
+
+ if(is_u){
+ trimVert.param[0] = u_val[j];
+ trimVert.param[1] = v;
+ }
+ else{
+ trimVert.param[1] = u_val[j];
+ trimVert.param[0] = v;
+ }
+ backend.tmeshvert(&trimVert);
+
+
+
+ }
+ backend.endqstrip();
+
+
+ }
+ if(dir == 0) //temp_u_val was mallocated
+ free(temp_u_val);
+ */
+}
+
+//n_ulines is the number of ulines inside, and n_vlines is the number of vlines
+//inside, different from meanings elsewhere!!!
+static void triangulateRectGen(Arc_ptr loop, int n_ulines, int n_vlines, Backend& backend)
+{
+
+ int i;
+ //we know the loop is a rectangle, but not sure which is top
+ Arc_ptr top, bot, left, right;
+
+ if(equalRect(loop->tail()[1] , loop->head()[1]))
+ {
+
+ if(loop->tail()[1] > loop->prev->prev->tail()[1])
+ {
+
+ top = loop;
+ }
+ else{
+
+ top = loop->prev->prev;
+ }
+ }
+ else
+ {
+ if(loop->tail()[0] > loop->prev->prev->tail()[0])
+ {
+ //loop is the right arc
+
+ top = loop->next;
+ }
+ else
+ {
+
+ top = loop->prev;
+ }
+ }
+
+ left = top->next;
+ bot = left->next;
+ right= bot->next;
+
+#ifdef COUNT_TRIANGLES
+ num_triangles += loop->pwlArc->npts +
+ left->pwlArc->npts +
+ bot->pwlArc->npts +
+ right->pwlArc->npts
+ + 2*n_ulines + 2*n_vlines
+ -8;
+ num_quads += (n_ulines-1)*(n_vlines-1);
+#endif
+/*
+ backend.surfgrid(left->tail()[0], right->tail()[0], n_ulines+1,
+ top->tail()[1], bot->tail()[1], n_vlines+1);
+// if(n_ulines>1 && n_vlines>1)
+ backend.surfmesh(0,0,n_ulines+1,n_vlines+1);
+return;
+*/
+ REAL* u_val=(REAL*) malloc(sizeof(REAL)*n_ulines);
+ assert(u_val);
+ REAL* v_val=(REAL*)malloc(sizeof(REAL) * n_vlines);
+ assert(v_val);
+ REAL u_stepsize = (right->tail()[0] - left->tail()[0])/( (REAL) n_ulines+1);
+ REAL v_stepsize = (top->tail()[1] - bot->tail()[1])/( (REAL) n_vlines+1);
+ Real temp=left->tail()[0]+u_stepsize;
+ for(i=0; i<n_ulines; i++)
+ {
+ u_val[i] = temp;
+ temp += u_stepsize;
+ }
+ temp = bot->tail()[1] + v_stepsize;
+ for(i=0; i<n_vlines; i++)
+ {
+ v_val[i] = temp;
+ temp += v_stepsize;
+ }
+
+ triangulateRectTopGen(top, n_ulines, u_val, v_val[n_vlines-1], 1,1, backend);
+ triangulateRectTopGen(bot, n_ulines, u_val, v_val[0], 0, 1, backend);
+ triangulateRectTopGen(left, n_vlines, v_val, u_val[0], 1, 0, backend);
+ triangulateRectTopGen(right, n_vlines, v_val, u_val[n_ulines-1], 0,0, backend);
+
+
+
+
+ //triangulate the center
+ triangulateRectCenter(n_ulines, u_val, n_vlines, v_val, backend);
+
+ free(u_val);
+ free(v_val);
+
+}
+
+
+
+
+/**********for reading newtess_flag from a file**********/
+#ifdef USE_READ_FLAG
+static Int read_flag(char* name)
+{
+ Int ret;
+ FILE* fp = fopen(name, "r");
+ if(fp == NULL)
+ {
+ fprintf(stderr, "can't open file %s\n", name);
+ exit(1);
+ }
+ fscanf(fp, "%i", &ret);
+ fclose(fp);
+ return ret;
+}
+#endif
+
+/***********nextgen tess****************/
+#include "sampleMonoPoly.h"
+directedLine* arcToDLine(Arc_ptr arc)
+{
+ int i;
+ Real vert[2];
+ directedLine* ret;
+ sampledLine* sline = new sampledLine(arc->pwlArc->npts);
+ for(i=0; i<arc->pwlArc->npts; i++)
+ {
+ vert[0] = arc->pwlArc->pts[i].param[0];
+ vert[1] = arc->pwlArc->pts[i].param[1];
+ sline->setPoint(i, vert);
+ }
+ ret = new directedLine(INCREASING, sline);
+ return ret;
+}
+
+/*an pwlArc may not be a straight line*/
+directedLine* arcToMultDLines(directedLine* original, Arc_ptr arc)
+{
+ directedLine* ret = original;
+ int is_linear = 0;
+ if(arc->pwlArc->npts == 2 )
+ is_linear = 1;
+ else if(area(arc->pwlArc->pts[0].param, arc->pwlArc->pts[1].param, arc->pwlArc->pts[arc->pwlArc->npts-1].param) == 0.0)
+ is_linear = 1;
+
+ if(is_linear)
+ {
+ directedLine *dline = arcToDLine(arc);
+ if(ret == NULL)
+ ret = dline;
+ else
+ ret->insert(dline);
+ return ret;
+ }
+ else /*not linear*/
+ {
+ for(Int i=0; i<arc->pwlArc->npts-1; i++)
+ {
+ Real vert[2][2];
+ vert[0][0] = arc->pwlArc->pts[i].param[0];
+ vert[0][1] = arc->pwlArc->pts[i].param[1];
+ vert[1][0] = arc->pwlArc->pts[i+1].param[0];
+ vert[1][1] = arc->pwlArc->pts[i+1].param[1];
+
+ sampledLine *sline = new sampledLine(2, vert);
+ directedLine *dline = new directedLine(INCREASING, sline);
+ if(ret == NULL)
+ ret = dline;
+ else
+ ret->insert(dline);
+ }
+ return ret;
+ }
+}
+
+
+
+directedLine* arcLoopToDLineLoop(Arc_ptr loop)
+{
+ directedLine* ret;
+
+ if(loop == NULL)
+ return NULL;
+ ret = arcToMultDLines(NULL, loop);
+//ret->printSingle();
+ for(Arc_ptr temp = loop->next; temp != loop; temp = temp->next){
+ ret = arcToMultDLines(ret, temp);
+//ret->printSingle();
+ }
+
+ return ret;
+}
+
+/*
+void Slicer::evalRBArray(rectBlockArray* rbArray, gridWrap* grid)
+{
+ TrimVertex *trimVert = (TrimVertex*)malloc(sizeof(TrimVertex));
+ trimVert -> nuid = 0;//????
+
+ Real* u_values = grid->get_u_values();
+ Real* v_values = grid->get_v_values();
+
+ Int i,j,k,l;
+
+ for(l=0; l<rbArray->get_n_elements(); l++)
+ {
+ rectBlock* block = rbArray->get_element(l);
+ for(k=0, i=block->get_upGridLineIndex(); i>block->get_lowGridLineIndex(); i--, k++)
+ {
+
+ backend.bgnqstrip();
+ for(j=block->get_leftIndices()[k+1]; j<= block->get_rightIndices()[k+1]; j++)
+ {
+ trimVert->param[0] = u_values[j];
+ trimVert->param[1] = v_values[i];
+ backend.tmeshvert(trimVert);
+
+ trimVert->param[1] = v_values[i-1];
+ backend.tmeshvert(trimVert);
+
+ }
+ backend.endqstrip();
+
+ }
+ }
+
+ free(trimVert);
+}
+*/
+
+void Slicer::evalRBArray(rectBlockArray* rbArray, gridWrap* grid)
+{
+ Int i,j,k;
+
+ Int n_vlines=grid->get_n_vlines();
+ //the reason to switch the position of v_max and v_min is because of the
+ //the orientation problem. glEvalMesh generates quad_strip clockwise, but
+ //we need counter-clockwise.
+ backend.surfgrid(grid->get_u_min(), grid->get_u_max(), grid->get_n_ulines()-1,
+ grid->get_v_max(), grid->get_v_min(), n_vlines-1);
+
+
+ for(j=0; j<rbArray->get_n_elements(); j++)
+ {
+ rectBlock* block = rbArray->get_element(j);
+ Int low = block->get_lowGridLineIndex();
+ Int high = block->get_upGridLineIndex();
+
+ for(k=0, i=high; i>low; i--, k++)
+ {
+ backend.surfmesh(block->get_leftIndices()[k+1], n_vlines-1-i, block->get_rightIndices()[k+1]-block->get_leftIndices()[k+1], 1);
+ }
+ }
+}
+
+
+void Slicer::evalStream(primStream* pStream)
+{
+ Int i,j,k;
+ k=0;
+/* TrimVertex X;*/
+ TrimVertex *trimVert =/*&X*/ (TrimVertex*)malloc(sizeof(TrimVertex));
+ trimVert -> nuid = 0;//???
+ Real* vertices = pStream->get_vertices(); //for efficiency
+ for(i=0; i<pStream->get_n_prims(); i++)
+ {
+
+ //ith primitive has #vertices = lengths[i], type=types[i]
+ switch(pStream->get_type(i)){
+ case PRIMITIVE_STREAM_FAN:
+
+ backend.bgntfan();
+
+ for(j=0; j<pStream->get_length(i); j++)
+ {
+ trimVert->param[0] = vertices[k];
+ trimVert->param[1] = vertices[k+1];
+ backend.tmeshvert(trimVert);
+
+// backend.tmeshvert(vertices[k], vertices[k+1]);
+ k += 2;
+ }
+ backend.endtfan();
+ break;
+
+ default:
+ fprintf(stderr, "evalStream: not implemented yet\n");
+ exit(1);
+
+ }
+ }
+ free(trimVert);
+}
+
+
+
+
+void Slicer::slice_new(Arc_ptr loop)
+{
+//count++;
+//if(count == 78) count=1;
+//printf("count=%i\n", count);
+//if( ! (4<= count && count <=4)) return;
+
+
+ Int num_ulines;
+ Int num_vlines;
+ Real uMin, uMax, vMin, vMax;
+ Real mydu, mydv;
+ uMin = uMax = loop->tail()[0];
+ vMin = vMax = loop->tail()[1];
+ mydu = (du>0)? du: -du;
+ mydv = (dv>0)? dv: -dv;
+
+ for(Arc_ptr jarc=loop->next; jarc != loop; jarc = jarc->next)
+ {
+
+ if(jarc->tail()[0] < uMin)
+ uMin = jarc->tail()[0];
+ if(jarc->tail()[0] > uMax)
+ uMax = jarc->tail()[0];
+ if(jarc->tail()[1] < vMin)
+ vMin = jarc->tail()[1];
+ if(jarc->tail()[1] > vMax)
+ vMax = jarc->tail()[1];
+ }
+
+ if (uMax == uMin)
+ return; // prevent divide-by-zero. Jon Perry. 17 June 2002
+
+ if(mydu > uMax - uMin)
+ num_ulines = 2;
+ else
+ {
+ num_ulines = 3 + (Int) ((uMax-uMin)/mydu);
+ }
+ if(mydv>=vMax-vMin)
+ num_vlines = 2;
+ else
+ {
+ num_vlines = 2+(Int)((vMax-vMin)/mydv);
+ }
+
+ Int isRect = is_rect(loop);
+
+ if(isRect && (num_ulines<=2 || num_vlines<=2))
+ {
+ if(vlinear)
+ triangulateRect(loop, backend, 1, ulinear, vlinear);
+ else if(ulinear)
+ triangulateRect(loop, backend, -1, ulinear, vlinear);
+ else
+ triangulateRect(loop, backend, 0, ulinear, vlinear);
+ }
+
+ else if(isRect)
+ {
+ triangulateRectGen(loop, num_ulines-2, num_vlines-2, backend);
+ }
+ else if( (num_ulines<=2 || num_vlines <=2) && ulinear)
+ {
+ monoTriangulationFunBackend(loop, compV2InY, &backend);
+ }
+ else if( (!ulinear) && (!vlinear) && (num_ulines == 2) && (num_vlines > 2))
+ {
+ monoTriangulationFunBackend(loop, compV2InY, &backend);
+ }
+ else
+ {
+ directedLine* poly = arcLoopToDLineLoop(loop);
+
+ gridWrap grid(num_ulines, num_vlines, uMin, uMax, vMin, vMax);
+ primStream pStream(20, 20);
+ rectBlockArray rbArray(20);
+
+ sampleMonoPoly(poly, &grid, ulinear, vlinear, &pStream, &rbArray);
+
+ evalStream(&pStream);
+
+ evalRBArray(&rbArray, &grid);
+
+#ifdef COUNT_TRIANGLES
+ num_triangles += pStream.num_triangles();
+ num_quads += rbArray.num_quads();
+#endif
+ poly->deleteSinglePolygonWithSline();
+ }
+
+#ifdef COUNT_TRIANGLES
+ printf("num_triangles=%i\n", num_triangles);
+ printf("num_quads = %i\n", num_quads);
+#endif
+}
+
+void Slicer::slice(Arc_ptr loop)
+{
+#ifdef USE_READ_FLAG
+ if(read_flag("flagFile"))
+ slice_new(loop);
+ else
+ slice_old(loop);
+
+#else
+ slice_new(loop);
+#endif
+
+}
+
+
+
+Slicer::Slicer( Backend &b )
+ : CoveAndTiler( b ), Mesher( b ), backend( b )
+{
+ ulinear = 0;
+ vlinear = 0;
+}
+
+Slicer::~Slicer()
+{
+}
+
+void
+Slicer::setisolines( int x )
+{
+ isolines = x;
+}
+
+void
+Slicer::setstriptessellation( REAL x, REAL y )
+{
+ assert(x > 0 && y > 0);
+ du = x;
+ dv = y;
+ setDu( du );
+}
+
+void
+Slicer::slice_old( Arc_ptr loop )
+{
+ loop->markverts();
+
+ Arc_ptr extrema[4];
+ loop->getextrema( extrema );
+
+ unsigned int npts = loop->numpts();
+ TrimRegion::init( npts, extrema[0] );
+
+ Mesher::init( npts );
+
+ long ulines = uarray.init( du, extrema[1], extrema[3] );
+//printf("ulines = %i\n", ulines);
+ Varray varray;
+ long vlines = varray.init( dv, extrema[0], extrema[2] );
+//printf("vlines = %i\n", vlines);
+ long botv = 0;
+ long topv;
+ TrimRegion::init( varray.varray[botv] );
+ getGridExtent( &extrema[0]->pwlArc->pts[0], &extrema[0]->pwlArc->pts[0] );
+
+ for( long quad=0; quad<varray.numquads; quad++ ) {
+ backend.surfgrid( uarray.uarray[0],
+ uarray.uarray[ulines-1],
+ ulines-1,
+ varray.vval[quad],
+ varray.vval[quad+1],
+ varray.voffset[quad+1] - varray.voffset[quad] );
+
+ for( long i=varray.voffset[quad]+1; i <= varray.voffset[quad+1]; i++ ) {
+ topv = botv++;
+ advance( topv - varray.voffset[quad],
+ botv - varray.voffset[quad],
+ varray.varray[botv] );
+ if( i == vlines )
+ getPts( extrema[2] );
+ else
+ getPts( backend );
+ getGridExtent();
+ if( isolines ) {
+ outline();
+ } else {
+ if( canTile() )
+ coveAndTile();
+ else
+ mesh();
+ }
+ }
+ }
+}
+
+
+void
+Slicer::outline( void )
+{
+ GridTrimVertex upper, lower;
+ Hull::init( );
+
+ backend.bgnoutline();
+ while( (nextupper( &upper )) ) {
+ if( upper.isGridVert() )
+ backend.linevert( upper.g );
+ else
+ backend.linevert( upper.t );
+ }
+ backend.endoutline();
+
+ backend.bgnoutline();
+ while( (nextlower( &lower )) ) {
+ if( lower.isGridVert() )
+ backend.linevert( lower.g );
+ else
+ backend.linevert( lower.t );
+ }
+ backend.endoutline();
+}
+
+
+void
+Slicer::outline( Arc_ptr jarc )
+{
+ jarc->markverts();
+
+ if( jarc->pwlArc->npts >= 2 ) {
+ backend.bgnoutline();
+ for( int j = jarc->pwlArc->npts-1; j >= 0; j-- )
+ backend.linevert( &(jarc->pwlArc->pts[j]) );
+ backend.endoutline();
+ }
+}
+
+
diff --git a/src/glu/sgi/libnurbs/internals/slicer.h b/src/glu/sgi/libnurbs/internals/slicer.h
new file mode 100644
index 00000000000..69fc75055bf
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/slicer.h
@@ -0,0 +1,90 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * slicer.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/slicer.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __gluslicer_h_
+#define __gluslicer_h_
+
+#include "trimregion.h"
+#include "mesher.h"
+#include "coveandtiler.h"
+#include "primitiveStream.h"
+#include "rectBlock.h"
+
+class Backend;
+class Arc;
+class TrimVertex;
+
+class Slicer : public CoveAndTiler, public Mesher {
+public:
+ Slicer( Backend & );
+ ~Slicer( void );
+ void slice( Arc_ptr );
+ void slice_old( Arc_ptr);
+ void slice_new( Arc_ptr );
+ void evalStream(primStream* );
+ void evalRBArray(rectBlockArray* rbArray, gridWrap* grid);
+
+ void outline( Arc_ptr );
+ void setstriptessellation( REAL, REAL );
+ void setisolines( int );
+
+ void set_ulinear(int ulinear_flag)
+ {
+ ulinear = ulinear_flag;
+ }
+ void set_vlinear(int vlinear_flag)
+ {
+ vlinear = vlinear_flag;
+ }
+private:
+ Backend& backend;
+ REAL oneOverDu;
+ REAL du, dv;
+ int isolines;
+
+ void outline( void );
+ void initGridlines( void );
+ void advanceGridlines( long );
+
+ int ulinear; //indicate whether uorder is 2 or not
+ int vlinear; //indicate whether vorder is 2 or not
+};
+#endif /* __gluslicer_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/sorter.cc b/src/glu/sgi/libnurbs/internals/sorter.cc
new file mode 100644
index 00000000000..925801de249
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/sorter.cc
@@ -0,0 +1,141 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * sorter.c++
+ *
+ * $Date: 2001/11/29 16:16:55 $ $Revision: 1.2 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/sorter.cc,v 1.2 2001/11/29 16:16:55 kschultz Exp $
+ */
+
+#include "glimports.h"
+#include "sorter.h"
+#include "mystdio.h"
+
+Sorter::Sorter( int _es )
+{
+ es = _es;
+}
+
+void
+Sorter::qsort( void *a, int n )
+{
+ qs1( (char *)a, ((char *)a)+n*es);
+}
+
+int
+Sorter::qscmp( char *, char * )
+{
+ dprintf( "Sorter::qscmp: pure virtual called\n" );
+ return 0;
+}
+
+
+void
+Sorter::qsexc( char *, char * )
+{
+ dprintf( "Sorter::qsexc: pure virtual called\n" );
+}
+
+
+void
+Sorter::qstexc( char *, char *, char * )
+{
+ dprintf( "Sorter::qstexc: pure virtual called\n" );
+}
+
+void
+Sorter::qs1( char *a, char *l )
+{
+ char *i, *j;
+ char *lp, *hp;
+ int c;
+ unsigned int n;
+
+start:
+ if((n=l-a) <= (unsigned int)es)
+ return;
+ n = es * (n / (2*es));
+ hp = lp = a+n;
+ i = a;
+ j = l-es;
+ while(1) {
+ if(i < lp) {
+ if((c = qscmp(i, lp)) == 0) {
+ qsexc(i, lp -= es);
+ continue;
+ }
+ if(c < 0) {
+ i += es;
+ continue;
+ }
+ }
+
+loop:
+ if(j > hp) {
+ if((c = qscmp(hp, j)) == 0) {
+ qsexc(hp += es, j);
+ goto loop;
+ }
+ if(c > 0) {
+ if(i == lp) {
+ qstexc(i, hp += es, j);
+ i = lp += es;
+ goto loop;
+ }
+ qsexc(i, j);
+ j -= es;
+ i += es;
+ continue;
+ }
+ j -= es;
+ goto loop;
+ }
+
+ if(i == lp) {
+ if(lp-a >= l-hp) {
+ qs1(hp+es, l);
+ l = lp;
+ } else {
+ qs1(a, lp);
+ a = hp+es;
+ }
+ goto start;
+ }
+
+ qstexc(j, lp -= es, i);
+ j = hp -= es;
+ }
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/sorter.h b/src/glu/sgi/libnurbs/internals/sorter.h
new file mode 100644
index 00000000000..cc4aecfa82a
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/sorter.h
@@ -0,0 +1,57 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/sorter.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#ifndef __glusorter_h_
+#define __glusorter_h_
+
+class Sorter {
+public:
+ Sorter( int es );
+ void qsort( void *a, int n );
+
+protected:
+ virtual int qscmp( char *, char * );
+ virtual void qsexc( char *i, char *j ); // i<-j, j<-i
+ virtual void qstexc( char *i, char *j, char *k ); // i<-k, k<-j, j<-i
+
+private:
+ void qs1( char *, char * );
+ int es;
+};
+#endif /* __glusorter_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/splitarcs.cc b/src/glu/sgi/libnurbs/internals/splitarcs.cc
new file mode 100644
index 00000000000..1481d065798
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/splitarcs.cc
@@ -0,0 +1,295 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * splitarcs.c++
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/splitarcs.cc,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mysetjmp.h"
+#include "mystdio.h"
+#include "subdivider.h"
+#include "arcsorter.h"
+#include "arc.h"
+#include "bin.h"
+
+/* local preprocessor definitions */
+#define MAXARCS 10
+
+/*----------------------------------------------------------------------------
+ * Subdivider::split - split trim regions in source bin by line (param == value).
+ *----------------------------------------------------------------------------
+ */
+
+void
+Subdivider::split( Bin& bin, Bin& left, Bin& right, int param, REAL value )
+{
+ Bin intersections, unknown;
+
+ partition( bin, left, intersections, right, unknown, param, value );
+
+ int count = intersections.numarcs();
+ if( count % 2 ) {
+#ifndef NDEBUG
+ left.show( "left" );
+ intersections.show( "intersections" );
+ right.show( "right" );
+#endif
+ ::mylongjmp( jumpbuffer, 29 );
+ }
+
+ Arc_ptr arclist[MAXARCS], *list;
+ if( count >= MAXARCS ) {
+ list = new Arc_ptr[count];
+ } else {
+ list = arclist;
+ }
+
+ Arc_ptr jarc, *last, *lptr;
+ for( last = list; (jarc=intersections.removearc()) != NULL; last++ )
+ *last = jarc;
+
+ if( param == 0 ) { /* sort into increasing t order */
+ ArcSdirSorter sorter(*this);
+ sorter.qsort( list, count );
+
+ //::qsort ((void *)list, count, sizeof(Arc_ptr), (cmpfunc)compare_s);
+ for( lptr=list; lptr<last; lptr+=2 )
+ check_s ( lptr[0], lptr[1] );
+ for( lptr=list; lptr<last; lptr+=2 )
+ join_s ( left, right, lptr[0], lptr[1] );
+ for( lptr=list; lptr != last; lptr++ ) {
+ if( ((*lptr)->head()[0] <= value) && ((*lptr)->tail()[0] <= value) )
+ left.addarc( *lptr );
+ else
+ right.addarc( *lptr );
+ }
+ } else { /* sort into decreasing s order */
+ ArcTdirSorter sorter(*this);
+ sorter.qsort( list, count );
+ //::qsort ((void *)list, count, sizeof(Arc_ptr), (cmpfunc)compare_t);
+ for( lptr=list; lptr<last; lptr+=2 )
+ check_t ( lptr[0], lptr[1] );
+ for( lptr=list; lptr<last; lptr+=2 )
+ join_t ( left, right, lptr[0], lptr[1] );
+ for( lptr=list; lptr != last; lptr++ ) {
+ if( ((*lptr)->head()[1] <= value) && ((*lptr)->tail()[1] <= value) )
+ left.addarc( *lptr );
+ else
+ right.addarc( *lptr );
+ }
+ }
+
+ if( list != arclist ) delete[] list;
+ unknown.adopt();
+}
+
+
+void
+Subdivider::check_s( Arc_ptr jarc1, Arc_ptr jarc2 )
+{
+ assert( jarc1->check( ) != 0 );
+ assert( jarc2->check( ) != 0 );
+ assert( jarc1->next->check( ) != 0 );
+ assert( jarc2->next->check( ) != 0 );
+ assert( jarc1 != jarc2 );
+
+ /* XXX - if these assertions fail, it is due to user error or
+ undersampling */
+ if( ! ( jarc1->tail()[0] < (jarc1)->head()[0] ) ) {
+#ifndef NDEBUG
+ dprintf( "s difference %f\n", (jarc1)->tail()[0] - (jarc1)->head()[0] );
+#endif
+ ::mylongjmp( jumpbuffer, 28 );
+ }
+
+ if( ! ( jarc2->tail()[0] > (jarc2)->head()[0] ) ) {
+#ifndef NDEBUG
+ dprintf( "s difference %f\n", (jarc2)->tail()[0] - (jarc2)->head()[0] );
+#endif
+ ::mylongjmp( jumpbuffer, 28 );
+ }
+}
+
+inline void
+Subdivider::link( Arc_ptr jarc1, Arc_ptr jarc2, Arc_ptr up, Arc_ptr down )
+{
+ up->nuid = down->nuid = 0; // XXX
+
+ up->next = jarc2;
+ down->next = jarc1;
+ up->prev = jarc1->prev;
+ down->prev = jarc2->prev;
+
+ down->next->prev = down;
+ up->next->prev = up;
+ down->prev->next = down;
+ up->prev->next = up;
+}
+
+inline void
+Subdivider::simple_link( Arc_ptr jarc1, Arc_ptr jarc2 )
+{
+ Arc_ptr tmp = jarc2->prev;
+ jarc2->prev = jarc1->prev;
+ jarc1->prev = tmp;
+ jarc2->prev->next = jarc2;
+ jarc1->prev->next = jarc1;
+}
+
+
+/*----------------------------------------------------------------------------
+ * join - add a pair of oppositely directed jordan arcs between two arcs
+ *----------------------------------------------------------------------------
+ */
+
+void
+Subdivider::join_s( Bin& left, Bin& right, Arc_ptr jarc1, Arc_ptr jarc2 )
+{
+ assert( jarc1->check( ) != 0);
+ assert( jarc2->check( ) != 0);
+ assert( jarc1 != jarc2 );
+
+ if( ! jarc1->getitail() )
+ jarc1 = jarc1->next;
+
+ if( ! jarc2->getitail() )
+ jarc2 = jarc2->next;
+
+ REAL s = jarc1->tail()[0];
+ REAL t1 = jarc1->tail()[1];
+ REAL t2 = jarc2->tail()[1];
+
+ if( t1 == t2 ) {
+ simple_link( jarc1, jarc2 );
+ } else {
+ Arc_ptr newright = new(arcpool) Arc( arc_right, 0 );
+ Arc_ptr newleft = new(arcpool) Arc( arc_left, 0 );
+ assert( t1 < t2 );
+ if( isBezierArcType() ) {
+ arctessellator.bezier( newright, s, s, t1, t2 );
+ arctessellator.bezier( newleft, s, s, t2, t1 );
+ } else {
+ arctessellator.pwl_right( newright, s, t1, t2, stepsizes[0] );
+ arctessellator.pwl_left( newleft, s, t2, t1, stepsizes[2] );
+ }
+ link( jarc1, jarc2, newright, newleft );
+ left.addarc( newright );
+ right.addarc( newleft );
+ }
+
+ assert( jarc1->check( ) != 0 );
+ assert( jarc2->check( ) != 0 );
+ assert( jarc1->next->check( ) != 0);
+ assert( jarc2->next->check( ) != 0);
+}
+
+void
+Subdivider::check_t( Arc_ptr jarc1, Arc_ptr jarc2 )
+{
+ assert( jarc1->check( ) != 0 );
+ assert( jarc2->check( ) != 0 );
+ assert( jarc1->next->check( ) != 0 );
+ assert( jarc2->next->check( ) != 0 );
+ assert( jarc1 != jarc2 );
+
+ /* XXX - if these assertions fail, it is due to user error or
+ undersampling */
+ if( ! ( jarc1->tail()[1] < (jarc1)->head()[1] ) ) {
+#ifndef NDEBUG
+ dprintf( "t difference %f\n", jarc1->tail()[1] - (jarc1)->head()[1] );
+#endif
+ ::mylongjmp( jumpbuffer, 28 );
+ }
+
+ if( ! ( jarc2->tail()[1] > (jarc2)->head()[1] ) ) {
+#ifndef NDEBUG
+ dprintf( "t difference %f\n", jarc2->tail()[1] - (jarc2)->head()[1] );
+#endif
+ ::mylongjmp( jumpbuffer, 28 );
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * join_t - add a pair of oppositely directed jordan arcs between two arcs
+ *----------------------------------------------------------------------------
+ */
+
+void
+Subdivider::join_t( Bin& bottom, Bin& top, Arc_ptr jarc1, Arc_ptr jarc2 )
+{
+ assert( jarc1->check( ) != 0 );
+ assert( jarc2->check( ) != 0 );
+ assert( jarc1->next->check( ) != 0 );
+ assert( jarc2->next->check( ) != 0 );
+ assert( jarc1 != jarc2 );
+
+ if( ! jarc1->getitail() )
+ jarc1 = jarc1->next;
+
+ if( ! jarc2->getitail() )
+ jarc2 = jarc2->next;
+
+ REAL s1 = jarc1->tail()[0];
+ REAL s2 = jarc2->tail()[0];
+ REAL t = jarc1->tail()[1];
+
+ if( s1 == s2 ) {
+ simple_link( jarc1, jarc2 );
+ } else {
+ Arc_ptr newtop = new(arcpool) Arc( arc_top, 0 );
+ Arc_ptr newbot = new(arcpool) Arc( arc_bottom, 0 );
+ assert( s1 > s2 );
+ if( isBezierArcType() ) {
+ arctessellator.bezier( newtop, s1, s2, t, t );
+ arctessellator.bezier( newbot, s2, s1, t, t );
+ } else {
+ arctessellator.pwl_top( newtop, t, s1, s2, stepsizes[1] );
+ arctessellator.pwl_bottom( newbot, t, s2, s1, stepsizes[3] );
+ }
+ link( jarc1, jarc2, newtop, newbot );
+ bottom.addarc( newtop );
+ top.addarc( newbot );
+ }
+
+ assert( jarc1->check( ) != 0 );
+ assert( jarc2->check( ) != 0 );
+ assert( jarc1->next->check( ) != 0 );
+ assert( jarc2->next->check( ) != 0 );
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/subdivider.cc b/src/glu/sgi/libnurbs/internals/subdivider.cc
new file mode 100644
index 00000000000..cc0b5147065
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/subdivider.cc
@@ -0,0 +1,910 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * subdivider.cxx
+ *
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "subdivider.h"
+#include "arc.h"
+#include "bezierarc.h"
+#include "bin.h"
+#include "renderhints.h"
+#include "backend.h"
+#include "mapdesc.h"
+#include "quilt.h"
+#include "patchlist.h"
+#include "patch.h"
+#include "nurbsconsts.h"
+#include "trimvertpool.h"
+#include "simplemath.h"
+
+#include "polyUtil.h" //for function area()
+
+//#define PARTITION_TEST
+#ifdef PARTITION_TEST
+#include "partitionY.h"
+#include "monoTriangulation.h"
+#include "dataTransform.h"
+#include "monoChain.h"
+
+#endif
+
+
+#define OPTIMIZE_UNTRIMED_CASE
+
+
+Bin*
+Subdivider::makePatchBoundary( const REAL *from, const REAL *to )
+{
+ Bin* ret = new Bin();
+ REAL smin = from[0];
+ REAL smax = to[0];
+ REAL tmin = from[1];
+ REAL tmax = to[1];
+
+ pjarc = 0;
+
+ Arc_ptr jarc = new(arcpool) Arc( arc_bottom, 0 );
+ arctessellator.bezier( jarc, smin, smax, tmin, tmin );
+ ret->addarc( jarc );
+ pjarc = jarc->append( pjarc );
+
+ jarc = new(arcpool) Arc( arc_right, 0 );
+ arctessellator.bezier( jarc, smax, smax, tmin, tmax );
+ ret->addarc( jarc );
+ pjarc = jarc->append( pjarc );
+
+ jarc = new(arcpool) Arc( arc_top, 0 );
+ arctessellator.bezier( jarc, smax, smin, tmax, tmax );
+ ret->addarc( jarc );
+ pjarc = jarc->append( pjarc );
+
+ jarc = new(arcpool) Arc( arc_left, 0 );
+ arctessellator.bezier( jarc, smin, smin, tmax, tmin );
+ ret->addarc( jarc );
+ jarc->append( pjarc );
+
+ assert( jarc->check() != 0 );
+ return ret;
+}
+
+/*---------------------------------------------------------------------------
+ * Subdivider - construct a subdivider
+ *---------------------------------------------------------------------------
+ */
+
+Subdivider::Subdivider( Renderhints& r, Backend& b )
+ : slicer( b ),
+ arctessellator( trimvertexpool, pwlarcpool ),
+ arcpool( sizeof( Arc), 1, "arcpool" ),
+ bezierarcpool( sizeof( BezierArc ), 1, "Bezarcpool" ),
+ pwlarcpool( sizeof( PwlArc ), 1, "Pwlarcpool" ),
+ renderhints( r ),
+ backend( b )
+{
+}
+
+void
+Subdivider::setJumpbuffer( JumpBuffer *j )
+{
+ jumpbuffer = j;
+}
+
+/*---------------------------------------------------------------------------
+ * clear - reset all state after possible error condition
+ *---------------------------------------------------------------------------
+ */
+
+void
+Subdivider::clear( void )
+{
+ trimvertexpool.clear();
+ arcpool.clear();
+ pwlarcpool.clear();
+ bezierarcpool.clear();
+}
+
+/*---------------------------------------------------------------------------
+ * ~Subdivider - destroy a subdivider
+ *---------------------------------------------------------------------------
+ */
+
+Subdivider::~Subdivider( void )
+{
+}
+
+/*---------------------------------------------------------------------------
+ * addArc - add a bezier arc to a trim loop and to a bin
+ *---------------------------------------------------------------------------
+ */
+void
+Subdivider::addArc( REAL *cpts, Quilt *quilt, long _nuid )
+{
+ BezierArc *bezierArc = new(bezierarcpool) BezierArc;
+ Arc *jarc = new(arcpool) Arc( arc_none, _nuid );
+ jarc->pwlArc = 0;
+ jarc->bezierArc = bezierArc;
+ bezierArc->order = quilt->qspec->order;
+ bezierArc->stride = quilt->qspec->stride;
+ bezierArc->mapdesc = quilt->mapdesc;
+ bezierArc->cpts = cpts;
+ initialbin.addarc( jarc );
+ pjarc = jarc->append( pjarc );
+}
+
+/*---------------------------------------------------------------------------
+ * addArc - add a pwl arc to a trim loop and to a bin
+ *---------------------------------------------------------------------------
+ */
+
+void
+Subdivider::addArc( int npts, TrimVertex *pts, long _nuid )
+{
+ Arc *jarc = new(arcpool) Arc( arc_none, _nuid );
+ jarc->pwlArc = new(pwlarcpool) PwlArc( npts, pts );
+ initialbin.addarc( jarc );
+ pjarc = jarc->append( pjarc );
+}
+
+void
+Subdivider::beginQuilts( void )
+{
+ qlist = 0;
+}
+
+void
+Subdivider::addQuilt( Quilt *quilt )
+{
+ quilt->next = qlist;
+ qlist = quilt;
+}
+
+/*---------------------------------------------------------------------------
+ * drawSurfaces - main entry point for surface tessellation
+ *---------------------------------------------------------------------------
+ */
+
+void
+Subdivider::drawSurfaces( long nuid )
+{
+ renderhints.init( );
+
+ if (qlist == NULL)
+ {
+ //initialbin could be nonempty due to some errors
+ freejarcs(initialbin);
+ return;
+ }
+
+ for( Quilt *q = qlist; q; q = q->next ) {
+ if( q->isCulled( ) == CULL_TRIVIAL_REJECT ) {
+ freejarcs( initialbin );
+ return;
+ }
+ }
+
+
+ REAL from[2], to[2];
+ qlist->getRange( from, to, spbrkpts, tpbrkpts );
+#ifdef OPTIMIZE_UNTRIMED_CASE
+ //perform optimization only when the samplng method is
+ //DOMAIN_DISTANCE and the display methdo is either
+ //fill or outline_polygon.
+ int optimize = (is_domain_distance_sampling && (renderhints.display_method != N_OUTLINE_PATCH));
+#endif
+
+ if( ! initialbin.isnonempty() ) {
+#ifdef OPTIMIZE_UNTRIMED_CASE
+ if(! optimize )
+ {
+
+ makeBorderTrim( from, to );
+ }
+#else
+ makeBorderTrim( from, to );
+#endif
+ } else {
+ REAL rate[2];
+ qlist->findRates( spbrkpts, tpbrkpts, rate );
+
+ if( decompose( initialbin, min(rate[0], rate[1]) ) )
+ mylongjmp( jumpbuffer, 31 );
+ }
+
+ backend.bgnsurf( renderhints.wiretris, renderhints.wirequads, nuid );
+
+#ifdef PARTITION_TEST
+ if( initialbin.isnonempty() && spbrkpts.end-2 == spbrkpts.start &&
+ tpbrkpts.end-2 == tpbrkpts.start)
+{
+ for(int i=spbrkpts.start; i<spbrkpts.end-1; i++){
+ for(int j=tpbrkpts.start; j<tpbrkpts.end-1; j++){
+ Real pta[2], ptb[2];
+ pta[0] = spbrkpts.pts[i];
+ ptb[0] = spbrkpts.pts[i+1];
+ pta[1] = tpbrkpts.pts[j];
+ ptb[1] = tpbrkpts.pts[j+1];
+ qlist->downloadAll(pta, ptb, backend);
+
+ directedLine *poly;
+
+ {
+
+ poly = bin_to_DLineLoops(initialbin);
+
+ poly=poly->deleteDegenerateLinesAllPolygons();
+
+ sampledLine* retSampledLines;
+//printf("before MC_partition\n");
+ poly = MC_partitionY(poly, &retSampledLines);
+//printf("after MC_partition\n");
+
+ }
+
+
+ {
+ primStream pStream(5000,5000);
+ directedLine* temp;
+
+ for(temp=poly; temp != NULL; temp=temp->getNextPolygon())
+
+ monoTriangulation(temp, &pStream);
+
+ slicer.evalStream(&pStream);
+
+ }
+ //need to clean up space
+ }
+ }
+ freejarcs( initialbin );
+ backend.endsurf();
+ return;
+
+ /*
+ printf("num_polygons=%i\n", poly->numPolygons());
+ printf("num_edges=%i\n", poly->numEdgesAllPolygons());
+ poly->writeAllPolygons("zloutputFile");
+ return;
+ {
+ primStream pStream(20,20);
+ for(directedLine* tempD = poly; tempD != NULL; tempD = tempD->getNextPolygon())
+ monoTriangulation(tempD, &pStream);
+ }
+ return;
+ */
+}
+#endif //PARTITION_TEST
+
+
+#ifdef OPTIMIZE_UNTRIMED_CASE
+ if( (!initialbin.isnonempty()) && optimize )
+ {
+ int i,j;
+ int num_u_steps;
+ int num_v_steps;
+ for(i=spbrkpts.start; i<spbrkpts.end-1; i++){
+ for(j=tpbrkpts.start; j<tpbrkpts.end-1; j++){
+ Real pta[2], ptb[2];
+ pta[0] = spbrkpts.pts[i];
+ ptb[0] = spbrkpts.pts[i+1];
+ pta[1] = tpbrkpts.pts[j];
+ ptb[1] = tpbrkpts.pts[j+1];
+ qlist->downloadAll(pta, ptb, backend);
+
+ num_u_steps = (int) (domain_distance_u_rate * (ptb[0]-pta[0]));
+ num_v_steps = (int) (domain_distance_v_rate * (ptb[1]-pta[1]));
+
+ if(num_u_steps <= 0) num_u_steps = 1;
+ if(num_v_steps <= 0) num_v_steps = 1;
+
+ backend.surfgrid(pta[0], ptb[0], num_u_steps,
+ ptb[1], pta[1], num_v_steps);
+ backend.surfmesh(0,0,num_u_steps,num_v_steps);
+
+
+
+ continue;
+ /* the following is left for reference purpose, don't delete
+ {
+ Bin* tempSource;
+ Patchlist patchlist(qlist, pta, ptb);
+ patchlist.getstepsize();
+
+ tempSource=makePatchBoundary(pta, ptb);
+
+ tessellation(*tempSource, patchlist);
+
+ render(*tempSource);
+ delete tempSource;
+ }
+ */
+ }
+ }
+ }
+ else
+ subdivideInS( initialbin );
+#else
+
+ subdivideInS( initialbin );
+#endif
+
+ backend.endsurf();
+
+}
+
+void
+Subdivider::subdivideInS( Bin& source )
+{
+ if( renderhints.display_method == N_OUTLINE_PARAM ) {
+ outline( source );
+ freejarcs( source );
+ } else {
+ setArcTypeBezier();
+ setNonDegenerate();
+ splitInS( source, spbrkpts.start, spbrkpts.end );
+ }
+}
+
+
+/*---------------------------------------------------------------------------
+ * splitInS - split a patch and a bin by an isoparametric line
+ *---------------------------------------------------------------------------
+ */
+
+void
+Subdivider::splitInS( Bin& source, int start, int end )
+{
+ if( source.isnonempty() ) {
+ if( start != end ) {
+ int i = start + (end - start) / 2;
+ Bin left, right;
+ split( source, left, right, 0, spbrkpts.pts[i] );
+ splitInS( left, start, i );
+ splitInS( right, i+1, end );
+ } else {
+ if( start == spbrkpts.start || start == spbrkpts.end ) {
+ freejarcs( source );
+ } else if( renderhints.display_method == N_OUTLINE_PARAM_S ) {
+ outline( source );
+ freejarcs( source );
+ } else {
+ setArcTypeBezier();
+ setNonDegenerate();
+ s_index = start;
+ splitInT( source, tpbrkpts.start, tpbrkpts.end );
+ }
+ }
+ }
+}
+
+/*---------------------------------------------------------------------------
+ * splitInT - split a patch and a bin by an isoparametric line
+ *---------------------------------------------------------------------------
+ */
+
+void
+Subdivider::splitInT( Bin& source, int start, int end )
+{
+ if( source.isnonempty() ) {
+ if( start != end ) {
+ int i = start + (end - start) / 2;
+ Bin left, right;
+ split( source, left, right, 1, tpbrkpts.pts[i] );
+ splitInT( left, start, i );
+ splitInT( right, i+1, end );
+ } else {
+ if( start == tpbrkpts.start || start == tpbrkpts.end ) {
+ freejarcs( source );
+ } else if( renderhints.display_method == N_OUTLINE_PARAM_ST ) {
+ outline( source );
+ freejarcs( source );
+ } else {
+ t_index = start;
+ setArcTypeBezier();
+ setDegenerate();
+
+ REAL pta[2], ptb[2];
+ pta[0] = spbrkpts.pts[s_index-1];
+ pta[1] = tpbrkpts.pts[t_index-1];
+
+ ptb[0] = spbrkpts.pts[s_index];
+ ptb[1] = tpbrkpts.pts[t_index];
+ qlist->downloadAll( pta, ptb, backend );
+
+ Patchlist patchlist( qlist, pta, ptb );
+/*
+printf("-------samplingSplit-----\n");
+source.show("samplingSplit source");
+*/
+ samplingSplit( source, patchlist, renderhints.maxsubdivisions, 0 );
+ setNonDegenerate();
+ setArcTypeBezier();
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * samplingSplit - recursively subdivide patch, cull check each subpatch
+ *--------------------------------------------------------------------------
+ */
+
+void
+Subdivider::samplingSplit(
+ Bin& source,
+ Patchlist& patchlist,
+ int subdivisions,
+ int param )
+{
+ if( ! source.isnonempty() ) return;
+
+ if( patchlist.cullCheck() == CULL_TRIVIAL_REJECT ) {
+ freejarcs( source );
+ return;
+ }
+
+ patchlist.getstepsize();
+
+ if( renderhints.display_method == N_OUTLINE_PATCH ) {
+ tessellation( source, patchlist );
+ outline( source );
+ freejarcs( source );
+ return;
+ }
+
+ //patchlist.clamp();
+
+ tessellation( source, patchlist );
+
+ if( patchlist.needsSamplingSubdivision() && (subdivisions > 0) ) {
+ if( ! patchlist.needsSubdivision( 0 ) )
+ param = 1;
+ else if( ! patchlist.needsSubdivision( 1 ) )
+ param = 0;
+ else
+ param = 1 - param;
+
+ Bin left, right;
+ REAL mid = ( patchlist.pspec[param].range[0] +
+ patchlist.pspec[param].range[1] ) * 0.5;
+ split( source, left, right, param, mid );
+ Patchlist subpatchlist( patchlist, param, mid );
+ samplingSplit( left, subpatchlist, subdivisions-1, param );
+ samplingSplit( right, patchlist, subdivisions-1, param );
+ } else {
+ setArcTypePwl();
+ setDegenerate();
+ nonSamplingSplit( source, patchlist, subdivisions, param );
+ setDegenerate();
+ setArcTypeBezier();
+ }
+}
+
+void
+Subdivider::nonSamplingSplit(
+ Bin& source,
+ Patchlist& patchlist,
+ int subdivisions,
+ int param )
+{
+ if( patchlist.needsNonSamplingSubdivision() && (subdivisions > 0) ) {
+ param = 1 - param;
+
+ Bin left, right;
+ REAL mid = ( patchlist.pspec[param].range[0] +
+ patchlist.pspec[param].range[1] ) * 0.5;
+ split( source, left, right, param, mid );
+ Patchlist subpatchlist( patchlist, param, mid );
+ if( left.isnonempty() )
+ if( subpatchlist.cullCheck() == CULL_TRIVIAL_REJECT )
+ freejarcs( left );
+ else
+ nonSamplingSplit( left, subpatchlist, subdivisions-1, param );
+ if( right.isnonempty() )
+ if( patchlist.cullCheck() == CULL_TRIVIAL_REJECT )
+ freejarcs( right );
+ else
+ nonSamplingSplit( right, patchlist, subdivisions-1, param );
+
+ } else {
+ // make bbox calls
+ patchlist.bbox();
+ backend.patch( patchlist.pspec[0].range[0], patchlist.pspec[0].range[1],
+ patchlist.pspec[1].range[0], patchlist.pspec[1].range[1] );
+
+ if( renderhints.display_method == N_OUTLINE_SUBDIV ) {
+ outline( source );
+ freejarcs( source );
+ } else {
+ setArcTypePwl();
+ setDegenerate();
+ findIrregularS( source );
+ monosplitInS( source, smbrkpts.start, smbrkpts.end );
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * tessellation - set tessellation of interior and boundary of patch
+ *--------------------------------------------------------------------------
+ */
+
+void
+Subdivider::tessellation( Bin& bin, Patchlist &patchlist )
+{
+ // tessellate unsampled trim curves
+ tessellate( bin, patchlist.pspec[1].sidestep[1], patchlist.pspec[0].sidestep[1],
+ patchlist.pspec[1].sidestep[0], patchlist.pspec[0].sidestep[0] );
+
+ // set interior sampling rates
+ slicer.setstriptessellation( patchlist.pspec[0].stepsize, patchlist.pspec[1].stepsize );
+
+ //added by zl: set the order which will be used in slicer.c++
+ slicer.set_ulinear( (patchlist.get_uorder() == 2));
+ slicer.set_vlinear( (patchlist.get_vorder() == 2));
+
+ // set boundary sampling rates
+ stepsizes[0] = patchlist.pspec[1].stepsize;
+ stepsizes[1] = patchlist.pspec[0].stepsize;
+ stepsizes[2] = patchlist.pspec[1].stepsize;
+ stepsizes[3] = patchlist.pspec[0].stepsize;
+}
+
+/*---------------------------------------------------------------------------
+ * monosplitInS - split a patch and a bin by an isoparametric line
+ *---------------------------------------------------------------------------
+ */
+
+void
+Subdivider::monosplitInS( Bin& source, int start, int end )
+{
+ if( source.isnonempty() ) {
+ if( start != end ) {
+ int i = start + (end - start) / 2;
+ Bin left, right;
+ split( source, left, right, 0, smbrkpts.pts[i] );
+ monosplitInS( left, start, i );
+ monosplitInS( right, i+1, end );
+ } else {
+ if( renderhints.display_method == N_OUTLINE_SUBDIV_S ) {
+ outline( source );
+ freejarcs( source );
+ } else {
+ setArcTypePwl();
+ setDegenerate();
+ findIrregularT( source );
+ monosplitInT( source, tmbrkpts.start, tmbrkpts.end );
+ }
+ }
+ }
+}
+
+/*---------------------------------------------------------------------------
+ * monosplitInT - split a patch and a bin by an isoparametric line
+ *---------------------------------------------------------------------------
+ */
+
+void
+Subdivider::monosplitInT( Bin& source, int start, int end )
+{
+ if( source.isnonempty() ) {
+ if( start != end ) {
+ int i = start + (end - start) / 2;
+ Bin left, right;
+ split( source, left, right, 1, tmbrkpts.pts[i] );
+ monosplitInT( left, start, i );
+ monosplitInT( right, i+1, end );
+ } else {
+ if( renderhints.display_method == N_OUTLINE_SUBDIV_ST ) {
+ outline( source );
+ freejarcs( source );
+ } else {
+/*
+printf("*******render\n");
+source.show("source\n");
+*/
+ render( source );
+ freejarcs( source );
+ }
+ }
+ }
+}
+
+
+/*----------------------------------------------------------------------------
+ * findIrregularS - determine points of non-monotonicity is s direction
+ *----------------------------------------------------------------------------
+ */
+
+void
+Subdivider::findIrregularS( Bin& bin )
+{
+ assert( bin.firstarc()->check() != 0 );
+
+ smbrkpts.grow( bin.numarcs() );
+
+ for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
+ REAL *a = jarc->prev->tail();
+ REAL *b = jarc->tail();
+ REAL *c = jarc->head();
+
+ if( b[1] == a[1] && b[1] == c[1] ) continue;
+
+ //corrected code
+ if((b[1]<=a[1] && b[1] <= c[1]) ||
+ (b[1]>=a[1] && b[1] >= c[1]))
+ {
+ //each arc (jarc, jarc->prev, jarc->next) is a
+ //monotone arc consisting of multiple line segements.
+ //it may happen that jarc->prev and jarc->next are the same,
+ //that is, jarc->prev and jarc form a closed loop.
+ //In such case, a and c will be the same.
+ if(a[0]==c[0] && a[1] == c[1])
+ {
+ if(jarc->pwlArc->npts >2)
+ {
+ c = jarc->pwlArc->pts[jarc->pwlArc->npts-2].param;
+ }
+ else
+ {
+ assert(jarc->prev->pwlArc->npts>2);
+ a = jarc->prev->pwlArc->pts[jarc->prev->pwlArc->npts-2].param;
+ }
+
+ }
+ if(area(a,b,c) < 0)
+ {
+ smbrkpts.add(b[0]);
+ }
+
+ }
+
+ /* old code,
+ if( b[1] <= a[1] && b[1] <= c[1] ) {
+ if( ! ccwTurn_tr( jarc->prev, jarc ) )
+ smbrkpts.add( b[0] );
+ } else if( b[1] >= a[1] && b[1] >= c[1] ) {
+ if( ! ccwTurn_tl( jarc->prev, jarc ) )
+ smbrkpts.add( b[0] );
+ }
+ */
+
+ }
+
+ smbrkpts.filter();
+}
+
+/*----------------------------------------------------------------------------
+ * findIrregularT - determine points of non-monotonicity in t direction
+ * where one arc is parallel to the s axis.
+ *----------------------------------------------------------------------------
+ */
+
+void
+Subdivider::findIrregularT( Bin& bin )
+{
+ assert( bin.firstarc()->check() != 0 );
+
+ tmbrkpts.grow( bin.numarcs() );
+
+ for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
+ REAL *a = jarc->prev->tail();
+ REAL *b = jarc->tail();
+ REAL *c = jarc->head();
+
+ if( b[0] == a[0] && b[0] == c[0] ) continue;
+
+ if( b[0] <= a[0] && b[0] <= c[0] ) {
+ if( a[1] != b[1] && b[1] != c[1] ) continue;
+ if( ! ccwTurn_sr( jarc->prev, jarc ) )
+ tmbrkpts.add( b[1] );
+ } else if ( b[0] >= a[0] && b[0] >= c[0] ) {
+ if( a[1] != b[1] && b[1] != c[1] ) continue;
+ if( ! ccwTurn_sl( jarc->prev, jarc ) )
+ tmbrkpts.add( b[1] );
+ }
+ }
+ tmbrkpts.filter( );
+}
+
+/*-----------------------------------------------------------------------------
+ * makeBorderTrim - if no user input trimming data then create
+ * a trimming curve around the boundaries of the Quilt. The curve consists of
+ * four Jordan arcs, one for each side of the Quilt, connected, of course,
+ * head to tail.
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Subdivider::makeBorderTrim( const REAL *from, const REAL *to )
+{
+ REAL smin = from[0];
+ REAL smax = to[0];
+ REAL tmin = from[1];
+ REAL tmax = to[1];
+
+ pjarc = 0;
+
+ Arc_ptr jarc = new(arcpool) Arc( arc_bottom, 0 );
+ arctessellator.bezier( jarc, smin, smax, tmin, tmin );
+ initialbin.addarc( jarc );
+ pjarc = jarc->append( pjarc );
+
+ jarc = new(arcpool) Arc( arc_right, 0 );
+ arctessellator.bezier( jarc, smax, smax, tmin, tmax );
+ initialbin.addarc( jarc );
+ pjarc = jarc->append( pjarc );
+
+ jarc = new(arcpool) Arc( arc_top, 0 );
+ arctessellator.bezier( jarc, smax, smin, tmax, tmax );
+ initialbin.addarc( jarc );
+ pjarc = jarc->append( pjarc );
+
+ jarc = new(arcpool) Arc( arc_left, 0 );
+ arctessellator.bezier( jarc, smin, smin, tmax, tmin );
+ initialbin.addarc( jarc );
+ jarc->append( pjarc );
+
+ assert( jarc->check() != 0 );
+}
+
+/*----------------------------------------------------------------------------
+ * render - renders all monotone regions in a bin and frees the bin
+ *----------------------------------------------------------------------------
+ */
+
+void
+Subdivider::render( Bin& bin )
+{
+ bin.markall();
+
+#ifdef N_ISOLINE_S
+ slicer.setisolines( ( renderhints.display_method == N_ISOLINE_S ) ? 1 : 0 );
+#else
+ slicer.setisolines( 0 );
+#endif
+
+ for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
+ if( jarc->ismarked() ) {
+ assert( jarc->check( ) != 0 );
+ Arc_ptr jarchead = jarc;
+ do {
+ jarc->clearmark();
+ jarc = jarc->next;
+ } while (jarc != jarchead);
+ slicer.slice( jarc );
+ }
+ }
+}
+
+/*---------------------------------------------------------------------------
+ * outline - render the trimmed patch by outlining the boundary
+ *---------------------------------------------------------------------------
+ */
+
+void
+Subdivider::outline( Bin& bin )
+{
+ bin.markall();
+ for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
+ if( jarc->ismarked() ) {
+ assert( jarc->check( ) != 0 );
+ Arc_ptr jarchead = jarc;
+ do {
+ slicer.outline( jarc );
+ jarc->clearmark();
+ jarc = jarc->prev;
+ } while (jarc != jarchead);
+ }
+ }
+}
+
+/*---------------------------------------------------------------------------
+ * freejarcs - free all arcs in a bin
+ *---------------------------------------------------------------------------
+ */
+
+void
+Subdivider::freejarcs( Bin& bin )
+{
+ bin.adopt(); /* XXX - should not be necessary */
+
+ Arc_ptr jarc;
+ while( (jarc = bin.removearc()) != NULL ) {
+ if( jarc->pwlArc ) jarc->pwlArc->deleteMe( pwlarcpool ); jarc->pwlArc = 0;
+ if( jarc->bezierArc) jarc->bezierArc->deleteMe( bezierarcpool ); jarc->bezierArc = 0;
+ jarc->deleteMe( arcpool );
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * tessellate - tessellate all Bezier arcs in a bin
+ * 1) only accepts linear Bezier arcs as input
+ * 2) the Bezier arcs are stored in the pwlArc structure
+ * 3) only vertical or horizontal lines work
+ * -- should
+ * 1) represent Bezier arcs in BezierArc structure
+ * (this requires a multitude of changes to the code)
+ * 2) accept high degree Bezier arcs (hard)
+ * 3) map the curve onto the surface to determine tessellation
+ * 4) work for curves of arbitrary geometry
+ *----------------------------------------------------------------------------
+ */
+
+
+void
+Subdivider::tessellate( Bin& bin, REAL rrate, REAL trate, REAL lrate, REAL brate )
+{
+ for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
+ if( jarc->isbezier( ) ) {
+ assert( jarc->pwlArc->npts == 2 );
+ TrimVertex *pts = jarc->pwlArc->pts;
+ REAL s1 = pts[0].param[0];
+ REAL t1 = pts[0].param[1];
+ REAL s2 = pts[1].param[0];
+ REAL t2 = pts[1].param[1];
+
+ jarc->pwlArc->deleteMe( pwlarcpool ); jarc->pwlArc = 0;
+
+ switch( jarc->getside() ) {
+ case arc_left:
+ assert( s1 == s2 );
+ arctessellator.pwl_left( jarc, s1, t1, t2, lrate );
+ break;
+ case arc_right:
+ assert( s1 == s2 );
+ arctessellator.pwl_right( jarc, s1, t1, t2, rrate );
+ break;
+ case arc_top:
+ assert( t1 == t2 );
+ arctessellator.pwl_top( jarc, t1, s1, s2, trate );
+ break;
+ case arc_bottom:
+ assert( t1 == t2 );
+ arctessellator.pwl_bottom( jarc, t1, s1, s2, brate );
+ break;
+ case arc_none:
+ (void) abort();
+ break;
+ }
+ assert( ! jarc->isbezier() );
+ assert( jarc->check() != 0 );
+ }
+ }
+}
diff --git a/src/glu/sgi/libnurbs/internals/subdivider.h b/src/glu/sgi/libnurbs/internals/subdivider.h
new file mode 100644
index 00000000000..d190af03f59
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/subdivider.h
@@ -0,0 +1,206 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * subdivider.h
+ *
+ * $Date: 2001/08/07 17:34:11 $ $Revision: 1.2 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/subdivider.h,v 1.2 2001/08/07 17:34:11 brianp Exp $
+ */
+
+#ifndef __glusubdivider_h_
+#define __glusubdivider_h_
+
+#include "mysetjmp.h"
+#include "bin.h"
+#include "flist.h"
+#include "slicer.h"
+#include "arctess.h"
+#include "trimvertex.h"
+#include "trimvertpool.h"
+
+class Arc;
+class Pool;
+class Renderhints;
+class Quilt;
+class Patchlist;
+class Curvelist;
+struct JumpBuffer;
+
+class Subdivider {
+public:
+ Subdivider( Renderhints&, Backend& );
+ ~Subdivider( void );
+ void clear( void );
+
+ void beginTrims( void ) {}
+ void beginLoop( void );
+ void addArc( REAL *, Quilt *, long );
+ void addArc( int, TrimVertex *, long );
+ void endLoop( void ) {}
+ void endTrims( void ) {}
+
+ void beginQuilts( void );
+ void addQuilt( Quilt * );
+ void endQuilts( void ) {}
+
+ void drawCurves( void );
+ void drawSurfaces( long );
+
+ int ccwTurn_sl( Arc_ptr, Arc_ptr );
+ int ccwTurn_sr( Arc_ptr , Arc_ptr );
+ int ccwTurn_tl( Arc_ptr , Arc_ptr );
+ int ccwTurn_tr( Arc_ptr , Arc_ptr );
+
+ void setJumpbuffer( JumpBuffer * );
+
+ void set_domain_distance_u_rate(REAL u_rate)
+ {
+ domain_distance_u_rate = u_rate;
+ }
+ void set_domain_distance_v_rate(REAL v_rate)
+ {
+ domain_distance_v_rate = v_rate;
+ }
+ void set_is_domain_distance_sampling(int flag)
+ {
+ is_domain_distance_sampling = flag;
+ }
+
+private:
+ void classify_headonleft_s( Bin &, Bin &, Bin &, REAL );
+ void classify_tailonleft_s( Bin &, Bin &, Bin &, REAL );
+ void classify_headonright_s( Bin &, Bin &, Bin &, REAL );
+ void classify_tailonright_s( Bin &, Bin &, Bin &, REAL );
+ void classify_headonleft_t( Bin &, Bin &, Bin &, REAL );
+ void classify_tailonleft_t( Bin &, Bin &, Bin &, REAL );
+ void classify_headonright_t( Bin &, Bin &, Bin &, REAL );
+ void classify_tailonright_t( Bin &, Bin &, Bin &, REAL );
+
+ enum dir { down, same, up, none };
+ void tessellate( Arc_ptr, REAL );
+ void monotonize( Arc_ptr , Bin & );
+ int isMonotone( Arc_ptr );
+ int decompose( Bin &, REAL );
+
+
+ Slicer slicer;
+ ArcTessellator arctessellator;
+ Pool arcpool;
+ Pool bezierarcpool;
+ Pool pwlarcpool;
+ TrimVertexPool trimvertexpool;
+
+ JumpBuffer* jumpbuffer;
+ Renderhints& renderhints;
+ Backend& backend;
+
+ Bin initialbin;
+ Arc_ptr pjarc;
+ int s_index;
+ int t_index;
+ Quilt * qlist;
+ Flist spbrkpts;
+ Flist tpbrkpts;
+ Flist smbrkpts;
+ Flist tmbrkpts;
+ REAL stepsizes[4];
+ int showDegenerate;
+ int isArcTypeBezier;
+
+ void samplingSplit( Curvelist&, int );
+
+ void subdivideInS( Bin& );
+ void splitInS( Bin&, int, int );
+ void splitInT( Bin&, int, int );
+ void samplingSplit( Bin&, Patchlist&, int, int );
+ void nonSamplingSplit( Bin&, Patchlist&, int, int );
+ void tessellation( Bin&, Patchlist& );
+ void monosplitInS( Bin&, int, int );
+ void monosplitInT( Bin&, int, int );
+
+ void outline( Bin & );
+ void freejarcs( Bin & );
+ void render( Bin & );
+ void split( Bin &, Bin &, Bin &, int, REAL );
+ void tessellate( Bin &, REAL, REAL, REAL, REAL );
+
+ inline void setDegenerate( void ) { showDegenerate = 1; }
+ inline void setNonDegenerate( void ) { showDegenerate = 0; }
+ inline int showingDegenerate( void ) { return showDegenerate; }
+ inline void setArcTypeBezier( void ) { isArcTypeBezier = 1; }
+ inline void setArcTypePwl( void ) { isArcTypeBezier = 0; }
+ inline int isBezierArcType( void ) { return isArcTypeBezier; }
+
+ void makeBorderTrim( const REAL *, const REAL * );
+ void split( Bin &, int, const REAL *, int, int );
+ void partition( Bin &, Bin &, Bin &, Bin &, Bin &, int, REAL );
+ void findIrregularS( Bin & );
+ void findIrregularT( Bin & );
+
+
+ inline int bbox( TrimVertex *, TrimVertex *, TrimVertex *, int );
+ static int bbox( REAL, REAL, REAL, REAL, REAL, REAL );
+ static int ccw( TrimVertex *, TrimVertex *, TrimVertex * );
+ void join_s( Bin &, Bin &, Arc_ptr, Arc_ptr );
+ void join_t( Bin &, Bin &, Arc_ptr , Arc_ptr );
+ int arc_split( Arc_ptr , int, REAL, int );
+ void check_s( Arc_ptr , Arc_ptr );
+ void check_t( Arc_ptr , Arc_ptr );
+ inline void link( Arc_ptr , Arc_ptr , Arc_ptr , Arc_ptr );
+ inline void simple_link( Arc_ptr , Arc_ptr );
+
+ Bin* makePatchBoundary( const REAL *from, const REAL *to );
+
+ /*in domain distance method, the tessellation is controled by two numbers:
+ *GLU_U_STEP: number of u-segments per unit u length of domain
+ *GLU_V_STEP: number of v-segments per unit v length of domain
+ *These two numbers are normally stored in mapdesc->maxs(t)rate.
+ *I (ZL) put these two numbers here so that I can optimize the untrimmed
+ *case in the case of domain distance sampling.
+ *These two numbers are set by set_domain_distance_u_rate() and ..._v_..().
+ */
+ REAL domain_distance_u_rate;
+ REAL domain_distance_v_rate;
+ int is_domain_distance_sampling;
+};
+
+inline void
+Subdivider::beginLoop( void )
+{
+ pjarc = 0;
+}
+
+
+#endif /* __glusubdivider_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/tobezier.cc b/src/glu/sgi/libnurbs/internals/tobezier.cc
new file mode 100644
index 00000000000..6b4229da553
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/tobezier.cc
@@ -0,0 +1,689 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * tobezier.c++
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/tobezier.cc,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "mystring.h"
+#include "quilt.h"
+#include "knotvector.h"
+
+/* local type definitions */
+struct Breakpt { /* breakpoints */
+ Knot value; /* value */
+ int multi; /* multiplicity */
+ int def; /* deficit */
+};
+
+struct Knotspec { /* knotvector format */
+ long order; /* order of spline */
+ Knot_ptr inkbegin; /* input knot sequence */
+ Knot_ptr inkend; /* location after last knot */
+ Knot_ptr outkbegin; /* in-process knot subsequence */
+ Knot_ptr outkend; /* location after last knot */
+ Knot_ptr kleft; /* */
+ Knot_ptr kright; /* */
+ Knot_ptr kfirst; /* */
+ Knot_ptr klast; /* */
+ Knot_ptr sbegin; /* conversion factor values */
+ Breakpt * bbegin; /* in-process breakpoints */
+ Breakpt * bend; /* last breakpoint */
+ int ncoords; /* coordinates per control point */
+ int prestride; /* stride between input points */
+ int poststride; /* stride between output points */
+ int preoffset; /* scaled point offset */
+ int postoffset; /* scaled point offset */
+ int prewidth; /* width of dimension */
+ int postwidth; /* width of dimension */
+ int istransformed; /* was dimension transformed */
+ Knotspec * next; /* next knotspec */
+ Knotspec * kspectotrans; /* knotspec in transformation direction */
+
+ Knotspec( void );
+ ~Knotspec( void );
+ void factors( void );
+ void insert( REAL * );
+ void preselect();
+ void select( void );
+ void copy( INREAL *, REAL * );
+ void breakpoints( void );
+ void knots( void );
+ void transform( REAL * );
+ void showpts( REAL * );
+
+ void pt_io_copy( REAL *, INREAL * );
+ void pt_oo_copy( REAL *, REAL * );
+ void pt_oo_sum( REAL*, REAL*, REAL*, Knot, Knot );
+};
+
+struct Splinespec { /* a non-uniform tensor element */
+ Splinespec( int );
+ ~Splinespec(void);
+ Knotspec *kspec; /* format of each param. dir. */
+ int dim; /* domain dimension */
+ REAL * outcpts; /* Bezier control points */
+
+ void kspecinit( Knotvector & );
+ void kspecinit( Knotvector &, Knotvector & );
+ void select( void );
+ void layout( long );
+ void setupquilt( Quilt_ptr );
+ void copy( INREAL * );
+ void transform( void );
+};
+
+/*-----------------------------------------------------------------------------
+ * Quilt::toBezier - convert from NURBS to rational Bezier
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Quilt::toBezier(
+ Knotvector& knotvector, /* a knot vector */
+ INREAL *ctlpts, /* input contol points */
+ long ncoords ) /* number of coordinates per control point */
+{
+ Splinespec spline( 1 );
+ spline.kspecinit( knotvector );
+ spline.select();
+ spline.layout( ncoords );
+ spline.setupquilt( this );
+ spline.copy( ctlpts );
+ spline.transform();
+}
+
+void
+Quilt::toBezier(
+ Knotvector& sknotvector, /* a knot vector */
+ Knotvector& tknotvector, /* a knot vector */
+ INREAL *ctlpts, /* input contol points */
+ long ncoords ) /* number of coordinates per control point */
+{
+ Splinespec spline( 2 );
+ spline.kspecinit( sknotvector, tknotvector );
+ spline.select();
+ spline.layout( ncoords );
+ spline.setupquilt( this );
+ spline.copy( ctlpts );
+ spline.transform();
+}
+Splinespec::Splinespec( int dimen )
+{
+ dim = dimen;
+}
+
+Splinespec::~Splinespec( void )
+{
+ /* Note: do NOT delete 'outcpts' here since its address (not contents)
+ * is copied in 'cpts' in this file in function Splinespec::setupquilt().
+ * This block of memory will eventually be deleted in file quilt.c++ in
+ * function Quilt::deleteMe() through 'cpts' so do NOT delete it here!
+ */
+ Knotspec *ktrav= kspec; //start at beginning of list
+ while (ktrav != 0) { //any items to delete?
+ Knotspec *deleteThis= ktrav; //remember to delete this
+ ktrav= ktrav->next; //go to next item if any
+ delete deleteThis; //delete it
+ }
+} /* ~Splinespec() */
+
+/*-----------------------------------------------------------------------------
+ * Splinespec::kspecinit - initialize Splinespec structure
+ *
+ * Client: Quilt::toBezier
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Splinespec::kspecinit( Knotvector& knotvector )
+{
+ kspec = new Knotspec;
+ kspec->inkbegin = knotvector.knotlist;
+ kspec->inkend = knotvector.knotlist + knotvector.knotcount;
+ kspec->prestride = (int) knotvector.stride;
+ kspec->order = knotvector.order;
+ kspec->next = NULL;
+}
+
+void
+Splinespec::kspecinit( Knotvector& sknotvector, Knotvector& tknotvector )
+{
+ kspec = new Knotspec;
+ Knotspec *tkspec = new Knotspec;
+
+ kspec->inkbegin = sknotvector.knotlist;
+ kspec->inkend = sknotvector.knotlist + sknotvector.knotcount;
+ kspec->prestride = (int) sknotvector.stride;
+ kspec->order = sknotvector.order;
+ kspec->next = tkspec;
+
+ tkspec->inkbegin = tknotvector.knotlist;
+ tkspec->inkend = tknotvector.knotlist + tknotvector.knotcount;
+ tkspec->prestride = (int) tknotvector.stride;
+ tkspec->order = tknotvector.order;
+ tkspec->next = NULL;
+}
+
+
+/*-----------------------------------------------------------------------------
+ * Splinespec::select - select the subsegments to copy
+ *
+ * Client: gl_quilt_to_bezier
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Splinespec::select( )
+{
+ for( Knotspec *knotspec = kspec; knotspec; knotspec = knotspec->next ) {
+ knotspec->preselect();
+ knotspec->select();
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * Splinespec::layout -
+ *
+ * Client: gl_quilt_to_bezier
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Splinespec::layout( long ncoords )
+{
+
+ long stride = ncoords;
+ for( Knotspec *knotspec = kspec; knotspec; knotspec=knotspec->next ) {
+ knotspec->poststride = (int) stride;
+ stride *= ((knotspec->bend-knotspec->bbegin)*knotspec->order + knotspec->postoffset);
+ knotspec->preoffset *= knotspec->prestride;
+ knotspec->prewidth *= knotspec->poststride;
+ knotspec->postwidth *= knotspec->poststride;
+ knotspec->postoffset *= knotspec->poststride;
+ knotspec->ncoords = (int) ncoords;
+ }
+ outcpts = new REAL[stride];
+ assert( outcpts != 0 );
+}
+
+/*-----------------------------------------------------------------------------
+ * Splinespec::copy - copy the control points of current subobject
+ *
+ * Client: gl_quilt_to_bezier
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Splinespec::copy( INREAL *incpts )
+{
+ kspec->copy( incpts, outcpts );
+}
+
+/*-----------------------------------------------------------------------------
+ * Splinespec::setupquilt - assign all quilt variables from knotspec
+ *
+ * Client: gl_quilt_to_bezier
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Splinespec::setupquilt( Quilt_ptr quilt )
+{
+ Quiltspec_ptr qspec = quilt->qspec;
+ quilt->eqspec = qspec + dim;
+ for( Knotspec *knotspec = kspec; knotspec; knotspec=knotspec->next, qspec++ ) {
+ qspec->stride = knotspec->poststride;
+ qspec->width = knotspec->bend - knotspec->bbegin;
+ qspec->order = (int) knotspec->order;
+ qspec->offset = knotspec->postoffset;
+ qspec->index = 0;
+ qspec->bdry[0] = (knotspec->kleft == knotspec->kfirst) ? 1 : 0;
+ qspec->bdry[1] = (knotspec->kright == knotspec->klast) ? 1 : 0;
+ qspec->breakpoints = new Knot[qspec->width+1];
+ Knot_ptr k = qspec->breakpoints;
+ for( Breakpt *bk = knotspec->bbegin; bk <= knotspec->bend; bk++ )
+ *(k++) = bk->value;
+ }
+ quilt->cpts = outcpts;
+ quilt->next = 0;
+}
+
+/*-----------------------------------------------------------------------------
+ * Splinespec::transform - convert a spline to Bezier format
+ *
+ * Client: gl_quilt_to_bezier
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Splinespec::transform( void )
+{
+ Knotspec *knotspec;
+ for( knotspec = kspec; knotspec; knotspec=knotspec->next )
+ knotspec->istransformed = 0;
+
+ for( knotspec = kspec; knotspec; knotspec=knotspec->next ) {
+ for( Knotspec *kspec2 = kspec; kspec2; kspec2=kspec2->next )
+ kspec2->kspectotrans = knotspec;
+ kspec->transform( outcpts );
+ knotspec->istransformed = 1;
+ }
+}
+
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::Knotspec - constuct a knot spec
+ *-----------------------------------------------------------------------------
+ */
+
+Knotspec::Knotspec( void )
+{
+ bbegin = 0;
+ sbegin = 0;
+ outkbegin = 0;
+}
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::copy - copy the control points along minor direction
+ *
+ * Client: Splinespec::copy
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::copy( INREAL *inpt, REAL *outpt )
+{
+ inpt = (INREAL *) (((char *) inpt) + preoffset);
+
+ if( next ) {
+ for( REAL *lpt=outpt+prewidth; outpt != lpt; outpt += poststride ) {
+ next->copy( inpt, outpt );
+ inpt = (INREAL *) (((char *) inpt) + prestride);
+ }
+ } else {
+ for( REAL *lpt=outpt+prewidth; outpt != lpt; outpt += poststride ) {
+ pt_io_copy( outpt, inpt );
+ inpt = (INREAL *) (((char *) inpt) + prestride);
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::showpts - print out points before transformation
+ *
+ * Client: Knotspec::select
+ *-----------------------------------------------------------------------------
+ */
+void
+Knotspec::showpts( REAL *outpt )
+{
+ if( next ) {
+ for( REAL *lpt=outpt+prewidth; outpt != lpt; outpt += poststride )
+ next->showpts( outpt );
+ } else {
+ for( REAL *lpt=outpt+prewidth; outpt != lpt; outpt += poststride )
+ dprintf( "show %g %g %g\n", outpt[0], outpt[1], outpt[2] );
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::factors - precompute scale factors
+ * - overwrites knot vector, actual new knot vector is NOT produced
+ *
+ * Client: Knotspec::select
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::factors( void )
+{
+ Knot *mid = (outkend - 1) - order + bend->multi;
+ Knot_ptr fptr = sbegin;
+
+ for( Breakpt *bpt = bend; bpt >= bbegin; bpt-- ) {
+ mid -= bpt->multi; // last knot less than knot to insert
+ int def = bpt->def - 1; // number of knots to insert
+ if( def <= 0 ) continue;
+ Knot kv = bpt->value; // knot to insert
+
+ Knot *kf = (mid-def) + (order-1);
+ for( Knot *kl = kf + def; kl != kf; kl-- ) {
+ Knot *kh, *kt;
+ for( kt=kl, kh=mid; kt != kf; kh--, kt-- )
+ *(fptr++) = (kv - *kh) / (*kt - *kh);
+ *kl = kv;
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::insert - convert subobject in direction of kspec into Bezier
+ *
+ * Client: Knotspec::transform
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::insert( REAL *p )
+{
+ Knot_ptr fptr = sbegin;
+ REAL *srcpt = p + prewidth - poststride;
+ REAL *dstpt = p + postwidth + postoffset - poststride;
+ Breakpt *bpt = bend;
+
+ for( REAL *pend = srcpt - poststride*bpt->def; srcpt != pend; pend +=poststride ) {
+ REAL *p1 = srcpt;
+ for( REAL *p2 = srcpt-poststride; p2 != pend; p1 = p2, p2 -= poststride ) {
+ pt_oo_sum( p1, p1, p2, *fptr, 1.0-*fptr );
+ fptr++;
+ }
+ }
+
+ for( --bpt; bpt >= bbegin; bpt-- ) {
+
+ for( int multi = bpt->multi; multi > 0; multi-- ) {
+ pt_oo_copy( dstpt, srcpt );
+ dstpt -= poststride;
+ srcpt -= poststride;
+ }
+
+ for( REAL *pend = srcpt - poststride*bpt->def; srcpt != pend; pend +=poststride, dstpt-=poststride ) {
+ pt_oo_copy( dstpt, srcpt );
+ REAL *p1 = srcpt;
+
+ for( REAL *p2 = srcpt-poststride; p2 != pend; p1=p2, p2 -= poststride ) {
+ pt_oo_sum( p1, p1, p2, *fptr, 1.0-*fptr );
+ fptr++;
+ }
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::preselect - initialize kspec for processing
+ *
+ * Client: Splinespec::select
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::preselect( void )
+{
+ Knot kval;
+
+ /* position klast after last knot of "last" breakpoint */
+ for( klast = inkend - order, kval = *klast; klast != inkend; klast++ )
+ if( ! identical( *klast, kval ) ) break;
+
+ /* position kfirst after last knot of "first" breakpoint */
+ for( kfirst = inkbegin+order-1, kval= *kfirst; kfirst != inkend; kfirst++ )
+ if( ! identical( *kfirst, kval ) ) break;
+
+ /* compute multiplicity of first breakpoint */
+ Knot_ptr k;
+ for( k = kfirst - 1; k >= inkbegin; k-- )
+ if( ! identical( kval, *k ) ) break;
+ k++;
+
+ /* allocate space for breakpoints -
+ use worst case estimate on number of breakpoints */
+
+ bbegin = new Breakpt[(klast - kfirst)+1];
+ /* record multiplicity and value of first breakpoint */
+ bbegin->multi = kfirst - k;
+ bbegin->value = kval;
+ bend = bbegin;
+
+ kleft = kright = kfirst;
+}
+
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::select - Knotspec::select segments and precompute scale factors
+ *
+ * Client: Splinespec::select
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::select( void )
+{
+ breakpoints();
+ knots();
+ factors();
+
+ preoffset = kleft - (inkbegin + order);
+ postwidth = (int)((bend - bbegin) * order);
+ prewidth = (int)((outkend - outkbegin) - order);
+ postoffset = (bbegin->def > 1) ? (bbegin->def-1) : 0;
+}
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::breakpoints - compute breakpoints for knotspec
+ *
+ * Client: Knotspec::select
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::breakpoints( void )
+{
+ Breakpt *ubpt = bbegin;
+ Breakpt *ubend = bend;
+ long nfactors = 0;
+
+ ubpt->value = ubend->value;
+ ubpt->multi = ubend->multi;
+
+ kleft = kright;
+
+ for( ; kright != klast; kright++ ) {
+ if ( identical(*kright,ubpt->value) ) {
+ (ubpt->multi)++;
+ } else {
+ ubpt->def = (int) (order - ubpt->multi);
+ nfactors += (ubpt->def * (ubpt->def - 1)) / 2;
+ (++ubpt)->value = *kright;
+ ubpt->multi = 1;
+ }
+ }
+ ubpt->def = (int) (order - ubpt->multi);
+ nfactors += (ubpt->def * (ubpt->def - 1)) / 2;
+
+ bend = ubpt;
+
+ if( nfactors ) {
+ sbegin = new Knot[nfactors];
+ } else {
+ sbegin = NULL;
+ }
+}
+
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::knots - copy relevant subsequence of knots into temporary area
+ *
+ * Client: Knotspec::select
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::knots( void )
+{
+ Knot_ptr inkpt = kleft - order;
+ Knot_ptr inkend = kright + bend->def;
+
+ /* allocate space for knots and factors */
+ outkbegin = new Knot[inkend-inkpt];
+ Knot_ptr outkpt;
+ for( outkpt = outkbegin; inkpt != inkend; inkpt++, outkpt++ )
+ *outkpt = *inkpt;
+
+ outkend = outkpt;
+}
+
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::transform - convert a spline along a given direction
+ *
+ * Client: Splienspec::transform
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::transform( REAL *p )
+{
+ if( next ) {
+ if( this == kspectotrans ) {
+ next->transform( p );
+ } else {
+ if( istransformed ) {
+ p += postoffset;
+ for( REAL *pend = p + postwidth; p != pend; p += poststride )
+ next->transform( p );
+ } else {
+ REAL *pend = p + prewidth;
+ for( ; p != pend; p += poststride )
+ next->transform( p );
+ }
+ }
+ } else {
+ if( this == kspectotrans ) {
+ insert( p );
+ } else {
+ if( istransformed ) {
+ p += postoffset;
+ for( REAL *pend = p + postwidth; p != pend; p += poststride )
+ kspectotrans->insert( p );
+ } else {
+ REAL *pend = p + prewidth;
+ for( ; p != pend; p += poststride )
+ kspectotrans->insert( p );
+ }
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::~Knotspec - free space alocated for knotspec
+ *-----------------------------------------------------------------------------
+ */
+
+Knotspec::~Knotspec( void )
+{
+ if( bbegin ) delete[] bbegin;
+ if( sbegin ) delete[] sbegin;
+ if( outkbegin ) delete[] outkbegin;
+}
+
+
+/*-----------------------------------------------------------------------------
+ * pt_io_copy - make internal copy of input cntrl pt. of x coords
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::pt_io_copy( REAL *topt, INREAL *frompt )
+{
+ switch( ncoords ) {
+ case 4:
+ topt[3] = (REAL) frompt[3];
+ case 3:
+ topt[2] = (REAL) frompt[2];
+ case 2:
+ topt[1] = (REAL) frompt[1];
+ case 1:
+ topt[0] = (REAL) frompt[0];
+ break;
+ default: {
+ for( int i = 0; i < ncoords; i++ )
+ *topt++ = (REAL) *frompt++;
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * pt_oo_copy - make internal copy of internal cntrl pt. of x coords
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::pt_oo_copy( REAL *topt, REAL *frompt )
+{
+ switch( ncoords ) {
+ case 4:
+ topt[3] = frompt[3];
+ case 3:
+ topt[2] = frompt[2];
+ case 2:
+ topt[1] = frompt[1];
+ case 1:
+ topt[0] = frompt[0];
+ break;
+ default:
+ memcpy( topt, frompt, ncoords * sizeof( REAL ) );
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * pt_oo_sum - compute affine combination of internal cntrl pts
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::pt_oo_sum( REAL *x, REAL *y, REAL *z, Knot a, Knot b )
+{
+ switch( ncoords ) {
+ case 4:
+ x[3] = a * y[3] + b * z[3];
+ case 3:
+ x[2] = a * y[2] + b * z[2];
+ case 2:
+ x[1] = a * y[1] + b * z[1];
+ case 1:
+ x[0] = a * y[0] + b * z[0];
+ break;
+ default: {
+ for( int i = 0; i < ncoords; i++ )
+ *x++ = a * *y++ + b * *z++;
+ }
+ }
+}
diff --git a/src/glu/sgi/libnurbs/internals/trimline.cc b/src/glu/sgi/libnurbs/internals/trimline.cc
new file mode 100644
index 00000000000..72ace36999f
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/trimline.cc
@@ -0,0 +1,225 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * trimline.c++
+ *
+ * $Date: 2005/10/28 13:09:08 $ $Revision: 1.1.30.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/trimline.cc,v 1.1.30.1 2005/10/28 13:09:08 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "trimline.h"
+#include "backend.h"
+
+Trimline::Trimline()
+{
+ size = 0; pts = 0; numverts = 0;
+ tinterp = &t; binterp = &b;
+}
+
+Trimline::~Trimline()
+{
+ if( pts ) delete[] pts;
+}
+
+void
+Trimline::init( TrimVertex *v )
+{
+ reset();
+ grow(1);
+ append(v);
+}
+
+inline void
+Trimline::grow( long npts )
+{
+ if( size < npts ) {
+ size = 2 * npts;
+ if( pts ) delete[] pts;
+ pts = new TrimVertex_p[size];
+ }
+}
+
+inline void
+Trimline::append( TrimVertex *v )
+{
+ assert( numverts != size );
+ pts[numverts++] = v;
+}
+
+void
+Trimline::init( long npts, Arc_ptr jarc, long last )
+{
+ jarcl.init( jarc, 0, last );
+ grow( npts + 2 );
+}
+
+inline void
+Trimline::swap()
+{
+ TrimVertex *tmp=tinterp;
+ tinterp=binterp;
+ binterp=tmp;
+}
+
+void
+Trimline::getNextPt()
+{
+ *binterp = *jarcl.getnextpt();
+}
+
+void
+Trimline::getPrevPt()
+{
+ *binterp = *jarcl.getprevpt();
+}
+
+/*----------------------------------------------------------------------
+ * getNextPts - make arrays of pointers to trim points on left and right
+ * hulls of trim strip.
+ *----------------------------------------------------------------------
+ */
+void
+Trimline::getNextPts( REAL vval, Backend& backend )
+{
+ reset(); swap(); append( tinterp );
+ assert( tinterp->param[1] >= vval );
+
+ register TrimVertex *p;
+ for( p=jarcl.getnextpt() ; p->param[1] >= vval; p=jarcl.getnextpt() ) {
+ append( p );
+ }
+
+ /* compute and copy pointer to final point on left hull */
+ if( interpvert( last(), p, binterp, vval ) ) {
+ binterp->nuid = p->nuid;
+ backend.triangle( p, binterp, last() );
+ append( binterp );
+ }
+ jarcl.reverse();
+ (void) jarcl.getprevpt(); /* reset jarcl to proper position */
+ jarcl.reverse();
+}
+
+void
+Trimline::getPrevPts( REAL vval, Backend& backend )
+{
+ reset(); swap(); append( tinterp );
+ assert( tinterp->param[1] >= vval );
+
+ register TrimVertex *q;
+ for( q=jarcl.getprevpt(); q->param[1] >= vval; q=jarcl.getprevpt() ) {
+ append( q );
+ }
+
+ /* compute and copy pointer to final point on right hull */
+ if( interpvert( q, last(), binterp, vval ) ) {
+ binterp->nuid = q->nuid;
+ backend.triangle( last(), binterp, q );
+ append( binterp );
+ }
+ jarcl.reverse();
+ (void) jarcl.getnextpt(); /* reset jarcl to proper position */
+ jarcl.reverse();
+}
+
+void
+Trimline::getNextPts( Arc_ptr botarc )
+{
+ reset(); swap(); append( tinterp );
+
+#ifndef NDEBUG
+ PwlArc *lastpwl = botarc->prev->pwlArc;
+ TrimVertex *lastpt1 = &lastpwl->pts[lastpwl->npts-1];
+#endif
+ TrimVertex *lastpt2 = botarc->pwlArc->pts;
+ register TrimVertex *p = jarcl.getnextpt();
+ for( append( p ); p != lastpt2; append( p ) ) {
+ assert( p != lastpt1 );
+ p = jarcl.getnextpt();
+ }
+}
+
+void
+Trimline::getPrevPts( Arc_ptr botarc )
+{
+ reset(); swap(); append( tinterp );
+
+ PwlArc *lastpwl = botarc->prev->pwlArc;
+ TrimVertex *lastpt1 = &lastpwl->pts[lastpwl->npts-1];
+#ifndef NDEBUG
+ TrimVertex *lastpt2 = botarc->pwlArc->pts;
+#endif
+
+ register TrimVertex *q = jarcl.getprevpt();
+ for( append( q ); q != lastpt1; append( q ) ) {
+ assert( q != lastpt2 );
+ q = jarcl.getprevpt();
+ }
+}
+
+
+long
+Trimline::interpvert( TrimVertex *a, TrimVertex *b, TrimVertex *c, REAL vval )
+{
+ REAL denom = a->param[1] - b->param[1];
+
+ if(denom != 0) {
+ if( vval == a->param[1] ) {
+ c->param[0] = a->param[0];
+ c->param[1] = a->param[1];
+ c->nuid = a->nuid;
+ return 0;
+ } else if( vval == b->param[1] ) {
+ c->param[0] = b->param[0];
+ c->param[1] = b->param[1];
+ c->nuid = b->nuid;
+ return 0;
+ } else {
+ REAL r = (a->param[1] - vval)/denom;
+ c->param[0] = a->param[0] - r * (a->param[0] - b->param[0]);
+ c->param[1] = vval;
+ return 1;
+ }
+ } else {
+ c->param[0] = a->param[0];
+ c->param[1] = a->param[1];
+ c->nuid = a->nuid;
+ return 0;
+ }
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/trimline.h b/src/glu/sgi/libnurbs/internals/trimline.h
new file mode 100644
index 00000000000..13bb3e2adf9
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/trimline.h
@@ -0,0 +1,109 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * trimline.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/trimline.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __glutrimline_h_
+#define __glutrimline_h_
+
+class Arc;
+class Backend;
+
+#include "trimvertex.h"
+#include "jarcloc.h"
+
+
+class Trimline {
+private:
+ TrimVertex** pts;
+ long numverts;
+ long i;
+ long size;
+ Jarcloc jarcl;
+ TrimVertex t, b;
+ TrimVertex *tinterp, *binterp;
+ void reset( void ) { numverts = 0; }
+ inline void grow( long );
+ inline void swap( void );
+ inline void append( TrimVertex * );
+ static long interpvert( TrimVertex *, TrimVertex *, TrimVertex *, REAL );
+
+
+
+public:
+ Trimline();
+ ~Trimline();
+ void init( TrimVertex * );
+ void init( long, Arc_ptr, long );
+ void getNextPt( void );
+ void getPrevPt( void );
+ void getNextPts( REAL, Backend & );
+ void getPrevPts( REAL, Backend & );
+ void getNextPts( Arc_ptr );
+ void getPrevPts( Arc_ptr );
+ inline TrimVertex * next( void );
+ inline TrimVertex * prev( void );
+ inline TrimVertex * first( void );
+ inline TrimVertex * last( void );
+};
+
+inline TrimVertex *
+Trimline::next( void )
+{
+ if( i < numverts) return pts[i++]; else return 0;
+}
+
+inline TrimVertex *
+Trimline::prev( void )
+{
+ if( i >= 0 ) return pts[i--]; else return 0;
+}
+
+inline TrimVertex *
+Trimline::first( void )
+{
+ i = 0; return pts[i];
+}
+
+inline TrimVertex *
+Trimline::last( void )
+{
+ i = numverts; return pts[--i];
+}
+#endif /* __glutrimline_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/trimregion.cc b/src/glu/sgi/libnurbs/internals/trimregion.cc
new file mode 100644
index 00000000000..469f03678ff
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/trimregion.cc
@@ -0,0 +1,116 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * trimregion.c++
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/trimregion.cc,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "trimregion.h"
+#include "backend.h"
+
+TrimRegion::TrimRegion( void )
+{
+}
+
+void
+TrimRegion::setDu( REAL du )
+{
+ oneOverDu = 1.0/du;
+}
+
+void
+TrimRegion::init( long npts, Arc_ptr extrema )
+{
+ left.init( npts, extrema, extrema->pwlArc->npts - 1 );
+ left.getNextPt();
+
+ right.init( npts, extrema, 0 );
+ right.getPrevPt();
+}
+
+void
+TrimRegion::getPts( Arc_ptr extrema )
+{
+ left.getNextPts( extrema );
+ right.getPrevPts( extrema );
+}
+
+void
+TrimRegion::getPts( Backend &backend )
+{
+ left.getNextPts( bot.vval, backend );
+ right.getPrevPts( bot.vval, backend );
+}
+
+void
+TrimRegion::getGridExtent( void )
+{
+ getGridExtent( left.last(), right.last() );
+}
+
+void
+TrimRegion::getGridExtent( TrimVertex *l, TrimVertex *r )
+{
+ bot.ustart = (long) ((l->param[0] - uarray.uarray[0])*oneOverDu);
+ if( l->param[0] >= uarray.uarray[bot.ustart] ) bot.ustart++;
+// if( l->param[0] > uarray.uarray[bot.ustart] ) bot.ustart++;
+ assert( l->param[0] <= uarray.uarray[bot.ustart] );
+ assert( l->param[0] >= uarray.uarray[bot.ustart-1] );
+
+ bot.uend = (long) ((r->param[0] - uarray.uarray[0])*oneOverDu);
+ if( uarray.uarray[bot.uend] >= r->param[0] ) bot.uend--;
+// if( uarray.uarray[bot.uend] > r->param[0] ) bot.uend--;
+ assert( r->param[0] >= uarray.uarray[bot.uend] );
+ assert( r->param[0] <= uarray.uarray[bot.uend+1] );
+}
+
+int
+TrimRegion::canTile( void )
+{
+ TrimVertex *lf = left.first();
+ TrimVertex *ll = left.last();
+ TrimVertex *l = ( ll->param[0] > lf->param[0] ) ? ll : lf;
+
+ TrimVertex *rf = right.first();
+ TrimVertex *rl = right.last();
+ TrimVertex *r = ( rl->param[0] < rf->param[0] ) ? rl : rf;
+ return (l->param[0] <= r->param[0]) ? 1 : 0;
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/trimregion.h b/src/glu/sgi/libnurbs/internals/trimregion.h
new file mode 100644
index 00000000000..58dfe24914f
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/trimregion.h
@@ -0,0 +1,90 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * trimregion.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/trimregion.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __glutrimregion_h_
+#define __glutrimregion_h_
+
+#include "trimline.h"
+#include "gridline.h"
+#include "uarray.h"
+
+class Arc;
+class Backend;
+
+class TrimRegion {
+public:
+ TrimRegion();
+ Trimline left;
+ Trimline right;
+ Gridline top;
+ Gridline bot;
+ Uarray uarray;
+
+ void init( REAL );
+ void advance( REAL, REAL, REAL );
+ void setDu( REAL );
+ void init( long, Arc_ptr );
+ void getPts( Arc_ptr );
+ void getPts( Backend & );
+ void getGridExtent( TrimVertex *, TrimVertex * );
+ void getGridExtent( void );
+ int canTile( void );
+private:
+ REAL oneOverDu;
+};
+
+inline void
+TrimRegion::init( REAL vval )
+{
+ bot.vval = vval;
+}
+
+inline void
+TrimRegion::advance( REAL topVindex, REAL botVindex, REAL botVval )
+{
+ top.vindex = (long) topVindex;
+ bot.vindex = (long) botVindex;
+ top.vval = bot.vval;
+ bot.vval = botVval;
+ top.ustart = bot.ustart;
+ top.uend = bot.uend;
+}
+#endif /* __glutrimregion_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/trimvertex.h b/src/glu/sgi/libnurbs/internals/trimvertex.h
new file mode 100644
index 00000000000..5e3ea780151
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/trimvertex.h
@@ -0,0 +1,69 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * trimvertex.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/trimvertex.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __glutrimvertex_h_
+#define __glutrimvertex_h_
+
+#include "types.h"
+
+/*#define USE_OPTTT*/
+
+class TrimVertex { /* a vertex on a trim curve */
+public:
+ REAL param[2]; /* parametric space coords */
+#ifdef USE_OPTTT
+ REAL cache_point[4]; //only when USE_OPTTT is on in slicer.c++
+ REAL cache_normal[3];
+#endif
+ long nuid;
+};
+
+typedef class TrimVertex *TrimVertex_p;
+
+inline REAL
+det3( TrimVertex *a, TrimVertex *b, TrimVertex *c )
+{
+ return a->param[0] * (b->param[1]-c->param[1]) +
+ b->param[0] * (c->param[1]-a->param[1]) +
+ c->param[0] * (a->param[1]-b->param[1]);
+}
+
+#endif /* __glutrimvertex_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/trimvertpool.cc b/src/glu/sgi/libnurbs/internals/trimvertpool.cc
new file mode 100644
index 00000000000..f18c8c8b3eb
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/trimvertpool.cc
@@ -0,0 +1,121 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * trimvertexpool.c++
+ *
+ * $Date: 2003/05/08 15:47:00 $ $Revision: 1.2 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/trimvertpool.cc,v 1.2 2003/05/08 15:47:00 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "mystring.h"
+#include "trimvertex.h"
+#include "trimvertpool.h"
+#include "bufpool.h"
+
+/*----------------------------------------------------------------------------
+ * TrimVertexPool::TrimVertexPool
+ *----------------------------------------------------------------------------
+ */
+TrimVertexPool::TrimVertexPool( void )
+ : pool( sizeof(TrimVertex)*3, 32, "Threevertspool" )
+{
+ // initialize array of pointers to vertex lists
+ nextvlistslot = 0;
+ vlistsize = INIT_VERTLISTSIZE;
+ vlist = new TrimVertex_p[vlistsize];
+}
+
+/*----------------------------------------------------------------------------
+ * TrimVertexPool::~TrimVertexPool
+ *----------------------------------------------------------------------------
+ */
+TrimVertexPool::~TrimVertexPool( void )
+{
+ // free all arrays of TrimVertices vertices
+ while( nextvlistslot ) {
+ delete [] vlist[--nextvlistslot];
+ }
+
+ // reallocate space for array of pointers to vertex lists
+ if( vlist ) delete[] vlist;
+}
+
+/*----------------------------------------------------------------------------
+ * TrimVertexPool::clear
+ *----------------------------------------------------------------------------
+ */
+void
+TrimVertexPool::clear( void )
+{
+ // reinitialize pool of 3 vertex arrays
+ pool.clear();
+
+ // free all arrays of TrimVertices vertices
+ while( nextvlistslot ) {
+ delete [] vlist[--nextvlistslot];
+ vlist[nextvlistslot] = 0;
+ }
+
+ // reallocate space for array of pointers to vertex lists
+ if( vlist ) delete[] vlist;
+ vlist = new TrimVertex_p[vlistsize];
+}
+
+
+/*----------------------------------------------------------------------------
+ * TrimVertexPool::get - allocate a vertex list
+ *----------------------------------------------------------------------------
+ */
+TrimVertex *
+TrimVertexPool::get( int n )
+{
+ TrimVertex *v;
+ if( n == 3 ) {
+ v = (TrimVertex *) pool.new_buffer();
+ } else {
+ if( nextvlistslot == vlistsize ) {
+ vlistsize *= 2;
+ TrimVertex_p *nvlist = new TrimVertex_p[vlistsize];
+ memcpy( nvlist, vlist, nextvlistslot * sizeof(TrimVertex_p) );
+ if( vlist ) delete[] vlist;
+ vlist = nvlist;
+ }
+ v = vlist[nextvlistslot++] = new TrimVertex[n];
+ }
+ return v;
+}
diff --git a/src/glu/sgi/libnurbs/internals/trimvertpool.h b/src/glu/sgi/libnurbs/internals/trimvertpool.h
new file mode 100644
index 00000000000..afeedfe0bde
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/trimvertpool.h
@@ -0,0 +1,63 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * trimvertexpool.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/trimvertpool.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __glutrimvertpool_h_
+#define __glutrimvertpool_h_
+
+#include "bufpool.h"
+
+class TrimVertex;
+
+#define INIT_VERTLISTSIZE 200
+
+class TrimVertexPool {
+public:
+ TrimVertexPool( void );
+ ~TrimVertexPool( void );
+ void clear( void );
+ TrimVertex * get( int );
+private:
+ Pool pool;
+ TrimVertex ** vlist;
+ int nextvlistslot;
+ int vlistsize;
+};
+#endif /* __glutrimvertpool_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/types.h b/src/glu/sgi/libnurbs/internals/types.h
new file mode 100644
index 00000000000..7b7910d3ada
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/types.h
@@ -0,0 +1,53 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * types.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/types.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __glutypes_h_
+#define __glutypes_h_
+
+//typedef double INREAL;
+#define INREAL float
+typedef float REAL;
+typedef void (*Pfvv)( void );
+typedef void (*Pfvf)( float * );
+typedef int (*cmpfunc)(const void *, const void *);
+typedef REAL Knot, *Knot_ptr;/* knot values */
+
+#endif /* __glutypes_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/uarray.cc b/src/glu/sgi/libnurbs/internals/uarray.cc
new file mode 100644
index 00000000000..5d00f5d09b7
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/uarray.cc
@@ -0,0 +1,74 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * uarray.c++
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/uarray.cc,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "uarray.h"
+#include "arc.h"
+
+Uarray::Uarray( void )
+{
+ uarray = 0;
+ size = 0;
+}
+
+Uarray::~Uarray( void )
+{
+ if( uarray ) delete[] uarray;
+}
+
+long
+Uarray::init( REAL delta, Arc_ptr lo, Arc_ptr hi )
+{
+ ulines = (long) ((hi->tail()[0] - lo->tail()[0])/delta) + 3;
+ if( size < ulines ) {
+ size = ulines * 2;
+ if( uarray ) delete[] uarray;
+ uarray = new REAL[size];
+ assert( uarray != 0);
+ }
+ uarray[0] = lo->tail()[0] - delta/2.0;
+ for( long i = 1 ; i != ulines; i++ )
+ uarray[i] = uarray[0] + i*delta;
+ return ulines;
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/uarray.h b/src/glu/sgi/libnurbs/internals/uarray.h
new file mode 100644
index 00000000000..ae1b1c80916
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/uarray.h
@@ -0,0 +1,61 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * uarray.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/uarray.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __gluuarray_h_
+#define __gluuarray_h_
+
+#include "types.h"
+
+class Arc;
+typedef class Arc *Arc_ptr;
+
+class Uarray {
+private:
+ long size;
+ long ulines;
+public:
+ Uarray();
+ ~Uarray();
+ long init( REAL, Arc_ptr, Arc_ptr );
+ REAL * uarray;
+};
+
+#endif /* __gluuarray_h_ */
diff --git a/src/glu/sgi/libnurbs/internals/varray.cc b/src/glu/sgi/libnurbs/internals/varray.cc
new file mode 100644
index 00000000000..9b60f59b72a
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/varray.cc
@@ -0,0 +1,146 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * varray.c++
+ *
+ * $Date: 2002/11/01 23:35:07 $ $Revision: 1.2 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/varray.cc,v 1.2 2002/11/01 23:35:07 brianp Exp $
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "varray.h"
+#include "arc.h"
+#include "simplemath.h" // glu_abs()
+
+#define TINY 0.0001
+inline long sgn( REAL x )
+{
+ return (x < -TINY) ? -1 : ((x > TINY) ? 1 : 0 );
+}
+
+
+Varray::Varray( void )
+{
+ varray = 0;
+ size = 0;
+}
+
+Varray::~Varray( void )
+{
+ if( varray ) delete[] varray;
+}
+
+inline void
+Varray::update( Arc_ptr arc, long dir[2], REAL val )
+{
+ register long ds = sgn(arc->tail()[0] - arc->prev->tail()[0]);
+ register long dt = sgn(arc->tail()[1] - arc->prev->tail()[1]);
+
+ if( dir[0] != ds || dir[1] != dt ) {
+ dir[0] = ds;
+ dir[1] = dt;
+ append( val );
+ }
+}
+
+void
+Varray::grow( long guess )
+{
+ if( size < guess ) {
+ size = guess * 2;
+ if( varray ) delete[] varray;
+ varray = new REAL[size];
+ assert( varray != 0 );
+ }
+}
+
+long
+Varray::init( REAL delta, Arc_ptr toparc, Arc_ptr botarc )
+{
+ Arc_ptr left = toparc->next;
+ Arc_ptr right = toparc;
+ long ldir[2], rdir[2];
+
+ ldir[0] = sgn( left->tail()[0] - left->prev->tail()[0] );
+ ldir[1] = sgn( left->tail()[1] - left->prev->tail()[1] );
+ rdir[0] = sgn( right->tail()[0] - right->prev->tail()[0] );
+ rdir[1] = sgn( right->tail()[1] - right->prev->tail()[1] );
+
+ vval[0] = toparc->tail()[1];
+ numquads = 0;
+
+ while( 1 ) {
+ switch( sgn( left->tail()[1] - right->prev->tail()[1] ) ) {
+ case 1:
+ left = left->next;
+ update( left, ldir, left->prev->tail()[1] );
+ break;
+ case -1:
+ right = right->prev;
+ update( right, rdir, right->tail()[1] );
+ break;
+ case 0:
+ if( glu_abs(left->tail()[1] - botarc->tail()[1]) < TINY) goto end;
+ if( glu_abs(left->tail()[0]-right->prev->tail()[0]) < TINY &&
+ glu_abs(left->tail()[1]-right->prev->tail()[1]) < TINY) goto end;
+ left = left->next;
+ break;
+ }
+ }
+
+end:
+ append( botarc->tail()[1] );
+
+ grow( ((long) ((vval[0] - vval[numquads])/delta)) + numquads + 2 );
+
+ long i, index = 0;
+ for( i=0; i<numquads; i++ ) {
+ voffset[i] = index;
+ varray[index++] = vval[i];
+ REAL dist = vval[i] - vval[i+1];
+ if( dist > delta ) {
+ long steps = ((long) (dist/delta)) +1;
+ float deltav = - dist / (REAL) steps;
+ for( long j=1; j<steps; j++ )
+ varray[index++] = vval[i] + j * deltav;
+ }
+ }
+ voffset[i] = index;
+ varray[index] = vval[i];
+ return index;
+}
+
diff --git a/src/glu/sgi/libnurbs/internals/varray.h b/src/glu/sgi/libnurbs/internals/varray.h
new file mode 100644
index 00000000000..3e4cfdf7aa3
--- /dev/null
+++ b/src/glu/sgi/libnurbs/internals/varray.h
@@ -0,0 +1,74 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * varray.h
+ *
+ * $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/internals/varray.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef __gluvarray_h_
+#define __gluvarray_h_
+
+#include "types.h"
+
+class Arc;
+
+class Varray {
+public:
+ Varray();
+ ~Varray();
+ long init( REAL, Arc *, Arc * );
+ REAL * varray;
+ REAL vval[1000];
+ long voffset[1000];
+ long numquads;
+
+private:
+ long size;
+ inline void update( Arc *, long[2], REAL );
+ void grow( long );
+ inline void append( REAL );
+};
+
+inline void
+Varray::append( REAL v )
+{
+ if( v != vval[numquads] )
+ vval[++numquads] = v;
+}
+
+
+#endif /* __gluvarray_h_ */
diff --git a/src/glu/sgi/libnurbs/nurbtess/definitions.h b/src/glu/sgi/libnurbs/nurbtess/definitions.h
new file mode 100644
index 00000000000..0355c954dc1
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/definitions.h
@@ -0,0 +1,47 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/definitions.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#ifndef _DEFINITIONS_H
+#define _DEFINITIONS_H
+
+typedef float Real;
+typedef int Int;
+typedef Real Real2[2];
+
+#endif
diff --git a/src/glu/sgi/libnurbs/nurbtess/directedLine.cc b/src/glu/sgi/libnurbs/nurbtess/directedLine.cc
new file mode 100644
index 00000000000..74450352d8c
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/directedLine.cc
@@ -0,0 +1,848 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include "glimports.h"
+#include "zlassert.h"
+
+#include "quicksort.h"
+#include "directedLine.h"
+#include "polyDBG.h"
+
+#ifdef __WATCOMC__
+#pragma warning 726 10
+#endif
+
+//we must return the newLine
+directedLine* directedLine::deleteChain(directedLine* begin, directedLine* end)
+{
+ if(begin->head()[0] == end->tail()[0] &&
+ begin->head()[1] == end->tail()[1]
+ )
+ {
+ directedLine *ret = begin->prev;
+ begin->prev->next = end->next;
+ end->next->prev = begin->prev;
+ delete begin->sline;
+ delete end->sline;
+ delete begin;
+ delete end;
+
+ return ret;
+ }
+
+ directedLine* newLine;
+ sampledLine* sline = new sampledLine(begin->head(), end->tail());
+ newLine = new directedLine(INCREASING, sline);
+ directedLine *p = begin->prev;
+ directedLine *n = end->next;
+ p->next = newLine;
+ n->prev = newLine;
+ newLine->prev = p;
+ newLine->next = n;
+
+ delete begin->sline;
+ delete end->sline;
+ delete begin;
+ delete end;
+ return newLine;
+}
+
+
+void directedLine::deleteSingleLine(directedLine* dline)
+{
+ //make sure that dline->prev->tail is the same as
+ //dline->next->head. This is for numerical erros.
+ //for example, if we delete a line which is almost degeneate
+ //within (epsilon), then we want to make that the polygon after deletion
+ //is still a valid polygon
+
+ dline->next->head()[0] = dline->prev->tail()[0];
+ dline->next->head()[1] = dline->prev->tail()[1];
+
+ dline->prev->next = dline->next;
+ dline->next->prev = dline->prev;
+
+ delete dline;
+
+}
+
+static Int myequal(Real a[2], Real b[2])
+{
+ /*
+ if(a[0]==b[0] && a[1] == b[1])
+ return 1;
+ else
+ return 0;
+ */
+
+
+ if(fabs(a[0]-b[0]) < 0.00001 &&
+ fabs(a[1]-b[1]) < 0.00001)
+ return 1;
+ else
+ return 0;
+
+}
+
+directedLine* directedLine::deleteDegenerateLines()
+{
+ //if there is only one edge or two edges, don't do anything
+ if(this->next == this)
+ return this;
+ if(this->next == this->prev)
+ return this;
+
+ //find a nondegenerate line
+ directedLine* temp;
+ directedLine* first = NULL;
+ if(! myequal(head(), tail()))
+ /*
+ if(head()[0] != tail()[0] ||
+ head()[1] != tail()[1])
+ */
+ first = this;
+ else
+ {
+ for(temp = this->next; temp != this; temp = temp->next)
+ {
+ /*
+ if(temp->head()[0] != temp->tail()[0] ||
+ temp->head()[1] != temp->tail()[1])
+ */
+ if(! myequal(temp->head(), temp->tail()))
+ {
+ first = temp;
+ break;
+ }
+
+ }
+ }
+
+ //if there are no non-degenerate lines, then we simply return NULL.
+ if(first == NULL)
+ {
+ deleteSinglePolygonWithSline();
+ return NULL;
+ }
+
+ directedLine* tempNext = NULL;
+ for(temp =first->next; temp != first; temp = tempNext)
+ {
+ tempNext = temp->getNext();
+/*
+ if(temp->head()[0] == temp->tail()[0] &&
+ temp->head()[1] == temp->tail()[1])
+*/
+
+ if(myequal(temp->head(), temp->tail()))
+ deleteSingleLine(temp);
+ }
+ return first;
+}
+
+directedLine* directedLine::deleteDegenerateLinesAllPolygons()
+{
+ directedLine* temp;
+ directedLine *tempNext = NULL;
+ directedLine* ret= NULL;
+ directedLine* retEnd = NULL;
+ for(temp=this; temp != NULL; temp = tempNext)
+ {
+ tempNext = temp->nextPolygon;
+ temp->nextPolygon = NULL;
+ if(ret == NULL)
+ {
+ ret = retEnd = temp->deleteDegenerateLines();
+
+ }
+ else
+ {
+ directedLine *newPolygon = temp->deleteDegenerateLines();
+ if(newPolygon != NULL)
+ {
+ retEnd->nextPolygon = temp->deleteDegenerateLines();
+ retEnd = retEnd->nextPolygon;
+ }
+ }
+ }
+ return ret;
+}
+
+directedLine* directedLine::cutIntersectionAllPoly(int &cutOccur)
+{
+ directedLine* temp;
+ directedLine *tempNext = NULL;
+ directedLine* ret= NULL;
+ directedLine* retEnd = NULL;
+ cutOccur = 0;
+ for(temp=this; temp != NULL; temp = tempNext)
+ {
+ int eachCutOccur=0;
+ tempNext = temp->nextPolygon;
+ temp->nextPolygon = NULL;
+ if(ret == NULL)
+ {
+
+ ret = retEnd = DBG_cutIntersectionPoly(temp, eachCutOccur);
+ if(eachCutOccur)
+ cutOccur = 1;
+ }
+ else
+ {
+
+ retEnd->nextPolygon = DBG_cutIntersectionPoly(temp, eachCutOccur);
+ retEnd = retEnd->nextPolygon;
+ if(eachCutOccur)
+ cutOccur = 1;
+ }
+ }
+ return ret;
+}
+
+
+void directedLine::deleteSinglePolygonWithSline()
+{
+ directedLine *temp, *tempNext;
+ prev->next = NULL;
+ for(temp=this; temp != NULL; temp = tempNext)
+ {
+ tempNext = temp->next;
+ delete temp->sline;
+ delete temp;
+ }
+}
+
+void directedLine::deletePolygonListWithSline()
+{
+ directedLine *temp, *tempNext;
+ for(temp=this; temp != NULL; temp=tempNext)
+ {
+ tempNext = temp->nextPolygon;
+ temp->deleteSinglePolygonWithSline();
+ }
+}
+
+void directedLine::deleteSinglePolygon()
+{
+ directedLine *temp, *tempNext;
+ prev->next = NULL;
+ for(temp=this; temp != NULL; temp = tempNext)
+ {
+ tempNext = temp->next;
+ delete temp;
+ }
+}
+
+void directedLine::deletePolygonList()
+{
+ directedLine *temp, *tempNext;
+ for(temp=this; temp != NULL; temp=tempNext)
+ {
+ tempNext = temp->nextPolygon;
+ temp->deleteSinglePolygon();
+ }
+}
+
+
+/*a loop by itself*/
+directedLine::directedLine(short dir, sampledLine* sl)
+{
+ direction = dir;
+ sline = sl;
+ next = this;
+ prev = this;
+ nextPolygon = NULL;
+// prevPolygon = NULL;
+ rootBit = 0;/*important to initilzae to 0 meaning not root yet*/
+
+ rootLink = NULL;
+
+}
+
+void directedLine::init(short dir, sampledLine* sl)
+{
+ direction = dir;
+ sline = sl;
+}
+
+directedLine::directedLine()
+{
+ next = this;
+ prev = this;
+ nextPolygon = NULL;
+ rootBit = 0;/*important to initilzae to 0 meaning not root yet*/
+ rootLink = NULL;
+}
+
+directedLine::~directedLine()
+{
+}
+
+Real* directedLine::head()
+{
+
+ return (direction==INCREASING)? (sline->get_points())[0] : (sline->get_points())[sline->get_npoints()-1];
+}
+
+/*inline*/ Real* directedLine::getVertex(Int i)
+{
+ return (direction==INCREASING)? (sline->get_points())[i] : (sline->get_points())[sline->get_npoints() - 1 -i];
+}
+
+Real* directedLine::tail()
+{
+ return (direction==DECREASING)? (sline->get_points())[0] : (sline->get_points())[sline->get_npoints()-1];
+}
+
+ /*insert a new line between prev and this*/
+void directedLine::insert(directedLine* nl)
+{
+ nl->next = this;
+ nl->prev = prev;
+ prev->next = nl;
+ prev = nl;
+ nl->rootLink = this; /*assuming that 'this' is the root!!!*/
+}
+
+Int directedLine::numEdges()
+{
+ Int ret=0;
+ directedLine* temp;
+ if(next == this) return 1;
+
+ ret = 1;
+ for(temp = next; temp != this; temp = temp->next)
+ ret++;
+ return ret;
+}
+
+Int directedLine::numEdgesAllPolygons()
+{
+ Int ret=0;
+ directedLine* temp;
+ for(temp=this; temp!= NULL; temp=temp->nextPolygon)
+ {
+ ret += temp->numEdges();
+ }
+ return ret;
+}
+
+/*return 1 if the double linked list forms a polygon.
+ */
+short directedLine::isPolygon()
+{
+ directedLine* temp;
+
+ /*a polygon contains at least 3 edges*/
+ if(numEdges() <=2) return 0;
+
+ /*check this edge*/
+ if(! isConnected()) return 0;
+
+ /*check all other edges*/
+ for(temp=next; temp != this; temp = temp->next){
+ if(!isConnected()) return 0;
+ }
+ return 1;
+}
+
+/*check if the head of this edge is connected to
+ *the tail of the prev
+ */
+short directedLine::isConnected()
+{
+ if( (head()[0] == prev->tail()[0]) && (head()[1] == prev->tail()[1]))
+ return 1;
+ else
+ return 0;
+}
+
+Int compV2InY(Real A[2], Real B[2])
+{
+ if(A[1] < B[1]) return -1;
+ if(A[1] == B[1] && A[0] < B[0]) return -1;
+ if(A[1] == B[1] && A[0] == B[0]) return 0;
+ return 1;
+}
+
+Int compV2InX(Real A[2], Real B[2])
+{
+ if(A[0] < B[0]) return -1;
+ if(A[0] == B[0] && A[1] < B[1]) return -1;
+ if(A[0] == B[0] && A[1] == B[1]) return 0;
+ return 1;
+}
+
+/*compare two vertices NOT lines!
+ *A vertex is the head of a directed line.
+ *(x_1, y_1) <= (x_2, y_2) if
+ *either y_1 < y_2
+ *or y_1 == y_2 && x_1 < x_2.
+ *return -1 if this->head() <= nl->head(),
+ *return 1 otherwise
+ */
+Int directedLine::compInY(directedLine* nl)
+{
+ if(head()[1] < nl->head()[1]) return -1;
+ if(head()[1] == nl->head()[1] && head()[0] < nl->head()[0]) return -1;
+ return 1;
+}
+
+/*compare two vertices NOT lines!
+ *A vertex is the head of a directed line.
+ *(x_1, y_1) <= (x_2, y_2) if
+ *either x_1 < x_2
+ *or x_1 == x_2 && y_1 < y_2.
+ *return -1 if this->head() <= nl->head(),
+ *return 1 otherwise
+ */
+Int directedLine::compInX(directedLine* nl)
+{
+ if(head()[0] < nl->head()[0]) return -1;
+ if(head()[0] == nl->head()[0] && head()[1] < nl->head()[1]) return -1;
+ return 1;
+}
+
+/*used by sort precedures
+ */
+static Int compInY2(directedLine* v1, directedLine* v2)
+{
+ return v1->compInY(v2);
+}
+#ifdef NOT_USED
+static Int compInX(directedLine* v1, directedLine* v2)
+{
+ return v1->compInX(v2);
+}
+#endif
+
+/*sort all the vertices NOT the lines!
+ *a vertex is the head of a directed line
+ */
+directedLine** directedLine::sortAllPolygons()
+{
+ Int total_num_edges = 0;
+ directedLine** array = toArrayAllPolygons(total_num_edges);
+ quicksort( (void**)array, 0, total_num_edges-1, (Int (*)(void *, void *)) compInY2);
+
+ return array;
+}
+
+void directedLine::printSingle()
+{
+ if(direction == INCREASING)
+ printf("direction is INCREASING\n");
+ else
+ printf("direction is DECREASING\n");
+ printf("head=%f,%f)\n", head()[0], head()[1]);
+ sline->print();
+}
+
+/*print one polygon*/
+void directedLine::printList()
+{
+ directedLine* temp;
+ printSingle();
+ for(temp = next; temp!=this; temp=temp->next)
+ temp->printSingle();
+}
+
+/*print all the polygons*/
+void directedLine::printAllPolygons()
+{
+ directedLine *temp;
+ for(temp = this; temp!=NULL; temp = temp->nextPolygon)
+ {
+ printf("polygon:\n");
+ temp->printList();
+ }
+}
+
+/*insert this polygon into the head of the old polygon List*/
+directedLine* directedLine::insertPolygon(directedLine* oldList)
+{
+ /*this polygon is a root*/
+ setRootBit();
+ if(oldList == NULL) return this;
+ nextPolygon = oldList;
+/* oldList->prevPolygon = this;*/
+ return this;
+}
+
+/*cutoff means delete. but we don't deallocate any space,
+ *so we use cutoff instead of delete
+ */
+directedLine* directedLine::cutoffPolygon(directedLine *p)
+{
+ directedLine* temp;
+ directedLine* prev_polygon = NULL;
+ if(p == NULL) return this;
+
+ for(temp=this; temp != p; temp = temp->nextPolygon)
+ {
+ if(temp == NULL)
+ {
+ fprintf(stderr, "in cutoffPolygon, not found\n");
+ exit(1);
+ }
+ prev_polygon = temp;
+ }
+
+/* prev_polygon = p->prevPolygon;*/
+
+ p->resetRootBit();
+ if(prev_polygon == NULL) /*this is the one to cutoff*/
+ return nextPolygon;
+ else {
+ prev_polygon->nextPolygon = p->nextPolygon;
+ return this;
+ }
+}
+
+Int directedLine::numPolygons()
+{
+ if(nextPolygon == NULL) return 1;
+ else return 1+nextPolygon->numPolygons();
+}
+
+
+/*let array[index ...] denote
+ *all the edges in this polygon
+ *return the next available index of array.
+ */
+Int directedLine::toArraySinglePolygon(directedLine** array, Int index)
+{
+ directedLine *temp;
+ array[index++] = this;
+ for(temp = next; temp != this; temp = temp->next)
+ {
+ array[index++] = temp;
+ }
+ return index;
+}
+
+/*the space is allocated. The caller is responsible for
+ *deallocate the space.
+ *total_num_edges is set to be the total number of edges of all polygons
+ */
+directedLine** directedLine::toArrayAllPolygons(Int& total_num_edges)
+{
+ total_num_edges=numEdgesAllPolygons();
+ directedLine** ret = (directedLine**) malloc(sizeof(directedLine*) * total_num_edges);
+ assert(ret);
+
+ directedLine *temp;
+ Int index = 0;
+ for(temp=this; temp != NULL; temp=temp->nextPolygon) {
+ index = temp->toArraySinglePolygon(ret, index);
+ }
+ return ret;
+}
+
+/*assume the polygon is a simple polygon, return
+ *the area enclosed by it.
+ *if thee order is counterclock wise, the area is positive.
+ */
+Real directedLine::polyArea()
+{
+ directedLine* temp;
+ Real ret=0.0;
+ Real x1,y1,x2,y2;
+ x1 = this->head()[0];
+ y1 = this->head()[1];
+ x2 = this->next->head()[0];
+ y2 = this->next->head()[1];
+ ret = -(x2*y1-x1*y2);
+ for(temp=this->next; temp!=this; temp = temp->next)
+ {
+ x1 = temp->head()[0];
+ y1 = temp->head()[1];
+ x2 = temp->next->head()[0];
+ y2 = temp->next->head()[1];
+ ret += -( x2*y1-x1*y2);
+ }
+ return Real(0.5)*ret;
+}
+
+/*******************split or combine polygons begin********************/
+/*conect a diagonal of a single simple polygon or two simple polygons.
+ *If the two vertices v1 (head) and v2 (head) are in the same simple polygon,
+ *then we actually split the simple polygon into two polygons.
+ *If instead two vertices velong to two difference polygons,
+ *then we combine the two polygons into one polygon.
+ *It is upto the caller to decide whether this is a split or a
+ *combination.
+ *
+ *Case Split:
+ *split a single simple polygon into two simple polygons by
+ *connecting a diagonal (two vertices).
+ *v1, v2: the two vertices are the head() of the two directedLines.
+ * this routine generates one new sampledLine which is returned in
+ *generatedLine,
+ *and it generates two directedLines returned in ret_p1 and ret_p2.
+ *ret_p1 and ret_p2 are used as the entry to the two new polygons.
+ *Notice the caller should not deallocate the space of v2 and v2 after
+ *calling this function, since all of the edges are connected to
+ *ret_p1 or ret_p2.
+ *
+ *combine:
+ *combine two simpolygons into one by connecting one diagonal.
+ *the returned polygon is returned in ret_p1.
+ */
+/*ARGSUSED*/
+void directedLine::connectDiagonal(directedLine* v1, directedLine* v2,
+ directedLine** ret_p1,
+ directedLine** ret_p2,
+ sampledLine** generatedLine,
+ directedLine* polygonList )
+{
+ sampledLine *nsline = new sampledLine(2);
+
+
+
+ nsline->setPoint(0, v1->head());
+ nsline->setPoint(1, v2->head());
+
+
+
+ /*the increasing line is from v1 head to v2 head*/
+ directedLine* newLineInc = new directedLine(INCREASING, nsline);
+
+
+
+ directedLine* newLineDec = new directedLine(DECREASING, nsline);
+
+
+ directedLine* v1Prev = v1->prev;
+ directedLine* v2Prev = v2->prev;
+
+ v1 ->prev = newLineDec;
+ v2Prev ->next = newLineDec;
+ newLineDec->next = v1;
+ newLineDec->prev = v2Prev;
+
+ v2 ->prev = newLineInc;
+ v1Prev ->next = newLineInc;
+ newLineInc->next = v2;
+ newLineInc->prev = v1Prev;
+
+ *ret_p1 = newLineDec;
+ *ret_p2 = newLineInc;
+ *generatedLine = nsline;
+}
+
+//see the function connectDiangle
+/*ARGSUSED*/
+void directedLine::connectDiagonal_2slines(directedLine* v1, directedLine* v2,
+ directedLine** ret_p1,
+ directedLine** ret_p2,
+ directedLine* polygonList )
+{
+ sampledLine *nsline = new sampledLine(2);
+ sampledLine *nsline2 = new sampledLine(2);
+
+ nsline->setPoint(0, v1->head());
+ nsline->setPoint(1, v2->head());
+ nsline2->setPoint(0, v1->head());
+ nsline2->setPoint(1, v2->head());
+
+ /*the increasing line is from v1 head to v2 head*/
+ directedLine* newLineInc = new directedLine(INCREASING, nsline);
+
+ directedLine* newLineDec = new directedLine(DECREASING, nsline2);
+
+ directedLine* v1Prev = v1->prev;
+ directedLine* v2Prev = v2->prev;
+
+ v1 ->prev = newLineDec;
+ v2Prev ->next = newLineDec;
+ newLineDec->next = v1;
+ newLineDec->prev = v2Prev;
+
+ v2 ->prev = newLineInc;
+ v1Prev ->next = newLineInc;
+ newLineInc->next = v2;
+ newLineInc->prev = v1Prev;
+
+ *ret_p1 = newLineDec;
+ *ret_p2 = newLineInc;
+
+}
+
+Int directedLine::samePolygon(directedLine* v1, directedLine* v2)
+{
+ if(v1 == v2) return 1;
+ directedLine *temp;
+ for(temp = v1->next; temp != v1; temp = temp->next)
+ {
+ if(temp == v2) return 1;
+ }
+ return 0;
+}
+
+directedLine* directedLine::findRoot()
+{
+ if(rootBit) return this;
+ directedLine* temp;
+ for(temp = next; temp != this; temp = temp->next)
+ if(temp -> rootBit ) return temp;
+ return NULL; /*should not happen*/
+}
+
+directedLine* directedLine::rootLinkFindRoot()
+{
+ directedLine* tempRoot;
+ directedLine* tempLink;
+ tempRoot = this;
+ tempLink = rootLink;
+ while(tempLink != NULL){
+ tempRoot = tempLink;
+ tempLink = tempRoot->rootLink;
+ }
+ return tempRoot;
+}
+
+/*******************split or combine polygons end********************/
+
+/*****************IO stuff begin*******************/
+
+/*format:
+ *#polygons
+ * #vertices
+ * vertices
+ * #vertices
+ * vertices
+ *...
+ */
+void directedLine::writeAllPolygons(char* filename)
+{
+ FILE* fp = fopen(filename, "w");
+ assert(fp);
+ Int nPolygons = numPolygons();
+ directedLine *root;
+ fprintf(fp, "%i\n", nPolygons);
+ for(root = this; root != NULL; root = root->nextPolygon)
+ {
+ directedLine *temp;
+ Int npoints=0;
+ npoints = root->get_npoints()-1;
+ for(temp = root->next; temp != root; temp=temp->next)
+ npoints += temp->get_npoints()-1;
+ fprintf(fp, "%i\n", npoints/*root->numEdges()*/);
+
+
+ for(Int i=0; i<root->get_npoints()-1; i++){
+ fprintf(fp, "%f ", root->getVertex(i)[0]);
+ fprintf(fp, "%f ", root->getVertex(i)[1]);
+ }
+
+ for(temp=root->next; temp != root; temp = temp->next)
+ {
+ for(Int i=0; i<temp->get_npoints()-1; i++){
+
+ fprintf(fp, "%f ", temp->getVertex(i)[0]);
+ fprintf(fp, "%f ", temp->getVertex(i)[1]);
+ }
+ fprintf(fp,"\n");
+ }
+ fprintf(fp, "\n");
+ }
+ fclose(fp);
+}
+
+directedLine* readAllPolygons(char* filename)
+{
+ Int i,j;
+ FILE* fp = fopen(filename, "r");
+ assert(fp);
+ Int nPolygons;
+ fscanf(fp, "%i", &nPolygons);
+ directedLine *ret = NULL;
+
+ for(i=0; i<nPolygons; i++)
+ {
+ Int nEdges;
+ fscanf(fp, "%i", &nEdges);
+ Real vert[2][2];
+ Real VV[2][2];
+ /*the first two vertices*/
+ fscanf(fp, "%f", &(vert[0][0]));
+ fscanf(fp, "%f", &(vert[0][1]));
+ fscanf(fp, "%f", &(vert[1][0]));
+ fscanf(fp, "%f", &(vert[1][1]));
+ VV[1][0] = vert[0][0];
+ VV[1][1] = vert[0][1];
+ sampledLine *sLine = new sampledLine(2, vert);
+ directedLine *thisPoly = new directedLine(INCREASING, sLine);
+thisPoly->rootLinkSet(NULL);
+
+ directedLine *dLine;
+ for(j=2; j<nEdges; j++)
+ {
+ vert[0][0]=vert[1][0];
+ vert[0][1]=vert[1][1];
+ fscanf(fp, "%f", &(vert[1][0]));
+ fscanf(fp, "%f", &(vert[1][1]));
+ sLine = new sampledLine(2,vert);
+ dLine = new directedLine(INCREASING, sLine);
+dLine->rootLinkSet(thisPoly);
+ thisPoly->insert(dLine);
+ }
+
+ VV[0][0]=vert[1][0];
+ VV[0][1]=vert[1][1];
+ sLine = new sampledLine(2,VV);
+ dLine = new directedLine(INCREASING, sLine);
+dLine->rootLinkSet(thisPoly);
+ thisPoly->insert(dLine);
+
+ ret = thisPoly->insertPolygon(ret);
+ }
+ fclose(fp);
+ return ret;
+}
+
+
+
+
+
+
+
+
diff --git a/src/glu/sgi/libnurbs/nurbtess/directedLine.h b/src/glu/sgi/libnurbs/nurbtess/directedLine.h
new file mode 100644
index 00000000000..4b65063156e
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/directedLine.h
@@ -0,0 +1,178 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/directedLine.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#ifndef _DIRECTEDLINE_H
+#define _DIRECTEDLINE_H
+
+#include "definitions.h"
+#include "sampledLine.h"
+
+enum {INCREASING, DECREASING};
+
+class directedLine {
+ short direction; /*INCREASING or DECREASING*/
+ sampledLine* sline;
+ directedLine* next; /*double linked list*/
+ directedLine* prev; /*double linked list*/
+
+ /*in case we need a list of polygons each
+ *consisting of a double linked list
+ */
+ directedLine* nextPolygon;
+
+ /*optimization make cutoff polygon faster*/
+/* directedLine* prevPolygon;*/
+
+ Int rootBit; /*1 if this is a root of the polygon, set by setRootBit*/
+ /*and reset by resetRootBit()*/
+
+ directedLine* rootLink; /*fast root-finding*/
+
+
+
+public:
+ directedLine(short dir, sampledLine* sl);
+ directedLine();
+ ~directedLine();
+
+ void init(short dir, sampledLine* sl);
+
+ Real* head(); /*points[0] if INCREASING, points[n-1] otherwise*/
+ Real* tail(); /*points[n-1] if INCREASING, points[0] otherwise*/
+ Real* getVertex(Int i); /*points[i] if INCREASING, points[n-1-i] otherwise*/
+ Int get_npoints() {return sline->get_npoints();}
+ directedLine* getPrev() {return prev;}
+ directedLine* getNext() {return next;}
+ directedLine* getNextPolygon() {return nextPolygon;}
+ sampledLine* getSampledLine() {return sline;}
+
+ short getDirection(){return direction;}
+ void putDirection(short dir) {direction = dir;}
+ void putPrev(directedLine *p) {prev = p;}
+ void putNext(directedLine *p) {next = p;}
+
+ /*insert a new line between prev and this*/
+ void insert(directedLine* nl);
+
+ /*delete all the polygons following the link: nextPolygon.
+ *notice that sampledLine is not deleted. The caller is
+ *responsible for that
+ */
+ void deletePolygonList();
+ void deleteSinglePolygon();
+
+ void deleteSinglePolygonWithSline(); //also delete sanmpled line
+ void deletePolygonListWithSline(); //also delete sanmpled line
+
+ void deleteSingleLine(directedLine* dline);
+ directedLine* deleteDegenerateLines();
+ directedLine* deleteDegenerateLinesAllPolygons();
+ directedLine* cutIntersectionAllPoly(int& cutOccur);
+
+ /*check to see if the list forms a closed polygon
+ *return 1 if yes
+ */
+ short isPolygon();
+
+ Int compInY(directedLine* nl);
+ Int compInX(directedLine* nl);
+
+ /*return an array of pointers.
+ *the
+ */
+ directedLine** sortAllPolygons();
+
+ Int numEdges();
+ Int numEdgesAllPolygons();
+ Int numPolygons();
+
+ /*check if the head of this edge is connected to
+ *the tail of the prev
+ */
+ short isConnected();
+
+ Real polyArea();
+
+ void printSingle();
+ void printList();
+ void printAllPolygons();
+ void writeAllPolygons(char* filename);
+
+
+ /*insert a polygon: using nextPolygon*/
+ directedLine* insertPolygon(directedLine* newpolygon);
+ directedLine* cutoffPolygon(directedLine *p);
+
+ Int toArraySinglePolygon(directedLine** array, Int index);
+ directedLine** toArrayAllPolygons(Int& total_num_edges);
+
+ void connectDiagonal(directedLine* v1, directedLine* v2,
+ directedLine** ret_p1,
+ directedLine** ret_p2,
+ sampledLine** generatedLine, directedLine* list);
+
+ /*generate two slines
+ */
+ void connectDiagonal_2slines(directedLine* v1, directedLine* v2,
+ directedLine** ret_p1,
+ directedLine** ret_p2,
+ directedLine* list);
+
+ Int samePolygon(directedLine* v1, directedLine* v2);
+ void setRootBit() {rootBit = 1;}
+ void resetRootBit() {rootBit = 0;}
+ directedLine* findRoot();
+
+ void rootLinkSet(directedLine* r) {rootLink = r;}
+ directedLine* rootLinkFindRoot();
+
+ //the chain from begin to end is deleted (the space is deallocated)
+ //and a new edge(which connectes the head of begin and the tail of end)
+ // is inserted. The new polygon is returned.
+ //notice that "this" is arbitrary
+ directedLine* deleteChain(directedLine* begin, directedLine* end);
+};
+
+directedLine* readAllPolygons(char* filename);
+
+extern Int compV2InY(Real A[2], Real B[2]);
+extern Int compV2InX(Real A[2], Real B[2]);
+
+#endif
+
diff --git a/src/glu/sgi/libnurbs/nurbtess/glimports.h b/src/glu/sgi/libnurbs/nurbtess/glimports.h
new file mode 100644
index 00000000000..44d45868f52
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/glimports.h
@@ -0,0 +1,48 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * glimports.h
+ *
+ * $Date: 2001/03/19 17:52:03 $ $Revision: 1.3 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/glimports.h,v 1.3 2001/03/19 17:52:03 pesco Exp $
+ */
+
+#ifndef __gluimports_h_
+#define __gluimports_h_
+
+#include "mystdlib.h"
+#include "mystdio.h"
+
+#endif /* __gluimports_h_ */
diff --git a/src/glu/sgi/libnurbs/nurbtess/gridWrap.cc b/src/glu/sgi/libnurbs/nurbtess/gridWrap.cc
new file mode 100644
index 00000000000..71ea18e1100
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/gridWrap.cc
@@ -0,0 +1,295 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/gridWrap.cc,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <GL/gl.h>
+#include "zlassert.h"
+#include "gridWrap.h"
+
+
+/*******************grid structure****************************/
+void gridWrap::print()
+{
+ printf("n_ulines = %i\n", n_ulines);
+ printf("n_vlines = %i\n", n_vlines);
+ printf("u_min=%f, umax=%f, vmin=%f, vmax=%f\n", u_min, u_max, v_min, v_max);
+}
+
+gridWrap::gridWrap(Int nUlines, Real* uvals,
+ Int nVlines, Real* vvals)
+{
+ assert(nUlines>=2);
+ assert(nVlines>=2);
+
+ is_uniform = 0;
+ n_ulines = nUlines;
+ n_vlines = nVlines;
+ u_min = uvals[0];
+ u_max = uvals[nUlines-1];
+ v_min = vvals[0];
+ v_max = vvals[nVlines-1];
+ u_values = (Real*) malloc(sizeof(Real) * n_ulines);
+ assert(u_values);
+ v_values = (Real*) malloc(sizeof(Real) * n_vlines);
+ assert(v_values);
+
+ Int i;
+ for(i=0; i<n_ulines; i++)
+ u_values[i] = uvals[i];
+ for(i=0; i<n_vlines; i++)
+ v_values[i] = vvals[i];
+}
+
+gridWrap::gridWrap(Int nUlines, Int nVlines,
+ Real uMin, Real uMax,
+ Real vMin, Real vMax
+ )
+{
+ is_uniform = 1;
+ n_ulines = nUlines;
+ n_vlines = nVlines;
+ u_min = uMin;
+ u_max = uMax;
+ v_min = vMin;
+ v_max = vMax;
+ u_values = (Real*) malloc(sizeof(Real) * n_ulines);
+ assert(u_values);
+ v_values = (Real*) malloc(sizeof(Real) * n_vlines);
+ assert(v_values);
+
+ Int i;
+ assert(nUlines>=2);
+ assert(nVlines>=2);
+ Real du = (uMax-uMin)/(nUlines-1);
+ Real dv = (vMax-vMin)/(nVlines-1);
+
+ float tempu=uMin;
+ u_values[0] = tempu;
+ for(i=1; i<nUlines; i++)
+ {
+ tempu += du;
+ u_values[i] = tempu;
+ }
+ u_values[nUlines-1] = uMax;
+
+ float tempv=vMin;
+ v_values[0] = tempv;
+ for(i=1; i<nVlines; i++)
+ {
+ tempv += dv;
+ v_values[i] = tempv;
+ }
+ v_values[nVlines-1] = vMax;
+}
+
+gridWrap::~gridWrap()
+{
+ free(u_values);
+ free(v_values);
+}
+
+void gridWrap::draw()
+{
+ int i,j;
+ glBegin(GL_POINTS);
+ for(i=0; i<n_ulines; i++)
+ for(j=0; j<n_vlines; j++)
+ glVertex2f(get_u_value(i), get_v_value(j));
+ glEnd();
+}
+
+void gridWrap::outputFanWithPoint(Int v, Int uleft, Int uright, Real vert[2], primStream* pStream)
+{
+ Int i;
+ if(uleft >= uright)
+ return; //no triangles to output.
+
+ pStream->begin();
+ pStream->insert(vert);
+
+ assert(vert[1] != v_values[v]); //don't output degenerate triangles
+
+ if(vert[1] > v_values[v]) //vertex is above this grid line: notice the orientation
+ {
+ for(i=uleft; i<=uright; i++)
+ pStream->insert(u_values[i], v_values[v]);
+ }
+ else //vertex is below the grid line
+ {
+ for(i=uright; i>= uleft; i--)
+ pStream->insert(u_values[i], v_values[v]);
+ }
+
+ pStream->end(PRIMITIVE_STREAM_FAN);
+}
+
+
+
+/*each chain stores a number of consecutive
+ *V-lines within a grid.
+ *There is one grid vertex on each V-line.
+ * The total number of V-lines is:
+ * nVlines.
+ * with respect to the grid, the index of the first V-line is
+ * firstVlineIndex.
+ * So with respect to the grid, the index of the ith V-line is
+ * firstVlineIndex-i.
+ * the grid-index of the uline at the ith vline (recall that each vline has one grid point)
+ * is ulineIndices[i]. The u_value is cached in ulineValues[i], that is,
+ * ulineValues[i] = grid->get_u_value(ulineIndices[i])
+ */
+gridBoundaryChain::gridBoundaryChain(
+ gridWrap* gr,
+ Int first_vline_index,
+ Int n_vlines,
+ Int* uline_indices,
+ Int* inner_indices
+ )
+: grid(gr), firstVlineIndex(first_vline_index), nVlines(n_vlines)
+{
+ ulineIndices = (Int*) malloc(sizeof(Int) * n_vlines);
+ assert(ulineIndices);
+
+ innerIndices = (Int*) malloc(sizeof(Int) * n_vlines);
+ assert(innerIndices);
+
+ vertices = (Real2*) malloc(sizeof(Real2) * n_vlines);
+ assert(vertices);
+
+
+
+ Int i;
+ for(i=0; i<n_vlines; i++){
+ ulineIndices[i] = uline_indices[i];
+ innerIndices[i] = inner_indices[i];
+ }
+
+ for(i=0; i<n_vlines; i++){
+ vertices[i][0] = gr->get_u_value(ulineIndices[i]);
+ vertices[i][1] = gr->get_v_value(first_vline_index-i);
+ }
+}
+
+void gridBoundaryChain::draw()
+{
+ Int i;
+ glBegin(GL_LINE_STRIP);
+ for(i=0; i<nVlines; i++)
+ {
+ glVertex2fv(vertices[i]);
+ }
+ glEnd();
+}
+
+void gridBoundaryChain::drawInner()
+{
+ Int i;
+ for(i=1; i<nVlines; i++)
+ {
+ glBegin(GL_LINE_STRIP);
+ glVertex2f(grid->get_u_value(innerIndices[i]), get_v_value(i-1) );
+ glVertex2f(grid->get_u_value(innerIndices[i]), get_v_value(i) );
+ glEnd();
+ }
+}
+
+Int gridBoundaryChain::lookfor(Real v, Int i1, Int i2)
+{
+ Int mid;
+ while(i1 < i2-1)
+ {
+ mid = (i1+i2)/2;
+ if(v > vertices[mid][1])
+ {
+ i2 = mid;
+ }
+ else
+ i1 = mid;
+ }
+ return i1;
+}
+
+/*output the fan of the right end between grid line i-1 and grid line i*/
+void gridBoundaryChain::rightEndFan(Int i, primStream* pStream)
+{
+ Int j;
+ if(getUlineIndex(i) > getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(get_vertex(i-1));
+ for(j=getUlineIndex(i-1); j<= getUlineIndex(i); j++)
+ pStream->insert(grid->get_u_value(j), get_v_value(i));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ else if(getUlineIndex(i) < getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(get_vertex(i));
+ for(j=getUlineIndex(i-1); j>= getUlineIndex(i); j--)
+ pStream->insert(grid->get_u_value(j), get_v_value(i-1));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ //otherside, the two are equal, so there is no fan to output
+}
+
+
+/*output the fan of the left end between grid line i-1 and grid line i*/
+void gridBoundaryChain::leftEndFan(Int i, primStream* pStream)
+{
+ Int j;
+ if(getUlineIndex(i) < getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(get_vertex(i-1));
+ for(j=getUlineIndex(i); j<= getUlineIndex(i-1); j++)
+ pStream->insert(grid->get_u_value(j), get_v_value(i));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ else if(getUlineIndex(i) > getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(get_vertex(i));
+ for(j=getUlineIndex(i); j>= getUlineIndex(i-1); j--)
+ pStream->insert(grid->get_u_value(j), get_v_value(i-1));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ /*otherwisem, the two are equal, so there is no fan to outout*/
+}
diff --git a/src/glu/sgi/libnurbs/nurbtess/gridWrap.h b/src/glu/sgi/libnurbs/nurbtess/gridWrap.h
new file mode 100644
index 00000000000..a6eb621cb89
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/gridWrap.h
@@ -0,0 +1,144 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/gridWrap.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#ifndef _GRIDWRAP_H
+#define _GRIDWRAP_H
+
+#include <stdio.h>
+#include "definitions.h"
+
+#include "primitiveStream.h"
+#include "zlassert.h"
+
+class gridWrap{
+ Int n_ulines;
+ Int n_vlines;
+ Real u_min, u_max;
+ Real v_min, v_max;
+
+ /*cache the coordinate values for efficiency.
+ *these are redundant information when
+ *the grid is uniform.
+ */
+ Real* u_values; /*size is n_ulines*/
+ Real* v_values; /*size is n_vlines*/
+
+ Int is_uniform;
+
+public:
+ //uniform grid constructor
+ gridWrap(Int nUlines, Int nVlines,
+ Real uMin, Real uMax,
+ Real vMin, Real vMax
+ );
+
+ //nonuniform grid constructor.
+ gridWrap(Int nUlines, Real *uvals,
+ Int nVlines, Real *vvlas
+ );
+ ~gridWrap();
+
+ void print();
+ Int get_n_ulines() {return n_ulines;}
+ Int get_n_vlines() {return n_vlines;}
+ Real get_u_min() {return u_min;}
+ Real get_u_max() {return u_max;}
+ Real get_v_min() {return v_min;}
+ Real get_v_max() {return v_max;}
+
+ Real get_u_value(Int i)
+ {
+ assert(i<n_ulines);
+ /*if(i>=n_ulines){printf("ERROR, n_ulines=%i,i=%i\n",n_ulines,i);exit(0);}*/
+ return u_values[i];}
+ Real get_v_value(Int j) {return v_values[j];}
+
+ Real* get_u_values() {return u_values;}
+ Real* get_v_values() {return v_values;}
+
+ void outputFanWithPoint(Int v, Int uleft, Int uright,
+ Real vert[2], primStream* pStream);
+
+ void draw();
+
+ Int isUniform() {return is_uniform;}
+};
+
+class gridBoundaryChain{
+ gridWrap* grid;
+ Int firstVlineIndex;
+ Int nVlines;
+ Int* ulineIndices; /*each v line has a boundary*/
+ Int* innerIndices; /*the segment of the vertical gridline from */
+ /*(innerIndices[i], i) to (innerIndices[i+1], i-1) */
+ /*is inside the polygon: i=1,...,nVlines-1*/
+
+ Real2* vertices; /*one grid point at each grid V-line, cached for efficiency*/
+
+public:
+ gridBoundaryChain(gridWrap* gr, Int first_vline_index, Int n_vlines, Int* uline_indices, Int* inner_indices);
+
+ ~gridBoundaryChain()
+ {
+ free(innerIndices);
+ free(ulineIndices);
+ free(vertices);
+ }
+
+ /*i indexes the vlines in this chain.
+ */
+ Int getVlineIndex(Int i) {return firstVlineIndex-i;}
+ Int getUlineIndex(Int i) {return ulineIndices[i];}
+ Real get_u_value(Int i) {return vertices[i][0];}
+ Real get_v_value(Int i) {return vertices[i][1];}
+ Int get_nVlines() {return nVlines;}
+ Int getInnerIndex(Int i) {return innerIndices[i];}
+ Real getInner_u_value(Int i) {return grid->get_u_value(innerIndices[i]);}
+
+ Real* get_vertex(Int i) {return vertices[i];}
+ gridWrap* getGrid() {return grid;}
+ void leftEndFan(Int i, primStream* pStream);
+ void rightEndFan(Int i, primStream* pStream);
+
+ Int lookfor(Real v, Int i1, Int i2); //find i in [i1,i2] so that vertices[i][1]>= v > vertices[i+1][1]
+ void draw();
+ void drawInner();
+};
+
+#endif
diff --git a/src/glu/sgi/libnurbs/nurbtess/monoChain.cc b/src/glu/sgi/libnurbs/nurbtess/monoChain.cc
new file mode 100644
index 00000000000..469e8aaeefa
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/monoChain.cc
@@ -0,0 +1,936 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2005/10/28 13:09:08 $ $Revision: 1.2.8.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/monoChain.cc,v 1.2.8.1 2005/10/28 13:09:08 brianp Exp $
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <GL/gl.h>
+
+#include "glimports.h"
+#include "zlassert.h"
+
+#include "monoChain.h"
+#include "quicksort.h"
+#include "searchTree.h"
+#include "polyUtil.h"
+
+#ifndef max
+#define max(a,b) ((a>b)? a:b)
+#endif
+#ifndef min
+#define min(a,b) ((a>b)? b:a)
+#endif
+
+extern Int isCusp(directedLine *v);
+extern Int deleteRepeatDiagonals(Int num_diagonals, directedLine** diagonal_vertices, directedLine** new_vertices);
+
+//for debug purpose only
+#if 0 // UNUSED
+static void drawDiagonals(Int num_diagonals, directedLine** diagonal_vertices)
+{
+ Int i;
+ for(i=0; i<num_diagonals; i++)
+ {
+ glBegin(GL_LINE);
+ glVertex2fv(diagonal_vertices[2*i]->head());
+ glVertex2fv(diagonal_vertices[2*i+1]->head());
+ glEnd();
+ }
+}
+#endif
+
+/*given (x_1, y_1) and (x_2, y_2), and y
+ *return x such that (x,y) is on the line
+ */
+inline Real intersectHoriz(Real x1, Real y1, Real x2, Real y2, Real y)
+{
+ return ((y2==y1)? (x1+x2)*0.5 : x1 + ((y-y1)/(y2-y1)) * (x2-x1));
+}
+
+//compare the heads of the two chains
+static int compChainHeadInY(monoChain* mc1, monoChain* mc2)
+{
+ return compV2InY(mc1->getHead()->head(), mc2->getHead()->head());
+}
+
+monoChain::monoChain(directedLine* cHead, directedLine* cTail)
+{
+ chainHead = cHead;
+ chainTail = cTail;
+ next = this;
+ prev = this;
+
+ nextPolygon = NULL;
+
+ //compute bounding box
+ directedLine* temp;
+ minX = maxX = chainTail->head()[0];
+ minY = maxY = chainTail->head()[1];
+
+ for(temp=chainHead; temp!=cTail; temp = temp->getNext())
+ {
+ if(temp->head()[0] < minX)
+ minX = temp->head()[0];
+ if(temp->head()[0] > maxX)
+ maxX = temp->head()[0];
+
+ if(temp->head()[1] < minY)
+ minY = temp->head()[1];
+ if(temp->head()[1] > maxY)
+ maxY = temp->head()[1];
+ }
+
+ //check whether the chain is increasing or decreasing
+ if(chainHead->compInY(chainTail) <0)
+ isIncrease = 1;
+ else
+ isIncrease = 0;
+
+ //initilize currrent, this is used for accelerating search
+ if(isIncrease)
+ current = chainHead;
+ else
+ current = chainTail;
+
+ isKey = 0;
+}
+
+//insert a new line between prev and this
+void monoChain::insert(monoChain* nc)
+{
+ nc->next = this;
+ nc->prev = prev;
+ prev->next = nc;
+ prev = nc;
+}
+
+void monoChain::deleteLoop()
+{
+ monoChain *temp, *tempNext;
+ prev->next = NULL;
+ for(temp=this; temp != NULL; temp = tempNext)
+ {
+ tempNext = temp->next;
+ delete temp;
+ }
+}
+
+void monoChain::deleteLoopList()
+{
+ monoChain *temp, *tempNext;
+ for(temp=this; temp != NULL; temp = tempNext)
+ {
+ tempNext = temp->nextPolygon;
+ temp->deleteLoop();
+ }
+}
+
+Int monoChain::toArraySingleLoop(monoChain** array, Int index)
+{
+ monoChain *temp;
+ array[index++] = this;
+ for(temp = next; temp != this; temp = temp->next)
+ {
+ array[index++] = temp;
+ }
+ return index;
+}
+
+monoChain** monoChain::toArrayAllLoops(Int& num_chains)
+{
+ num_chains = numChainsAllLoops();
+ monoChain **ret = (monoChain**) malloc(sizeof(monoChain*) * num_chains);
+ assert(ret);
+ monoChain *temp;
+ Int index = 0;
+ for(temp = this; temp != NULL; temp=temp->nextPolygon){
+ index = temp->toArraySingleLoop(ret, index);
+ }
+ return ret;
+}
+
+Int monoChain::numChainsSingleLoop()
+{
+ Int ret=0;
+ monoChain* temp;
+ if(next == this) return 1;
+ ret = 1;
+ for(temp=next; temp != this; temp = temp->next)
+ ret++;
+ return ret;
+}
+
+Int monoChain::numChainsAllLoops()
+{
+ Int ret=0;
+ monoChain *temp;
+ for(temp =this; temp != NULL; temp = temp->nextPolygon)
+ ret += temp->numChainsSingleLoop();
+ return ret;
+}
+
+//update 'current'
+Real monoChain::chainIntersectHoriz(Real y)
+{
+ directedLine* temp;
+ if(isIncrease)
+ {
+ for(temp= current; temp != chainTail; temp = temp->getNext())
+ {
+ if(temp->head()[1] > y)
+ break;
+ }
+ current = temp->getPrev();
+ }
+ else
+ {
+ for(temp = current; temp != chainHead; temp = temp->getPrev())
+ {
+ if(temp->head()[1] > y)
+ break;
+ }
+ current = temp->getNext();
+ }
+ return intersectHoriz(current->head()[0], current->head()[1], current->tail()[0], current->tail()[1], y);
+}
+
+monoChain* directedLineLoopToMonoChainLoop(directedLine* loop)
+{
+ directedLine *temp;
+ monoChain *ret=NULL;
+
+ //find the first cusp
+ directedLine *prevCusp=NULL;
+ directedLine *firstCusp;
+
+ if(isCusp(loop))
+ prevCusp = loop;
+ else
+ {
+ for(temp = loop->getNext(); temp != loop; temp = temp->getNext())
+ if(isCusp(temp))
+ break;
+ prevCusp = temp;
+ }
+ firstCusp = prevCusp;
+//printf("first cusp is (%f,%f), (%f,%f), (%f,%f)\n", prevCusp->getPrev()->head()[0], prevCusp->getPrev()->head()[1], prevCusp->head()[0], prevCusp->head()[1], prevCusp->tail()[0], prevCusp->tail()[1]);
+
+ for(temp = prevCusp->getNext(); temp != loop; temp = temp->getNext())
+ {
+ if(isCusp(temp))
+ {
+//printf("the cusp is (%f,%f), (%f,%f), (%f,%f)\n", temp->getPrev()->head()[0], temp->getPrev()->head()[1], temp->head()[0], temp->head()[1], temp->tail()[0], temp->tail()[1]);
+ if(ret == NULL)
+ {
+ ret = new monoChain(prevCusp, temp);
+ }
+ else
+ ret->insert(new monoChain(prevCusp, temp));
+ prevCusp = temp;
+ }
+ }
+ ret->insert(new monoChain(prevCusp, firstCusp));
+
+ return ret;
+}
+
+monoChain* directedLineLoopListToMonoChainLoopList(directedLine* list)
+{
+ directedLine* temp;
+ monoChain* mc;
+ monoChain* mcEnd;
+ mc = directedLineLoopToMonoChainLoop(list);
+ mcEnd = mc;
+ for(temp = list->getNextPolygon(); temp != NULL; temp = temp->getNextPolygon())
+ {
+ monoChain *newLoop = directedLineLoopToMonoChainLoop(temp);
+ mcEnd->setNextPolygon(newLoop);
+ mcEnd = newLoop;
+ }
+ return mc;
+}
+
+/*compare two edges of a polygon.
+ *edge A < edge B if there is a horizontal line so that the intersection
+ *with A is to the left of the intersection with B.
+ *This function is used in sweepY for the dynamic search tree insertion to
+ *order the edges.
+ * Implementation: (x_1,y_1) and (x_2, y_2)
+ */
+static Int compEdges(directedLine *e1, directedLine *e2)
+{
+ Real* head1 = e1->head();
+ Real* tail1 = e1->tail();
+ Real* head2 = e2->head();
+ Real* tail2 = e2->tail();
+/*
+ Real h10 = head1[0];
+ Real h11 = head1[1];
+ Real t10 = tail1[0];
+ Real t11 = tail1[1];
+ Real h20 = head2[0];
+ Real h21 = head2[1];
+ Real t20 = tail2[0];
+ Real t21 = tail2[1];
+*/
+ Real e1_Ymax, e1_Ymin, e2_Ymax, e2_Ymin;
+/*
+ if(h11>t11) {
+ e1_Ymax= h11;
+ e1_Ymin= t11;
+ }
+ else{
+ e1_Ymax = t11;
+ e1_Ymin = h11;
+ }
+
+ if(h21>t21) {
+ e2_Ymax= h21;
+ e2_Ymin= t21;
+ }
+ else{
+ e2_Ymax = t21;
+ e2_Ymin = h21;
+ }
+*/
+
+ if(head1[1]>tail1[1]) {
+ e1_Ymax= head1[1];
+ e1_Ymin= tail1[1];
+ }
+ else{
+ e1_Ymax = tail1[1];
+ e1_Ymin = head1[1];
+ }
+
+ if(head2[1]>tail2[1]) {
+ e2_Ymax= head2[1];
+ e2_Ymin= tail2[1];
+ }
+ else{
+ e2_Ymax = tail2[1];
+ e2_Ymin = head2[1];
+ }
+
+
+ /*Real e1_Ymax = max(head1[1], tail1[1]);*/ /*max(e1->head()[1], e1->tail()[1]);*/
+ /*Real e1_Ymin = min(head1[1], tail1[1]);*/ /*min(e1->head()[1], e1->tail()[1]);*/
+ /*Real e2_Ymax = max(head2[1], tail2[1]);*/ /*max(e2->head()[1], e2->tail()[1]);*/
+ /*Real e2_Ymin = min(head2[1], tail2[1]);*/ /*min(e2->head()[1], e2->tail()[1]);*/
+
+ Real Ymax = min(e1_Ymax, e2_Ymax);
+ Real Ymin = max(e1_Ymin, e2_Ymin);
+
+ Real y = 0.5*(Ymax + Ymin);
+
+/* Real x1 = intersectHoriz(e1->head()[0], e1->head()[1], e1->tail()[0], e1->tail()[1], y);
+ Real x2 = intersectHoriz(e2->head()[0], e2->head()[1], e2->tail()[0], e2->tail()[1], y);
+*/
+/*
+ Real x1 = intersectHoriz(h10, h11, t10, t11, y);
+ Real x2 = intersectHoriz(h20, h21, t20, t21, y);
+*/
+ Real x1 = intersectHoriz(head1[0], head1[1], tail1[0], tail1[1], y);
+ Real x2 = intersectHoriz(head2[0], head2[1], tail2[0], tail2[1], y);
+
+ if(x1<= x2) return -1;
+ else return 1;
+}
+
+Int compChains(monoChain* mc1, monoChain* mc2)
+{
+ Real y;
+ assert(mc1->isKey || mc2->isKey);
+ if(mc1->isKey)
+ y = mc1->keyY;
+ else
+ y = mc2->keyY;
+ directedLine *d1 = mc1->find(y);
+ directedLine *d2 = mc2->find(y);
+ mc2->find(y);
+// Real x1 = mc1->chainIntersectHoriz(y);
+// Real x2 = mc2->chainIntersectHoriz(y);
+ return compEdges(d1, d2);
+}
+
+//this function modifies current for efficiency
+directedLine* monoChain::find(Real y)
+{
+ directedLine *ret;
+ directedLine *temp;
+ assert(current->head()[1] <= y);
+ if(isIncrease)
+ {
+ assert(chainTail->head()[1] >=y);
+ for(temp=current; temp!=chainTail; temp = temp->getNext())
+ {
+ if(temp->head()[1] > y)
+ break;
+ }
+ current = temp->getPrev();
+ ret = current;
+ }
+ else
+ {
+ for(temp=current; temp != chainHead; temp = temp->getPrev())
+ {
+ if(temp->head()[1] > y)
+ break;
+ }
+ current = temp->getNext();
+ ret = temp;
+ }
+ return ret;
+}
+
+void monoChain::printOneChain()
+{
+ directedLine* temp;
+ for(temp = chainHead; temp != chainTail; temp = temp->getNext())
+ {
+ printf("(%f,%f) ", temp->head()[0], temp->head()[1]);
+ }
+ printf("(%f,%f) \n", chainTail->head()[0], chainTail->head()[1]);
+}
+
+void monoChain::printChainLoop()
+{
+ monoChain* temp;
+ this->printOneChain();
+ for(temp = next; temp != this; temp = temp->next)
+ {
+ temp->printOneChain();
+ }
+ printf("\n");
+}
+
+void monoChain::printAllLoops()
+{
+ monoChain* temp;
+ for(temp=this; temp != NULL; temp = temp->nextPolygon)
+ temp->printChainLoop();
+}
+
+//return 1 if error occures
+Int MC_sweepY(Int nVertices, monoChain** sortedVertices, sweepRange** ret_ranges)
+{
+ Int i;
+ Real keyY;
+ Int errOccur=0;
+//printf("enter MC_sweepY\n");
+//printf("nVertices=%i\n", nVertices);
+ /*for each vertex in the sorted list, update the binary search tree.
+ *and store the range information for each vertex.
+ */
+ treeNode* searchTree = NULL;
+//printf("nVertices=%i\n", nVertices);
+ for(i=0; i<nVertices; i++)
+ {
+ monoChain* vert = sortedVertices[i];
+ keyY = vert->getHead()->head()[1]; //the sweep line
+ directedLine *dline = vert->getHead();
+ directedLine *dlinePrev = dline->getPrev();
+ if(isBelow(dline, dline) && isBelow(dline, dlinePrev))
+ {
+//printf("case 1\n");
+ //this<v and prev < v
+ //delete both edges
+ vert->isKey = 1;
+ vert->keyY = keyY;
+ treeNode* thisNode = TreeNodeFind(searchTree, vert, (Int (*) (void *, void *))compChains);
+ vert->isKey = 0;
+
+ vert->getPrev()->isKey = 1;
+ vert->getPrev()->keyY = keyY;
+ treeNode* prevNode = TreeNodeFind(searchTree, vert->getPrev(), (Int (*) (void *, void *))compChains);
+ vert->getPrev()->isKey = 0;
+
+ if(cuspType(dline) == 1)//interior cusp
+ {
+
+ treeNode* leftEdge = TreeNodePredecessor(prevNode);
+ treeNode* rightEdge = TreeNodeSuccessor(thisNode);
+ if(leftEdge == NULL || rightEdge == NULL)
+ {
+ errOccur = 1;
+ goto JUMP_HERE;
+ }
+
+ directedLine* leftEdgeDline = ((monoChain* ) leftEdge->key)->find(keyY);
+
+
+
+ directedLine* rightEdgeDline = ((monoChain* ) rightEdge->key)->find(keyY);
+
+ ret_ranges[i] = sweepRangeMake(leftEdgeDline, 1, rightEdgeDline, 1);
+ }
+ else /*exterior cusp*/
+ {
+ ret_ranges[i] = sweepRangeMake( dline, 1, dlinePrev, 1);
+ }
+
+ searchTree = TreeNodeDeleteSingleNode(searchTree, thisNode);
+ searchTree = TreeNodeDeleteSingleNode(searchTree, prevNode);
+
+ }
+ else if(isAbove(dline, dline) && isAbove(dline, dlinePrev))
+ {
+//printf("case 2\n");
+ //insert both edges
+ treeNode* thisNode = TreeNodeMake(vert);
+ treeNode* prevNode = TreeNodeMake(vert->getPrev());
+
+ vert->isKey = 1;
+ vert->keyY = keyY;
+ searchTree = TreeNodeInsert(searchTree, thisNode, (Int (*) (void *, void *))compChains);
+ vert->isKey = 0;
+
+ vert->getPrev()->isKey = 1;
+ vert->getPrev()->keyY = keyY;
+ searchTree = TreeNodeInsert(searchTree, prevNode, (Int (*) (void *, void *))compChains);
+ vert->getPrev()->isKey = 0;
+
+ if(cuspType(dline) == 1) //interior cusp
+ {
+//printf("cuspType is 1\n");
+ treeNode* leftEdge = TreeNodePredecessor(thisNode);
+ treeNode* rightEdge = TreeNodeSuccessor(prevNode);
+ if(leftEdge == NULL || rightEdge == NULL)
+ {
+ errOccur = 1;
+ goto JUMP_HERE;
+ }
+//printf("leftEdge is %i, rightEdge is %i\n", leftEdge, rightEdge);
+ directedLine* leftEdgeDline = ((monoChain*) leftEdge->key)->find(keyY);
+ directedLine* rightEdgeDline = ((monoChain*) rightEdge->key)->find(keyY);
+ ret_ranges[i] = sweepRangeMake( leftEdgeDline, 1, rightEdgeDline, 1);
+ }
+ else //exterior cusp
+ {
+//printf("cuspType is not 1\n");
+ ret_ranges[i] = sweepRangeMake(dlinePrev, 1, dline, 1);
+ }
+ }
+ else
+ {
+//printf("%i,%i\n", isAbove(dline, dline), isAbove(dline, dlinePrev));
+ errOccur = 1;
+ goto JUMP_HERE;
+
+ fprintf(stderr, "error in MC_sweepY\n");
+ exit(1);
+ }
+ }
+
+ JUMP_HERE:
+ //finally clean up space: delete the search tree
+ TreeNodeDeleteWholeTree(searchTree);
+ return errOccur;
+}
+
+void MC_findDiagonals(Int total_num_edges, monoChain** sortedVertices,
+ sweepRange** ranges, Int& num_diagonals,
+ directedLine** diagonal_vertices)
+{
+ Int i,j,k;
+ k=0;
+ //reset 'current' of all the monoChains
+ for(i=0; i<total_num_edges; i++)
+ sortedVertices[i]->resetCurrent();
+
+ for(i=0; i<total_num_edges; i++)
+ {
+ directedLine* vert = sortedVertices[i]->getHead();
+ directedLine* thisEdge = vert;
+ directedLine* prevEdge = vert->getPrev();
+ if(isBelow(vert, thisEdge) && isBelow(vert, prevEdge) && compEdges(prevEdge, thisEdge)<0)
+ {
+ //this is an upward interior cusp
+ diagonal_vertices[k++] = vert;
+
+ directedLine* leftEdge = ranges[i]->left;
+ directedLine* rightEdge = ranges[i]->right;
+
+ directedLine* leftVert = leftEdge;
+ directedLine* rightVert = rightEdge->getNext();
+ assert(leftVert->head()[1] >= vert->head()[1]);
+ assert(rightVert->head()[1] >= vert->head()[1]);
+ directedLine* minVert = (leftVert->head()[1] <= rightVert->head()[1])?leftVert:rightVert;
+ Int found = 0;
+ for(j=i+1; j<total_num_edges; j++)
+ {
+ if(sortedVertices[j]->getHead()->head()[1] > minVert->head()[1])
+ break;
+
+ if(sweepRangeEqual(ranges[i], ranges[j]))
+ {
+ found = 1;
+ break;
+ }
+ }
+
+ if(found)
+ diagonal_vertices[k++] = sortedVertices[j]->getHead();
+ else
+ diagonal_vertices[k++] = minVert;
+ }
+ else if(isAbove(vert, thisEdge) && isAbove(vert, prevEdge) && compEdges(prevEdge, thisEdge)>0)
+ {
+ //downward interior cusp
+ diagonal_vertices[k++] = vert;
+ directedLine* leftEdge = ranges[i]->left;
+ directedLine* rightEdge = ranges[i]->right;
+ directedLine* leftVert = leftEdge->getNext();
+ directedLine* rightVert = rightEdge;
+ assert(leftVert->head()[1] <= vert->head()[1]);
+ assert(rightVert->head()[1] <= vert->head()[1]);
+ directedLine* maxVert = (leftVert->head()[1] > rightVert->head()[1])? leftVert:rightVert;
+ Int found=0;
+ for(j=i-1; j>=0; j--)
+ {
+ if(sortedVertices[j]->getHead()->head()[1] < maxVert->head()[1])
+ break;
+ if(sweepRangeEqual(ranges[i], ranges[j]))
+ {
+ found = 1;
+ break;
+ }
+ }
+ if(found)
+ diagonal_vertices[k++] = sortedVertices[j]->getHead();
+ else
+ diagonal_vertices[k++] = maxVert;
+ }
+ }
+ num_diagonals = k/2;
+}
+
+
+
+
+directedLine* MC_partitionY(directedLine *polygons, sampledLine **retSampledLines)
+{
+//printf("enter mc_partitionY\n");
+ Int total_num_chains = 0;
+ monoChain* loopList = directedLineLoopListToMonoChainLoopList(polygons);
+ monoChain** array = loopList->toArrayAllLoops(total_num_chains);
+
+ if(total_num_chains<=2) //there is just one single monotone polygon
+ {
+ loopList->deleteLoopList();
+ free(array);
+ *retSampledLines = NULL;
+ return polygons;
+ }
+
+//loopList->printAllLoops();
+//printf("total_num_chains=%i\n", total_num_chains);
+ quicksort( (void**)array, 0, total_num_chains-1, (Int (*)(void*, void*))compChainHeadInY);
+//printf("after quicksort\n");
+
+ sweepRange** ranges = (sweepRange**)malloc(sizeof(sweepRange*) * (total_num_chains));
+ assert(ranges);
+
+ if(MC_sweepY(total_num_chains, array, ranges))
+ {
+ loopList->deleteLoopList();
+ free(array);
+ *retSampledLines = NULL;
+ return NULL;
+ }
+//printf("after MC_sweepY\n");
+
+
+ Int num_diagonals;
+ /*number diagonals is < total_num_edges*total_num_edges*/
+ directedLine** diagonal_vertices = (directedLine**) malloc(sizeof(directedLine*) * total_num_chains*2/*total_num_edges*/);
+ assert(diagonal_vertices);
+
+//printf("before call MC_findDiagonales\n");
+
+ MC_findDiagonals(total_num_chains, array, ranges, num_diagonals, diagonal_vertices);
+//printf("after call MC_findDia, num_diagnla=%i\n", num_diagonals);
+
+ directedLine* ret_polygons = polygons;
+ sampledLine* newSampledLines = NULL;
+ Int i,k;
+
+ num_diagonals=deleteRepeatDiagonals(num_diagonals, diagonal_vertices, diagonal_vertices);
+
+
+
+//drawDiagonals(num_diagonals, diagonal_vertices);
+//printf("diagoanls are \n");
+//for(i=0; i<num_diagonals; i++)
+// {
+// printf("(%f,%f)\n", diagonal_vertices[2*i]->head()[0], diagonal_vertices[2*i]->head()[1]);
+// printf("**(%f,%f)\n", diagonal_vertices[2*i+1]->head()[0], diagonal_vertices[2*i+1]->head()[1]);
+// }
+
+ Int *removedDiagonals=(Int*)malloc(sizeof(Int) * num_diagonals);
+ for(i=0; i<num_diagonals; i++)
+ removedDiagonals[i] = 0;
+// printf("first pass\n");
+
+
+ for(i=0,k=0; i<num_diagonals; i++,k+=2)
+ {
+
+
+ directedLine* v1=diagonal_vertices[k];
+ directedLine* v2=diagonal_vertices[k+1];
+ directedLine* ret_p1;
+ directedLine* ret_p2;
+
+ /*we ahve to determine whether v1 and v2 belong to the same polygon before
+ *their structure are modified by connectDiagonal().
+ */
+/*
+ directedLine *root1 = v1->findRoot();
+ directedLine *root2 = v2->findRoot();
+ assert(root1);
+ assert(root2);
+*/
+
+directedLine* root1 = v1->rootLinkFindRoot();
+directedLine* root2 = v2->rootLinkFindRoot();
+
+ if(root1 != root2)
+ {
+
+ removedDiagonals[i] = 1;
+ sampledLine* generatedLine;
+
+
+
+ v1->connectDiagonal(v1,v2, &ret_p1, &ret_p2, &generatedLine, ret_polygons);
+
+
+
+ newSampledLines = generatedLine->insert(newSampledLines);
+/*
+ ret_polygons = ret_polygons->cutoffPolygon(root1);
+
+ ret_polygons = ret_polygons->cutoffPolygon(root2);
+ ret_polygons = ret_p1->insertPolygon(ret_polygons);
+root1->rootLinkSet(ret_p1);
+root2->rootLinkSet(ret_p1);
+ret_p1->rootLinkSet(NULL);
+ret_p2->rootLinkSet(ret_p1);
+*/
+ ret_polygons = ret_polygons->cutoffPolygon(root2);
+
+
+
+root2->rootLinkSet(root1);
+ret_p1->rootLinkSet(root1);
+ret_p2->rootLinkSet(root1);
+
+ /*now that we have connected the diagonal v1 and v2,
+ *we have to check those unprocessed diagonals which
+ *have v1 or v2 as an end point. Notice that the head of v1
+ *has the same coodinates as the head of v2->prev, and the head of
+ *v2 has the same coordinate as the head of v1->prev.
+ *Suppose these is a diagonal (v1, x). If (v1,x) is still a valid
+ *diagonal, then x should be on the left hand side of the directed line: *v1->prev->head -- v1->head -- v1->tail. Otherwise, (v1,x) should be
+ *replaced by (v2->prev, x), that is, x is on the left of
+ * v2->prev->prev->head, v2->prev->head, v2->prev->tail.
+ */
+ Int ii, kk;
+ for(ii=0, kk=0; ii<num_diagonals; ii++, kk+=2)
+ if( removedDiagonals[ii]==0)
+ {
+ directedLine* d1=diagonal_vertices[kk];
+ directedLine* d2=diagonal_vertices[kk+1];
+ /*check d1, and replace diagonal_vertices[kk] if necessary*/
+ if(d1 == v1) {
+ /*check if d2 is to left of v1->prev->head:v1->head:v1->tail*/
+ if(! pointLeft2Lines(v1->getPrev()->head(),
+ v1->head(), v1->tail(), d2->head()))
+ {
+/*
+ assert(pointLeft2Lines(v2->getPrev()->getPrev()->head(),
+ v2->getPrev()->head(),
+ v2->getPrev()->tail(), d2->head()));
+*/
+ diagonal_vertices[kk] = v2->getPrev();
+ }
+ }
+ if(d1 == v2) {
+ /*check if d2 is to left of v2->prev->head:v2->head:v2->tail*/
+ if(! pointLeft2Lines(v2->getPrev()->head(),
+ v2->head(), v2->tail(), d2->head()))
+ {
+/*
+ assert(pointLeft2Lines(v1->getPrev()->getPrev()->head(),
+ v1->getPrev()->head(),
+ v1->getPrev()->tail(), d2->head()));
+*/
+ diagonal_vertices[kk] = v1->getPrev();
+ }
+ }
+ /*check d2 and replace diagonal_vertices[k+1] if necessary*/
+ if(d2 == v1) {
+ /*check if d1 is to left of v1->prev->head:v1->head:v1->tail*/
+ if(! pointLeft2Lines(v1->getPrev()->head(),
+ v1->head(), v1->tail(), d1->head()))
+ {
+/* assert(pointLeft2Lines(v2->getPrev()->getPrev()->head(),
+ v2->getPrev()->head(),
+ v2->getPrev()->tail(), d1->head()));
+*/
+ diagonal_vertices[kk+1] = v2->getPrev();
+ }
+ }
+ if(d2 == v2) {
+ /*check if d1 is to left of v2->prev->head:v2->head:v2->tail*/
+ if(! pointLeft2Lines(v2->getPrev()->head(),
+ v2->head(), v2->tail(), d1->head()))
+ {
+/* assert(pointLeft2Lines(v1->getPrev()->getPrev()->head(),
+ v1->getPrev()->head(),
+ v1->getPrev()->tail(), d1->head()));
+*/
+ diagonal_vertices[kk+1] = v1->getPrev();
+ }
+ }
+ }
+}/*end if (root1 not equal to root 2)*/
+}
+
+ /*second pass, now all diagoals should belong to the same polygon*/
+//printf("second pass: \n");
+
+// for(i=0; i<num_diagonals; i++)
+// printf("%i ", removedDiagonals[i]);
+
+
+ for(i=0,k=0; i<num_diagonals; i++, k += 2)
+ if(removedDiagonals[i] == 0)
+ {
+
+
+ directedLine* v1=diagonal_vertices[k];
+ directedLine* v2=diagonal_vertices[k+1];
+
+
+
+ directedLine* ret_p1;
+ directedLine* ret_p2;
+
+ /*we ahve to determine whether v1 and v2 belong to the same polygon before
+ *their structure are modified by connectDiagonal().
+ */
+ directedLine *root1 = v1->findRoot();
+/*
+ directedLine *root2 = v2->findRoot();
+
+
+
+ assert(root1);
+ assert(root2);
+ assert(root1 == root2);
+ */
+ sampledLine* generatedLine;
+
+
+
+ v1->connectDiagonal(v1,v2, &ret_p1, &ret_p2, &generatedLine, ret_polygons);
+ newSampledLines = generatedLine->insert(newSampledLines);
+
+ ret_polygons = ret_polygons->cutoffPolygon(root1);
+
+ ret_polygons = ret_p1->insertPolygon(ret_polygons);
+
+ ret_polygons = ret_p2->insertPolygon(ret_polygons);
+
+
+
+ for(Int j=i+1; j<num_diagonals; j++)
+ {
+ if(removedDiagonals[j] ==0)
+ {
+
+ directedLine* temp1=diagonal_vertices[2*j];
+ directedLine* temp2=diagonal_vertices[2*j+1];
+ if(temp1==v1 || temp1==v2 || temp2==v1 || temp2==v2)
+ if(! temp1->samePolygon(temp1, temp2))
+ {
+ /*if temp1 and temp2 are in different polygons,
+ *then one of them must be v1 or v2.
+ */
+
+
+
+ assert(temp1==v1 || temp1 == v2 || temp2==v1 || temp2 ==v2);
+ if(temp1==v1)
+ {
+ diagonal_vertices[2*j] = v2->getPrev();
+ }
+ if(temp2==v1)
+ {
+ diagonal_vertices[2*j+1] = v2->getPrev();
+ }
+ if(temp1==v2)
+ {
+ diagonal_vertices[2*j] = v1->getPrev();
+ }
+ if(temp2==v2)
+ {
+ diagonal_vertices[2*j+1] = v1->getPrev();
+ }
+ }
+ }
+ }
+
+ }
+
+
+ //clean up
+ loopList->deleteLoopList();
+ free(array);
+ free(ranges);
+ free(diagonal_vertices);
+ free(removedDiagonals);
+
+ *retSampledLines = newSampledLines;
+ return ret_polygons;
+}
+
+
diff --git a/src/glu/sgi/libnurbs/nurbtess/monoChain.h b/src/glu/sgi/libnurbs/nurbtess/monoChain.h
new file mode 100644
index 00000000000..4cff62f9ae3
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/monoChain.h
@@ -0,0 +1,110 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/monoChain.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#ifndef _MONO_CHAIN_H
+#define _MONO_CHAIN_H
+
+#include "directedLine.h"
+#include "partitionY.h"
+
+class monoChain;
+
+class monoChain{
+ directedLine* chainHead;
+ directedLine* chainTail;
+ monoChain* next;
+ monoChain* prev;
+ monoChain* nextPolygon; //a list of polygons
+
+ //cached informatin
+ //bounding box
+ Real minX, maxX, minY, maxY;
+ Int isIncrease;
+
+ //for efficiently comparing two chains
+
+ directedLine* current;
+
+public:
+ monoChain(directedLine* cHead, directedLine* cTail);
+ ~monoChain() {}
+
+ inline void setNext(monoChain* n) {next = n;}
+ inline void setPrev(monoChain* p) {prev = p;}
+ inline void setNextPolygon(monoChain* np) {nextPolygon = np;}
+ inline monoChain* getNext() {return next;}
+ inline monoChain* getPrev() {return prev;}
+ inline directedLine* getHead() {return chainHead;}
+ inline directedLine* getTail() {return chainTail;}
+
+ inline void resetCurrent() { current = ((isIncrease==1)? chainHead:chainTail);}
+
+ void deleteLoop();
+ void deleteLoopList();
+
+ //insert a new chain between prev and this
+ void insert(monoChain* nc);
+
+ Int numChainsSingleLoop();
+ Int numChainsAllLoops();
+ monoChain** toArrayAllLoops(Int& num_chains);
+ Int toArraySingleLoop(monoChain** array, Int index);
+
+ Int isKey;
+ Real keyY; //the current horizotal line
+ Real chainIntersectHoriz(Real y); //updates current incrementally for efficiency
+ directedLine* find(Real y);//find dline so that y intersects dline.
+
+ void printOneChain();
+ void printChainLoop();
+ void printAllLoops();
+
+};
+
+monoChain* directedLineLoopToMonoChainLoop(directedLine* loop);
+monoChain* directedLineLoopListToMonoChainLoopList(directedLine* list);
+Int MC_sweepY(Int nVertices, monoChain** sortedVertices, sweepRange** ret_ranges);
+
+void MC_findDiagonals(Int total_num_edges, monoChain** sortedVertices,
+ sweepRange** ranges, Int& num_diagonals,
+ directedLine** diagonal_vertices);
+
+directedLine* MC_partitionY(directedLine *polygons, sampledLine **retSampledLines);
+
+#endif
diff --git a/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.cc b/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.cc
new file mode 100644
index 00000000000..6405d277fe9
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.cc
@@ -0,0 +1,300 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+ *monoPolyPart.C
+ *
+ *To partition a v-monotone polygon into some uv-monotone polygons.
+ *The algorithm is different from the general monotone partition algorithm.
+ *while the general monotone partition algorithm works for this special case,
+ *but it is more expensive (O(nlogn)). The algorithm implemented here takes
+ *advantage of the fact that the input is a v-monotone polygon and it is
+ *conceptually simpler and computationally cheaper (a linear time algorithm).
+ *The algorithm is described in Zicheng Liu's paper
+ * "Quality-Oriented Linear Time Tessellation".
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "directedLine.h"
+#include "monoPolyPart.h"
+
+/*a vertex is u_maximal if both of its two neightbors are to the left of this
+ *vertex
+ */
+static Int is_u_maximal(directedLine* v)
+{
+ if (compV2InX(v->getPrev()->head(), v->head()) == -1 &&
+ compV2InX(v->getNext()->head(), v->head()) == -1)
+ return 1;
+ else
+ return 0;
+}
+
+/*a vertex is u_minimal if both of its two neightbors are to the right of this
+ *vertex
+ */
+static Int is_u_minimal(directedLine* v)
+{
+ if (compV2InX(v->getPrev()->head(), v->head()) == 1 &&
+ compV2InX(v->getNext()->head(), v->head()) == 1)
+ return 1;
+ else
+ return 0;
+}
+
+/*poly: a v-monotone polygon
+ *return: a linked list of uv-monotone polygons.
+ */
+directedLine* monoPolyPart(directedLine* polygon)
+{
+ //handle special cases:
+ if(polygon == NULL)
+ return NULL;
+ if(polygon->getPrev() == polygon)
+ return polygon;
+ if(polygon->getPrev() == polygon->getNext())
+ return polygon;
+ if(polygon->getPrev()->getPrev() == polygon->getNext())
+ return polygon;
+
+ //find the top and bottom vertexes
+ directedLine *tempV, *topV, *botV;
+ topV = botV = polygon;
+ for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext())
+ {
+ if(compV2InY(topV->head(), tempV->head())<0) {
+ topV = tempV;
+ }
+ if(compV2InY(botV->head(), tempV->head())>0) {
+ botV = tempV;
+ }
+ }
+
+ //initilization
+ directedLine *A, *B, *C, *D, *G, *H;
+ //find A:the first u_maximal vertex on the left chain
+ //and C: the left most vertex between top and A
+ A = NULL;
+ C = topV;
+ for(tempV=topV->getNext(); tempV != botV; tempV = tempV->getNext())
+ {
+ if(tempV->head()[0] < C->head()[0])
+ C = tempV;
+
+ if(is_u_maximal(tempV))
+ {
+ A = tempV;
+ break;
+ }
+ }
+ if(A == NULL)
+ {
+ A = botV;
+ if(A->head()[0] < C->head()[0])
+ C = A;
+ }
+
+ //find B: the first u_minimal vertex on the right chain
+ //and D: the right most vertex between top and B
+ B = NULL;
+ D = topV;
+ for(tempV=topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
+ {
+ if(tempV->head()[0] > D->head()[0])
+ D = tempV;
+ if(is_u_minimal(tempV))
+ {
+ B = tempV;
+ break;
+ }
+ }
+ if(B == NULL)
+ {
+ B = botV;
+ if(B->head()[0] > D->head()[0])
+ D = B;
+ }
+
+ //error checking XXX
+ if(C->head()[0] >= D->head()[0])
+ return polygon;
+
+ //find G on the left chain that is right above B
+ for(tempV=topV; compV2InY(tempV->head(), B->head()) == 1; tempV=tempV->getNext());
+ G = tempV->getPrev();
+ //find H on the right chain that is right above A
+ for(tempV=topV; compV2InY(tempV->head(), A->head()) == 1; tempV = tempV->getPrev());
+ H = tempV->getNext();
+
+ //Main Loop
+ directedLine* ret = NULL;
+ directedLine* currentPolygon = polygon;
+ while(1)
+ {
+ //if both B and D are equal to botV, then this polygon is already
+ //u-monotone
+ if(A == botV && B == botV)
+ {
+ ret = currentPolygon->insertPolygon(ret);
+ return ret;
+ }
+ else //not u-monotone
+ {
+ directedLine *ret_p1, *ret_p2;
+ if(compV2InY(A->head(),B->head()) == 1) //A is above B
+ {
+ directedLine* E = NULL;
+ for(tempV = C; tempV != D; tempV = tempV->getPrev())
+ {
+ if(tempV->head()[0] >= A->head()[0])
+ {
+ E = tempV;
+ break;
+ }
+ }
+
+ if(E == NULL)
+ E = D;
+ if(E->head()[0]> H->head()[0])
+ E = H;
+ //connect AE and output polygon ECA
+ polygon->connectDiagonal_2slines(A, E,
+ &ret_p1,
+ &ret_p2,
+ NULL);
+ ret = ret_p2->insertPolygon(ret);
+ currentPolygon = ret_p1;
+
+ if(E == D)
+ D = ret_p1;
+ if(E == H)
+ H = ret_p1;
+ if(G->head()[1] >= A->head()[1])
+ G = A;
+ //update A to be the next u-maxiaml vertex on left chain
+ //and C the leftmost vertex between the old A and the new A
+ C = A;
+ for(tempV = A->getNext(); tempV != botV; tempV = tempV->getNext())
+ {
+
+ if(tempV->head()[0] < C->head()[0])
+ C = tempV;
+ if(is_u_maximal(tempV))
+ {
+ A = tempV;
+ break;
+ }
+ }
+
+ if(tempV == botV)
+ {
+ A = botV;
+ if(botV->head()[0] < C->head()[0])
+ C = botV;
+ }
+ //update H
+
+ if(A == botV)
+ H = botV;
+ else
+ {
+ for(tempV = H; compV2InY(tempV->head(), A->head()) == 1; tempV = tempV->getPrev());
+ H = tempV->getNext();
+ }
+
+ }
+ else //A is below B
+ {
+
+ directedLine* F = NULL;
+ for(tempV = D; tempV != C; tempV = tempV->getNext())
+ {
+ if(tempV->head()[0] <= B->head()[0])
+ {
+ F = tempV;
+ break;
+ }
+ }
+ if(F == NULL)
+ F = C;
+ if(F->head()[0] < G->head()[0])
+ F = G;
+
+ //connect FB
+ polygon->connectDiagonal_2slines(F, B,
+ &ret_p1,
+ &ret_p2,
+ NULL);
+ ret = ret_p2->insertPolygon(ret);
+ currentPolygon = ret_p1;
+ B = ret_p1;
+ if(H ->head()[1] >= B->head()[1])
+ H = ret_p1;
+
+ //update B to be the next u-minimal vertex on right chain
+ //and D the rightmost vertex between the old B and the new B
+ D = B;
+ for(tempV = B->getPrev(); tempV != botV; tempV = tempV->getPrev())
+ {
+ if(tempV->head()[0] > D->head()[0])
+ D = tempV;
+ if(is_u_minimal(tempV))
+ {
+ B = tempV;
+ break;
+ }
+ }
+ if(tempV == botV)
+ {
+ B = botV;
+ if(botV->head()[0] > D->head()[0])
+ D = botV;
+ }
+ //update G
+ if(B == botV)
+ G = botV;
+ else
+ {
+ for(tempV = G; compV2InY(tempV->head(), B->head()) == 1; tempV = tempV->getNext());
+ G = tempV->getPrev();
+ }
+ } //end of A is below B
+ } //end not u-monotone
+ } //end of main loop
+}
+
+
+
diff --git a/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.h b/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.h
new file mode 100644
index 00000000000..b760862dcb7
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.h
@@ -0,0 +1,47 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+ *monoPolyPart.h
+ */
+
+#ifndef _MONO_POLY_PART_H
+#define _MONO_POLY_PART_H
+
+class directedLine;
+
+directedLine* monoPolyPart(directedLine* polygon);
+
+#endif
diff --git a/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.cc b/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.cc
new file mode 100644
index 00000000000..66b34a4b374
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.cc
@@ -0,0 +1,1482 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2005/10/28 13:09:09 $ $Revision: 1.3.8.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.cc,v 1.3.8.1 2005/10/28 13:09:09 brianp Exp $
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "gluos.h"
+#include "glimports.h"
+#include "zlassert.h"
+
+#include "monoTriangulation.h"
+#include "polyUtil.h" /*for area*/
+#include "partitionX.h"
+#include "monoPolyPart.h"
+
+
+
+extern directedLine* polygonConvert(directedLine* polygon);
+
+/*poly is NOT deleted
+ */
+void monoTriangulationOpt(directedLine* poly, primStream* pStream)
+{
+ Int n_cusps;
+ Int n_edges = poly->numEdges();
+ directedLine** cusps = (directedLine**) malloc(sizeof(directedLine*)*n_edges);
+ assert(cusps);
+ findInteriorCuspsX(poly, n_cusps, cusps);
+ if(n_cusps ==0) //u monotine
+ {
+ monoTriangulationFun(poly, compV2InX, pStream);
+ }
+ else if(n_cusps == 1) // one interior cusp
+ {
+ directedLine* new_polygon = polygonConvert(cusps[0]);
+ directedLine* other = findDiagonal_singleCuspX(new_polygon);
+ //<other> should NOT be null unless there are self-intersecting
+ //trim curves. In that case, we don't want to core dump, instead,
+ //we triangulate anyway, and print out error message.
+ if(other == NULL)
+ {
+ monoTriangulationFun(poly, compV2InX, pStream);
+ }
+ else
+ {
+ directedLine* ret_p1;
+ directedLine* ret_p2;
+
+ new_polygon->connectDiagonal_2slines(new_polygon, other,
+ &ret_p1,
+ &ret_p2,
+ new_polygon);
+
+ monoTriangulationFun(ret_p1, compV2InX, pStream);
+ monoTriangulationFun(ret_p2, compV2InX, pStream);
+
+ ret_p1->deleteSinglePolygonWithSline();
+ ret_p2->deleteSinglePolygonWithSline();
+ }
+ }
+ else
+ {
+ //we need a general partitionX funtion (supposed to be in partitionX.C,
+ //not implemented yet. XXX
+ monoTriangulationFun(poly, compV2InY, pStream);
+ }
+
+ free(cusps);
+}
+
+void monoTriangulationRecOpt(Real* topVertex, Real* botVertex,
+ vertexArray* left_chain, Int left_current,
+ vertexArray* right_chain, Int right_current,
+ primStream* pStream)
+{
+ Int i,j;
+ Int n_left = left_chain->getNumElements();
+ Int n_right = right_chain->getNumElements();
+ if(left_current>= n_left-1 ||
+ right_current>= n_right-1)
+ {
+ monoTriangulationRec(topVertex, botVertex, left_chain, left_current,
+ right_chain, right_current, pStream);
+ return;
+ }
+ //now both left and right have at least two vertices each.
+ Real left_v = left_chain->getVertex(left_current)[1];
+ Real right_v = right_chain->getVertex(right_current)[1];
+
+ if(left_v <= right_v) //first left vertex is below right
+ {
+ //find the last vertex of right which is above or equal to left
+ for(j=right_current; j<=n_right-1; j++)
+ {
+ if(right_chain->getVertex(j)[1] < left_v)
+ break;
+ }
+ monoTriangulationRecGen(topVertex, left_chain->getVertex(left_current),
+ left_chain, left_current, left_current,
+ right_chain, right_current, j-1,
+ pStream);
+ monoTriangulationRecOpt(right_chain->getVertex(j-1),
+ botVertex,
+ left_chain, left_current,
+ right_chain, j,
+ pStream);
+ }
+ else //first right vertex is strictly below left
+ {
+ //find the last vertex of left which is strictly above right
+ for(i=left_current; i<=n_left-1; i++)
+ {
+ if(left_chain->getVertex(i)[1] <= right_v)
+ break;
+ }
+ monoTriangulationRecGen(topVertex, right_chain->getVertex(right_current),
+ left_chain, left_current, i-1,
+ right_chain, right_current, right_current,
+ pStream);
+ monoTriangulationRecOpt(left_chain->getVertex(i-1),
+ botVertex,
+ left_chain, i,
+ right_chain, right_current,
+ pStream);
+ }
+}
+
+
+void monoTriangulationRecGenTBOpt(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream)
+{
+ pStream->triangle(topVertex, inc_chain->getVertex(inc_current), dec_chain->getVertex(dec_current));
+
+/*printf("**(%f,%f)\n", inc_chain->getArray()[0][0],inc_chain->getArray()[0][1]);*/
+ triangulateXYMonoTB(inc_end-inc_current+1, inc_chain->getArray()+inc_current, dec_end-dec_current+1, dec_chain->getArray()+dec_current, pStream);
+
+ pStream->triangle(botVertex, dec_chain->getVertex(dec_end), inc_chain->getVertex(inc_end));
+}
+
+
+/*n_left>=1
+ *n_right>=1
+ *the strip is going top to bottom. compared to the funtion
+ * triangulateXYmono()
+ */
+void triangulateXYMonoTB(Int n_left, Real** leftVerts,
+ Int n_right, Real** rightVerts,
+ primStream* pStream)
+{
+
+
+ Int i,j,k,l;
+ Real* topMostV;
+
+ assert(n_left>=1 && n_right>=1);
+ if(leftVerts[0][1] >= rightVerts[0][1])
+ {
+ i=1;
+ j=0;
+ topMostV = leftVerts[0];
+ }
+ else
+ {
+ i=0;
+ j=1;
+ topMostV = rightVerts[0];
+ }
+
+ while(1)
+ {
+ if(i >= n_left) /*case1: no more in left*/
+ {
+
+ if(j<n_right-1) /*at least two vertices in right*/
+ {
+ pStream->begin();
+ pStream->insert(topMostV);
+ for(k=n_right-1; k>=j; k--)
+ pStream->insert(rightVerts[j]);
+
+ pStream->end(PRIMITIVE_STREAM_FAN);
+
+ }
+
+ break;
+ }
+ else if(j>= n_right) /*case2: no more in right*/
+ {
+
+ if(i<n_left-1) /*at least two vertices in left*/
+ {
+ pStream->begin();
+ pStream->insert(topMostV);
+
+ for(k=i; k<n_left; k++)
+ pStream->insert(leftVerts[k]);
+
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+
+ break;
+ }
+ else /* case3: neither is empty, plus the topMostV, there is at least one triangle to output*/
+ {
+
+ if(leftVerts[i][1] >= rightVerts[j][1])
+ {
+ pStream->begin();
+ pStream->insert(rightVerts[j]); /*the origin of this fan*/
+
+ pStream->insert(topMostV);
+
+ /*find the last k>=i such that
+ *leftverts[k][1] >= rightverts[j][1]
+ */
+ k=i;
+ while(k<n_left)
+ {
+ if(leftVerts[k][1] < rightVerts[j][1])
+ break;
+ k++;
+ }
+ k--;
+ for(l=i; l<=k; l++)
+ {
+ pStream->insert(leftVerts[l]);
+ }
+
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ //update i for next loop
+ i = k+1;
+ topMostV = leftVerts[k];
+
+ }
+ else /*leftVerts[i][1] < rightVerts[j][1]*/
+ {
+ pStream->begin();
+ pStream->insert(leftVerts[i]);/*the origion of this fan*/
+
+ /*find the last k>=j such that
+ *rightverts[k][1] > leftverts[i][1]*/
+ k=j;
+ while(k< n_right)
+ {
+ if(rightVerts[k][1] <= leftVerts[i][1])
+ break;
+ k++;
+ }
+ k--;
+
+ for(l=k; l>= j; l--)
+ pStream->insert(rightVerts[l]);
+
+ pStream->insert(topMostV);
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ j=k+1;
+ topMostV = rightVerts[j-1];
+ }
+ }
+ }
+}
+
+static int chainConvex(vertexArray* inc_chain, Int inc_current, Int inc_end)
+{
+ Int i;
+ //if there are no more than 2 vertices, return 1
+ if(inc_current >= inc_end-1) return 1;
+ for(i=inc_current; i<= inc_end-2; i++)
+ {
+ if(area(inc_chain->getVertex(i), inc_chain->getVertex(i+1), inc_chain->getVertex(i+2)) <0)
+ return 0;
+ }
+ return 1;
+}
+
+static int chainConcave(vertexArray* dec_chain, Int dec_current, Int dec_end)
+{
+ Int i;
+ //if there are no more than 2 vertices, return 1
+ if(dec_current >= dec_end -1) return 1;
+ for(i=dec_current; i<=dec_end-2; i++)
+ {
+ if(area(dec_chain->getVertex(i), dec_chain->getVertex(i+1), dec_chain->getVertex(i+2)) >0)
+ return 0;
+ }
+ return 1;
+}
+
+void monoTriangulationRecGenInU(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream)
+{
+
+}
+
+void monoTriangulationRecGenOpt(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream)
+{
+ Int i;
+ //copy this to a polygon: directedLine Lioop
+ sampledLine* sline;
+ directedLine* dline;
+ directedLine* poly;
+
+ if(inc_current <= inc_end) //at least one vertex in inc_chain
+ {
+ sline = new sampledLine(topVertex, inc_chain->getVertex(inc_current));
+ poly = new directedLine(INCREASING, sline);
+ for(i=inc_current; i<=inc_end-1; i++)
+ {
+ sline = new sampledLine(inc_chain->getVertex(i), inc_chain->getVertex(i+1));
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+ sline = new sampledLine(inc_chain->getVertex(inc_end), botVertex);
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+ else //inc_chian is empty
+ {
+ sline = new sampledLine(topVertex, botVertex);
+ dline = new directedLine(INCREASING, sline);
+ poly = dline;
+ }
+
+ assert(poly != NULL);
+
+ if(dec_current <= dec_end) //at least on vertex in dec_Chain
+ {
+ sline = new sampledLine(botVertex, dec_chain->getVertex(dec_end));
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ for(i=dec_end; i>dec_current; i--)
+ {
+ sline = new sampledLine(dec_chain->getVertex(i), dec_chain->getVertex(i-1));
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+ sline = new sampledLine(dec_chain->getVertex(dec_current), topVertex);
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+ else //dec_chain is empty
+ {
+ sline = new sampledLine(botVertex, topVertex);
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+
+ {
+ Int n_cusps;
+ Int n_edges = poly->numEdges();
+ directedLine** cusps = (directedLine**) malloc(sizeof(directedLine*)*n_edges);
+ assert(cusps);
+ findInteriorCuspsX(poly, n_cusps, cusps);
+
+ if(n_cusps ==0) //u monotine
+ {
+ monoTriangulationFun(poly, compV2InX, pStream);
+ }
+ else if(n_cusps == 1) // one interior cusp
+ {
+ directedLine* new_polygon = polygonConvert(cusps[0]);
+ directedLine* other = findDiagonal_singleCuspX(new_polygon);
+ //<other> should NOT be null unless there are self-intersecting
+ //trim curves. In that case, we don't want to core dump, instead,
+ //we triangulate anyway, and print out error message.
+ if(other == NULL)
+ {
+ monoTriangulationFun(poly, compV2InX, pStream);
+ }
+ else
+ {
+ directedLine* ret_p1;
+ directedLine* ret_p2;
+
+ new_polygon->connectDiagonal_2slines(new_polygon, other,
+ &ret_p1,
+ &ret_p2,
+ new_polygon);
+
+ monoTriangulationFun(ret_p1, compV2InX, pStream);
+ monoTriangulationFun(ret_p2, compV2InX, pStream);
+
+ ret_p1->deleteSinglePolygonWithSline();
+ ret_p2->deleteSinglePolygonWithSline();
+ }
+ }
+ else
+ {
+ //we need a general partitionX funtion (supposed to be in partitionX.C,
+ //not implemented yet. XXX
+ //monoTriangulationFun(poly, compV2InY, pStream);
+
+ directedLine* new_polygon = polygonConvert(poly);
+ directedLine* list = monoPolyPart(new_polygon);
+ for(directedLine* temp = list; temp != NULL; temp = temp->getNextPolygon())
+ {
+ monoTriangulationFun(temp, compV2InX, pStream);
+ }
+ //clean up
+ list->deletePolygonListWithSline();
+
+ }
+
+ free(cusps);
+ /*
+ if(numInteriorCuspsX(poly) == 0) //is u monotone
+ monoTriangulationFun(poly, compV2InX, pStream);
+ else //it is not u motone
+ monoTriangulationFun(poly, compV2InY, pStream);
+ */
+ //clean up space
+ poly->deleteSinglePolygonWithSline();
+ return;
+ }
+
+ //apparently the following code is not reachable,
+ //it is for test purpose
+ if(inc_current > inc_end || dec_current>dec_end)
+ {
+ monoTriangulationRecGen(topVertex, botVertex, inc_chain, inc_current, inc_end,
+ dec_chain, dec_current, dec_end,
+ pStream);
+ return;
+ }
+
+
+ if(
+ area(dec_chain->getVertex(dec_current),
+ topVertex,
+ inc_chain->getVertex(inc_current)) >=0
+ && chainConvex(inc_chain, inc_current, inc_end)
+ && chainConcave(dec_chain, dec_current, dec_end)
+ && area(inc_chain->getVertex(inc_end), botVertex, dec_chain->getVertex(dec_end)) >=0
+ )
+ {
+ monoTriangulationRecFunGen(topVertex, botVertex,
+ inc_chain, inc_current, inc_end,
+ dec_chain, dec_current, dec_end,
+ compV2InX, pStream);
+ }
+ else
+ {
+ monoTriangulationRecGen(topVertex, botVertex, inc_chain, inc_current, inc_end,
+ dec_chain, dec_current, dec_end,
+ pStream);
+ }
+}
+
+/*if inc_current>inc_end, then inc_chain has no points to be considered
+ *same for dec_chain
+ */
+void monoTriangulationRecGen(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream)
+{
+ Real** inc_array ;
+ Real** dec_array ;
+ Int i;
+
+ if(inc_current > inc_end && dec_current>dec_end)
+ return;
+ else if(inc_current>inc_end) /*no more vertices on inc_chain*/
+ {
+ dec_array = dec_chain->getArray();
+ reflexChain rChain(100,0);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the dec_chain*/
+ for(i=dec_current; i<=dec_end; i++){
+ rChain.processNewVertex(dec_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+ }
+ else if(dec_current> dec_end) /*no more vertices on dec_chain*/
+ {
+ inc_array = inc_chain->getArray();
+
+ reflexChain rChain(100,1);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the inc_chain*/
+ for(i=inc_current; i<=inc_end; i++){
+ rChain.processNewVertex(inc_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+ }
+ else /*neither chain is empty*/
+ {
+ inc_array = inc_chain -> getArray();
+ dec_array = dec_chain -> getArray();
+
+ /*if top of inc_chain is 'lower' than top of dec_chain, process all the
+ *vertices on the dec_chain which are higher than top of inc_chain
+ */
+ if(compV2InY(inc_array[inc_current], dec_array[dec_current]) <= 0)
+ {
+
+ reflexChain rChain(100, 0);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=dec_current; i<=dec_end; i++)
+ {
+ if(compV2InY(inc_array[inc_current], dec_array[i]) <= 0)
+ rChain.processNewVertex(dec_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(inc_array[inc_current], pStream);
+ monoTriangulationRecGen(dec_array[i-1], botVertex,
+ inc_chain, inc_current, inc_end,
+ dec_chain, i, dec_end,
+ pStream);
+ }
+ else /*compV2InY(inc_array[inc_current], dec_array[dec_current]) > 0*/
+ {
+
+ reflexChain rChain(100, 1);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=inc_current; i<=inc_end; i++)
+ {
+ if(compV2InY(inc_array[i], dec_array[dec_current]) >0)
+ rChain.processNewVertex(inc_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(dec_array[dec_current], pStream);
+ monoTriangulationRecGen(inc_array[i-1], botVertex,
+ inc_chain, i, inc_end,
+ dec_chain, dec_current,dec_end,
+ pStream);
+ }
+ }/*end case neither is empty*/
+}
+
+void monoTriangulationFun(directedLine* monoPolygon, Int (*compFun)(Real*, Real*), primStream* pStream)
+{
+ Int i;
+ /*find the top vertex, bottom vertex, inccreasing chain, and decreasing chain,
+ *then call monoTriangulationRec
+ */
+ directedLine* tempV;
+ directedLine* topV;
+ directedLine* botV;
+ topV = botV = monoPolygon;
+ for(tempV = monoPolygon->getNext(); tempV != monoPolygon; tempV = tempV->getNext())
+ {
+ if(compFun(topV->head(), tempV->head())<0) {
+ topV = tempV;
+ }
+ if(compFun(botV->head(), tempV->head())>0) {
+ botV = tempV;
+ }
+ }
+
+ /*creat increase and decrease chains*/
+ vertexArray inc_chain(20); /*this is a dynamic array*/
+ for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
+ inc_chain.appendVertex(topV->getVertex(i));
+ }
+ for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext())
+ {
+ for(i=0; i<=tempV->get_npoints()-2; i++){
+ inc_chain.appendVertex(tempV->getVertex(i));
+ }
+ }
+
+ vertexArray dec_chain(20);
+ for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
+ {
+ for(i=tempV->get_npoints()-2; i>=0; i--){
+ dec_chain.appendVertex(tempV->getVertex(i));
+ }
+ }
+ for(i=botV->get_npoints()-2; i>=1; i--){
+ dec_chain.appendVertex(tempV->getVertex(i));
+ }
+
+ monoTriangulationRecFun(topV->head(), botV->head(), &inc_chain, 0, &dec_chain, 0, compFun, pStream);
+
+}
+
+void monoTriangulation(directedLine* monoPolygon, primStream* pStream)
+{
+ Int i;
+ /*find the top vertex, bottom vertex, inccreasing chain, and decreasing chain,
+ *then call monoTriangulationRec
+ */
+ directedLine* tempV;
+ directedLine* topV;
+ directedLine* botV;
+ topV = botV = monoPolygon;
+ for(tempV = monoPolygon->getNext(); tempV != monoPolygon; tempV = tempV->getNext())
+ {
+ if(compV2InY(topV->head(), tempV->head())<0) {
+ topV = tempV;
+ }
+ if(compV2InY(botV->head(), tempV->head())>0) {
+ botV = tempV;
+ }
+ }
+ /*creat increase and decrease chains*/
+ vertexArray inc_chain(20); /*this is a dynamic array*/
+ for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
+ inc_chain.appendVertex(topV->getVertex(i));
+ }
+ for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext())
+ {
+ for(i=0; i<=tempV->get_npoints()-2; i++){
+ inc_chain.appendVertex(tempV->getVertex(i));
+ }
+ }
+
+ vertexArray dec_chain(20);
+ for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
+ {
+ for(i=tempV->get_npoints()-2; i>=0; i--){
+ dec_chain.appendVertex(tempV->getVertex(i));
+ }
+ }
+ for(i=botV->get_npoints()-2; i>=1; i--){
+ dec_chain.appendVertex(tempV->getVertex(i));
+ }
+
+ monoTriangulationRec(topV->head(), botV->head(), &inc_chain, 0, &dec_chain, 0, pStream);
+
+}
+
+/*the chain could be increasing or decreasing, although we use the
+ * name inc_chain.
+ *the argument is_increase_chain indicates whether this chain
+ *is increasing (left chain in V-monotone case) or decreaing (right chain
+ *in V-monotone case).
+ */
+void monoTriangulation2(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_smallIndex,
+ Int inc_largeIndex,
+ Int is_increase_chain,
+ primStream* pStream)
+{
+ assert( inc_chain != NULL);
+ Real** inc_array ;
+
+ if(inc_smallIndex > inc_largeIndex)
+ return; //no triangles
+ if(inc_smallIndex == inc_largeIndex)
+ {
+ if(is_increase_chain)
+ pStream->triangle(inc_chain->getVertex(inc_smallIndex), botVertex, topVertex);
+ else
+ pStream->triangle(inc_chain->getVertex(inc_smallIndex), topVertex, botVertex);
+ return;
+ }
+ Int i;
+
+ if(is_increase_chain && botVertex[1] == inc_chain->getVertex(inc_largeIndex)[1])
+ {
+ pStream->triangle(botVertex, inc_chain->getVertex(inc_largeIndex-1),
+ inc_chain->getVertex(inc_largeIndex));
+ monoTriangulation2(topVertex, botVertex, inc_chain, inc_smallIndex,
+ inc_largeIndex-1,
+ is_increase_chain,
+ pStream);
+ return;
+ }
+ else if( (!is_increase_chain) && topVertex[1] == inc_chain->getVertex(inc_smallIndex)[1])
+ {
+ pStream->triangle(topVertex, inc_chain->getVertex(inc_smallIndex+1),
+ inc_chain->getVertex(inc_smallIndex));
+ monoTriangulation2(topVertex, botVertex, inc_chain, inc_smallIndex+1,
+ inc_largeIndex, is_increase_chain, pStream);
+ return ;
+ }
+
+ inc_array = inc_chain->getArray();
+
+ reflexChain rChain(20,is_increase_chain); /*1 means the chain is increasing*/
+
+ rChain.processNewVertex(topVertex, pStream);
+
+ for(i=inc_smallIndex; i<=inc_largeIndex; i++){
+ rChain.processNewVertex(inc_array[i], pStream);
+ }
+ rChain.processNewVertex(botVertex, pStream);
+
+}
+
+/*if compFun == compV2InY, top to bottom: V-monotone
+ *if compFun == compV2InX, right to left: U-monotone
+ */
+void monoTriangulationRecFunGen(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ Int (*compFun)(Real*, Real*),
+ primStream* pStream)
+{
+ assert( inc_chain != NULL && dec_chain != NULL);
+ assert( ! (inc_current> inc_end &&
+ dec_current> dec_end));
+ /*
+ Int inc_nVertices;
+ Int dec_nVertices;
+ */
+ Real** inc_array ;
+ Real** dec_array ;
+ Int i;
+ assert( ! ( (inc_chain==NULL) && (dec_chain==NULL)));
+
+ if(inc_current> inc_end) /*no more vertices on inc_chain*/
+ {
+
+ dec_array = dec_chain->getArray();
+ reflexChain rChain(20,0);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the dec_chain*/
+ for(i=dec_current; i<=dec_end; i++){
+ rChain.processNewVertex(dec_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+
+ }
+ else if(dec_current> dec_end) /*no more vertices on dec_chain*/
+ {
+ inc_array = inc_chain->getArray();
+ reflexChain rChain(20,1);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the inc_chain*/
+ for(i=inc_current; i<=inc_end; i++){
+ rChain.processNewVertex(inc_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+ }
+ else /*neither chain is empty*/
+ {
+ inc_array = inc_chain -> getArray();
+ dec_array = dec_chain -> getArray();
+
+ /*if top of inc_chain is 'lower' than top of dec_chain, process all the
+ *vertices on the dec_chain which are higher than top of inc_chain
+ */
+ if(compFun(inc_array[inc_current], dec_array[dec_current]) <= 0)
+ {
+
+ reflexChain rChain(20, 0);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=dec_current; i<=dec_end; i++)
+ {
+ if(compFun(inc_array[inc_current], dec_array[i]) <= 0)
+ rChain.processNewVertex(dec_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(inc_array[inc_current], pStream);
+ monoTriangulationRecFunGen(dec_array[i-1], botVertex,
+ inc_chain, inc_current, inc_end,
+ dec_chain, i, dec_end,
+ compFun,
+ pStream);
+ }
+ else /*compFun(inc_array[inc_current], dec_array[dec_current]) > 0*/
+ {
+
+ reflexChain rChain(20, 1);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=inc_current; i<=inc_end; i++)
+ {
+ if(compFun(inc_array[i], dec_array[dec_current]) >0)
+ rChain.processNewVertex(inc_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(dec_array[dec_current], pStream);
+ monoTriangulationRecFunGen(inc_array[i-1], botVertex,
+ inc_chain, i,inc_end,
+ dec_chain, dec_current,dec_end,
+ compFun,
+ pStream);
+ }
+ }/*end case neither is empty*/
+}
+
+/*if compFun == compV2InY, top to bottom: V-monotone
+ *if compFun == compV2InX, right to left: U-monotone
+ */
+void monoTriangulationRecFun(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ Int (*compFun)(Real*, Real*),
+ primStream* pStream)
+{
+ assert( inc_chain != NULL && dec_chain != NULL);
+ assert( ! (inc_current>=inc_chain->getNumElements() &&
+ dec_current>=dec_chain->getNumElements()));
+ Int inc_nVertices;
+ Int dec_nVertices;
+ Real** inc_array ;
+ Real** dec_array ;
+ Int i;
+ assert( ! ( (inc_chain==NULL) && (dec_chain==NULL)));
+
+ if(inc_current>=inc_chain->getNumElements()) /*no more vertices on inc_chain*/
+ {
+
+ dec_array = dec_chain->getArray();
+ dec_nVertices = dec_chain->getNumElements();
+ reflexChain rChain(20,0);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the dec_chain*/
+ for(i=dec_current; i<dec_nVertices; i++){
+ rChain.processNewVertex(dec_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+
+ }
+ else if(dec_current>= dec_chain->getNumElements()) /*no more vertices on dec_chain*/
+ {
+ inc_array = inc_chain->getArray();
+ inc_nVertices= inc_chain->getNumElements();
+ reflexChain rChain(20,1);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the inc_chain*/
+ for(i=inc_current; i<inc_nVertices; i++){
+ rChain.processNewVertex(inc_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+ }
+ else /*neither chain is empty*/
+ {
+ inc_array = inc_chain -> getArray();
+ dec_array = dec_chain -> getArray();
+ inc_nVertices= inc_chain->getNumElements();
+ dec_nVertices= dec_chain->getNumElements();
+ /*if top of inc_chain is 'lower' than top of dec_chain, process all the
+ *vertices on the dec_chain which are higher than top of inc_chain
+ */
+ if(compFun(inc_array[inc_current], dec_array[dec_current]) <= 0)
+ {
+
+ reflexChain rChain(20, 0);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=dec_current; i<dec_nVertices; i++)
+ {
+ if(compFun(inc_array[inc_current], dec_array[i]) <= 0)
+ rChain.processNewVertex(dec_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(inc_array[inc_current], pStream);
+ monoTriangulationRecFun(dec_array[i-1], botVertex,
+ inc_chain, inc_current,
+ dec_chain, i,
+ compFun,
+ pStream);
+ }
+ else /*compFun(inc_array[inc_current], dec_array[dec_current]) > 0*/
+ {
+
+ reflexChain rChain(20, 1);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=inc_current; i<inc_nVertices; i++)
+ {
+ if(compFun(inc_array[i], dec_array[dec_current]) >0)
+ rChain.processNewVertex(inc_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(dec_array[dec_current], pStream);
+ monoTriangulationRecFun(inc_array[i-1], botVertex,
+ inc_chain, i,
+ dec_chain, dec_current,
+ compFun,
+ pStream);
+ }
+ }/*end case neither is empty*/
+}
+
+
+void monoTriangulationRec(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ primStream* pStream)
+{
+ assert( inc_chain != NULL && dec_chain != NULL);
+ assert( ! (inc_current>=inc_chain->getNumElements() &&
+ dec_current>=dec_chain->getNumElements()));
+ Int inc_nVertices;
+ Int dec_nVertices;
+ Real** inc_array ;
+ Real** dec_array ;
+ Int i;
+ assert( ! ( (inc_chain==NULL) && (dec_chain==NULL)));
+
+ if(inc_current>=inc_chain->getNumElements()) /*no more vertices on inc_chain*/
+ {
+
+ dec_array = dec_chain->getArray();
+ dec_nVertices = dec_chain->getNumElements();
+ reflexChain rChain(20,0);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the dec_chain*/
+ for(i=dec_current; i<dec_nVertices; i++){
+ rChain.processNewVertex(dec_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+
+ }
+ else if(dec_current>= dec_chain->getNumElements()) /*no more vertices on dec_chain*/
+ {
+ inc_array = inc_chain->getArray();
+ inc_nVertices= inc_chain->getNumElements();
+ reflexChain rChain(20,1);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the inc_chain*/
+ for(i=inc_current; i<inc_nVertices; i++){
+ rChain.processNewVertex(inc_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+ }
+ else /*neither chain is empty*/
+ {
+ inc_array = inc_chain -> getArray();
+ dec_array = dec_chain -> getArray();
+ inc_nVertices= inc_chain->getNumElements();
+ dec_nVertices= dec_chain->getNumElements();
+ /*if top of inc_chain is 'lower' than top of dec_chain, process all the
+ *vertices on the dec_chain which are higher than top of inc_chain
+ */
+ if(compV2InY(inc_array[inc_current], dec_array[dec_current]) <= 0)
+ {
+
+ reflexChain rChain(20, 0);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=dec_current; i<dec_nVertices; i++)
+ {
+ if(compV2InY(inc_array[inc_current], dec_array[i]) <= 0)
+ rChain.processNewVertex(dec_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(inc_array[inc_current], pStream);
+ monoTriangulationRec(dec_array[i-1], botVertex,
+ inc_chain, inc_current,
+ dec_chain, i,
+ pStream);
+ }
+ else /*compV2InY(inc_array[inc_current], dec_array[dec_current]) > 0*/
+ {
+
+ reflexChain rChain(20, 1);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=inc_current; i<inc_nVertices; i++)
+ {
+ if(compV2InY(inc_array[i], dec_array[dec_current]) >0)
+ rChain.processNewVertex(inc_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(dec_array[dec_current], pStream);
+ monoTriangulationRec(inc_array[i-1], botVertex,
+ inc_chain, i,
+ dec_chain, dec_current,
+ pStream);
+ }
+ }/*end case neither is empty*/
+}
+
+
+
+/* the name here assumes that the polygon is Y-monotone, but
+ *this function also works for X-monotone polygons.
+ * a monotne polygon consists of two extrem verteices: topVertex and botVertex, and
+ *two monotone chains: inc_chain, and dec_chain. The edges of the increasing chain (inc_chain)
+ *is ordered by following pointer: next, while the edges of the decreasing chain (dec_chain)
+ *is ordered by following pointer: prev
+ * inc_index index the vertex which is the toppest of the inc_chain which we are handling currently.
+ * dec_index index the vertex which is the toppest of the dec_chain which we are handling currently.
+ */
+void monoTriangulationRec(directedLine* inc_chain, Int inc_index,
+ directedLine* dec_chain, Int dec_index,
+ directedLine* topVertex, Int top_index,
+ directedLine* botVertex,
+ primStream* pStream)
+{
+ Int i;
+ directedLine *temp, *oldtemp = NULL;
+ Int tempIndex, oldtempIndex = 0;
+
+ assert(inc_chain != NULL && dec_chain != NULL);
+
+ if(inc_chain == botVertex) {
+ reflexChain rChain(20, 0);
+ rChain.processNewVertex(topVertex->getVertex(top_index), pStream);
+ for(i=dec_index; i< dec_chain->get_npoints(); i++){
+ rChain.processNewVertex(dec_chain->getVertex(i), pStream);
+ }
+ for(temp = dec_chain->getPrev(); temp != botVertex; temp = temp->getPrev())
+ {
+ for(i=0; i<temp->get_npoints(); i++){
+ rChain.processNewVertex(temp->getVertex(i), pStream);
+ }
+ }
+ }
+ else if(dec_chain==botVertex) {
+ reflexChain rChain(20, 1);
+ rChain.processNewVertex(topVertex->getVertex(top_index), pStream);
+ for(i=inc_index; i< inc_chain->get_npoints(); i++){
+ rChain.processNewVertex(inc_chain->getVertex(i), pStream);
+ }
+ for(temp = inc_chain->getPrev(); temp != botVertex; temp = temp->getNext())
+ {
+ for(i=0; i<temp->get_npoints(); i++){
+ rChain.processNewVertex(temp->getVertex(i), pStream);
+ }
+ }
+ }
+ else /*neither reached the bottom*/{
+ if(compV2InY(inc_chain->getVertex(inc_index), dec_chain->getVertex(dec_index)) <=0) {
+ reflexChain rChain(20, 0);
+ rChain.processNewVertex(topVertex -> getVertex(top_index), pStream);
+ temp = dec_chain;
+ tempIndex = dec_index;
+ while( compV2InY(inc_chain->getVertex(inc_index), temp->getVertex(tempIndex))<=0) {
+ oldtemp = temp;
+ oldtempIndex = tempIndex;
+ rChain.processNewVertex(temp->getVertex(tempIndex), pStream);
+
+ if(tempIndex == temp->get_npoints()-1){
+ tempIndex = 0;
+ temp = temp->getPrev();
+ }
+ else{
+ tempIndex++;
+ }
+ }
+ rChain.outputFan(inc_chain->getVertex(inc_index), pStream);
+ monoTriangulationRec(inc_chain, inc_index, temp, tempIndex, oldtemp, oldtempIndex, botVertex, pStream);
+ }
+ else /* >0*/ {
+ reflexChain rChain(20, 1);
+ rChain.processNewVertex(topVertex -> getVertex(top_index), pStream);
+ temp = inc_chain;
+ tempIndex = inc_index;
+ while( compV2InY(temp->getVertex(tempIndex), dec_chain->getVertex(dec_index))>0){
+ oldtemp = temp;
+ oldtempIndex = tempIndex;
+ rChain.processNewVertex(temp->getVertex(tempIndex), pStream);
+
+ if(tempIndex == temp->get_npoints()-1){
+ tempIndex = 0;
+ temp = temp->getNext();
+ }
+ else{
+ tempIndex++;
+ }
+ }
+ rChain.outputFan(dec_chain->getVertex(dec_index), pStream);
+ monoTriangulationRec(temp, tempIndex, dec_chain, dec_index, oldtemp, oldtempIndex, botVertex, pStream);
+ }
+ } /*end case neither reached the bottom*/
+}
+
+/***************************vertexArray begin here**********************************/
+vertexArray::vertexArray(Real2* vertices, Int nVertices)
+{
+ Int i;
+ size = index = nVertices;
+ array = (Real**) malloc(sizeof(Real*) * nVertices);
+ assert(array);
+ for(i=0; i<nVertices; i++)
+ {
+ array[i] = vertices[i];
+ array[i] = vertices[i];
+ }
+}
+
+vertexArray::vertexArray(Int s)
+{
+ size = s;
+ array = (Real**) malloc(sizeof(Real*) * s);
+ assert(array);
+ index = 0;
+}
+
+vertexArray::~vertexArray()
+{
+ free(array);
+}
+
+void vertexArray::appendVertex(Real* ptr)
+{
+ Int i;
+ if(index >= size){
+ Real** temp = (Real**) malloc(sizeof(Real*) * (2*size +1));
+ assert(temp);
+ for(i=0; i<index; i++)
+ temp[i] = array[i];
+ free(array);
+ array = temp;
+ size = 2*size+1;
+ }
+ array[index++] = ptr;
+}
+
+void vertexArray::print()
+{
+ printf("vertex Array:index=%i, size=%i\n", index, size);
+ for(Int i=0; i<index; i++)
+ {
+ printf("(%f,%f) ", array[i][0], array[i][1]);
+ }
+ printf("\n");
+}
+
+/*find the first i such that array[i][1] >= v
+ * and array[i+1][1] <v
+ * if index == 0 (the array is empty, return -1.
+ * if v is above all, return -1.
+ * if v is below all, return index-1.
+ */
+Int vertexArray::findIndexAbove(Real v)
+{
+ Int i;
+ if(index == 0)
+ return -1;
+ else if(array[0][1] < v)
+ return -1;
+ else
+ {
+ for(i=1; i<index; i++)
+ {
+ if(array[i][1] < v)
+ break;
+ }
+ return i-1;
+ }
+}
+
+/*find the first i<=endIndex such that array[i][1] <= v
+ * and array[i-1][1] > v
+ *if sartIndex>endIndex, then return endIndex+1.
+ *otherwise, startIndex<=endIndex, it is assumed that
+ * 0<=startIndex<=endIndex<index.
+ * if v is below all, return endIndex+1
+ * if v is above all, return startIndex.
+ */
+Int vertexArray::findIndexBelowGen(Real v, Int startIndex, Int endIndex)
+{
+ Int i;
+ if(startIndex > endIndex)
+ return endIndex+1;
+ else if(array[endIndex][1] > v)
+ return endIndex+1;
+ else //now array[endIndex][1] <= v
+ {
+ for(i=endIndex-1; i>=startIndex; i--)
+ {
+ if(array[i][1] > v)
+ break;
+ }
+ return i+1;
+ }
+}
+
+/*find the first i<=endIndex such that array[i-1][1] >= v
+ * and array[i][1] < v
+ *if sartIndex>endIndex, then return endIndex+1.
+ *otherwise, startIndex<=endIndex, it is assumed that
+ * 0<=startIndex<=endIndex<index.
+ * if v is below or equal to all, return endIndex+1
+ * if v is strictly above all, return startIndex.
+ */
+Int vertexArray::findIndexStrictBelowGen(Real v, Int startIndex, Int endIndex)
+{
+ Int i;
+ if(startIndex > endIndex)
+ return endIndex+1;
+ else if(array[endIndex][1] >= v)
+ return endIndex+1;
+ else //now array[endIndex][1] < v
+ {
+ for(i=endIndex-1; i>=startIndex; i--)
+ {
+ if(array[i][1] >= v)
+ break;
+ }
+ return i+1;
+ }
+}
+
+/*find the first i>startIndex such that array[i-1][1] > v
+ * and array[i][1] >=v
+ *if sartIndex>endIndex, then return startIndex-1.
+ *otherwise, startIndex<=endIndex, it is assumed that
+ * 0<=startIndex<=endIndex<index.
+ * if v is strictly above all, return startIndex-1
+ * if v is strictly below all, return endIndex.
+ */
+Int vertexArray::findIndexFirstAboveEqualGen(Real v, Int startIndex, Int endIndex)
+{
+
+ Int i;
+ if(startIndex > endIndex)
+ return startIndex-1;
+ else if(array[startIndex][1] < v)
+ return startIndex-1;
+ else //now array[startIndex][1] >= v
+ {
+
+ for(i=startIndex; i<=endIndex; i++)
+ {
+ if(array[i][1] <= v)
+ break;
+ }
+ if(i>endIndex) // v is strictly below all
+ return endIndex;
+ else if(array[i][1] == v)
+ return i;
+ else
+ return i-1;
+ }
+
+}
+
+
+/*find the first i>=startIndex such that array[i][1] >= v
+ * and array[i+1][1] <v
+ *if sartIndex>endIndex, then return startIndex-1.
+ *otherwise, startIndex<=endIndex, it is assumed that
+ * 0<=startIndex<=endIndex<index.
+ * if v is above all, return startIndex-1
+ * if v is below all, return endIndex.
+ */
+Int vertexArray::findIndexAboveGen(Real v, Int startIndex, Int endIndex)
+{
+ Int i;
+ if(startIndex > endIndex)
+ return startIndex-1;
+ else if(array[startIndex][1] < v)
+ return startIndex-1;
+ else //now array[startIndex][1] >= v
+ {
+ for(i=startIndex+1; i<=endIndex; i++)
+ {
+ if(array[i][1] < v)
+ break;
+ }
+ return i-1;
+ }
+}
+
+Int vertexArray::findDecreaseChainFromEnd(Int begin, Int end)
+{
+ Int i = end;
+ Real prevU = array[i][0];
+ Real thisU;
+ for(i=end-1; i>=begin; i--){
+ thisU = array[i][0];
+ if(thisU < prevU)
+ prevU = thisU;
+ else
+ break;
+ }
+ return i;
+}
+
+//if(V(start) == v, return start, other wise return the
+//last i so that V(i)==v
+Int vertexArray::skipEqualityFromStart(Real v, Int start, Int end)
+{
+ Int i;
+ if(array[start][1] != v)
+ return start;
+ //now array[start][1] == v
+ for(i=start+1; i<= end; i++)
+ if(array[i][1] != v)
+ break;
+ return i-1;
+}
+
+
+/***************************vertexArray end****************************************/
+
+
+
+/***************************relfex chain stuff begin here*****************************/
+
+reflexChain::reflexChain(Int size, Int is_increasing)
+{
+ queue = (Real2*) malloc(sizeof(Real2) * size);
+ assert(queue);
+ index_queue = 0;
+ size_queue = size;
+ isIncreasing = is_increasing;
+}
+
+reflexChain::~reflexChain()
+{
+ free(queue);
+}
+
+/*put (u,v) at the end of the queue
+ *pay attention to space
+ */
+void reflexChain::insert(Real u, Real v)
+{
+ Int i;
+ if(index_queue >= size_queue) {
+ Real2 *temp = (Real2*) malloc(sizeof(Real2) * (2*size_queue+1));
+ assert(temp);
+
+ /*copy*/
+ for(i=0; i<index_queue; i++){
+ temp[i][0] = queue[i][0];
+ temp[i][1] = queue[i][1];
+ }
+
+ free(queue);
+ queue = temp;
+ size_queue = 2*size_queue + 1;
+ }
+
+ queue[index_queue][0] = u;
+ queue[index_queue][1] = v;
+ index_queue ++;
+}
+
+void reflexChain::insert(Real v[2])
+{
+ insert(v[0], v[1]);
+}
+
+/*
+static Real area(Real A[2], Real B[2], Real C[2])
+{
+ Real Bx, By, Cx, Cy;
+ Bx = B[0] - A[0];
+ By = B[1] - A[1];
+ Cx = C[0] - A[0];
+ Cy = C[1] - A[1];
+ return Bx*Cy - Cx*By;
+}
+*/
+
+/*the chain is reflex, and the vertex v is
+ *on the other side of the chain, so that
+ *we can outout the fan with v as the
+ *the center
+ */
+void reflexChain::outputFan(Real v[2], primStream* pStream)
+{
+ Int i;
+ pStream->begin();
+ pStream->insert(v);
+ if(isIncreasing) {
+ for(i=0; i<index_queue; i++)
+ pStream->insert(queue[i]);
+ }
+ else {
+ for(i=index_queue-1; i>=0; i--)
+ pStream->insert(queue[i]);
+ }
+ pStream->end(PRIMITIVE_STREAM_FAN);
+}
+
+void reflexChain::processNewVertex(Real v[2], primStream* pStream)
+{
+ Int i,j,k;
+ Int isReflex;
+ /*if there are at most one vertex in the queue, then simply insert
+ */
+ if(index_queue <=1){
+ insert(v);
+ return;
+ }
+
+ /*there are at least two vertices in the queue*/
+ j=index_queue-1;
+
+ for(i=j; i>=1; i--) {
+ if(isIncreasing) {
+ isReflex = (area(queue[i-1], queue[i], v) <= 0.0);
+ }
+ else /*decreasing*/{
+ isReflex = (area(v, queue[i], queue[i-1]) <= 0.0);
+ }
+ if(isReflex) {
+ break;
+ }
+ }
+
+ /*
+ *if i<j then vertices: i+1--j are convex
+ * output triangle fan:
+ * v, and queue[i], i+1, ..., j
+ */
+ if(i<j)
+ {
+ pStream->begin();
+ pStream->insert(v);
+ if(isIncreasing) {
+ for(k=i; k<=j; k++)
+ pStream->insert(queue[k]);
+ }
+ else {
+ for(k=j; k>=i; k--)
+ pStream->insert(queue[k]);
+ }
+
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+
+ /*delete vertices i+1--j from the queue*/
+ index_queue = i+1;
+ /*finally insert v at the end of the queue*/
+ insert(v);
+
+}
+
+void reflexChain::print()
+{
+ Int i;
+ printf("reflex chain: isIncreasing=%i\n", isIncreasing);
+ for(i=0; i<index_queue; i++) {
+ printf("(%f,%f) ", queue[i][0], queue[i][1]);
+ }
+ printf("\n");
+}
diff --git a/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.h b/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.h
new file mode 100644
index 00000000000..2b8f38226b6
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.h
@@ -0,0 +1,192 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#ifndef _MONO_TRIANGULATION_H
+#define _MONO_TRIANGULATION_H
+
+#include "definitions.h"
+#include "primitiveStream.h"
+#include "directedLine.h"
+
+class Backend;
+class Arc;
+typedef Arc *Arc_ptr;
+
+class reflexChain{
+ Real2 *queue;
+ /*the order of the polygon vertices: either q[0],q[1].., or
+ * q[n-1], q[n-2], ..., q[0]
+ *this order determines the interior of the polygon, so it
+ *also used to determines whether a chain is reflex or convex
+ */
+ Int isIncreasing;
+ Int index_queue;
+ Int size_queue; /*allocated size*/
+
+public:
+ reflexChain(Int size, Int isIncreasing);
+ ~reflexChain();
+
+ void insert(Real u, Real v);
+ void insert(Real v[2]);
+
+ void processNewVertex(Real v[2], primStream* pStream);
+ void outputFan(Real v[2], primStream* pStream);
+
+ void processNewVertex(Real v[2], Backend* backend);
+ void outputFan(Real v[2], Backend* backend);
+
+ void print();
+};
+
+/*dynamic array of pointers to reals.
+ *Intended to store an array of (u,v).
+ *Notice that it doesn't allocate or dealocate the space
+ *for the (u,v) themselfs. So it assums that someone else
+ *is taking care of them, while this class only plays with
+ *the pointers.
+ */
+class vertexArray{
+ Real** array;
+ Int index;
+ Int size;
+public:
+ vertexArray(Int s);
+ vertexArray(Real vertices[][2], Int nVertices);
+ ~vertexArray();
+ void appendVertex(Real* ptr); /*the content (pointed by ptr is NOT copied*/
+ Real* getVertex(Int i) {return array[i];}
+ Real** getArray() {return array;}
+ Int getNumElements() {return index;}
+ Int findIndexAbove(Real v);
+ Int findIndexAboveGen(Real v, Int startIndex, Int EndIndex);
+ Int findIndexBelowGen(Real v, Int startIndex, Int EndIndex);
+ Int findIndexStrictBelowGen(Real v, Int startIndex, Int EndIndex);
+ Int findIndexFirstAboveEqualGen(Real v, Int startIndex, Int endIndex);
+ Int skipEqualityFromStart(Real v, Int start, Int end);
+ //return i such that fron [i+1, end] is strictly U-monotone (left to right
+ Int findDecreaseChainFromEnd(Int begin, Int end);
+ void print();
+};
+
+void monoTriangulation(directedLine* monoPolygon, primStream* pStream);
+
+void monoTriangulationRec(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ primStream* pStream);
+
+void monoTriangulationRec(directedLine* inc_chain, Int inc_index,
+ directedLine* dec_chain, Int dec_index,
+ directedLine* topVertex, Int top_index,
+ directedLine* botVertex,
+ primStream* pStream);
+
+/*the chain could be increasing or decreasing, although we use the
+ * name inc_chain.
+ *the argument is_increase_chain indicates whether this chain
+ *is increasing (left chain in V-monotone case) or decreaing (right chain
+ *in V-monotone case).
+ */
+void monoTriangulation2(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_smallIndex,
+ Int inc_largeIndex,
+ Int is_increase_chain,
+ primStream* pStream);
+void monoTriangulationRecGen(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream);
+
+void monoTriangulationRecGenOpt(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream);
+
+void triangulateXYMonoTB(Int n_left, Real** leftVerts,
+ Int n_right, Real** rightVerts,
+ primStream* pStream);
+
+void monoTriangulationRecGenTBOpt(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream);
+
+void monoTriangulationRecOpt(Real* topVertex, Real* botVertex,
+ vertexArray* left_chain, Int left_current,
+ vertexArray* right_chain, Int right_current,
+ primStream* pStream);
+
+void monoTriangulationRecFunGen(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ Int (*compFun)(Real*, Real*),
+ primStream* pStream);
+
+void monoTriangulationRecFun(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ Int (*compFun)(Real*, Real*),
+ primStream* pStream);
+void monoTriangulationFun(directedLine* monoPolygon,
+ Int (*compFun)(Real*, Real*), primStream* pStream);
+
+
+
+
+void monoTriangulationRec(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ Backend* backend);
+
+void monoTriangulationFunBackend(Arc_ptr loop, Int (*compFun)(Real*, Real*), Backend* backend);
+
+void monoTriangulationRecFunBackend(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ Int (*compFun)(Real*, Real*),
+ Backend* backend);
+
+void monoTriangulationOpt(directedLine* poly, primStream* pStream);
+
+#endif
+
+
+
+
diff --git a/src/glu/sgi/libnurbs/nurbtess/mystdio.h b/src/glu/sgi/libnurbs/nurbtess/mystdio.h
new file mode 100644
index 00000000000..7ec520e8bfa
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/mystdio.h
@@ -0,0 +1,66 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * mystdio.h
+ *
+ * $Date: 2001/03/19 17:52:03 $ $Revision: 1.3 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/mystdio.h,v 1.3 2001/03/19 17:52:03 pesco Exp $
+ */
+
+#ifndef __glumystdio_h_
+#define __glumystdio_h_
+
+#ifdef STANDALONE
+inline void dprintf( char *, ... ) { }
+#endif
+
+#ifdef LIBRARYBUILD
+#ifndef NDEBUG
+#include <stdio.h>
+#define dprintf printf
+#else
+inline void dprintf( char *, ... ) { }
+#endif
+#endif
+
+#ifdef GLBUILD
+inline void dprintf( char *, ... ) { }
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#endif /* __glumystdio_h_ */
diff --git a/src/glu/sgi/libnurbs/nurbtess/mystdlib.h b/src/glu/sgi/libnurbs/nurbtess/mystdlib.h
new file mode 100644
index 00000000000..4820818259d
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/mystdlib.h
@@ -0,0 +1,63 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * mystdlib.h
+ *
+ * $Date: 2001/03/19 17:52:03 $ $Revision: 1.3 $
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/mystdlib.h,v 1.3 2001/03/19 17:52:03 pesco Exp $
+ */
+
+#ifndef __glumystdlib_h_
+#define __glumystdlib_h_
+
+#ifdef STANDALONE
+typedef unsigned int size_t;
+extern "C" void abort( void );
+extern "C" void * malloc( size_t );
+extern "C" void free( void * );
+#endif
+
+#ifdef LIBRARYBUILD
+#include <stdlib.h>
+#endif
+
+#ifdef GLBUILD
+typedef unsigned int size_t;
+extern "C" void abort( void );
+extern "C" void * malloc( size_t );
+extern "C" void free( void * );
+#endif
+
+#endif /* __glumystdlib_h_ */
diff --git a/src/glu/sgi/libnurbs/nurbtess/partitionX.cc b/src/glu/sgi/libnurbs/nurbtess/partitionX.cc
new file mode 100644
index 00000000000..0887009a0f0
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/partitionX.cc
@@ -0,0 +1,164 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/partitionX.cc,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "partitionX.h"
+
+#define CONCAVITY_ZERO 1.0e-6 //this number is used to test whether a vertex is concave (refelx)
+ //or not. The test needs to compute the area of the three adjacent
+ //vertices to see if the are is positive or negative.
+
+Int isCuspX(directedLine *v)
+{
+ //if v->prev <= v && v->next <= v
+ //|| v->prev >= v && v->next >= v
+ Real* T = v->head();
+ Real* P = v->getPrev()->head();
+ Real* N = v->getNext()->head();
+ if(
+ (compV2InX(T,P) != -1 &&
+ compV2InX(T,N) != -1
+ ) ||
+ (compV2InX(T,P) != 1 &&
+ compV2InX(T,N) != 1
+ )
+ )
+ return 1;
+ else
+ return 0;
+}
+
+Int isReflexX(directedLine* v)
+{
+ Real* A = v->getPrev()->head();
+ Real* B = v->head();
+ Real* C = v->tail();
+ Real Bx,By, Cx, Cy;
+ //scale them in case they are too small
+ Bx = 10*(B[0] - A[0]);
+ By = 10*(B[1] - A[1]);
+ Cx = 10*(C[0] - A[0]);
+ Cy = 10*(C[1] - A[1]);
+
+ if(Bx*Cy - Cx*By < -CONCAVITY_ZERO) return 1;
+ else return 0;
+}
+
+
+/*return
+ *0: not-cusp
+ *1: interior cusp
+ *2: exterior cusp
+ */
+Int cuspTypeX(directedLine *v)
+{
+ if(! isCuspX(v)) return 0;
+ else
+ {
+//printf("isCusp,%f,%f\n", v->head()[0], v->head()[1]);
+ if(isReflexX(v))
+ {
+// printf("isReflex\n");
+ return 1;
+ }
+ else
+ {
+// printf("not isReflex\n");
+ return 2;
+ }
+ }
+}
+
+Int numInteriorCuspsX(directedLine *polygon)
+{
+ directedLine *temp;
+ int ret = 0;
+ if(cuspTypeX(polygon) == 1)
+ ret++;
+ for(temp = polygon->getNext(); temp != polygon; temp = temp->getNext())
+ if(cuspTypeX(temp) == 1)
+ ret++;
+ return ret;
+}
+
+
+void findInteriorCuspsX(directedLine *polygon, Int& ret_n_interior_cusps,
+ directedLine** ret_interior_cusps)
+{
+ directedLine *temp;
+ ret_n_interior_cusps = 0;
+ if(cuspTypeX(polygon) == 1)
+ {
+ ret_interior_cusps[ret_n_interior_cusps++] = polygon;
+ }
+ for(temp = polygon->getNext(); temp != polygon; temp = temp->getNext())
+ if(cuspTypeX(temp) == 1)
+ {
+ ret_interior_cusps[ret_n_interior_cusps++] = temp;
+ }
+}
+
+directedLine* findDiagonal_singleCuspX(directedLine* cusp)
+{
+ directedLine* temp;
+ Int is_minimal = ((compV2InX(cusp->head(), cusp->tail()) == -1)? 1:0);
+
+ if(is_minimal)
+ for(temp = cusp->getNext(); temp != cusp; temp = temp->getNext())
+ {
+ if(compV2InX(cusp->head(), temp->head()) == 1)
+ {
+ return temp;
+ }
+ }
+ else //is maxmal
+ for(temp = cusp->getNext(); temp != cusp; temp = temp->getNext())
+ {
+ if(compV2InX(cusp->head(), temp->head()) == -1)
+ {
+ return temp;
+ }
+ }
+ return NULL;
+}
+
+
+
diff --git a/src/glu/sgi/libnurbs/nurbtess/partitionX.h b/src/glu/sgi/libnurbs/nurbtess/partitionX.h
new file mode 100644
index 00000000000..abb96114b6d
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/partitionX.h
@@ -0,0 +1,61 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/partitionX.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#ifndef _PARTITIONX_H
+#define _PARTITIONX_H
+
+#include "directedLine.h"
+
+Int isCuspX(directedLine *v);
+Int isReflexX(directedLine *v);
+Int cuspTypeX(directedLine *v);
+
+//assuming the array of ret_interior_cusps has been allocated
+void findInteriorCuspsX(directedLine* polygon, Int& ret_n_interior_cusps,
+ directedLine** ret_interior_cusps);
+
+Int numInteriorCuspsX(directedLine* polygon);
+
+/*a single polygon with a single cusp
+ *return the diagonal vertex corresponding to this cusp
+ */
+directedLine* findDiagonal_singleCuspX(directedLine* cusp);
+
+#endif
+
diff --git a/src/glu/sgi/libnurbs/nurbtess/partitionY.cc b/src/glu/sgi/libnurbs/nurbtess/partitionY.cc
new file mode 100644
index 00000000000..08c1866d1a0
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/partitionY.cc
@@ -0,0 +1,838 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/11/29 16:16:55 $ $Revision: 1.2 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/partitionY.cc,v 1.2 2001/11/29 16:16:55 kschultz Exp $
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "zlassert.h"
+#include "partitionY.h"
+#include "searchTree.h"
+#include "quicksort.h"
+#include "polyUtil.h"
+
+
+#define max(a,b) ((a>b)? a:b)
+#define min(a,b) ((a>b)? b:a)
+
+
+/*retrurn
+ *-1: if A < B (Ya<Yb) || (Ya==Yb)
+ * 0: if A == B
+ * 1: if A>B
+ */
+static Int compVertInY(Real A[2], Real B[2])
+{
+ if( (A[1] < B[1]) || (A[1]==B[1] && A[0]<B[0]))
+ return -1;
+ else if
+ ( A[1] == B[1] && A[0] == B[0]) return 0;
+ else
+ return 1;
+}
+
+/*v is a vertex: the head of en edge,
+ *e is an edge,
+ *return 1 if e is below v: assume v1 and v2 are the two endpoints of e:
+ * v1<= v, v2<=v.
+ */
+Int isBelow(directedLine *v, directedLine *e)
+{
+ Real* vert = v->head();
+ if( compVertInY(e->head(), vert) != 1
+ && compVertInY(e->tail(), vert) != 1
+ )
+ return 1;
+ else
+ return 0;
+}
+
+/*v is a vertex: the head of en edge,
+ *e is an edge,
+ *return 1 if e is below v: assume v1 and v2 are the two endpoints of e:
+ * v1>= v, v2>=v.
+ */
+Int isAbove(directedLine *v, directedLine *e)
+{
+ Real* vert = v->head();
+ if( compVertInY(e->head(), vert) != -1
+ && compVertInY(e->tail(), vert) != -1
+ )
+ return 1;
+ else
+ return 0;
+}
+
+Int isCusp(directedLine *v)
+{
+ Real *A=v->getPrev()->head();
+ Real *B=v->head();
+ Real *C=v->tail();
+ if(A[1] < B[1] && B[1] < C[1])
+ return 0;
+ else if(A[1] > B[1] && B[1] > C[1])
+ return 0;
+ else if(A[1] < B[1] && C[1] < B[1])
+ return 1;
+ else if(A[1] > B[1] && C[1] > B[1])
+ return 1;
+
+ if(isAbove(v, v) && isAbove(v, v->getPrev()) ||
+ isBelow(v, v) && isBelow(v, v->getPrev()))
+ return 1;
+ else
+ return 0;
+}
+
+/*crossproduct is strictly less than 0*/
+Int isReflex(directedLine *v)
+{
+ Real* A = v->getPrev()->head();
+ Real* B = v->head();
+ Real* C = v->tail();
+ Real Bx,By, Cx, Cy;
+ Bx = B[0] - A[0];
+ By = B[1] - A[1];
+ Cx = C[0] - A[0];
+ Cy = C[1] - A[1];
+
+ if(Bx*Cy - Cx*By < 0) return 1;
+ else return 0;
+}
+
+ /*return
+ *0: not-cusp
+ *1: interior cusp
+ *2: exterior cusp
+ */
+Int cuspType(directedLine *v)
+{
+ if(! isCusp(v)) return 0;
+ else if(isReflex(v)) return 1;
+ else
+ return 2;
+}
+
+sweepRange* sweepRangeMake(directedLine* left, Int leftType,
+ directedLine* right, Int rightType)
+{
+ sweepRange* ret = (sweepRange*)malloc(sizeof(sweepRange));
+ assert(ret);
+ ret->left = left;
+ ret->leftType = leftType;
+ ret->right = right;
+ ret->rightType = rightType;
+ return ret;
+}
+
+void sweepRangeDelete(sweepRange* range)
+{
+ free(range);
+}
+
+Int sweepRangeEqual(sweepRange* src1, sweepRange* src2)
+{
+ Int leftEqual;
+ Int rightEqual;
+
+
+ /*The case when both are vertices should not happen*/
+ assert(! (src1->leftType == 0 && src2->leftType == 0));
+ if(src1->leftType == 0 && src2->leftType == 1){
+ if(src1->left == src2->left ||
+ src1->left->getPrev() == src2->left
+ )
+ leftEqual = 1;
+ else
+ leftEqual = 0;
+ }
+ else if(src1->leftType == 1 && src2->leftType == 1){
+ if(src1->left == src2->left)
+ leftEqual = 1;
+ else
+ leftEqual = 0;
+ }
+ else /*src1->leftType == 1 && src2->leftType == 0*/{
+ if(src1->left == src2->left ||
+ src1->left == src2->left->getPrev()
+ )
+ leftEqual = 1;
+ else
+ leftEqual = 0;
+ }
+
+ /*the same thing for right*/
+ /*The case when both are vertices should not happen*/
+ assert(! (src1->rightType == 0 && src2->rightType == 0));
+ if(src1->rightType == 0 && src2->rightType == 1){
+ if(src1->right == src2->right ||
+ src1->right->getPrev() == src2->right
+ )
+ rightEqual = 1;
+ else
+ rightEqual = 0;
+ }
+ else if(src1->rightType == 1 && src2->rightType == 1){
+ if(src1->right == src2->right)
+ rightEqual = 1;
+ else
+ rightEqual = 0;
+ }
+ else /*src1->rightType == 1 && src2->rightType == 0*/{
+ if(src1->right == src2->right ||
+ src1->right == src2->right->getPrev()
+ )
+ rightEqual = 1;
+ else
+ rightEqual = 0;
+ }
+
+ return (leftEqual == 1 || rightEqual == 1);
+}
+
+/*given (x_1, y_1) and (x_2, y_2), and y
+ *return x such that (x,y) is on the line
+ */
+inline/*static*/ Real intersectHoriz(Real x1, Real y1, Real x2, Real y2, Real y)
+{
+ return ((y2==y1)? (x1+x2)*Real(0.5) : x1 + ((y-y1)/(y2-y1)) * (x2-x1));
+/*
+ if(y2 == y1) return (x1+x2)*0.5;
+ else return x1 + ((y-y1)/(y2-y1)) * (x2-x1);
+*/
+}
+
+/*compare two edges of a polygon.
+ *edge A < edge B if there is a horizontal line so that the intersection
+ *with A is to the left of the intersection with B.
+ *This function is used in sweepY for the dynamic search tree insertion to
+ *order the edges.
+ * Implementation: (x_1,y_1) and (x_2, y_2)
+ */
+static Int compEdges(directedLine *e1, directedLine *e2)
+{
+ Real* head1 = e1->head();
+ Real* tail1 = e1->tail();
+ Real* head2 = e2->head();
+ Real* tail2 = e2->tail();
+/*
+ Real h10 = head1[0];
+ Real h11 = head1[1];
+ Real t10 = tail1[0];
+ Real t11 = tail1[1];
+ Real h20 = head2[0];
+ Real h21 = head2[1];
+ Real t20 = tail2[0];
+ Real t21 = tail2[1];
+*/
+ Real e1_Ymax, e1_Ymin, e2_Ymax, e2_Ymin;
+/*
+ if(h11>t11) {
+ e1_Ymax= h11;
+ e1_Ymin= t11;
+ }
+ else{
+ e1_Ymax = t11;
+ e1_Ymin = h11;
+ }
+
+ if(h21>t21) {
+ e2_Ymax= h21;
+ e2_Ymin= t21;
+ }
+ else{
+ e2_Ymax = t21;
+ e2_Ymin = h21;
+ }
+*/
+
+ if(head1[1]>tail1[1]) {
+ e1_Ymax= head1[1];
+ e1_Ymin= tail1[1];
+ }
+ else{
+ e1_Ymax = tail1[1];
+ e1_Ymin = head1[1];
+ }
+
+ if(head2[1]>tail2[1]) {
+ e2_Ymax= head2[1];
+ e2_Ymin= tail2[1];
+ }
+ else{
+ e2_Ymax = tail2[1];
+ e2_Ymin = head2[1];
+ }
+
+
+ /*Real e1_Ymax = max(head1[1], tail1[1]);*/ /*max(e1->head()[1], e1->tail()[1]);*/
+ /*Real e1_Ymin = min(head1[1], tail1[1]);*/ /*min(e1->head()[1], e1->tail()[1]);*/
+ /*Real e2_Ymax = max(head2[1], tail2[1]);*/ /*max(e2->head()[1], e2->tail()[1]);*/
+ /*Real e2_Ymin = min(head2[1], tail2[1]);*/ /*min(e2->head()[1], e2->tail()[1]);*/
+
+ Real Ymax = min(e1_Ymax, e2_Ymax);
+ Real Ymin = max(e1_Ymin, e2_Ymin);
+
+ Real y = Real(0.5)*(Ymax + Ymin);
+
+/* Real x1 = intersectHoriz(e1->head()[0], e1->head()[1], e1->tail()[0], e1->tail()[1], y);
+ Real x2 = intersectHoriz(e2->head()[0], e2->head()[1], e2->tail()[0], e2->tail()[1], y);
+*/
+/*
+ Real x1 = intersectHoriz(h10, h11, t10, t11, y);
+ Real x2 = intersectHoriz(h20, h21, t20, t21, y);
+*/
+ Real x1 = intersectHoriz(head1[0], head1[1], tail1[0], tail1[1], y);
+ Real x2 = intersectHoriz(head2[0], head2[1], tail2[0], tail2[1], y);
+
+ if(x1<= x2) return -1;
+ else return 1;
+}
+
+/*used by sort precedures
+ */
+static Int compInY(directedLine* v1, directedLine* v2)
+{
+ return v1->compInY(v2);
+}
+
+void findDiagonals(Int total_num_edges, directedLine** sortedVertices, sweepRange** ranges, Int& num_diagonals, directedLine** diagonal_vertices)
+{
+ Int i,j,k;
+
+ k=0;
+
+ for(i=0; i<total_num_edges; i++)
+ {
+ directedLine* vert =sortedVertices[i];
+ directedLine* thisEdge = vert;
+ directedLine* prevEdge = vert->getPrev();
+/*
+printf("find i=%i\n", i);
+printf("the vertex is\n");
+vert->printSingle();
+*/
+ if(isBelow(vert, thisEdge) && isBelow(vert, prevEdge) && compEdges(prevEdge, thisEdge)<0)
+ {
+ /*this is an upward interior cusp*/
+ diagonal_vertices[k++] = vert;
+
+ for(j=i+1; j<total_num_edges; j++)
+ if(sweepRangeEqual(ranges[i], ranges[j]))
+ {
+ diagonal_vertices[k++] = sortedVertices[j];
+ break;
+ }
+ assert(j<total_num_edges);
+
+
+ }
+ else if(isAbove(vert, thisEdge) && isAbove(vert, prevEdge) && compEdges(prevEdge, thisEdge)>0)
+ {
+ /*this is an downward interior cusp*/
+ diagonal_vertices[k++] = vert;
+ for(j=i-1; j>=0; j--)
+ if(sweepRangeEqual(ranges[i], ranges[j]))
+ {
+ diagonal_vertices[k++] = sortedVertices[j];
+ break;
+ }
+/* printf("j=%i\n", j);*/
+ assert(j>=0);
+
+
+
+ }
+ }
+ num_diagonals = k/2;
+}
+
+/*get rid of repeated diagonlas so that each diagonal appears only once in the array
+ */
+Int deleteRepeatDiagonals(Int num_diagonals, directedLine** diagonal_vertices, directedLine** new_vertices)
+{
+ Int i,k;
+ Int j,l;
+ Int index;
+ index=0;
+ for(i=0,k=0; i<num_diagonals; i++, k+=2)
+ {
+ Int isRepeated=0;
+ /*check the diagonla (diagonal_vertice[k], diagonal_vertices[k+1])
+ *is repeated or not
+ */
+ for(j=0,l=0; j<index; j++, l+=2)
+ {
+ if(
+ (diagonal_vertices[k] == new_vertices[l] &&
+ diagonal_vertices[k+1] == new_vertices[l+1]
+ )
+ ||
+ (
+ diagonal_vertices[k] == new_vertices[l+1] &&
+ diagonal_vertices[k+1] == new_vertices[l]
+ )
+ )
+ {
+ isRepeated=1;
+ break;
+ }
+ }
+ if(! isRepeated)
+ {
+ new_vertices[index+index] = diagonal_vertices[k];
+ new_vertices[index+index+1] = diagonal_vertices[k+1];
+ index++;
+ }
+ }
+ return index;
+}
+
+/*for debug only*/
+directedLine** DBGfindDiagonals(directedLine *polygons, Int& num_diagonals)
+{
+ Int total_num_edges = 0;
+ directedLine** array = polygons->toArrayAllPolygons(total_num_edges);
+ quicksort( (void**)array, 0, total_num_edges-1, (Int (*)(void*, void*)) compInY);
+ sweepRange** ranges = (sweepRange**) malloc(sizeof(sweepRange*) * total_num_edges);
+ assert(ranges);
+
+ sweepY(total_num_edges, array, ranges);
+
+ directedLine** diagonal_vertices = (directedLine**) malloc(sizeof(directedLine*) * total_num_edges);
+ assert(diagonal_vertices);
+ findDiagonals(total_num_edges, array, ranges, num_diagonals, diagonal_vertices);
+
+ num_diagonals=deleteRepeatDiagonals(num_diagonals, diagonal_vertices, diagonal_vertices);
+ return diagonal_vertices;
+
+}
+
+
+/*partition into Y-monotone polygons*/
+directedLine* partitionY(directedLine *polygons, sampledLine **retSampledLines)
+{
+ Int total_num_edges = 0;
+ directedLine** array = polygons->toArrayAllPolygons(total_num_edges);
+
+ quicksort( (void**)array, 0, total_num_edges-1, (Int (*)(void*, void*)) compInY);
+
+ sweepRange** ranges = (sweepRange**) malloc(sizeof(sweepRange*) * (total_num_edges));
+ assert(ranges);
+
+
+
+ sweepY(total_num_edges, array, ranges);
+
+
+
+ /*the diagonal vertices are stored as:
+ *v0-v1: 1st diagonal
+ *v2-v3: 2nd diagonal
+ *v5-v5: 3rd diagonal
+ *...
+ */
+
+
+ Int num_diagonals;
+ /*number diagonals is < total_num_edges*total_num_edges*/
+ directedLine** diagonal_vertices = (directedLine**) malloc(sizeof(directedLine*) * total_num_edges*2/*total_num_edges*/);
+ assert(diagonal_vertices);
+
+
+
+ findDiagonals(total_num_edges, array, ranges, num_diagonals, diagonal_vertices);
+
+
+
+ directedLine* ret_polygons = polygons;
+ sampledLine* newSampledLines = NULL;
+ Int i,k;
+
+num_diagonals=deleteRepeatDiagonals(num_diagonals, diagonal_vertices, diagonal_vertices);
+
+
+
+ Int *removedDiagonals=(Int*)malloc(sizeof(Int) * num_diagonals);
+ for(i=0; i<num_diagonals; i++)
+ removedDiagonals[i] = 0;
+
+
+
+
+
+ for(i=0,k=0; i<num_diagonals; i++,k+=2)
+ {
+
+
+ directedLine* v1=diagonal_vertices[k];
+ directedLine* v2=diagonal_vertices[k+1];
+ directedLine* ret_p1;
+ directedLine* ret_p2;
+
+ /*we ahve to determine whether v1 and v2 belong to the same polygon before
+ *their structure are modified by connectDiagonal().
+ */
+/*
+ directedLine *root1 = v1->findRoot();
+ directedLine *root2 = v2->findRoot();
+ assert(root1);
+ assert(root2);
+*/
+
+directedLine* root1 = v1->rootLinkFindRoot();
+directedLine* root2 = v2->rootLinkFindRoot();
+
+ if(root1 != root2)
+ {
+
+ removedDiagonals[i] = 1;
+ sampledLine* generatedLine;
+
+
+
+ v1->connectDiagonal(v1,v2, &ret_p1, &ret_p2, &generatedLine, ret_polygons);
+
+
+
+ newSampledLines = generatedLine->insert(newSampledLines);
+/*
+ ret_polygons = ret_polygons->cutoffPolygon(root1);
+
+ ret_polygons = ret_polygons->cutoffPolygon(root2);
+ ret_polygons = ret_p1->insertPolygon(ret_polygons);
+root1->rootLinkSet(ret_p1);
+root2->rootLinkSet(ret_p1);
+ret_p1->rootLinkSet(NULL);
+ret_p2->rootLinkSet(ret_p1);
+*/
+ ret_polygons = ret_polygons->cutoffPolygon(root2);
+
+
+
+root2->rootLinkSet(root1);
+ret_p1->rootLinkSet(root1);
+ret_p2->rootLinkSet(root1);
+
+ /*now that we have connected the diagonal v1 and v2,
+ *we have to check those unprocessed diagonals which
+ *have v1 or v2 as an end point. Notice that the head of v1
+ *has the same coodinates as the head of v2->prev, and the head of
+ *v2 has the same coordinate as the head of v1->prev.
+ *Suppose these is a diagonal (v1, x). If (v1,x) is still a valid
+ *diagonal, then x should be on the left hand side of the directed line: *v1->prev->head -- v1->head -- v1->tail. Otherwise, (v1,x) should be
+ *replaced by (v2->prev, x), that is, x is on the left of
+ * v2->prev->prev->head, v2->prev->head, v2->prev->tail.
+ */
+ Int ii, kk;
+ for(ii=0, kk=0; ii<num_diagonals; ii++, kk+=2)
+ if( removedDiagonals[ii]==0)
+ {
+ directedLine* d1=diagonal_vertices[kk];
+ directedLine* d2=diagonal_vertices[kk+1];
+ /*check d1, and replace diagonal_vertices[kk] if necessary*/
+ if(d1 == v1) {
+ /*check if d2 is to left of v1->prev->head:v1->head:v1->tail*/
+ if(! pointLeft2Lines(v1->getPrev()->head(),
+ v1->head(), v1->tail(), d2->head()))
+ {
+/*
+ assert(pointLeft2Lines(v2->getPrev()->getPrev()->head(),
+ v2->getPrev()->head(),
+ v2->getPrev()->tail(), d2->head()));
+*/
+ diagonal_vertices[kk] = v2->getPrev();
+ }
+ }
+ if(d1 == v2) {
+ /*check if d2 is to left of v2->prev->head:v2->head:v2->tail*/
+ if(! pointLeft2Lines(v2->getPrev()->head(),
+ v2->head(), v2->tail(), d2->head()))
+ {
+/*
+ assert(pointLeft2Lines(v1->getPrev()->getPrev()->head(),
+ v1->getPrev()->head(),
+ v1->getPrev()->tail(), d2->head()));
+*/
+ diagonal_vertices[kk] = v1->getPrev();
+ }
+ }
+ /*check d2 and replace diagonal_vertices[k+1] if necessary*/
+ if(d2 == v1) {
+ /*check if d1 is to left of v1->prev->head:v1->head:v1->tail*/
+ if(! pointLeft2Lines(v1->getPrev()->head(),
+ v1->head(), v1->tail(), d1->head()))
+ {
+/* assert(pointLeft2Lines(v2->getPrev()->getPrev()->head(),
+ v2->getPrev()->head(),
+ v2->getPrev()->tail(), d1->head()));
+*/
+ diagonal_vertices[kk+1] = v2->getPrev();
+ }
+ }
+ if(d2 == v2) {
+ /*check if d1 is to left of v2->prev->head:v2->head:v2->tail*/
+ if(! pointLeft2Lines(v2->getPrev()->head(),
+ v2->head(), v2->tail(), d1->head()))
+ {
+/* assert(pointLeft2Lines(v1->getPrev()->getPrev()->head(),
+ v1->getPrev()->head(),
+ v1->getPrev()->tail(), d1->head()));
+*/
+ diagonal_vertices[kk+1] = v1->getPrev();
+ }
+ }
+ }
+}/*end if (root1 not equal to root 2)*/
+}
+
+ /*second pass, now all diagoals should belong to the same polygon*/
+
+
+
+ for(i=0,k=0; i<num_diagonals; i++, k += 2)
+ if(removedDiagonals[i] == 0)
+ {
+
+
+ directedLine* v1=diagonal_vertices[k];
+ directedLine* v2=diagonal_vertices[k+1];
+
+
+
+ directedLine* ret_p1;
+ directedLine* ret_p2;
+
+ /*we ahve to determine whether v1 and v2 belong to the same polygon before
+ *their structure are modified by connectDiagonal().
+ */
+ directedLine *root1 = v1->findRoot();
+/*
+ directedLine *root2 = v2->findRoot();
+
+
+
+ assert(root1);
+ assert(root2);
+ assert(root1 == root2);
+ */
+ sampledLine* generatedLine;
+
+
+
+ v1->connectDiagonal(v1,v2, &ret_p1, &ret_p2, &generatedLine, ret_polygons);
+ newSampledLines = generatedLine->insert(newSampledLines);
+
+ ret_polygons = ret_polygons->cutoffPolygon(root1);
+
+ ret_polygons = ret_p1->insertPolygon(ret_polygons);
+
+ ret_polygons = ret_p2->insertPolygon(ret_polygons);
+
+
+
+ for(Int j=i+1; j<num_diagonals; j++)
+ {
+ if(removedDiagonals[j] ==0)
+ {
+
+ directedLine* temp1=diagonal_vertices[2*j];
+ directedLine* temp2=diagonal_vertices[2*j+1];
+ if(temp1==v1 || temp1==v2 || temp2==v1 || temp2==v2)
+ if(! temp1->samePolygon(temp1, temp2))
+ {
+ /*if temp1 and temp2 are in different polygons,
+ *then one of them must be v1 or v2.
+ */
+
+
+
+ assert(temp1==v1 || temp1 == v2 || temp2==v1 || temp2 ==v2);
+ if(temp1==v1)
+ {
+ diagonal_vertices[2*j] = v2->getPrev();
+ }
+ if(temp2==v1)
+ {
+ diagonal_vertices[2*j+1] = v2->getPrev();
+ }
+ if(temp1==v2)
+ {
+ diagonal_vertices[2*j] = v1->getPrev();
+ }
+ if(temp2==v2)
+ {
+ diagonal_vertices[2*j+1] = v1->getPrev();
+ }
+ }
+ }
+ }
+
+ }
+
+ /*clean up spaces*/
+ free(array);
+ free(ranges);
+ free(diagonal_vertices);
+ free(removedDiagonals);
+
+ *retSampledLines = newSampledLines;
+ return ret_polygons;
+}
+
+/*given a set of simple polygons where the interior
+ *is decided by left-hand principle,
+ *return a range (sight) for each vertex. This is called
+ *Trapezoidalization.
+ */
+void sweepY(Int nVertices, directedLine** sortedVertices, sweepRange** ret_ranges)
+{
+ Int i;
+ /*for each vertex in the sorted list, update the binary search tree.
+ *and store the range information for each vertex.
+ */
+ treeNode* searchTree = NULL;
+ for(i=0; i<nVertices;i++)
+ {
+
+ directedLine* vert = sortedVertices[i];
+
+ directedLine* thisEdge = vert;
+ directedLine* prevEdge = vert->getPrev();
+
+ if(isBelow(vert, thisEdge) && isAbove(vert, prevEdge))
+ {
+
+ /*case 1: this < v < prev
+ *the polygon is going down at v, the interior is to
+ *the right hand side.
+ * find the edge to the right of thisEdge for right range.
+ * delete thisEdge
+ * insert prevEdge
+ */
+ treeNode* thisNode = TreeNodeFind(searchTree, thisEdge, ( Int (*) (void *, void *))compEdges);
+ assert(thisNode);
+
+ treeNode* succ = TreeNodeSuccessor(thisNode);
+ assert(succ);
+ searchTree = TreeNodeDeleteSingleNode(searchTree, thisNode);
+ searchTree = TreeNodeInsert(searchTree, TreeNodeMake(prevEdge), ( Int (*) (void *, void *))compEdges);
+
+
+ ret_ranges[i] = sweepRangeMake(vert, 0, (directedLine*) (succ->key), 1);
+
+ }
+ else if(isAbove(vert, thisEdge) && isBelow(vert, prevEdge))
+ {
+
+ /*case 2: this > v > prev
+ *the polygon is going up at v, the interior is to
+ *the left hand side.
+ * find the edge to the left of thisEdge for left range.
+ * delete prevEdge
+ * insert thisEdge
+ */
+ treeNode* prevNode = TreeNodeFind(searchTree, prevEdge, ( Int (*) (void *, void *))compEdges);
+ assert(prevNode);
+ treeNode* pred = TreeNodePredecessor(prevNode);
+ searchTree = TreeNodeDeleteSingleNode(searchTree, prevNode);
+ searchTree = TreeNodeInsert(searchTree, TreeNodeMake(thisEdge), ( Int (*) (void *, void *))compEdges);
+ ret_ranges[i] = sweepRangeMake((directedLine*)(pred->key), 1, vert, 0);
+ }
+ else if(isAbove(vert, thisEdge) && isAbove(vert, prevEdge))
+ {
+
+ /*case 3: insert both edges*/
+ treeNode* thisNode = TreeNodeMake(thisEdge);
+ treeNode* prevNode = TreeNodeMake(prevEdge);
+ searchTree = TreeNodeInsert(searchTree, thisNode, ( Int (*) (void *, void *))compEdges);
+ searchTree = TreeNodeInsert(searchTree, prevNode, ( Int (*) (void *, void *))compEdges);
+ if(compEdges(thisEdge, prevEdge)<0) /*interior cusp*/
+ {
+
+ treeNode* leftEdge = TreeNodePredecessor(thisNode);
+ treeNode* rightEdge = TreeNodeSuccessor(prevNode);
+ ret_ranges[i] = sweepRangeMake( (directedLine*) leftEdge->key, 1,
+ (directedLine*) rightEdge->key, 1
+ );
+ }
+ else /*exterior cusp*/
+ {
+
+ ret_ranges[i] = sweepRangeMake( prevEdge, 1, thisEdge, 1);
+ }
+ }
+ else if(isBelow(vert, thisEdge) && isBelow(vert, prevEdge))
+ {
+
+ /*case 4: delete both edges*/
+ treeNode* thisNode = TreeNodeFind(searchTree, thisEdge, ( Int (*) (void *, void *))compEdges);
+ treeNode* prevNode = TreeNodeFind(searchTree, prevEdge, ( Int (*) (void *, void *))compEdges);
+ if(compEdges(thisEdge, prevEdge)>0) /*interior cusp*/
+ {
+ treeNode* leftEdge = TreeNodePredecessor(prevNode);
+ treeNode* rightEdge = TreeNodeSuccessor(thisNode);
+ ret_ranges[i] = sweepRangeMake( (directedLine*) leftEdge->key, 1,
+ (directedLine*) rightEdge->key, 1
+ );
+ }
+ else /*exterior cusp*/
+ {
+ ret_ranges[i] = sweepRangeMake( thisEdge, 1, prevEdge, 1);
+ }
+ searchTree = TreeNodeDeleteSingleNode(searchTree, thisNode);
+ searchTree = TreeNodeDeleteSingleNode(searchTree, prevNode);
+ }
+ else
+ {
+ fprintf(stderr,"error in partitionY.C, invalid case\n");
+ printf("vert is\n");
+ vert->printSingle();
+ printf("thisEdge is\n");
+ thisEdge->printSingle();
+ printf("prevEdge is\n");
+ prevEdge->printSingle();
+
+ exit(1);
+ }
+ }
+
+ /*finaly clean up space: delete the search tree*/
+ TreeNodeDeleteWholeTree(searchTree);
+}
diff --git a/src/glu/sgi/libnurbs/nurbtess/partitionY.h b/src/glu/sgi/libnurbs/nurbtess/partitionY.h
new file mode 100644
index 00000000000..814c6e83bed
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/partitionY.h
@@ -0,0 +1,104 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+ *partitionY.h:
+ *partition a polygon into a Y-monotone polygon:
+ * A polygon is Y-monotone if the boundary can be split into two polygon chains
+ *A and B such that each chain is Y-monotonic that is the intersection of any
+ *horizontal line intersects each chain has at most one connected componenets
+ * (empty, single point or a single line).
+ *
+ * A vertex is a cusp if both its ajacent vertices are either at or above v,
+ *or both at or below v. In addition, at least one of the ajacent verteces is
+ *strictly below or above v.
+ * A vertex is a relex vertex if the internals angle is strictly greater than
+ *180. In other words, if the the signed area is negative:
+ *(x1, y1), (x2, y2), (x3, y3) are the three vertices along a polygon, the
+ *order is such that left hand side is inside the polygon. Then (x2,y2) is
+ *reflex if:
+ * (x2-x1, y2-y1) cross (x3-x1, y3-y1) <0.
+ *A vertex is an interior cusp if it is a cusp and a reflex.
+ *A vertex is an exterior cusp if it is a cusp but not a reflex.
+ *
+ * $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/partitionY.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+ */
+
+#ifndef _PARTITIONY_H
+#define _PARTITIONY_H
+
+#include "directedLine.h"
+
+/*whether an edge is below a vertex*/
+Int isBelow(directedLine *v, directedLine *e);
+
+/*whether an edge is above a vertex*/
+Int isAbove(directedLine *v, directedLine *e);
+
+/*not-cusp,
+ *inerior cusp
+ *exterior cusp
+ */
+Int cuspType(directedLine *v);
+
+/*used in trapezoidalization*/
+typedef struct sweepRange{
+ directedLine *left;
+ Int leftType; /*either a vertex (leftType=0) or an edge (leftType =1) */
+ directedLine *right;
+ Int rightType; /*either a vertex (rightType=0) or an edge (rightType =1) */
+} sweepRange;
+
+sweepRange* sweepRangeMake(directedLine* left, Int leftType,
+ directedLine* right, Int rightType);
+
+void sweepRangeDelete(sweepRange* range);
+Int sweepRangeEqual(sweepRange* sr1, sweepRange* sr2);
+
+/*given a set of simple polygons where the interior
+ *is decided by left-hand principle,
+ *return a range (sight) for each vertex. This is called
+ *Trapezoidalization.
+ */
+void sweepY(Int nVertices, directedLine **sortedVerteces, sweepRange** ret_ranges);
+
+
+directedLine* partitionY(directedLine *polygons, sampledLine **retSampledLines);
+
+void findDiagonals(Int total_num_edges, directedLine** sortedVertices, sweepRange** ranges, Int& num_diagonals, directedLine** diagonal_vertices);
+
+directedLine** DBGfindDiagonals(directedLine *polygons, Int& num_diagonals);
+
+#endif
diff --git a/src/glu/sgi/libnurbs/nurbtess/polyDBG.cc b/src/glu/sgi/libnurbs/nurbtess/polyDBG.cc
new file mode 100644
index 00000000000..4d04df73f69
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/polyDBG.cc
@@ -0,0 +1,734 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include "zlassert.h"
+#include "polyDBG.h"
+
+#ifdef __WATCOMC__
+#pragma warning 14 10
+#pragma warning 391 10
+#pragma warning 726 10
+#endif
+
+static Real area(Real A[2], Real B[2], Real C[2])
+{
+ Real Bx, By, Cx, Cy;
+ Bx = B[0] - A[0];
+ By = B[1] - A[1];
+ Cx = C[0] - A[0];
+ Cy = C[1] - A[1];
+ return Bx*Cy - Cx*By;
+}
+
+Int DBG_isConvex(directedLine *poly)
+{
+ directedLine* temp;
+ if(area(poly->head(), poly->tail(), poly->getNext()->tail()) < 0.00000)
+ return 0;
+ for(temp = poly->getNext(); temp != poly; temp = temp->getNext())
+ {
+ if(area(temp->head(), temp->tail(), temp->getNext()->tail()) < 0.00000)
+ return 0;
+ }
+ return 1;
+}
+
+Int DBG_is_U_monotone(directedLine* poly)
+{
+ Int n_changes = 0;
+ Int prev_sign;
+ Int cur_sign;
+ directedLine* temp;
+ cur_sign = compV2InX(poly->tail(), poly->head());
+
+ n_changes = (compV2InX(poly->getPrev()->tail(), poly->getPrev()->head())
+ != cur_sign);
+
+ for(temp = poly->getNext(); temp != poly; temp = temp->getNext())
+ {
+ prev_sign = cur_sign;
+ cur_sign = compV2InX(temp->tail(), temp->head());
+
+ if(cur_sign != prev_sign)
+ n_changes++;
+ }
+
+ if(n_changes ==2) return 1;
+ else return 0;
+}
+
+/*if u-monotone, and there is a long horizontal edge*/
+Int DBG_is_U_direction(directedLine* poly)
+{
+/*
+ if(! DBG_is_U_monotone(poly))
+ return 0;
+*/
+ Int V_count = 0;
+ Int U_count = 0;
+ directedLine* temp;
+ if( fabs(poly->head()[0] - poly->tail()[0]) <= fabs(poly->head()[1]-poly->tail()[1]))
+ V_count += poly->get_npoints();
+ else
+ U_count += poly->get_npoints();
+ /*
+ else if(poly->head()[1] == poly->tail()[1])
+ U_count += poly->get_npoints();
+ */
+ for(temp = poly->getNext(); temp != poly; temp = temp->getNext())
+ {
+ if( fabs(temp->head()[0] - temp->tail()[0]) <= fabs(temp->head()[1]-temp->tail()[1]))
+ V_count += temp->get_npoints();
+ else
+ U_count += temp->get_npoints();
+ /*
+ if(temp->head()[0] == temp->tail()[0])
+ V_count += temp->get_npoints();
+ else if(temp->head()[1] == temp->tail()[1])
+ U_count += temp->get_npoints();
+ */
+ }
+
+ if(U_count > V_count) return 1;
+ else return 0;
+}
+
+/*given two line segments, determine whether
+ *they intersect each other or not.
+ *return 1 if they do,
+ *return 0 otherwise
+ */
+Int DBG_edgesIntersect(directedLine* l1, directedLine* l2)
+{
+ if(l1->getNext() == l2)
+ {
+ if(area(l1->head(), l1->tail(), l2->tail()) == 0) //colinear
+ {
+ if( (l1->tail()[0] - l1->head()[0])*(l2->tail()[0]-l2->head()[0]) +
+ (l1->tail()[1] - l1->head()[1])*(l2->tail()[1]-l2->head()[1]) >=0)
+ return 0; //not intersect
+ else
+ return 1;
+ }
+ //else we use the normal code
+ }
+ else if(l1->getPrev() == l2)
+ {
+ if(area(l2->head(), l2->tail(), l1->tail()) == 0) //colinear
+ {
+ if( (l2->tail()[0] - l2->head()[0])*(l1->tail()[0]-l1->head()[0]) +
+ (l2->tail()[1] - l2->head()[1])*(l1->tail()[1]-l1->head()[1]) >=0)
+ return 0; //not intersect
+ else
+ return 1;
+ }
+ //else we use the normal code
+ }
+ else //the two edges are not connected
+ {
+ if((l1->head()[0] == l2->head()[0] &&
+ l1->head()[1] == l2->head()[1]) ||
+ (l1->tail()[0] == l2->tail()[0] &&
+ l1->tail()[1] == l2->tail()[1]))
+ return 1;
+
+ }
+
+
+ if(
+ (
+ area(l1->head(), l1->tail(), l2->head())
+ *
+ area(l1->head(), l1->tail(), l2->tail())
+ < 0
+ )
+ &&
+ (
+ area(l2->head(), l2->tail(), l1->head())
+ *area(l2->head(), l2->tail(), l1->tail())
+ < 0
+ )
+ )
+ return 1;
+ else
+ return 0;
+}
+
+/*whether AB and CD intersect
+ *return 1 if they do
+ *retur 0 otheriwse
+ */
+Int DBG_edgesIntersectGen(Real A[2], Real B[2], Real C[2], Real D[2])
+{
+ if(
+ (
+ area(A, B, C) * area(A,B,D) <0
+ )
+ &&
+ (
+ area(C,D,A) * area(C,D,B) < 0
+ )
+ )
+ return 1;
+ else
+ return 0;
+}
+
+/*determien whether (A,B) interesect chain[start] to [end]
+ */
+Int DBG_intersectChain(vertexArray* chain, Int start, Int end, Real A[2], Real B[2])
+{
+ Int i;
+ for(i=start; i<=end-2; i++)
+ if(DBG_edgesIntersectGen(chain->getVertex(i), chain->getVertex(i+1), A, B))
+ return 1;
+
+ return 0;
+}
+
+/*determine whether a polygon intersect itself or not
+ *return 1 is it does,
+ * 0 otherwise
+ */
+Int DBG_polygonSelfIntersect(directedLine* poly)
+{
+ directedLine* temp1;
+ directedLine* temp2;
+ temp1=poly;
+ for(temp2=temp1->getNext(); temp2 != temp1; temp2=temp2->getNext())
+ {
+ if(DBG_edgesIntersect(temp1, temp2))
+ {
+ return 1;
+ }
+
+ }
+
+ for(temp1=poly->getNext(); temp1 != poly; temp1 = temp1->getNext())
+ for(temp2=temp1->getNext(); temp2 != temp1; temp2=temp2->getNext())
+ {
+ if(DBG_edgesIntersect(temp1, temp2))
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*check whether a line segment intersects a polygon
+ */
+Int DBG_edgeIntersectPoly(directedLine* edge, directedLine* poly)
+{
+ directedLine* temp;
+ if(DBG_edgesIntersect(edge, poly))
+ return 1;
+ for(temp=poly->getNext(); temp != poly; temp=temp->getNext())
+ if(DBG_edgesIntersect(edge, temp))
+ return 1;
+ return 0;
+}
+
+/*check whether two polygons intersect
+ */
+Int DBG_polygonsIntersect(directedLine* p1, directedLine* p2)
+{
+ directedLine* temp;
+ if(DBG_edgeIntersectPoly(p1, p2))
+ return 1;
+ for(temp=p1->getNext(); temp!= p1; temp = temp->getNext())
+ if(DBG_edgeIntersectPoly(temp, p2))
+ return 1;
+ return 0;
+}
+
+/*check whether there are polygons intersecting each other in
+ *a list of polygons
+ */
+Int DBG_polygonListIntersect(directedLine* pList)
+{
+ directedLine *temp;
+ for(temp=pList; temp != NULL; temp = temp->getNextPolygon())
+ if(DBG_polygonSelfIntersect(temp))
+ return 1;
+ directedLine* temp2;
+ for(temp=pList; temp!=NULL; temp=temp->getNextPolygon())
+ {
+ for(temp2=temp->getNextPolygon(); temp2 != NULL; temp2=temp2->getNextPolygon())
+ if(DBG_polygonsIntersect(temp, temp2))
+ return 1;
+ }
+
+ return 0;
+}
+
+
+Int DBG_isCounterclockwise(directedLine* poly)
+{
+ return (poly->polyArea() > 0);
+}
+
+/*ray: v0 with direction (dx,dy).
+ *edge: v1-v2.
+ * the extra point v10[2] is given for the information at
+ *v1. Basically this edge is connectd to edge
+ * v10-v1. If v1 is on the ray,
+ * then we need v10 to determine whether this ray intersects
+ * the edge or not (that is, return 1 or return 0).
+ * If v1 is on the ray, then if v2 and v10 are on the same side of the ray,
+ * we return 0, otherwise return 1.
+ *For v2, if v2 is on the ray, we always return 0.
+ *Notice that v1 and v2 are not symmetric. So the edge is directed!!!
+ * The purpose for this convention is such that: a point is inside a polygon
+ * if and only if it intersets with odd number of edges.
+ */
+Int DBG_rayIntersectEdge(Real v0[2], Real dx, Real dy, Real v10[2], Real v1[2], Real v2[2])
+{
+/*
+if( (v1[1] >= v0[1] && v2[1]<= v0[1] )
+ ||(v2[1] >= v0[1] && v1[1]<= v0[1] )
+ )
+ printf("rayIntersectEdge, *********\n");
+*/
+
+ Real denom = (v2[0]-v1[0])*(-dy) - (v2[1]-v1[1]) * (-dx);
+ Real nomRay = (v2[0]-v1[0]) * (v0[1] - v1[1]) - (v2[1]-v1[1])*(v0[0]-v1[0]);
+ Real nomEdge = (v0[0]-v1[0]) * (-dy) - (v0[1]-v1[1])*(-dx);
+
+
+ /*if the ray is parallel to the edge, return 0: not intersect*/
+ if(denom == 0.0)
+ return 0;
+
+ /*if v0 is on the edge, return 0: not intersect*/
+ if(nomRay == 0.0)
+ return 0;
+
+ /*if v1 is on the positive ray, and the neighbor of v1 crosses the ray
+ *return 1: intersect
+ */
+ if(nomEdge == 0)
+ { /*v1 is on the positive or negative ray*/
+
+/*
+ printf("v1 is on the ray\n");
+*/
+
+ if(dx*(v1[0]-v0[0])>=0 && dy*(v1[1]-v0[1])>=0) /*v1 on positive ray*/
+ {
+ if(area(v0, v1, v10) * area(v0, v1, v2) >0)
+ return 0;
+ else
+ return 1;
+ }
+ else /*v1 on negative ray*/
+ return 0;
+ }
+
+ /*if v2 is on the ray, always return 0: not intersect*/
+ if(nomEdge == denom) {
+/* printf("v2 is on the ray\n");*/
+ return 0;
+ }
+
+ /*finally */
+ if(denom*nomRay>0 && denom*nomEdge>0 && nomEdge/denom <=1.0)
+ return 1;
+ return 0;
+}
+
+
+/*return the number of intersections*/
+Int DBG_rayIntersectPoly(Real v0[2], Real dx, Real dy, directedLine* poly)
+{
+ directedLine* temp;
+ Int count=0;
+ if(DBG_rayIntersectEdge(v0, dx, dy, poly->getPrev()->head(), poly->head(), poly->tail()))
+ count++;
+
+ for(temp=poly->getNext(); temp != poly; temp = temp->getNext())
+ if(DBG_rayIntersectEdge(v0, dx, dy, temp->getPrev()->head(), temp->head(), temp->tail()))
+ count++;
+/*printf("ray intersect poly: count=%i\n", count);*/
+ return count;
+}
+
+Int DBG_pointInsidePoly(Real v[2], directedLine* poly)
+{
+/*
+printf("enter pointInsidePoly , v=(%f,%f)\n", v[0], v[1]);
+printf("the polygon is\n");
+poly->printList();
+*/
+ /*for debug purpose*/
+ assert( (DBG_rayIntersectPoly(v,1,0,poly) % 2 )
+ == (DBG_rayIntersectPoly(v,1,Real(0.1234), poly) % 2 )
+ );
+ if(DBG_rayIntersectPoly(v, 1, 0, poly) % 2 == 1)
+ return 1;
+ else
+ return 0;
+}
+
+/*return the number of polygons which contain thie polygon
+ * as a subset
+ */
+Int DBG_enclosingPolygons(directedLine* poly, directedLine* list)
+{
+ directedLine* temp;
+ Int count=0;
+/*
+printf("%i\n", DBG_pointInsidePoly(poly->head(),
+ list->getNextPolygon()
+ ->getNextPolygon()
+ ->getNextPolygon()
+ ->getNextPolygon()
+));
+*/
+
+ for(temp = list; temp != NULL; temp = temp->getNextPolygon())
+ {
+ if(poly != temp)
+ if(DBG_pointInsidePoly(poly->head(), temp))
+ count++;
+/* printf("count=%i\n", count);*/
+ }
+ return count;
+}
+
+void DBG_reverse(directedLine* poly)
+{
+ if(poly->getDirection() == INCREASING)
+ poly->putDirection(DECREASING);
+ else
+ poly->putDirection(INCREASING);
+
+ directedLine* oldNext = poly->getNext();
+ poly->putNext(poly->getPrev());
+ poly->putPrev(oldNext);
+
+ directedLine* temp;
+ for(temp=oldNext; temp!=poly; temp = oldNext)
+ {
+ if(temp->getDirection() == INCREASING)
+ temp->putDirection(DECREASING);
+ else
+ temp->putDirection(INCREASING);
+
+ oldNext = temp->getNext();
+ temp->putNext(temp->getPrev());
+ temp->putPrev(oldNext);
+ }
+ printf("reverse done\n");
+}
+
+Int DBG_checkConnectivity(directedLine *polygon)
+{
+ if(polygon == NULL) return 1;
+ directedLine* temp;
+ if(polygon->head()[0] != polygon->getPrev()->tail()[0] ||
+ polygon->head()[1] != polygon->getPrev()->tail()[1])
+ return 0;
+ for(temp=polygon->getNext(); temp != polygon; temp=temp->getNext())
+ {
+ if(temp->head()[0] != temp->getPrev()->tail()[0] ||
+ temp->head()[1] != temp->getPrev()->tail()[1])
+ return 0;
+ }
+ return 1;
+}
+
+/*print out error message.
+ *If it cannot modify the polygon list to make it satify the
+ *requirements, return 1.
+ *otherwise modify the polygon list, and return 0
+ */
+Int DBG_check(directedLine *polyList)
+{
+ directedLine* temp;
+ if(polyList == NULL) return 0;
+
+ /*if there are intersections, print out error message
+ */
+ if(DBG_polygonListIntersect(polyList))
+ {
+ fprintf(stderr, "DBG_check: there are self intersections, don't know to modify the polygons\n");
+ return 1;
+ }
+
+ /*check the connectivity of each polygon*/
+ for(temp = polyList; temp!= NULL; temp = temp ->getNextPolygon())
+ {
+ if(! DBG_checkConnectivity(temp))
+ {
+ fprintf(stderr, "DBG_check, polygon not connected\n");
+ return 1;
+ }
+ }
+
+ /*check the orientation of each polygon*/
+ for(temp = polyList; temp!= NULL; temp = temp ->getNextPolygon())
+ {
+
+
+ Int correctDir;
+
+ if( DBG_enclosingPolygons(temp, polyList) % 2 == 0)
+ correctDir = 1; /*counterclockwise*/
+ else
+ correctDir = 0; /*clockwise*/
+
+ Int actualDir = DBG_isCounterclockwise(temp);
+
+ if(correctDir != actualDir)
+ {
+ fprintf(stderr, "DBG_check: polygon with incorrect orientations. reversed\n");
+
+ DBG_reverse(temp);
+ }
+
+ }
+ return 0;
+}
+
+/**************handle self intersections*****************/
+//determine whether e interects [begin, end] or not
+static directedLine* DBG_edgeIntersectChainD(directedLine *e,
+ directedLine *begin, directedLine *end)
+{
+ directedLine *temp;
+ for(temp=begin; temp != end; temp = temp->getNext())
+ {
+ if(DBG_edgesIntersect(e, temp))
+ return temp;
+ }
+ if(DBG_edgesIntersect(e, end))
+ return end;
+ return NULL;
+}
+
+//given a polygon, cut the edges off and finally obtain a
+//a polygon without intersections. The cut-off edges are
+//dealloated. The new polygon is returned.
+directedLine* DBG_cutIntersectionPoly(directedLine *polygon, int& cutOccur)
+{
+ directedLine *begin, *end, *next;
+ begin = polygon;
+ end = polygon;
+ cutOccur = 0;
+ while( (next = end->getNext()) != begin)
+ {
+ directedLine *interc = NULL;
+ if( (interc = DBG_edgeIntersectChainD(next, begin, end)))
+ {
+ int fixed = 0;
+ if(DBG_edgesIntersect(next, interc->getNext()))
+ {
+ //trying to fix it
+ Real buf[2];
+ int i;
+ Int n=5;
+ buf[0] = interc->tail()[0];
+ buf[1] = interc->tail()[1];
+
+ for(i=1; i<n; i++)
+ {
+ Real r = ((Real)i) / ((Real) n);
+ Real u = (1-r) * interc->head()[0] + r * interc->tail()[0];
+ Real v = (1-r) * interc->head()[1] + r * interc->tail()[1];
+ interc->tail()[0] = interc->getNext()->head()[0] = u;
+ interc->tail()[1] = interc->getNext()->head()[1] = v;
+ if( (! DBG_edgesIntersect(next, interc)) &&
+ (! DBG_edgesIntersect(next, interc->getNext())))
+ break; //we fixed it
+ }
+ if(i==n) // we didn't fix it
+ {
+ fixed = 0;
+ //back to original
+ interc->tail()[0] = interc->getNext()->head()[0] = buf[0];
+ interc->tail()[1] = interc->getNext()->head()[1] = buf[1];
+ }
+ else
+ {
+ fixed = 1;
+ }
+ }
+ if(fixed == 0)
+ {
+ cutOccur = 1;
+ begin->deleteSingleLine(next);
+
+ if(begin != end)
+ {
+ if(DBG_polygonSelfIntersect(begin))
+ {
+ directedLine* newEnd = end->getPrev();
+ begin->deleteSingleLine(end);
+ end = newEnd;
+ }
+ }
+ }
+ else
+ {
+ end = end->getNext();
+ }
+ }
+ else
+ {
+ end = end->getNext();
+ }
+ }
+ return begin;
+}
+
+//given a polygon, cut the edges off and finally obtain a
+//a polygon without intersections. The cut-off edges are
+//dealloated. The new polygon is returned.
+#if 0 // UNUSED
+static directedLine* DBG_cutIntersectionPoly_notwork(directedLine *polygon)
+{
+ directedLine *crt;//current polygon
+ directedLine *begin;
+ directedLine *end;
+ directedLine *temp;
+ crt = polygon;
+ int find=0;
+ while(1)
+ {
+//printf("loop\n");
+ //if there are less than 3 edges, we should stop
+ if(crt->getPrev()->getPrev() == crt)
+ return NULL;
+
+ if(DBG_edgesIntersect(crt, crt->getNext()) ||
+ (crt->head()[0] == crt->getNext()->tail()[0] &&
+ crt->head()[1] == crt->getNext()->tail()[1])
+ )
+ {
+ find = 1;
+ crt=crt->deleteChain(crt, crt->getNext());
+ }
+ else
+ {
+ //now we know crt and crt->getNext do not intersect
+ begin = crt;
+ end = crt->getNext();
+//printf("begin=(%f,%f)\n", begin->head()[0], begin->head()[1]);
+//printf("end=(%f,%f)\n", end->head()[0], end->head()[1]);
+ for(temp=end->getNext(); temp!=begin; temp= temp->getNext())
+ {
+//printf("temp=(%f,%f)\n", temp->head()[0], temp->head()[1]);
+ directedLine *intersect = DBG_edgeIntersectChainD(temp, begin, end);
+ if(intersect != NULL)
+ {
+ crt = crt->deleteChain(intersect, temp);
+ find=1;
+ break; //the for loop
+ }
+ else
+ {
+ end = temp;
+ }
+ }
+ }
+ if(find == 0)
+ return crt;
+ else
+ find = 0; //go to next loop
+}
+}
+#endif
+
+directedLine* DBG_cutIntersectionAllPoly(directedLine* list)
+{
+ directedLine* temp;
+ directedLine* tempNext=NULL;
+ directedLine* ret = NULL;
+ int cutOccur=0;
+ for(temp=list; temp != NULL; temp = tempNext)
+ {
+ directedLine *left;
+ tempNext = temp->getNextPolygon();
+
+ left = DBG_cutIntersectionPoly(temp, cutOccur);
+ if(left != NULL)
+ ret=left->insertPolygon(ret);
+ }
+ return ret;
+}
+
+sampledLine* DBG_collectSampledLinesAllPoly(directedLine *polygonList)
+{
+ directedLine *temp;
+ sampledLine* tempHead = NULL;
+ sampledLine* tempTail = NULL;
+ sampledLine* cHead = NULL;
+ sampledLine* cTail = NULL;
+
+ if(polygonList == NULL)
+ return NULL;
+
+ DBG_collectSampledLinesPoly(polygonList, cHead, cTail);
+
+ assert(cHead);
+ assert(cTail);
+ for(temp = polygonList->getNextPolygon(); temp != NULL; temp = temp->getNextPolygon())
+ {
+ DBG_collectSampledLinesPoly(temp, tempHead, tempTail);
+ cTail->insert(tempHead);
+ cTail = tempTail;
+ }
+ return cHead;
+}
+
+void DBG_collectSampledLinesPoly(directedLine *polygon, sampledLine*& retHead, sampledLine*& retTail)
+{
+ directedLine *temp;
+ retHead = NULL;
+ retTail = NULL;
+ if(polygon == NULL)
+ return;
+
+ retHead = retTail = polygon->getSampledLine();
+ for(temp = polygon->getNext(); temp != polygon; temp=temp->getNext())
+ {
+ retHead = temp->getSampledLine()->insert(retHead);
+ }
+}
diff --git a/src/glu/sgi/libnurbs/nurbtess/polyDBG.h b/src/glu/sgi/libnurbs/nurbtess/polyDBG.h
new file mode 100644
index 00000000000..18169931686
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/polyDBG.h
@@ -0,0 +1,75 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/polyDBG.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#ifndef _POLYDBG_H
+#define _POLYDBG_H
+
+#include "definitions.h"
+#include "directedLine.h"
+#include "monoTriangulation.h"
+
+Int DBG_edgesIntersectGen(Real A[2], Real B[2], Real C[2], Real D[2]);
+Int DBG_intersectChain(vertexArray* chain, Int start, Int end, Real A[2], Real B[2]);
+
+
+Int DBG_edgesIntersect(directedLine* l1, directedLine* l2);
+Int DBG_polygonSelfIntersect(directedLine* poly);
+Int DBG_edgeIntersectPoly(directedLine* edge, directedLine* poly);
+Int DBG_polygonsIntersect(directedLine* p1, directedLine* p2);
+Int DBG_polygonListIntersect(directedLine* pList);
+
+Int DBG_isCounterclockwise(directedLine* poly);
+Int DBG_rayIntersectEdge(Real v0[2], Real dx, Real dy, Real v10[2], Real v1[2], Real v2[2]);
+Int DBG_pointInsidePoly(Real v[2], directedLine* poly);
+Int DBG_enclosingPolygons(directedLine* poly, directedLine* list);
+void DBG_reverse(directedLine* poly);
+Int DBG_check(directedLine *polyList);
+
+Int DBG_isConvex(directedLine *poly);
+Int DBG_is_U_direction(directedLine *poly);
+Int DBG_is_U_monotone(directedLine* poly);
+
+directedLine* DBG_cutIntersectionAllPoly(directedLine* list);
+directedLine* DBG_cutIntersectionPoly(directedLine *polygon, int& cutOccur);
+
+sampledLine* DBG_collectSampledLinesAllPoly(directedLine *polygonList);
+
+void DBG_collectSampledLinesPoly(directedLine *polygon, sampledLine*& retHead, sampledLine*& retTail);
+
+#endif
diff --git a/src/glu/sgi/libnurbs/nurbtess/polyUtil.cc b/src/glu/sgi/libnurbs/nurbtess/polyUtil.cc
new file mode 100644
index 00000000000..701c6368b10
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/polyUtil.cc
@@ -0,0 +1,92 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/polyUtil.cc,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "polyUtil.h"
+
+Real area(Real A[2], Real B[2], Real C[2])
+{
+ Real Bx, By, Cx, Cy;
+ Bx = B[0] - A[0];
+ By = B[1] - A[1];
+ Cx = C[0] - A[0];
+ Cy = C[1] - A[1];
+ return Bx*Cy - Cx*By;
+
+/* return (B[0]-A[0])*(C[1]-A[1]) - (C[0]-A[0])*(B[1]-A[1]);*/
+}
+
+/*given a directed line A->B, and a point P,
+ *determine whether P is to the left of AB.
+ *the line A->B (imagine it has beedn extended both
+ *end to the infinity) divides the plan into two
+ *half planes. When we walk from A to B, one
+ *half is to the left and the other half is to the right.
+ *return 1 if P is to the left.
+ *if P is on AB, 0 is returned.
+ */
+Int pointLeftLine(Real A[2], Real B[2], Real P[2])
+{
+ if(area(A, B, P) >0) return 1;
+ else return 0;
+}
+
+/*given two directed line: A -> B -> C, and another point P.
+ *determine whether P is to the left hand side of A->B->C.
+ *Think of BA and BC extended as two rays. So that the plane is
+ * divided into two parts. One part is to the left we walk from A
+ *to B and to C, the other part is to the right.
+ * In order for P to be the left, P must be either to the left
+ *of
+ */
+Int pointLeft2Lines(Real A[2], Real B[2], Real C[2], Real P[2])
+{
+ Int C_left_AB = (area(A, B, C)>0);
+ Int P_left_AB = (area(A, B, P)>0);
+ Int P_left_BC = (area(B, C, P)>0);
+
+ if(C_left_AB)
+ {
+ return (P_left_AB && P_left_BC);
+ }
+ else
+ return (P_left_AB || P_left_BC);
+}
diff --git a/src/glu/sgi/libnurbs/nurbtess/polyUtil.h b/src/glu/sgi/libnurbs/nurbtess/polyUtil.h
new file mode 100644
index 00000000000..dfb78a3df45
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/polyUtil.h
@@ -0,0 +1,54 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/11/29 16:16:55 $ $Revision: 1.2 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/polyUtil.h,v 1.2 2001/11/29 16:16:55 kschultz Exp $
+*/
+
+#ifndef _POLYUTIL_H
+#define _POLYUTIL_H
+
+#include "definitions.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+Real area(Real A[2], Real B[2], Real C[2]);
+
+Int pointLeftLine(Real A[2], Real B[2], Real P[2]);
+Int pointLeft2Lines(Real A[2], Real B[2], Real C[2], Real P[2]);
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/glu/sgi/libnurbs/nurbtess/primitiveStream.cc b/src/glu/sgi/libnurbs/nurbtess/primitiveStream.cc
new file mode 100644
index 00000000000..81a06ce5d99
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/primitiveStream.cc
@@ -0,0 +1,192 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/primitiveStream.cc,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <GL/gl.h>
+
+#include "primitiveStream.h"
+
+Int primStream::num_triangles()
+{
+ Int i;
+ Int ret=0;
+ for(i=0; i<index_lengths; i++)
+ {
+ ret += lengths[i]-2;
+ }
+ return ret;
+}
+
+
+
+/*the begining of inserting a new primitive.
+ *reset counter to be 0.
+ */
+void primStream::begin()
+{
+ counter = 0;
+}
+
+void primStream::insert(Real u, Real v)
+{
+ /*if the space cannot hold u and v,
+ *we have to expand the array
+ */
+ if(index_vertices+1 >= size_vertices) {
+ Real* temp = (Real*) malloc (sizeof(Real) * (2*size_vertices + 2));
+ assert(temp);
+
+ /*copy*/
+ for(Int i=0; i<index_vertices; i++)
+ temp[i] = vertices[i];
+
+ free(vertices);
+ vertices = temp;
+ size_vertices = 2*size_vertices + 2;
+ }
+
+ vertices[index_vertices++] = u;
+ vertices[index_vertices++] = v;
+ counter++;
+}
+
+/*the end of a primitive.
+ *increase index_lengths
+ */
+void primStream::end(Int type)
+{
+ Int i;
+ /*if there is no vertex in this primitive,
+ *nothing needs to be done
+ */
+ if(counter == 0) return ;
+
+ if(index_lengths >= size_lengths){
+ Int* temp = (Int*) malloc(sizeof(Int) * (2*size_lengths + 2));
+ assert(temp);
+ Int* tempTypes = (Int*) malloc(sizeof(Int) * (2*size_lengths + 2));
+ assert(tempTypes);
+
+ /*copy*/
+ for(i=0; i<index_lengths; i++){
+ temp[i] = lengths[i];
+ tempTypes[i] = types[i];
+ }
+
+ free(lengths);
+ free(types);
+ lengths = temp;
+ types = tempTypes;
+ size_lengths = 2*size_lengths + 2;
+ }
+ lengths[index_lengths] = counter;
+ types[index_lengths] = type;
+ index_lengths++;
+}
+
+void primStream::print()
+{
+ Int i,j,k;
+ printf("index_lengths=%i,size_lengths=%i\n", index_lengths, size_lengths);
+ printf("index_vertices=%i,size_vertices=%i\n", index_vertices, size_vertices);
+ k=0;
+ for(i=0; i<index_lengths; i++)
+ {
+ if(types[i] == PRIMITIVE_STREAM_FAN)
+ printf("primitive-FAN:\n");
+ else
+ printf("primitive-STRIP:\n");
+ for(j=0; j<lengths[i]; j++)
+ {
+ printf("(%f,%f) ", vertices[k], vertices[k+1]);
+ k += 2;
+ }
+ printf("\n");
+ }
+}
+
+primStream::primStream(Int sizeLengths, Int sizeVertices)
+{
+ lengths = (Int*)malloc (sizeof(Int) * sizeLengths);
+ assert(lengths);
+ types = (Int*)malloc (sizeof(Int) * sizeLengths);
+ assert(types);
+
+ vertices = (Real*) malloc(sizeof(Real) * sizeVertices);
+ assert(vertices);
+
+ index_lengths = 0;
+ index_vertices = 0;
+ size_lengths = sizeLengths;
+ size_vertices = sizeVertices;
+}
+
+primStream::~primStream()
+{
+ free(lengths);
+ free(types);
+ free(vertices);
+}
+
+void primStream::draw()
+{
+ Int i,j,k;
+ k=0;
+ for(i=0; i<index_lengths; i++)
+ {
+ switch(types[i]){
+ case PRIMITIVE_STREAM_FAN:
+ glBegin(GL_TRIANGLE_FAN);
+ break;
+ case PRIMITIVE_STREAM_STRIP:
+ glBegin(GL_TRIANGLE_STRIP);
+ break;
+ }
+
+ for(j=0; j<lengths[i]; j++){
+ glVertex2fv(vertices+k);
+ k += 2;
+ }
+ glEnd();
+ }
+}
+
diff --git a/src/glu/sgi/libnurbs/nurbtess/primitiveStream.h b/src/glu/sgi/libnurbs/nurbtess/primitiveStream.h
new file mode 100644
index 00000000000..7590950be48
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/primitiveStream.h
@@ -0,0 +1,116 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/primitiveStream.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+/*we do not use the constans GL_... so that this file is independent of
+ *<GL/gl.h>
+ */
+
+#ifndef _PRIMITIVE_STREAM_H
+#define _PRIMITIVE_STREAM_H
+
+enum {PRIMITIVE_STREAM_FAN, PRIMITIVE_STREAM_STRIP};
+
+#include "definitions.h"
+
+class primStream {
+ Int *lengths; /*length[i]=number of vertices of ith primitive*/
+ Int *types; /*each primive has a type: FAN or STREAM*/
+ Real *vertices; /*the size >= 2 * num_vertices, each vertex (u,v)*/
+
+ /*the following size information are used for dynamic arrays*/
+ Int index_lengths; /*the current available entry*/
+ Int size_lengths; /*the allocated size of the array: lengths*/
+ Int index_vertices;
+ Int size_vertices;
+
+ /*the vertex is inserted one by one. counter is used to
+ *count the number of vertices which have been inserted so far in
+ *the current primitive
+ */
+ Int counter;
+
+public:
+ primStream(Int sizeLengths, Int sizeVertices);
+ ~primStream();
+
+ Int get_n_prims() //num of primitives
+ {
+ return index_lengths;
+ }
+ Int get_type(Int i) //the type of ith primitive
+ {
+ return types[i];
+ }
+ Int get_length(Int i) //the length of the ith primitive
+ {
+ return lengths[i];
+ }
+ Real* get_vertices() {return vertices;}
+
+ /*the begining of inserting a new primitive.
+ *reset counter to be 0.
+ */
+ void begin();
+ void insert(Real u, Real v);
+ void insert(Real v[2]) {insert(v[0], v[1]);}
+ void end(Int type);
+
+ Int num_triangles();
+
+ void triangle(Real A[2], Real B[2], Real C[2])
+ {
+ begin();
+ insert(A);
+ insert(B);
+ insert(C);
+ end(PRIMITIVE_STREAM_FAN);
+ }
+ void print();
+ void draw(); /*using GL to draw the primitives*/
+};
+
+
+
+
+
+
+
+
+#endif
+
diff --git a/src/glu/sgi/libnurbs/nurbtess/quicksort.cc b/src/glu/sgi/libnurbs/nurbtess/quicksort.cc
new file mode 100644
index 00000000000..bb49779bc31
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/quicksort.cc
@@ -0,0 +1,79 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2002/04/17 19:30:41 $ $Revision: 1.2 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/quicksort.cc,v 1.2 2002/04/17 19:30:41 brianp Exp $
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+
+static void swap(void *v[], int i, int j)
+{
+ void *temp;
+ temp = v[i];
+ v[i] = v[j];
+ v[j] = temp;
+}
+
+/*as an example to use this function to
+ *sort integers, you need to supply the function
+ *int comp(int *i1, int *i2)
+ *{
+ * if( *i1 < * i2) return -1;
+ * else return 1;
+ *}
+ *and an array of pointers to integers:
+ * int *v[100] (allocate space for where each v[i] points to).
+ *then you can call:
+ * quicksort( (void**)v, left, right, (int (*)(void *, void *))comp)
+ */
+void quicksort(void *v[], int left, int right,
+ int (*comp) (void *, void *))
+{
+ int i, last;
+ if(left >= right) /*do nothing if array contains */
+ return; /*fewer than two elements*/
+
+ swap(v, left, (left+right)/2);
+ last = left;
+ for(i=left+1; i<=right; i++)
+ if((*comp)(v[i], v[left])<0)
+ swap(v, ++last, i);
+ swap(v, left, last);
+ quicksort(v, left, last-1, comp);
+ quicksort(v, last+1, right, comp);
+}
diff --git a/src/glu/sgi/libnurbs/nurbtess/quicksort.h b/src/glu/sgi/libnurbs/nurbtess/quicksort.h
new file mode 100644
index 00000000000..4112ba0b23a
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/quicksort.h
@@ -0,0 +1,49 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/quicksort.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#ifndef _QUICKSORT_H
+#define _QUICKSORT_H
+
+#include <stdlib.h>
+#include <stdio.h>
+
+void quicksort(void *v[], int left, int right,
+ int (*comp) (void *, void *));
+
+#endif
diff --git a/src/glu/sgi/libnurbs/nurbtess/rectBlock.cc b/src/glu/sgi/libnurbs/nurbtess/rectBlock.cc
new file mode 100644
index 00000000000..9c9a75b44c6
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/rectBlock.cc
@@ -0,0 +1,198 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/rectBlock.cc,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include "glimports.h"
+#include "zlassert.h"
+#include <GL/gl.h>
+
+#include "rectBlock.h"
+
+rectBlock::rectBlock(gridBoundaryChain* left, gridBoundaryChain* right, Int beginVline, Int endVline)
+{
+ Int i;
+
+
+ upGridLineIndex = left->getVlineIndex(beginVline);
+
+ lowGridLineIndex = left->getVlineIndex(endVline);
+
+ Int n = upGridLineIndex-lowGridLineIndex+1; //number of grid lines
+ leftIndices = (Int*) malloc(sizeof(Int) * n);
+ assert(leftIndices);
+ rightIndices = (Int*) malloc(sizeof(Int) * n);
+ assert(rightIndices);
+ for(i=0; i<n; i++)
+ {
+
+ leftIndices[i] = left->getInnerIndex(i+beginVline);
+ rightIndices[i] = right->getInnerIndex(i+beginVline);
+ }
+}
+
+
+rectBlock::~rectBlock()
+{
+ free(leftIndices);
+ free(rightIndices);
+}
+
+void rectBlock::print()
+{
+ Int i;
+ printf("block:\n");
+ for(i=upGridLineIndex; i >= lowGridLineIndex; i--)
+ {
+ printf("gridline %i, (%i,%i)\n", i, leftIndices[upGridLineIndex-i], rightIndices[upGridLineIndex-i]);
+ }
+}
+
+
+
+void rectBlock::draw(Real* u_values, Real* v_values)
+{
+ Int i,j,k;
+ //upgrid line to bot grid line
+#ifdef DEBUG
+printf("upGridLineIndex=%i, lowGridLineIndex=%i\n", upGridLineIndex, lowGridLineIndex);
+#endif
+ for(k=0, i=upGridLineIndex; i > lowGridLineIndex; i--, k++)
+ {
+ glBegin(GL_QUAD_STRIP);
+
+ for(j=leftIndices[k+1]; j<= rightIndices[k+1]; j++)
+ {
+ glVertex2f(u_values[j], v_values[i]);
+ glVertex2f(u_values[j], v_values[i-1]);
+ }
+ glEnd();
+ }
+}
+
+
+Int rectBlock::num_quads()
+{
+ Int ret=0;
+ Int k,i;
+ for(k=0, i=upGridLineIndex; i>lowGridLineIndex; i--, k++)
+ {
+ ret += (rightIndices[k+1]-leftIndices[k+1]);
+ }
+ return ret;
+}
+
+Int rectBlockArray::num_quads()
+{
+ Int ret=0;
+ for(Int i=0; i<n_elements; i++)
+ ret += array[i]->num_quads();
+ return ret;
+}
+
+rectBlockArray::rectBlockArray(Int s)
+{
+ Int i;
+ n_elements = 0;
+ size = s;
+ array = (rectBlock**) malloc(sizeof(rectBlock*) * s);
+ assert(array);
+//initialization
+ for(i=0; i<s; i++)
+ array[i] = NULL;
+}
+
+rectBlockArray::~rectBlockArray()
+{
+ Int i;
+ for(i=0; i<size; i++)
+ {
+ if(array[i] != NULL)
+ delete array[i];
+ }
+ free(array);
+}
+
+//put to the end of the array, check the size
+void rectBlockArray::insert(rectBlock* newBlock)
+{
+ Int i;
+ if(n_elements == size) //full
+ {
+ rectBlock** temp = (rectBlock**) malloc(sizeof(rectBlock) * (2*size+1));
+ assert(temp);
+ //initialization
+ for(i=0; i<2*size+1; i++)
+ temp[i] = NULL;
+
+ for(i=0; i<n_elements; i++)
+ temp[i] = array[i];
+
+ free(array);
+ array = temp;
+ size = 2*size + 1;
+ }
+
+ array[n_elements++] = newBlock;
+}
+
+void rectBlockArray::print()
+{
+ Int i;
+ for(i=0; i<n_elements; i++)
+ array[i]->print();
+}
+
+void rectBlockArray::draw(Real* u_values, Real* v_values)
+{
+ Int i;
+ for(i=0; i<n_elements; i++)
+ array[i]->draw(u_values, v_values);
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/glu/sgi/libnurbs/nurbtess/rectBlock.h b/src/glu/sgi/libnurbs/nurbtess/rectBlock.h
new file mode 100644
index 00000000000..6406ed7e32e
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/rectBlock.h
@@ -0,0 +1,89 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/rectBlock.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#ifndef _RECTBLOCK_H
+#define _RECTBLOCK_H
+
+#include "definitions.h"
+#include "gridWrap.h"
+
+class rectBlock{
+ Int upGridLineIndex;
+ Int lowGridLineIndex;
+ Int* leftIndices; //up to bottome
+ Int* rightIndices; //up to bottom
+public:
+ //the arrays are copies.
+ rectBlock(gridBoundaryChain* left, gridBoundaryChain* right, Int beginVline, Int endVline);
+ ~rectBlock(); //free the two arrays
+
+ Int get_upGridLineIndex() {return upGridLineIndex;}
+ Int get_lowGridLineIndex() {return lowGridLineIndex;}
+ Int* get_leftIndices() {return leftIndices;}
+ Int* get_rightIndices() {return rightIndices;}
+
+ Int num_quads();
+
+ void print();
+ void draw(Real* u_values, Real* v_values);
+};
+
+
+class rectBlockArray{
+ rectBlock** array;
+ Int n_elements;
+ Int size;
+public:
+ rectBlockArray(Int s);
+ ~rectBlockArray();//delete avarything including the blocks
+
+ Int get_n_elements() {return n_elements;}
+ rectBlock* get_element(Int i) {return array[i];}
+ void insert(rectBlock* newBlock); //only take the pointer, not ther cotent
+
+ Int num_quads();
+
+ void print();
+ void draw(Real* u_values, Real* v_values);
+};
+
+
+
+#endif
+
diff --git a/src/glu/sgi/libnurbs/nurbtess/sampleComp.cc b/src/glu/sgi/libnurbs/nurbtess/sampleComp.cc
new file mode 100644
index 00000000000..ae4d8005857
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/sampleComp.cc
@@ -0,0 +1,373 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2005/10/28 13:09:09 $ $Revision: 1.1.30.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/sampleComp.cc,v 1.1.30.1 2005/10/28 13:09:09 brianp Exp $
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "glimports.h"
+#include "sampleComp.h"
+#include "sampleCompTop.h"
+#include "sampleCompBot.h"
+#include "sampleCompRight.h"
+
+
+
+#define max(a,b) ((a>b)? a:b)
+#define min(a,b) ((a>b)? b:a)
+
+void sampleConnectedComp(Real* topVertex, Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex, Int leftEndIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex, Int rightEndIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1, Int gridIndex2,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int up_rightCornerWhere,
+ Int up_rightCornerIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ Int down_rightCornerWhere,
+ Int down_rightCornerIndex,
+ primStream* pStream,
+ rectBlockArray* rbArray
+ )
+{
+
+ sampleCompLeft(topVertex, botVertex,
+ leftChain,
+ leftStartIndex, leftEndIndex,
+ rightChain,
+ rightStartIndex, rightEndIndex,
+ leftGridChain,
+ gridIndex1,
+ gridIndex2,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ pStream);
+
+
+ sampleCompRight(topVertex, botVertex,
+ leftChain,
+ leftStartIndex, leftEndIndex,
+ rightChain,
+ rightStartIndex,
+ rightEndIndex,
+ rightGridChain,
+ gridIndex1, gridIndex2,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex,
+ pStream);
+
+
+ sampleCompTop(topVertex,
+ leftChain,
+ leftStartIndex,
+ rightChain,
+ rightStartIndex,
+ leftGridChain,
+ rightGridChain,
+ gridIndex1,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ pStream);
+
+ sampleCompBot(botVertex,
+ leftChain,
+ leftEndIndex,
+ rightChain,
+ rightEndIndex,
+ leftGridChain,
+ rightGridChain,
+ gridIndex2,
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex,
+ pStream);
+
+
+ //the center
+
+ rbArray->insert(new rectBlock(leftGridChain, rightGridChain, gridIndex1, gridIndex2));
+
+
+}
+
+/*notice that we need rightChain because the
+ *corners could be on the rightChain.
+ *here comp means component.
+ */
+void sampleCompLeft(Real* topVertex, Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex, Int leftEndIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex, Int rightEndIndex,
+ gridBoundaryChain* leftGridChain,
+ Int gridIndex1, Int gridIndex2,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ primStream* pStream)
+{
+ /*find out whether there is a trim vertex which is
+ *inbetween the top and bot grid lines or not.
+ */
+ Int midIndex1;
+ Int midIndex2;
+ Int gridMidIndex1 = 0, gridMidIndex2 = 0;
+ //midIndex1: array[i] <= v, array[i-1] > v
+ //midIndex2: array[i] >= v, array[i+1] < v
+ // v(gridMidIndex1) >= v(midindex1) > v(gridMidIndex1+1)
+ // v(gridMidIndex2-1) >= v(midIndex2) > v(gridMidIndex2) ??
+ midIndex1 = leftChain->findIndexBelowGen(
+ leftGridChain->get_v_value(gridIndex1),
+ leftStartIndex,
+ leftEndIndex);
+
+ midIndex2 = -1; /*initilization*/
+ if(midIndex1<= leftEndIndex && gridIndex1<gridIndex2)
+ if(leftChain->getVertex(midIndex1)[1] >= leftGridChain->get_v_value(gridIndex2))
+ {
+ midIndex2 = leftChain->findIndexAboveGen(
+ leftGridChain->get_v_value(gridIndex2),
+ midIndex1, //midIndex1 <= midIndex2.
+ leftEndIndex);
+ gridMidIndex1 = leftGridChain->lookfor(leftChain->getVertex(midIndex1)[1],
+ gridIndex1, gridIndex2);
+ gridMidIndex2 = 1+leftGridChain->lookfor(leftChain->getVertex(midIndex2)[1],
+ gridMidIndex1, gridIndex2);
+ }
+
+
+ /*to interprete the corner information*/
+ Real* cornerTop;
+ Real* cornerBot;
+ Int cornerLeftStart;
+ Int cornerLeftEnd;
+ Int cornerRightUpEnd;
+ Int cornerRightDownStart;
+ if(up_leftCornerWhere == 0) /*left corner is on left chain*/
+ {
+ cornerTop = leftChain->getVertex(up_leftCornerIndex);
+ cornerLeftStart = up_leftCornerIndex+1;
+ cornerRightUpEnd = -1; /*no right*/
+ }
+ else if(up_leftCornerWhere == 1) /*left corner is on top*/
+ {
+ cornerTop = topVertex;
+ cornerLeftStart = leftStartIndex;
+ cornerRightUpEnd = -1; /*no right*/
+ }
+ else /*left corner is on right chain*/
+ {
+ cornerTop = topVertex;
+ cornerLeftStart = leftStartIndex;
+ cornerRightUpEnd = up_leftCornerIndex;
+ }
+
+ if(down_leftCornerWhere == 0) /*left corner is on left chain*/
+ {
+ cornerBot = leftChain->getVertex(down_leftCornerIndex);
+ cornerLeftEnd = down_leftCornerIndex-1;
+ cornerRightDownStart = rightEndIndex+1; /*no right*/
+ }
+ else if(down_leftCornerWhere == 1) /*left corner is on bot*/
+ {
+ cornerBot = botVertex;
+ cornerLeftEnd = leftEndIndex;
+ cornerRightDownStart = rightEndIndex+1; /*no right*/
+ }
+ else /*left corner is on the right chian*/
+ {
+ cornerBot = botVertex;
+ cornerLeftEnd = leftEndIndex;
+ cornerRightDownStart = down_leftCornerIndex;
+ }
+
+
+
+
+ /*sample*/
+ if(midIndex2 >= 0) /*there is a trim point inbewteen grid lines*/
+ {
+
+ sampleLeftSingleTrimEdgeRegionGen(cornerTop, leftChain->getVertex(midIndex1),
+ leftChain,
+ cornerLeftStart,
+ midIndex1-1,
+ leftGridChain,
+ gridIndex1,
+ gridMidIndex1,
+ rightChain,
+ rightStartIndex,
+ cornerRightUpEnd,
+ 0, //no right down section
+ -1,
+ pStream);
+
+ sampleLeftSingleTrimEdgeRegionGen(leftChain->getVertex(midIndex2),
+ cornerBot,
+ leftChain,
+ midIndex2+1,
+ cornerLeftEnd,
+ leftGridChain,
+ gridMidIndex2,
+ gridIndex2,
+ rightChain,
+ 0, //no right up section
+ -1,
+ cornerRightDownStart,
+ rightEndIndex,
+ pStream);
+
+
+ sampleLeftStripRecF(leftChain,
+ midIndex1,
+ midIndex2,
+ leftGridChain,
+ gridMidIndex1,
+ gridMidIndex2,
+ pStream);
+ }
+ else
+ {
+ sampleLeftSingleTrimEdgeRegionGen(cornerTop, cornerBot,
+ leftChain,
+ cornerLeftStart,
+ cornerLeftEnd,
+ leftGridChain,
+ gridIndex1,
+ gridIndex2,
+ rightChain,
+ rightStartIndex,
+ cornerRightUpEnd,
+ cornerRightDownStart,
+ rightEndIndex,
+ pStream);
+ }
+}
+
+void sampleLeftSingleTrimEdgeRegionGen(Real topVert[2], Real botVert[2],
+ vertexArray* leftChain,
+ Int leftStart,
+ Int leftEnd,
+ gridBoundaryChain* gridChain,
+ Int gridBeginIndex,
+ Int gridEndIndex,
+ vertexArray* rightChain,
+ Int rightUpBegin,
+ Int rightUpEnd,
+ Int rightDownBegin,
+ Int rightDownEnd,
+ primStream* pStream)
+{
+ Int i,j,k;
+
+ /*creat an array to store all the up and down secments of the right chain,
+ *and the left end grid points
+ *
+ *although vertex array is a dynamic array, but to gain efficiency,
+ *it is better to initiliza the exact array size
+ */
+ vertexArray vArray(gridEndIndex-gridBeginIndex+1 +
+ max(0,rightUpEnd - rightUpBegin+1)+
+ max(0,rightDownEnd - rightDownBegin+1));
+
+ /*append the vertices on the up section of thr right chain*/
+ for(i=rightUpBegin; i<= rightUpEnd; i++)
+ vArray.appendVertex(rightChain->getVertex(i));
+
+ /*append the vertices of the left extremal grid points,
+ *and at the same time, perform triangulation for the stair cases
+ */
+ vArray.appendVertex(gridChain->get_vertex(gridBeginIndex));
+
+ for(k=1, i=gridBeginIndex+1; i<=gridEndIndex; i++, k++)
+ {
+ vArray.appendVertex(gridChain->get_vertex(i));
+
+ /*output the fan of the grid points of the (i)th and (i-1)th grid line.
+ */
+ if(gridChain->getUlineIndex(i) < gridChain->getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(gridChain->get_vertex(i-1));
+ for(j=gridChain->getUlineIndex(i); j<= gridChain->getUlineIndex(i-1); j++)
+ pStream->insert(gridChain->getGrid()->get_u_value(j), gridChain->get_v_value(i));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ else if(gridChain->getUlineIndex(i) > gridChain->getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(gridChain->get_vertex(i));
+ for(j=gridChain->getUlineIndex(i); j>= gridChain->getUlineIndex(i-1); j--)
+ pStream->insert(gridChain->getGrid()->get_u_value(j), gridChain->get_v_value(i-1));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ /*otherwisem, the two are equal, so there is no fan to outout*/
+ }
+
+ /*then append all the vertices on the down section of the right chain*/
+ for(i=rightDownBegin; i<= rightDownEnd; i++)
+ vArray.appendVertex(rightChain->getVertex(i));
+
+ monoTriangulationRecGen(topVert, botVert,
+ leftChain, leftStart, leftEnd,
+ &vArray, 0, vArray.getNumElements()-1,
+ pStream);
+
+}
+
+
+
+
+
+
+
+
+
diff --git a/src/glu/sgi/libnurbs/nurbtess/sampleComp.h b/src/glu/sgi/libnurbs/nurbtess/sampleComp.h
new file mode 100644
index 00000000000..276ec8640a5
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/sampleComp.h
@@ -0,0 +1,93 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/sampleComp.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#ifndef _SAMPLECOMP_H
+#define _SAMPLECOMP_H
+
+#include "sampleMonoPoly.h"
+#include "rectBlock.h"
+
+void sampleConnectedComp(Real* topVertex, Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex, Int botLeftIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex, Int botRightIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1, Int gridIndex2,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int up_rightCornerWhere,
+ Int up_rightCornerIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ Int down_rightCornerWhere,
+ Int down_rightCornerIndex,
+ primStream* pStream,
+ rectBlockArray* rbArray
+ );
+
+void sampleCompLeft(Real* topVertex, Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex, Int leftEndIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex, Int rightEndIndex,
+ gridBoundaryChain* leftGridChain,
+ Int gridIndex1, Int gridIndex2,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ primStream* pStream);
+
+void sampleLeftSingleTrimEdgeRegionGen(Real topVert[2], Real botVert[2],
+ vertexArray* leftChain,
+ Int leftStart,
+ Int leftEnd,
+ gridBoundaryChain* gridChain,
+ Int gridBegindex,
+ Int gridEndIndex,
+ vertexArray* rightChain,
+ Int rightUpBegin,
+ Int rightUpEnd,
+ Int rightDownBegin,
+ Int rightDownEnd,
+ primStream* pStream);
+
+#endif
diff --git a/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.cc b/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.cc
new file mode 100644
index 00000000000..c0e7442901a
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.cc
@@ -0,0 +1,846 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/11/29 16:16:55 $ $Revision: 1.2 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.cc,v 1.2 2001/11/29 16:16:55 kschultz Exp $
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "zlassert.h"
+#include "sampleCompBot.h"
+#include "sampleCompRight.h"
+
+#define max(a,b) ((a>b)? a:b)
+
+//return: index_mono, index_pass
+//from [pass, mono] is strictly U-monotone
+//from [corner, pass] is <u
+// vertex[pass][0] >= u
+//if everybost is <u, then pass = end+1.
+//otherwise both mono and pass are meanng full and we have corner<=pass<=mono<=end
+void findBotLeftSegment(vertexArray* leftChain,
+ Int leftEnd,
+ Int leftCorner,
+ Real u,
+ Int& ret_index_mono,
+ Int& ret_index_pass)
+{
+ Int i;
+
+ assert(leftCorner <= leftEnd);
+ for(i=leftCorner; i<= leftEnd; i++)
+ if(leftChain->getVertex(i)[0] >= u)
+ break;
+ ret_index_pass = i;
+ if(ret_index_pass <= leftEnd)
+ {
+ for(i=ret_index_pass; i< leftEnd; i++)
+ {
+ if(leftChain->getVertex(i+1)[0] <= leftChain->getVertex(i)[0])
+ break;
+ }
+ ret_index_mono = i;
+ }
+
+}
+
+void findBotRightSegment(vertexArray* rightChain,
+ Int rightEnd,
+ Int rightCorner,
+ Real u,
+ Int& ret_index_mono,
+ Int& ret_index_pass)
+{
+ Int i;
+ assert(rightCorner <= rightEnd);
+ for(i=rightCorner; i<= rightEnd; i++)
+ if(rightChain->getVertex(i)[0] <= u)
+ break;
+
+
+
+ ret_index_pass = i;
+
+ if(ret_index_pass <= rightEnd)
+ {
+ for(i=ret_index_pass; i< rightEnd; i++)
+ {
+ if(rightChain->getVertex(i+1)[0] >= rightChain->getVertex(i)[0])
+ break;
+ }
+ ret_index_mono = i;
+ }
+}
+
+
+void sampleBotRightWithGridLinePost(Real* botVertex,
+ vertexArray* rightChain,
+ Int rightEnd,
+ Int segIndexMono,
+ Int segIndexPass,
+ Int rightCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream)
+{
+ //the possible section which is to the right of rightU
+ if(segIndexPass > rightCorner) //from corner to pass-1 is > u.
+ {
+ Real *tempBot;
+ if(segIndexPass <= rightEnd) //there is a point to the left of u
+ tempBot = rightChain->getVertex(segIndexPass);
+ else //nothing is to the left of u.
+ tempBot = botVertex;
+ Real tempTop[2];
+ tempTop[0] = grid->get_u_value(rightU);
+ tempTop[1] = grid->get_v_value(gridV);
+
+ monoTriangulation2(tempTop, tempBot,
+ rightChain,
+ rightCorner,
+ segIndexPass-1,
+ 0, // a decrease chain
+ pStream);
+ }
+
+ //the possible section which is strictly Umonotone
+ if(segIndexPass <= rightEnd) //segIndex pass and mono exist
+ {
+ //if there are grid points which are to the left of botVertex
+ //then we should use botVertex to form a fan with these points to
+ //optimize the triangulation
+ int do_optimize = 1;
+ if(botVertex[0] <= grid->get_u_value(leftU))
+ do_optimize = 0;
+ else
+ {
+ //we also have to make sure that botVertex is the left most vertex on the chain
+ int i;
+ for(i=segIndexMono; i<=rightEnd; i++)
+ if(rightChain->getVertex(i)[0] <= botVertex[0])
+ {
+ do_optimize = 0;
+ break;
+ }
+ }
+
+ if(do_optimize)
+ {
+ //find midU so that grid->get_u_value(midU) <= botVertex[0]
+ //and grid->get_u_value(midU) > botVertex[0]
+ int midU = leftU;
+ while(grid->get_u_value(midU) <= botVertex[0])
+ {
+ midU++;
+ if(midU > rightU)
+ break;
+ }
+ midU--;
+
+ grid->outputFanWithPoint(gridV, leftU, midU, botVertex, pStream);
+ stripOfFanRight(rightChain, segIndexMono, segIndexPass, grid, gridV, midU, rightU, pStream, 1);
+ Real tempTop[2];
+ tempTop[0] = grid->get_u_value(midU);
+ tempTop[1] = grid->get_v_value(gridV);
+ monoTriangulation2(tempTop, botVertex, rightChain, segIndexMono, rightEnd, 0, pStream);
+ }
+ else //not optimize
+ {
+ stripOfFanRight(rightChain, segIndexMono, segIndexPass, grid, gridV, leftU, rightU, pStream, 1);
+ Real tempTop[2];
+ tempTop[0] = grid->get_u_value(leftU);
+ tempTop[1] = grid->get_v_value(gridV);
+ monoTriangulation2(tempTop, botVertex, rightChain, segIndexMono, rightEnd, 0, pStream);
+ }
+ }
+ else //the botVertex forms a fan witht eh grid points
+ grid->outputFanWithPoint(gridV, leftU, rightU, botVertex, pStream);
+}
+
+void sampleBotRightWithGridLine(Real* botVertex,
+ vertexArray* rightChain,
+ Int rightEnd,
+ Int rightCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream)
+{
+ //if right chaain is empty, then there is only one bot vertex with
+ //one grid line
+ if(rightEnd<rightCorner){
+ grid->outputFanWithPoint(gridV, leftU, rightU, botVertex, pStream);
+ return;
+ }
+
+ Int segIndexMono, segIndexPass;
+ findBotRightSegment(rightChain,
+ rightEnd,
+ rightCorner,
+ grid->get_u_value(rightU),
+ segIndexMono,
+ segIndexPass);
+
+ sampleBotRightWithGridLinePost(botVertex,
+ rightChain,
+ rightEnd,
+ segIndexMono,
+ segIndexPass,
+ rightCorner,
+ grid,
+ gridV,
+ leftU,
+ rightU,
+ pStream);
+}
+
+
+void sampleBotLeftWithGridLinePost(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ Int segIndexMono,
+ Int segIndexPass,
+ Int leftCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream)
+{
+
+ //the possible section which is to the left of leftU
+ if(segIndexPass > leftCorner) //at least leftCorner is to the left of leftU
+ {
+ Real *tempBot;
+ if(segIndexPass <= leftEnd) //from corner to pass-1 is <u
+ tempBot = leftChain->getVertex(segIndexPass);
+ else //nothing is to the rigth of u
+ tempBot = botVertex;
+ Real tempTop[2];
+ tempTop[0] = grid->get_u_value(leftU);
+ tempTop[1] = grid->get_v_value(gridV);
+ monoTriangulation2(tempTop, tempBot, leftChain, leftCorner, segIndexPass-1,
+ 1, //a increase chain,
+ pStream);
+ }
+ //the possible section which is strictly Umonotone
+ if(segIndexPass <= leftEnd) //segIndexpass and mono exist
+ {
+ stripOfFanLeft(leftChain, segIndexMono, segIndexPass, grid, gridV, leftU, rightU, pStream, 1);
+ Real tempTop[2];
+ tempTop[0] = grid->get_u_value(rightU);
+ tempTop[1] = grid->get_v_value(gridV);
+
+ monoTriangulation2(tempTop, botVertex, leftChain, segIndexMono, leftEnd,
+ 1, //increase chain
+ pStream);
+ }
+ else //the botVertex forms a fan with the grid points
+ {
+ grid->outputFanWithPoint(gridV, leftU, rightU, botVertex, pStream);
+ }
+
+}
+
+void sampleBotLeftWithGridLine(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ Int leftCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream)
+{
+
+ //if leftChain is empty, then there is only one botVertex with one grid line
+ if(leftEnd< leftCorner){
+ grid->outputFanWithPoint(gridV, leftU, rightU, botVertex, pStream);
+ return;
+ }
+
+ Int segIndexPass, segIndexMono;
+ findBotLeftSegment(leftChain, leftEnd, leftCorner, grid->get_u_value(leftU), segIndexMono, segIndexPass);
+
+ sampleBotLeftWithGridLinePost(botVertex,
+ leftChain,
+ leftEnd,
+ segIndexMono,
+ segIndexPass,
+ leftCorner,
+ grid,
+ gridV,
+ leftU, rightU, pStream);
+}
+
+//return 1 if separator exists, 0 otherwise
+Int findBotSeparator(vertexArray* leftChain,
+ Int leftEnd,
+ Int leftCorner,
+ vertexArray* rightChain,
+ Int rightEnd,
+ Int rightCorner,
+ Int& ret_sep_left,
+ Int& ret_sep_right)
+{
+ Int oldLeftI, oldRightI, newLeftI, newRightI;
+ Int i,j,k;
+ Real leftMax /*= leftChain->getVertex(leftCorner)[0]*/;
+ Real rightMin /*= rightChain->getVertex(rightCorner)[0]*/;
+ if(leftChain->getVertex(leftCorner)[1] < rightChain->getVertex(rightCorner)[1])//leftlower
+ {
+ oldLeftI = leftCorner-1;
+ oldRightI = rightCorner;
+ leftMax = leftChain->getVertex(leftCorner)[0] - Real(1.0) ; //initilize to be left of leftCorner
+ rightMin = rightChain->getVertex(rightCorner)[0];
+ }
+ else //rightlower
+ {
+ oldLeftI = leftCorner;
+ oldRightI = rightCorner-1;
+ leftMax = leftChain->getVertex(leftCorner)[0];
+ rightMin = rightChain->getVertex(rightCorner)[0] + Real(1.0);
+ }
+
+ //i: the current working leftChain Index
+ //j: the curent working right chian index
+ //if(left(i) is lower than right(j), then the two chains above right(j) are separated.
+ //else the two chains below left(i) are separated.
+ i = leftCorner;
+ j = rightCorner;
+ while(1)
+ {
+ newLeftI = oldLeftI;
+ newRightI = oldRightI;
+ if(i> leftEnd) //left chain is doen , go through remaining right chain
+ {
+ for(k=j+1; k<= rightEnd; k++)
+ {
+ if(rightChain->getVertex(k)[0] > leftMax) //no conflict
+ {
+ //update oldRightI if necessary
+ if(rightChain->getVertex(k)[0] < rightMin)
+ {
+ rightMin = rightChain->getVertex(k)[0];
+ oldRightI = k;
+ }
+ }
+ else //there is a conflict
+ break; //the for-loop, above right(k+1) is separated: oldLeftI, oldRightI
+ }
+ break; //the while loop
+ }
+ else if(j > rightEnd) //right Chain is doen
+ {
+ for(k=i+1; k<= leftEnd; k++)
+ {
+ if(leftChain->getVertex(k)[0] < rightMin) //no conflict
+ {
+ //update oldLeftI if necessary
+ if(leftChain->getVertex(k)[0] > leftMax)
+ {
+ leftMax = leftChain->getVertex(k)[0];
+ oldLeftI = k;
+ }
+ }
+ else //there is a conflict
+ break; //the for-loop, above left(k+1) is separated: oldLeftI, oldRightI
+ }
+ break; //the while loop
+ }
+ else if(leftChain->getVertex(i)[1] < rightChain->getVertex(j)[1]) //left lower
+ {
+
+ if(leftChain->getVertex(i)[0] > leftMax) //update leftMax amd newLeftI
+ {
+ leftMax = leftChain->getVertex(i)[0];
+ newLeftI = i;
+ }
+ for(k=j+1; k<= rightEnd; k++) //update rightMin and newRightI;
+ {
+ if(rightChain->getVertex(k)[1] < leftChain->getVertex(i)[1]) //right gets lower
+ break;
+ if(rightChain->getVertex(k)[0] < rightMin)
+ {
+ rightMin = rightChain->getVertex(k)[0];
+ newRightI = k;
+ }
+ }
+ j = k; //next working j, since j will he lower than i in next loop
+ if(leftMax >= rightMin) //there is a conflict
+ break;
+ else //still no conflict
+ {
+ oldLeftI = newLeftI;
+ oldRightI = newRightI;
+
+ }
+ }
+ else //right lower
+ {
+ if(rightChain->getVertex(j)[0] < rightMin)
+ {
+ rightMin = rightChain->getVertex(j)[0];
+ newRightI = j;
+ }
+ for(k=i+1; k<= leftEnd; k++)
+ {
+ if(leftChain->getVertex(k)[1] < rightChain->getVertex(j)[1])
+ break;
+ if(leftChain->getVertex(k)[0] > leftMax)
+ {
+ leftMax = leftChain->getVertex(k)[0];
+ newLeftI = k;
+ }
+ }
+ i=k; //nexct working i, since i will be lower than j next loop
+ if(leftMax >= rightMin) //there is conflict
+ break;
+ else //still no conflict
+ {
+ oldLeftI = newLeftI;
+ oldRightI = newRightI;
+ }
+ }
+ }//end of while loop
+ //now oldLeftI and oldRight I are the desired separator index notice that they are not
+ //necessarily valid
+ if(oldLeftI < leftCorner || oldRightI < rightCorner)
+ return 0; //no separator
+ else
+ {
+ ret_sep_left = oldLeftI;
+ ret_sep_right = oldRightI;
+ return 1;
+ }
+}
+
+void sampleCompBot(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ vertexArray* rightChain,
+ Int rightEnd,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ Int down_rightCornerWhere,
+ Int down_rightCornerIndex,
+ primStream* pStream)
+{
+
+ if(down_leftCornerWhere == 1 && down_rightCornerWhere == 1) //the bot is botVertex with possible grid points
+ {
+
+ leftGridChain->getGrid()->outputFanWithPoint(leftGridChain->getVlineIndex(gridIndex),
+ leftGridChain->getUlineIndex(gridIndex),
+ rightGridChain->getUlineIndex(gridIndex),
+ botVertex,
+ pStream);
+ return;
+ }
+ else if(down_leftCornerWhere != 0)
+ {
+
+ Real* tempBot;
+ Int tempRightEnd;
+ if(down_leftCornerWhere == 1){
+ tempRightEnd = rightEnd;
+ tempBot = botVertex;
+ }
+ else
+ {
+ tempRightEnd = down_leftCornerIndex-1;
+ tempBot = rightChain->getVertex(down_leftCornerIndex);
+ }
+
+ sampleBotRightWithGridLine(tempBot,
+ rightChain,
+ tempRightEnd,
+ down_rightCornerIndex,
+ rightGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex),
+ leftGridChain->getUlineIndex(gridIndex),
+ rightGridChain->getUlineIndex(gridIndex),
+ pStream);
+ }
+ else if(down_rightCornerWhere != 2)
+ {
+
+ Real* tempBot;
+ Int tempLeftEnd;
+ if(down_rightCornerWhere == 1){
+ tempLeftEnd = leftEnd;
+ tempBot = botVertex;
+ }
+ else //right corner is on left chain
+ {
+ tempLeftEnd = down_rightCornerIndex-1;
+ tempBot = leftChain->getVertex(down_rightCornerIndex);
+ }
+
+
+ sampleBotLeftWithGridLine(tempBot, leftChain, tempLeftEnd, down_leftCornerIndex,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex),
+ leftGridChain->getUlineIndex(gridIndex),
+ rightGridChain->getUlineIndex(gridIndex),
+ pStream);
+
+ }
+ else //down_leftCornereWhere == 0, down_rightCornerwhere == 2
+ {
+ sampleCompBotSimple(botVertex,
+ leftChain,
+ leftEnd,
+ rightChain,
+ rightEnd,
+ leftGridChain,
+ rightGridChain,
+ gridIndex,
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex,
+ pStream);
+
+ return;
+
+#ifdef NOT_REACHABLE
+ //the following code is trying to do some optimization, but not quite working. so it is not reachable, but leave it here for reference
+ Int sep_left, sep_right;
+ if(findBotSeparator(leftChain, leftEnd, down_leftCornerIndex,
+ rightChain, rightEnd, down_rightCornerIndex,
+ sep_left, sep_right)
+ )//separator exiosts
+ {
+
+ if(leftChain->getVertex(sep_left)[0] >= leftGridChain->get_u_value(gridIndex) &&
+ rightChain->getVertex(sep_right)[0] <= rightGridChain->get_u_value(gridIndex))
+ {
+ Int gridSep;
+ Int segLeftMono, segLeftPass, segRightMono, segRightPass;
+ findBotLeftSegment(leftChain,
+ sep_left,
+ down_leftCornerIndex,
+ leftGridChain->get_u_value(gridIndex),
+ segLeftMono,
+ segLeftPass);
+ findBotRightSegment(rightChain,
+ sep_right,
+ down_rightCornerIndex,
+ rightGridChain->get_u_value(gridIndex),
+ segRightMono,
+ segRightPass);
+ if(leftChain->getVertex(segLeftMono)[1] <= rightChain->getVertex(segRightMono)[1])
+ {
+ gridSep = rightGridChain->getUlineIndex(gridIndex);
+ while(leftGridChain->getGrid()->get_u_value(gridSep) > leftChain->getVertex(segLeftMono)[0])
+ gridSep--;
+ }
+ else
+ {
+ gridSep = leftGridChain->getUlineIndex(gridIndex);
+ while(leftGridChain->getGrid()->get_u_value(gridSep) < rightChain->getVertex(segRightMono)[0])
+ gridSep++;
+ }
+
+ sampleBotLeftWithGridLinePost(leftChain->getVertex(segLeftMono),
+ leftChain,
+ segLeftMono-1,
+ segLeftMono-1,
+ segLeftPass,
+ down_leftCornerIndex,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex),
+ leftGridChain->getUlineIndex(gridIndex),
+ gridSep,
+ pStream);
+ sampleBotRightWithGridLinePost(rightChain->getVertex(segRightMono),
+ rightChain,
+ segRightMono-1,
+ segRightMono-1,
+ segRightPass,
+ down_rightCornerIndex,
+ rightGridChain->getGrid(),
+ rightGridChain->getVlineIndex(gridIndex),
+ gridSep,
+ rightGridChain->getUlineIndex(gridIndex),
+ pStream);
+ Real tempTop[2];
+ tempTop[0] = leftGridChain->getGrid()->get_u_value(gridSep);
+ tempTop[1] = leftGridChain->get_v_value(gridIndex);
+ monoTriangulationRecGen(tempTop, botVertex,
+ leftChain, segLeftMono, leftEnd,
+ rightChain, segRightMono, rightEnd,
+ pStream);
+ }//end if both sides have vertices inside the gridboundary points
+ else if(leftChain->getVertex(sep_left)[0] >= leftGridChain->get_u_value(gridIndex)) //left n right out
+
+ {
+ Int segLeftMono, segLeftPass;
+ findBotLeftSegment(leftChain,
+ sep_left,
+ down_leftCornerIndex,
+ leftGridChain->get_u_value(gridIndex),
+ segLeftMono,
+ segLeftPass);
+ assert(segLeftPass <= sep_left); //make sure there is a point to the right of u.
+ monoTriangulation2(leftGridChain->get_vertex(gridIndex),
+ leftChain->getVertex(segLeftPass),
+ leftChain,
+ down_leftCornerIndex,
+ segLeftPass-1,
+ 1, //a increase chain
+ pStream);
+ stripOfFanLeft(leftChain, segLeftMono, segLeftPass,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex),
+ leftGridChain->getUlineIndex(gridIndex),
+ rightGridChain->getUlineIndex(gridIndex),
+ pStream,1 );
+/*
+ sampleBotLeftWithGridLinePost(leftChain->getVertex(segLeftMono),
+ leftChain,
+ segLeftMono-1,
+ segLeftMono-1,
+ segLeftPass,
+ down_leftCornerIndex,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex),
+ leftGridChain->getUlineIndex(gridIndex),
+ rightGridChain->getUlineIndex(gridIndex),
+ pStream);
+*/
+
+ monoTriangulationRecGen(rightGridChain->get_vertex(gridIndex),
+ botVertex,
+ leftChain, segLeftMono, leftEnd,
+ rightChain, down_rightCornerIndex, rightEnd,
+ pStream);
+ }//end left in right out
+ else if(rightChain->getVertex(sep_right)[0] <= rightGridChain->get_u_value(gridIndex))//left out right in
+ {
+ Int segRightMono, segRightPass;
+ findBotRightSegment(rightChain, sep_right, down_rightCornerIndex,
+ rightGridChain->get_u_value(gridIndex),
+ segRightMono,
+ segRightPass);
+
+ assert(segRightPass <= sep_right); //make sure there is a point to the left of u.
+ monoTriangulation2(rightGridChain->get_vertex(gridIndex),
+ rightChain->getVertex(segRightPass),
+ rightChain,
+ down_rightCornerIndex,
+ segRightPass-1,
+ 0, // a decrease chain
+ pStream);
+
+ stripOfFanRight(rightChain, segRightMono, segRightPass,
+ rightGridChain->getGrid(),
+ rightGridChain->getVlineIndex(gridIndex),
+ leftGridChain->getUlineIndex(gridIndex),
+ rightGridChain->getUlineIndex(gridIndex),
+ pStream, 1);
+
+
+ monoTriangulationRecGen(leftGridChain->get_vertex(gridIndex),
+ botVertex,
+ leftChain, down_leftCornerIndex, leftEnd,
+ rightChain, segRightMono, rightEnd,
+ pStream);
+
+ }//end left out right in
+ else //left out, right out
+ {
+ sampleCompBotSimple(botVertex,
+ leftChain,
+ leftEnd,
+ rightChain,
+ rightEnd,
+ leftGridChain,
+ rightGridChain,
+ gridIndex,
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex,
+ pStream);
+
+ }//end leftout right out
+ }//end if separator exists
+ else //no separator
+ {
+
+ sampleCompBotSimple(botVertex,
+ leftChain,
+ leftEnd,
+ rightChain,
+ rightEnd,
+ leftGridChain,
+ rightGridChain,
+ gridIndex,
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex,
+ pStream);
+ }
+#endif
+ }//end id 0 2
+}//end if the functin
+
+
+void sampleCompBotSimple(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ vertexArray* rightChain,
+ Int rightEnd,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ Int down_rightCornerWhere,
+ Int down_rightCornerIndex,
+ primStream* pStream)
+{
+ //the plan is to use monotriangulation algorithm.
+ Int i,k;
+ Real* ActualTop;
+ Real* ActualBot;
+ Int ActualLeftStart, ActualLeftEnd;
+ Int ActualRightStart, ActualRightEnd;
+
+ //creat an array to store the points on the grid line
+ gridWrap* grid = leftGridChain->getGrid();
+ Int gridV = leftGridChain->getVlineIndex(gridIndex);
+ Int gridLeftU = leftGridChain->getUlineIndex(gridIndex);
+ Int gridRightU = rightGridChain->getUlineIndex(gridIndex);
+ Real2* gridPoints = (Real2*) malloc(sizeof(Real2) * (gridRightU - gridLeftU +1));
+ assert(gridPoints);
+
+ for(k=0, i=gridRightU; i>= gridLeftU; i--, k++)
+ {
+ gridPoints[k][0] = grid->get_u_value(i);
+ gridPoints[k][1] = grid->get_v_value(gridV);
+ }
+
+ if(down_rightCornerWhere != 0) //rightCorner is not on lef
+ ActualLeftEnd = leftEnd;
+ else
+ ActualLeftEnd = down_rightCornerIndex-1; //down_rightCornerIndex will be th actualBot
+
+ if(down_leftCornerWhere != 0) //left corner is not on let chian
+ ActualLeftStart = leftEnd+1; //meaning that there is no actual left section
+ else
+ ActualLeftStart = down_leftCornerIndex;
+
+ vertexArray ActualLeftChain(max(0, ActualLeftEnd - ActualLeftStart +1) + gridRightU - gridLeftU +1);
+
+ for(i=0; i<gridRightU - gridLeftU +1 ; i++)
+ ActualLeftChain.appendVertex(gridPoints[i]);
+ for(i=ActualLeftStart; i<= ActualLeftEnd; i++)
+ ActualLeftChain.appendVertex(leftChain->getVertex(i));
+
+ //determine ActualRightStart
+ if(down_rightCornerWhere != 2) //right is not on right
+ ActualRightStart = rightEnd +1; //meaning no section on right
+ else
+ ActualRightStart = down_rightCornerIndex;
+
+ //determine actualrightEnd
+ if(down_leftCornerWhere != 2) //left is not on right
+ {
+
+ ActualRightEnd = rightEnd;
+ }
+ else //left corner is on right
+ {
+ ActualRightEnd = down_leftCornerIndex-1; //down_leftCornerIndex will be the bot
+
+ }
+
+ //actual bot
+ if(down_rightCornerWhere == 2)
+ {
+ if(down_leftCornerWhere == 2)
+ ActualBot = rightChain->getVertex(down_leftCornerIndex);
+ else
+ ActualBot = botVertex;
+ }
+ else if(down_rightCornerWhere == 1) //right corner bot
+ ActualBot = botVertex;
+ else //down_rightCornerWhere == 0
+ ActualBot = leftChain->getVertex(down_rightCornerIndex);
+
+ ActualTop = gridPoints[0];
+/*
+printf("in bot simple, actual leftChain is \n");
+ActualLeftChain.print();
+printf("Actual Top = %f,%f\n", ActualTop[0],ActualTop[1]);
+printf("Actual Bot = %f,%f\n", ActualBot[0],ActualBot[1]);
+printf("Actual right start = %i, end=%i\n",ActualRightStart, ActualRightEnd);
+*/
+ if(rightChain->getVertex(ActualRightStart)[1] == ActualTop[1])
+ monoTriangulationRecGenOpt(rightChain->getVertex(ActualRightStart),
+ ActualBot,
+ &ActualLeftChain,
+ 0,
+ ActualLeftChain.getNumElements()-1,
+ rightChain,
+ ActualRightStart+1,
+ ActualRightEnd,
+ pStream);
+ else
+ monoTriangulationRecGenOpt(ActualTop, ActualBot,
+ &ActualLeftChain,
+ 1, //the first one is the top vertex
+ ActualLeftChain.getNumElements()-1,
+ rightChain,
+ ActualRightStart,
+ ActualRightEnd,
+ pStream);
+ free(gridPoints);
+}
+
+
+
+
diff --git a/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.h b/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.h
new file mode 100644
index 00000000000..8147cfd70cc
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.h
@@ -0,0 +1,145 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#ifndef _SAMPLECOMPBOT_H
+#define _SAMPLECOMPBOT_H
+
+#include "sampleMonoPoly.h"
+
+void findBotLeftSegment(vertexArray* leftChain,
+ Int leftEnd,
+ Int leftCorner,
+ Real u,
+ Int& ret_index_mono,
+ Int& ret_index_pass);
+
+void findBotRightSegment(vertexArray* rightChain,
+ Int rightEnd,
+ Int rightCorner,
+ Real u,
+ Int& ret_index_mono,
+ Int& ret_index_pass);
+
+
+void sampleBotRightWithGridLinePost(Real* botVertex,
+ vertexArray* rightChain,
+ Int rightEnd,
+ Int segIndexMono,
+ Int segIndexPass,
+ Int rightCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream);
+
+
+void sampleBotRightWithGridLine(Real* botVertex,
+ vertexArray* rightChain,
+ Int rightEnd,
+ Int rightCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream);
+
+
+void sampleBotLeftWithGridLinePost(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ Int segIndexMono,
+ Int segIndexPass,
+ Int leftCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream);
+
+
+void sampleBotLeftWithGridLine(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ Int leftCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream);
+
+
+Int findBotSeparator(vertexArray* leftChain,
+ Int leftEnd,
+ Int leftCorner,
+ vertexArray* rightChain,
+ Int rightEnd,
+ Int rightCorner,
+ Int& ret_sep_left,
+ Int& ret_sep_right);
+
+void sampleCompBot(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ vertexArray* rightChain,
+ Int rightEnd,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ Int down_rightCornerWhere,
+ Int down_rightCornerIndex,
+ primStream* pStream);
+
+void sampleCompBotSimple(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ vertexArray* rightChain,
+ Int rightEnd,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ Int down_rightCornerWhere,
+ Int down_rightCornerIndex,
+ primStream* pStream);
+
+#endif
diff --git a/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.cc b/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.cc
new file mode 100644
index 00000000000..cc73fa4fc4c
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.cc
@@ -0,0 +1,646 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2005/10/28 13:09:09 $ $Revision: 1.2.30.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.cc,v 1.2.30.1 2005/10/28 13:09:09 brianp Exp $
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "gluos.h"
+#include "glimports.h"
+#include "zlassert.h"
+#include "sampleCompRight.h"
+
+#define max(a,b) ((a>b)? a:b)
+#define min(a,b) ((a>b)? b:a)
+
+
+
+#ifdef NOT_TAKEOUT
+
+/*notice that we need leftChain because the
+ *corners could be on the leftChain.
+ */
+void sampleCompRight(Real* topVertex, Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex, Int leftEndIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex, Int rightEndIndex,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1, Int gridIndex2,
+ Int up_rightCornerWhere,
+ Int up_rightCornerIndex,
+ Int down_rightCornerWhere,
+ Int down_rightCornerIndex,
+ primStream* pStream)
+{
+ /*find out whether there is a trim vertex which is
+ *inbetween the top and bot grid lines or not.
+ */
+ Int midIndex1;
+ Int midIndex2;
+ Int gridMidIndex1, gridMidIndex2 = 0;
+ //midIndex1: array[i] <= v, array[i+1] > v
+ //midIndex2: array[i] >= v, array[i+1] < v
+ midIndex1 = rightChain->findIndexBelowGen(rightGridChain->get_v_value(gridIndex1),
+ rightStartIndex,
+ rightEndIndex);
+ midIndex2 = -1; //initilization
+ if(midIndex1 <= rightEndIndex && gridIndex1 < gridIndex2)
+ if(rightChain->getVertex(midIndex1)[1] >= rightGridChain->get_v_value(gridIndex2))
+ {
+ //midIndex2 must exist:
+ midIndex2 = rightChain->findIndexAboveGen(rightGridChain->get_v_value(gridIndex2),
+ midIndex1, //midIndex1<=midIndex2
+ rightEndIndex);
+ //find gridMidIndex1 so that either it=gridIndex1 when the gridline is
+ // at the same height as trim vertex midIndex1, or it is the last one
+ //which is strictly above midIndex1.
+ {
+ Real temp = rightChain->getVertex(midIndex1)[1];
+ if(rightGridChain->get_v_value(gridIndex1) == temp)
+ gridMidIndex1 = gridIndex1;
+ else
+ {
+ gridMidIndex1 = gridIndex1;
+ while(rightGridChain->get_v_value(gridMidIndex1) > temp)
+ gridMidIndex1++;
+ gridMidIndex1--;
+ }
+ }//end of find gridMindIndex1
+ //find gridMidIndex2 so that it is the (first one below or equal
+ //midIndex) last one above or equal midIndex2
+ {
+ Real temp = rightChain->getVertex(midIndex2)[1];
+ for(gridMidIndex2 = gridMidIndex1+1; gridMidIndex2 <= gridIndex2; gridMidIndex2++)
+ if(rightGridChain->get_v_value(gridMidIndex2) <= temp)
+ break;
+
+ assert(gridMidIndex2 <= gridIndex2);
+ }//end of find gridMidIndex2
+ }
+
+
+
+ //to interprete the corner information
+ Real* cornerTop;
+ Real* cornerBot;
+ Int cornerRightStart;
+ Int cornerRightEnd;
+ Int cornerLeftUpEnd;
+ Int cornerLeftDownStart;
+ if(up_rightCornerWhere == 2) //right corner is on right chain
+ {
+ cornerTop = rightChain->getVertex(up_rightCornerIndex);
+ cornerRightStart = up_rightCornerIndex+1;
+ cornerLeftUpEnd = -1; //no left
+ }
+ else if(up_rightCornerWhere == 1) //right corner is on top
+ {
+ cornerTop = topVertex;
+ cornerRightStart = rightStartIndex;
+ cornerLeftUpEnd = -1; //no left
+ }
+ else //right corner is on left chain
+ {
+ cornerTop = topVertex;
+ cornerRightStart = rightStartIndex;
+ cornerLeftUpEnd = up_rightCornerIndex;
+ }
+
+ if(down_rightCornerWhere == 2) //right corner is on right chan
+ {
+ cornerBot = rightChain->getVertex(down_rightCornerIndex);
+ cornerRightEnd = down_rightCornerIndex-1;
+ cornerLeftDownStart = leftEndIndex+1; //no left
+ }
+ else if (down_rightCornerWhere == 1) //right corner is at bot
+ {
+ cornerBot = botVertex;
+ cornerRightEnd = rightEndIndex;
+ cornerLeftDownStart = leftEndIndex+1; //no left
+ }
+ else //right corner is on the left chain
+ {
+ cornerBot = botVertex;
+ cornerRightEnd = rightEndIndex;
+ cornerLeftDownStart = down_rightCornerIndex;
+ }
+
+ //sample
+ if(midIndex2 >= 0) //there is a trm point between grid lines
+ {
+
+ sampleRightSingleTrimEdgeRegionGen(cornerTop, rightChain->getVertex(midIndex1),
+ rightChain,
+ cornerRightStart,
+ midIndex1-1,
+ rightGridChain,
+ gridIndex1,
+ gridMidIndex1,
+ leftChain,
+ leftStartIndex,
+ cornerLeftUpEnd,
+ 0, //no left down section,
+ -1,
+ pStream);
+
+ sampleRightSingleTrimEdgeRegionGen(rightChain->getVertex(midIndex2),
+ cornerBot,
+ rightChain,
+ midIndex2+1,
+ cornerRightEnd,
+ rightGridChain,
+ gridMidIndex2,
+ gridIndex2,
+ leftChain,
+ 0, //no left up section
+ -1,
+ cornerLeftDownStart,
+ leftEndIndex,
+ pStream);
+
+ sampleRightStripRecF(rightChain,
+ midIndex1,
+ midIndex2,
+ rightGridChain,
+ gridMidIndex1,
+ gridMidIndex2,
+ pStream);
+
+ }
+ else
+ {
+ sampleRightSingleTrimEdgeRegionGen(cornerTop, cornerBot,
+ rightChain,
+ cornerRightStart,
+ cornerRightEnd,
+ rightGridChain,
+ gridIndex1,
+ gridIndex2,
+ leftChain,
+ leftStartIndex,
+ cornerLeftUpEnd,
+ cornerLeftDownStart,
+ leftEndIndex,
+ pStream);
+ }
+}
+
+void sampleRightSingleTrimEdgeRegionGen(Real topVertex[2], Real botVertex[2],
+ vertexArray* rightChain,
+ Int rightStart,
+ Int rightEnd,
+ gridBoundaryChain* gridChain,
+ Int gridBeginIndex,
+ Int gridEndIndex,
+ vertexArray* leftChain,
+ Int leftUpBegin,
+ Int leftUpEnd,
+ Int leftDownBegin,
+ Int leftDownEnd,
+ primStream* pStream)
+{
+ Int i,k;
+ /*creat an array to store all the up and down secments of the left chain,
+ *and the right end grid points
+ *
+ *although vertex array is a dynamic array, but to gain efficiency,
+ *it is better to initiliza the exact array size
+ */
+ vertexArray vArray(gridEndIndex-gridBeginIndex+1 +
+ max(0,leftUpEnd - leftUpBegin+1)+
+ max(0,leftDownEnd - leftDownBegin+1));
+ //append the vertices on the up section of the left chain
+ for(i=leftUpBegin; i<= leftUpEnd; i++)
+ vArray.appendVertex(leftChain->getVertex(i));
+
+ //append the vertices of the right extremal grid points,
+ //and at the same time, perform triangulation for the stair cases
+ vArray.appendVertex(gridChain->get_vertex(gridBeginIndex));
+
+ for(k=1, i=gridBeginIndex+1; i<= gridEndIndex; i++, k++)
+ {
+ vArray.appendVertex(gridChain->get_vertex(i));
+
+ //output the fan of the grid points of the (i)th and (i-1)th grid line.
+ gridChain->rightEndFan(i, pStream);
+ }
+
+ //append all the vertices on the down section of the left chain
+ for(i=leftDownBegin; i<= leftDownEnd; i++)
+ vArray.appendVertex(leftChain->getVertex(i));
+ monoTriangulationRecGen(topVertex, botVertex,
+ &vArray, 0, vArray.getNumElements()-1,
+ rightChain, rightStart, rightEnd,
+ pStream);
+}
+
+void sampleRightSingleTrimEdgeRegion(Real upperVert[2], Real lowerVert[2],
+ gridBoundaryChain* gridChain,
+ Int beginIndex,
+ Int endIndex,
+ primStream* pStream)
+{
+ Int i,k;
+ vertexArray vArray(endIndex-beginIndex+1);
+ vArray.appendVertex(gridChain->get_vertex(beginIndex));
+ for(k=1, i=beginIndex+1; i<= endIndex; i++, k++)
+ {
+ vArray.appendVertex(gridChain->get_vertex(i));
+ //output the fan of the grid points of the (i)_th and i-1th gridLine
+ gridChain->rightEndFan(i, pStream);
+ }
+ monoTriangulation2(upperVert, lowerVert, &vArray, 0, endIndex-beginIndex,
+ 1, //increase chain (to the left)
+ pStream);
+}
+
+
+/*the gridlines from rightGridChainStartIndex to
+ *rightGridChainEndIndex are assumed to form a
+ *connected componenet
+ *the trm vertex of topRightIndex is assumed to be below
+ *or equal the first gridLine, and the trm vertex of
+ *botRightIndex is assumed to be above or equal the last gridline
+ **there could be multipe trm vertices equal to the last gridline, but
+ **only one could be equal to top gridline. shape: ____| (recall that
+ **for left chain recF, we allow shape: |----
+ *if botRightIndex<topRightIndex, then no connected componenet exists, and
+ *no triangles are generated.
+ *Othewise, botRightIndex>= topRightIndex, there is at least one triangles to
+ *output
+ */
+void sampleRightStripRecF(vertexArray* rightChain,
+ Int topRightIndex,
+ Int botRightIndex,
+ gridBoundaryChain* rightGridChain,
+ Int rightGridChainStartIndex,
+ Int rightGridChainEndIndex,
+ primStream* pStream
+ )
+{
+
+ //sstop conditionL: if topRightIndex > botRightIndex, then stop
+ if(topRightIndex > botRightIndex)
+ return;
+
+ //if there is only one grid line, return
+ if(rightGridChainStartIndex >= rightGridChainEndIndex)
+ return;
+
+
+ assert(rightChain->getVertex(topRightIndex)[1] <= rightGridChain->get_v_value(rightGridChainStartIndex) &&
+ rightChain->getVertex(botRightIndex)[1] >= rightGridChain->get_v_value(rightGridChainEndIndex));
+
+ //firstfind the first trim vertex which is strictly below the second top
+ //grid line: index1.
+ Real secondGridChainV = rightGridChain->get_v_value(rightGridChainStartIndex+1);
+ Int index1 = topRightIndex;
+ while(rightChain->getVertex(index1)[1] >= secondGridChainV){
+ index1++;
+ if(index1 > botRightIndex)
+ break;
+ }
+ //now rightChain->getVertex(index1-1)[1] >= secondGridChainV and
+ //rightChain->getVertex(index1)[1] < secondGridChainV and
+ //we should include index1-1 to perform a gridStep
+ index1--;
+
+ //now we have rightChain->getVertex(index1)[1] >= secondGridChainV, and
+ //rightChain->getVertex(index1+1)[1] < secondGridChainV
+ sampleRightOneGridStep(rightChain, topRightIndex, index1, rightGridChain, rightGridChainStartIndex, pStream);
+
+ //if rightChain->getVertex(index1)[1] ==secondGridChainV then we can
+ //recurvesively to the rest
+ if(rightChain->getVertex(index1)[1] == secondGridChainV)
+ {
+
+
+ sampleRightStripRecF(rightChain, index1, botRightIndex, rightGridChain, rightGridChainStartIndex+1, rightGridChainEndIndex, pStream);
+ }
+ else if(index1 < botRightIndex)
+ {
+ //otherwise, we have rightChain->getVertex(index1)[1] > secondV
+ //let the next trim vertex be nextTrimVertex, (which should be strictly
+ //below the second grid line). Find the last grid line index2 which is STRICTLY ABOVE
+ //nextTrimVertex.
+ //sample one trm edge region.
+ Real *uppervert, *lowervert;
+ uppervert = rightChain->getVertex(index1);
+ lowervert = rightChain->getVertex(index1+1); //okay since index1<botRightindex
+ Int index2 = rightGridChainStartIndex+1;
+ while(rightGridChain->get_v_value(index2) > lowervert[1])
+ {
+ index2++;
+ if(index2 > rightGridChainEndIndex)
+ break;
+ }
+ index2--;
+
+ sampleRightSingleTrimEdgeRegion(uppervert, lowervert, rightGridChain, rightGridChainStartIndex+1, index2, pStream);
+
+ //recursion
+ sampleRightStripRecF(rightChain, index1+1, botRightIndex, rightGridChain, index2, rightGridChainEndIndex, pStream);
+ }
+}
+
+//the degenerate case of sampleRightOneGridStep
+void sampleRightOneGridStepNoMiddle(vertexArray* rightChain,
+ Int beginRightIndex,
+ Int endRightIndex,
+ gridBoundaryChain* rightGridChain,
+ Int rightGridChainStartIndex,
+ primStream* pStream)
+{
+ /*since there is no middle, there is at most one point which is on the
+ *second grid line, there could be multiple points on the first (top)
+ *grid line.
+ */
+ rightGridChain->rightEndFan(rightGridChainStartIndex+1, pStream);
+ monoTriangulation2(rightGridChain->get_vertex(rightGridChainStartIndex),
+ rightGridChain->get_vertex(rightGridChainStartIndex+1),
+ rightChain,
+ beginRightIndex,
+ endRightIndex,
+ 0, //decrease chain
+ pStream);
+}
+
+//sampling the right area in between two grid lines
+//shape: _________|
+void sampleRightOneGridStep(vertexArray* rightChain,
+ Int beginRightIndex,
+ Int endRightIndex,
+ gridBoundaryChain* rightGridChain,
+ Int rightGridChainStartIndex,
+ primStream* pStream)
+{
+ if(checkMiddle(rightChain, beginRightIndex, endRightIndex,
+ rightGridChain->get_v_value(rightGridChainStartIndex),
+ rightGridChain->get_v_value(rightGridChainStartIndex+1))<0)
+ {
+ sampleRightOneGridStepNoMiddle(rightChain, beginRightIndex, endRightIndex, rightGridChain, rightGridChainStartIndex, pStream);
+ return;
+ }
+
+ //copy into a polygn
+ {
+ directedLine* poly = NULL;
+ sampledLine* sline;
+ directedLine* dline;
+ gridWrap* grid = rightGridChain->getGrid();
+ float vert1[2];
+ float vert2[2];
+ Int i;
+
+ Int innerInd = rightGridChain->getInnerIndex(rightGridChainStartIndex+1);
+ Int upperInd = rightGridChain->getUlineIndex(rightGridChainStartIndex);
+ Int lowerInd = rightGridChain->getUlineIndex(rightGridChainStartIndex+1);
+ Real upperV = rightGridChain->get_v_value(rightGridChainStartIndex);
+ Real lowerV = rightGridChain->get_v_value(rightGridChainStartIndex+1);
+
+ //the upper gridline
+ vert1[1]=vert2[1]=upperV;
+ for(i=upperInd;
+ i>innerInd;
+ i--)
+ {
+ vert1[0]=grid->get_u_value(i);
+ vert2[0]=grid->get_u_value(i-1);
+ sline = new sampledLine(vert1, vert2);
+ dline = new directedLine(INCREASING, sline);
+ if(poly == NULL)
+ poly = dline;
+ else
+ poly->insert(dline);
+ }
+
+ //the vertical grid line segment
+ vert1[0]=vert2[0] = grid->get_u_value(innerInd);
+ vert1[1]=upperV;
+ vert2[1]=lowerV;
+ sline=new sampledLine(vert1, vert2);
+ dline=new directedLine(INCREASING, sline);
+ if(poly == NULL)
+ poly = dline;
+ else
+ poly->insert(dline);
+
+ //the lower grid line
+ vert1[1]=vert2[1]=lowerV;
+ for(i=innerInd; i<lowerInd; i++)
+ {
+ vert1[0] = grid->get_u_value(i);
+ vert2[0] = grid->get_u_value(i+1);
+ sline = new sampledLine(vert1, vert2);
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+
+ //the edge connecting lower grid to right chain
+ vert1[0]=grid->get_u_value(lowerInd);
+ sline = new sampledLine(vert1, rightChain->getVertex(endRightIndex));
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+
+
+ //the right Chain
+ for(i=endRightIndex; i>beginRightIndex; i--)
+ {
+ sline = new sampledLine(rightChain->getVertex(i), rightChain->getVertex(i-1));
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+
+ //the edge connecting right chain with upper grid
+ vert2[1]=upperV;
+ vert2[0]=grid->get_u_value(upperInd);
+ sline = new sampledLine(rightChain->getVertex(beginRightIndex), vert2);
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ monoTriangulationOpt(poly, pStream);
+ //clean up
+ poly->deleteSinglePolygonWithSline();
+
+ return;
+ }
+
+ //this following code cannot be reached, but leave it for debuggig purpose.
+ Int i;
+ //find the maximal U-monotone chain of beginRightIndex, beginRightIndex+1,...
+ i=beginRightIndex;
+ Real prevU = rightChain->getVertex(i)[0];
+ for(i=beginRightIndex+1; i<= endRightIndex; i++){
+ Real thisU = rightChain->getVertex(i)[0];
+ if(thisU < prevU)
+ prevU = thisU;
+ else
+ break;
+ }
+ //from beginRightIndex to i-1 is strictly U-monotne
+ //if(i-1==beginRightIndex and the vertex of rightchain is on the first
+ //gridline, then we should use 2 vertices on the right chain. Of we only
+ //use one (begin), we would output degenrate triangles.
+ if(i-1 == beginRightIndex && rightChain->getVertex(beginRightIndex)[1] == rightGridChain->get_v_value(rightGridChainStartIndex))
+ i++;
+
+ Int j = endRightIndex -1;
+ if(rightGridChain->getInnerIndex(rightGridChainStartIndex+1) < rightGridChain->getUlineIndex(rightGridChainStartIndex+1))
+ {
+ j = rightChain->findDecreaseChainFromEnd(i-1/*beginRightIndex*/, endRightIndex);
+ Int temp = endRightIndex;
+ //now from j+1 to end is strictly U-monotone.
+ //if j+1 is on the last grid line, then we wat to skip to the vertex
+ //whcih is strictly above the second grid line. This vertex must exist
+ //since there is a middle vertex
+ if(j+1 == endRightIndex)
+ {
+ while(rightChain->getVertex(j+1)[1] == rightGridChain->get_v_value(rightGridChainStartIndex+1))
+ j--;
+
+ monoTriangulation2(rightChain->getVertex(j+1),
+ rightGridChain->get_vertex(rightGridChainStartIndex+1),
+ rightChain,
+ j+2,
+ endRightIndex,
+ 0, //a decrease chain
+ pStream);
+
+ temp = j+1;
+ }
+
+ stripOfFanRight(rightChain, temp, j+1, rightGridChain->getGrid(),
+ rightGridChain->getVlineIndex(rightGridChainStartIndex+1),
+ rightGridChain->getInnerIndex(rightGridChainStartIndex+1),
+ rightGridChain->getUlineIndex(rightGridChainStartIndex+1),
+ pStream,
+ 0 //the grid line is below the trim line
+ );
+
+ }
+
+
+ stripOfFanRight(rightChain, i-1, beginRightIndex, rightGridChain->getGrid(),
+ rightGridChain->getVlineIndex(rightGridChainStartIndex),
+ rightGridChain->getInnerIndex(rightGridChainStartIndex+1),
+ rightGridChain->getUlineIndex(rightGridChainStartIndex),
+ pStream,
+ 1 //the grid line is above the trm lines
+ );
+
+ //monotone triangulate the remaining rightchain together with the
+ //two vertices on the two grid v-lines
+ Real vert[2][2];
+ vert[0][0] = vert[1][0] = rightGridChain->getInner_u_value(rightGridChainStartIndex+1);
+ vert[0][1] = rightGridChain->get_v_value(rightGridChainStartIndex);
+ vert[1][1] = rightGridChain->get_v_value(rightGridChainStartIndex+1);
+
+ monoTriangulation2(&vert[0][0],
+ &vert[1][0],
+ rightChain,
+ i-1,
+ j+1,
+ 0, ///a decreae chain
+ pStream);
+}
+
+#endif
+
+void stripOfFanRight(vertexArray* rightChain,
+ Int largeIndex,
+ Int smallIndex,
+ gridWrap* grid,
+ Int vlineIndex,
+ Int ulineSmallIndex,
+ Int ulineLargeIndex,
+ primStream* pStream,
+ Int gridLineUp /*1 if the grid line is above the trim lines*/
+ )
+{
+ assert(largeIndex >= smallIndex);
+
+ Real grid_v_value;
+ grid_v_value = grid->get_v_value(vlineIndex);
+
+ Real2* trimVerts=(Real2*) malloc(sizeof(Real2)* (largeIndex-smallIndex+1));
+ assert(trimVerts);
+
+
+ Real2* gridVerts=(Real2*) malloc(sizeof(Real2)* (ulineLargeIndex-ulineSmallIndex+1));
+ assert(gridVerts);
+
+ Int k,i;
+ if(! gridLineUp) /*trim line is above grid line, so trim vertices are going right when index increases*/
+ for(k=0, i=smallIndex; i<=largeIndex; i++, k++)
+ {
+ trimVerts[k][0] = rightChain->getVertex(i)[0];
+ trimVerts[k][1] = rightChain->getVertex(i)[1];
+ }
+ else
+ for(k=0, i=largeIndex; i>=smallIndex; i--, k++)
+ {
+ trimVerts[k][0] = rightChain->getVertex(i)[0];
+ trimVerts[k][1] = rightChain->getVertex(i)[1];
+ }
+
+ for(k=0, i=ulineSmallIndex; i<= ulineLargeIndex; i++, k++)
+ {
+ gridVerts[k][0] = grid->get_u_value(i);
+ gridVerts[k][1] = grid_v_value;
+ }
+
+ if(gridLineUp)
+ triangulateXYMono(
+ ulineLargeIndex-ulineSmallIndex+1, gridVerts,
+ largeIndex-smallIndex+1, trimVerts,
+ pStream);
+ else
+ triangulateXYMono(largeIndex-smallIndex+1, trimVerts,
+ ulineLargeIndex-ulineSmallIndex+1, gridVerts,
+ pStream);
+ free(trimVerts);
+ free(gridVerts);
+}
+
+
+
+
+
+
+
+
+
diff --git a/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.h b/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.h
new file mode 100644
index 00000000000..805db962be5
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.h
@@ -0,0 +1,124 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#ifndef _SAMPLECOMPRIGHT_H
+#define _SAMPLECOMPRIGHT_H
+
+#define NOT_TAKEOUT
+
+#include "sampleMonoPoly.h"
+void stripOfFanRight(vertexArray* rightChain,
+ Int largeIndex,
+ Int smallIndex,
+ gridWrap* grid,
+ Int vlineIndex,
+ Int ulineSmallIndex,
+ Int ulineLargeIndex,
+ primStream* pStream,
+ Int gridLineUp /*1 if grid line is above the trim lines */
+ );
+
+#ifdef NOT_TAKEOUT
+void sampleRightStripRecF(vertexArray* rightChain,
+ Int topRightIndex,
+ Int botRightIndex,
+ gridBoundaryChain* rightGridChain,
+ Int rightGridChainStartIndex,
+ Int rightGridChainEndIndex,
+ primStream* pStream
+ );
+//the degenerate case of sampleRightOneGridStep
+void sampleRightOneGridStepNoMiddle(vertexArray* rightChain,
+ Int beginRightIndex,
+ Int endRightIndex,
+ gridBoundaryChain* rightGridChain,
+ Int rightGridChainStartIndex,
+ primStream* pStream);
+//sampling the right area in between two grid lines
+//shape: _________|
+void sampleRightOneGridStep(vertexArray* rightChain,
+ Int beginRightIndex,
+ Int endRightIndex,
+ gridBoundaryChain* rightGridChain,
+ Int rightGridChainStartIndex,
+ primStream* pStream);
+void sampleRightSingleTrimEdgeRegion(Real upperVert[2], Real lowerVert[2],
+ gridBoundaryChain* gridChain,
+ Int beginIndex,
+ Int endIndex,
+ primStream* pStream);
+//the degenerate case of sampleRightOneGridStep
+void sampleRightOneGridStepNoMiddle(vertexArray* rightChain,
+ Int beginRightIndex,
+ Int endRightIndex,
+ gridBoundaryChain* rightGridChain,
+ Int rightGridChainStartIndex,
+ primStream* pStream);
+
+void sampleCompRight(Real* topVertex, Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex, Int leftEndIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex, Int rightEndIndex,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1, Int gridIndex2,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ primStream* pStream);
+
+void sampleRightSingleTrimEdgeRegionGen(Real topVert[2], Real botVert[2],
+ vertexArray* rightChain,
+ Int rightStart,
+ Int rightEnd,
+ gridBoundaryChain* gridChain,
+ Int gridBegindex,
+ Int gridEndIndex,
+ vertexArray* leftChain,
+ Int leftUpBegin,
+ Int leftUpEnd,
+ Int leftDownBegin,
+ Int leftDownEnd,
+ primStream* pStream);
+#endif
+
+#endif
+
+
diff --git a/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.cc b/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.cc
new file mode 100644
index 00000000000..548767b57b1
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.cc
@@ -0,0 +1,1032 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/11/29 16:16:55 $ $Revision: 1.2 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.cc,v 1.2 2001/11/29 16:16:55 kschultz Exp $
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include "zlassert.h"
+#include "sampleCompTop.h"
+#include "sampleCompRight.h"
+
+#define max(a,b) ((a>b)? a:b)
+
+//return : index_small, and index_large,
+//from [small, large] is strictly U-monotne,
+//from [large+1, end] is <u
+//and vertex[large][0] is >= u
+//if eveybody is <u, the large = start-1.
+//otherwise both large and small are meaningful and we have start<=small<=large<=end
+void findTopLeftSegment(vertexArray* leftChain,
+ Int leftStart,
+ Int leftEnd,
+ Real u,
+ Int& ret_index_small,
+ Int& ret_index_large
+ )
+{
+ Int i;
+ assert(leftStart <= leftEnd);
+ for(i=leftEnd; i>= leftStart; i--)
+ {
+ if(leftChain->getVertex(i)[0] >= u)
+ break;
+ }
+ ret_index_large = i;
+ if(ret_index_large >= leftStart)
+ {
+ for(i=ret_index_large; i>leftStart; i--)
+ {
+ if(leftChain->getVertex(i-1)[0] <= leftChain->getVertex(i)[0])
+ break;
+ }
+ ret_index_small = i;
+ }
+}
+
+void findTopRightSegment(vertexArray* rightChain,
+ Int rightStart,
+ Int rightEnd,
+ Real u,
+ Int& ret_index_small,
+ Int& ret_index_large)
+{
+ Int i;
+ assert(rightStart<=rightEnd);
+ for(i=rightEnd; i>=rightStart; i--)
+ {
+ if(rightChain->getVertex(i)[0] <= u)
+ break;
+ }
+ ret_index_large = i;
+ if(ret_index_large >= rightStart)
+ {
+ for(i=ret_index_large; i>rightStart;i--)
+ {
+ if(rightChain->getVertex(i-1)[0] >= rightChain->getVertex(i)[0])
+ break;
+ }
+ ret_index_small = i;
+ }
+}
+
+
+void sampleTopRightWithGridLinePost(Real* topVertex,
+ vertexArray* rightChain,
+ Int rightStart,
+ Int segIndexSmall,
+ Int segIndexLarge,
+ Int rightEnd,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream)
+{
+ //the possible section which is to the right of rightU
+ if(segIndexLarge < rightEnd)
+ {
+ Real *tempTop;
+ if(segIndexLarge >= rightStart)
+ tempTop = rightChain->getVertex(segIndexLarge);
+ else
+ tempTop = topVertex;
+ Real tempBot[2];
+ tempBot[0] = grid->get_u_value(rightU);
+ tempBot[1] = grid->get_v_value(gridV);
+monoTriangulationRecGenOpt(tempTop, tempBot,
+ NULL, 1,0,
+ rightChain, segIndexLarge+1, rightEnd,
+ pStream);
+/*
+ monoTriangulation2(tempTop, tempBot,
+ rightChain,
+ segIndexLarge+1,
+ rightEnd,
+ 0, //a decrease chian
+ pStream);
+*/
+
+ }
+
+ //the possible section which is strictly Umonotone
+ if(segIndexLarge >= rightStart)
+ {
+ stripOfFanRight(rightChain, segIndexLarge, segIndexSmall, grid, gridV, leftU, rightU, pStream, 0);
+ Real tempBot[2];
+ tempBot[0] = grid->get_u_value(leftU);
+ tempBot[1] = grid->get_v_value(gridV);
+ monoTriangulation2(topVertex, tempBot, rightChain, rightStart, segIndexSmall, 0, pStream);
+ }
+ else //the topVertex forms a fan with the grid points
+ grid->outputFanWithPoint(gridV, leftU, rightU, topVertex, pStream);
+}
+
+void sampleTopRightWithGridLine(Real* topVertex,
+ vertexArray* rightChain,
+ Int rightStart,
+ Int rightEnd,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream
+ )
+{
+ //if right chian is empty, then there is only one topVertex with one grid line
+ if(rightEnd < rightStart){
+ grid->outputFanWithPoint(gridV, leftU, rightU, topVertex, pStream);
+ return;
+ }
+
+ Int segIndexSmall, segIndexLarge;
+ findTopRightSegment(rightChain,
+ rightStart,
+ rightEnd,
+ grid->get_u_value(rightU),
+ segIndexSmall,
+ segIndexLarge
+ );
+ sampleTopRightWithGridLinePost(topVertex, rightChain,
+ rightStart,
+ segIndexSmall,
+ segIndexLarge,
+ rightEnd,
+ grid,
+ gridV,
+ leftU,
+ rightU,
+ pStream);
+}
+
+
+void sampleTopLeftWithGridLinePost(Real* topVertex,
+ vertexArray* leftChain,
+ Int leftStart,
+ Int segIndexSmall,
+ Int segIndexLarge,
+ Int leftEnd,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream)
+{
+ //the possible section which is to the left of leftU
+
+ if(segIndexLarge < leftEnd)
+ {
+ Real *tempTop;
+ if(segIndexLarge >= leftStart)
+ tempTop = leftChain->getVertex(segIndexLarge);
+ else
+ tempTop = topVertex;
+ Real tempBot[2];
+ tempBot[0] = grid->get_u_value(leftU);
+ tempBot[1] = grid->get_v_value(gridV);
+
+ monoTriangulation2(tempTop, tempBot,
+ leftChain,
+ segIndexLarge+1,
+ leftEnd,
+ 1, //a increase chian
+ pStream);
+ }
+
+ //the possible section which is strictly Umonotone
+ if(segIndexLarge >= leftStart)
+ {
+ //if there are grid points which are to the right of topV,
+ //then we should use topVertex to form a fan with these points to
+ //optimize the triangualtion
+ int do_optimize=1;
+ if(topVertex[0] >= grid->get_u_value(rightU))
+ do_optimize = 0;
+ else
+ {
+ //we also have to make sure that topVertex are the right most vertex
+ //on the chain.
+ int i;
+ for(i=leftStart; i<=segIndexSmall; i++)
+ if(leftChain->getVertex(i)[0] >= topVertex[0])
+ {
+ do_optimize = 0;
+ break;
+ }
+ }
+
+ if(do_optimize)
+ {
+ //find midU so that grid->get_u_value(midU) >= topVertex[0]
+ //and grid->get_u_value(midU-1) < topVertex[0]
+ int midU=rightU;
+ while(grid->get_u_value(midU) >= topVertex[0])
+ {
+ midU--;
+ if(midU < leftU)
+ break;
+ }
+ midU++;
+
+ grid->outputFanWithPoint(gridV, midU, rightU, topVertex, pStream);
+ stripOfFanLeft(leftChain, segIndexLarge, segIndexSmall, grid, gridV, leftU, midU, pStream, 0);
+ Real tempBot[2];
+ tempBot[0] = grid->get_u_value(midU);
+ tempBot[1] = grid->get_v_value(gridV);
+ monoTriangulation2(topVertex, tempBot, leftChain, leftStart, segIndexSmall, 1, pStream);
+ }
+ else //not optimize
+ {
+
+ stripOfFanLeft(leftChain, segIndexLarge, segIndexSmall, grid, gridV, leftU, rightU, pStream, 0);
+ Real tempBot[2];
+ tempBot[0] = grid->get_u_value(rightU);
+ tempBot[1] = grid->get_v_value(gridV);
+ monoTriangulation2(topVertex, tempBot, leftChain, leftStart, segIndexSmall, 1, pStream);
+ }
+ }
+ else //the topVertex forms a fan with the grid points
+ grid->outputFanWithPoint(gridV, leftU, rightU, topVertex, pStream);
+}
+
+
+void sampleTopLeftWithGridLine(Real* topVertex,
+ vertexArray* leftChain,
+ Int leftStart,
+ Int leftEnd,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream
+ )
+{
+ Int segIndexSmall, segIndexLarge;
+ //if left chain is empty, then there is only one top vertex with one grid
+ // line
+ if(leftEnd < leftStart) {
+ grid->outputFanWithPoint(gridV, leftU, rightU, topVertex, pStream);
+ return;
+ }
+ findTopLeftSegment(leftChain,
+ leftStart,
+ leftEnd,
+ grid->get_u_value(leftU),
+ segIndexSmall,
+ segIndexLarge
+ );
+ sampleTopLeftWithGridLinePost(topVertex,
+ leftChain,
+ leftStart,
+ segIndexSmall,
+ segIndexLarge,
+ leftEnd,
+ grid,
+ gridV,
+ leftU,
+ rightU,
+ pStream);
+}
+
+
+//return 1 if saprator exits, 0 otherwise
+Int findTopSeparator(vertexArray* leftChain,
+ Int leftStartIndex,
+ Int leftEndIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex,
+ Int rightEndIndex,
+ Int& ret_sep_left,
+ Int& ret_sep_right)
+{
+
+ Int oldLeftI, oldRightI, newLeftI, newRightI;
+ Int i,j,k;
+ Real leftMax /*= leftChain->getVertex(leftEndIndex)[0]*/;
+ Real rightMin /*= rightChain->getVertex(rightEndIndex)[0]*/;
+ if(leftChain->getVertex(leftEndIndex)[1] > rightChain->getVertex(rightEndIndex)[1]) //left higher
+ {
+ oldLeftI = leftEndIndex+1;
+ oldRightI = rightEndIndex;
+ leftMax = leftChain->getVertex(leftEndIndex)[0] - Real(1.0); //initilza to left of leftU
+ rightMin = rightChain->getVertex(rightEndIndex)[0];
+ }
+ else
+ {
+ oldLeftI = leftEndIndex;
+ oldRightI = rightEndIndex+1;
+ leftMax = leftChain->getVertex(leftEndIndex)[0];
+ rightMin = rightChain->getVertex(rightEndIndex)[0] + Real(1.0);
+ }
+
+ //i: the current working leftChain index,
+ //j: the current working rightChain index,
+ //if left(i) is higher than right(j), then the two chains beloew right(j) are separated.
+ //else the two chains below left(i) are separeated.
+ i=leftEndIndex;
+ j=rightEndIndex;
+ while(1)
+ {
+ newLeftI = oldLeftI;
+ newRightI = oldRightI;
+
+ if(i<leftStartIndex) //left chain is done, go through remining right chain.
+ {
+ for(k=j-1; k>= rightStartIndex; k--)
+ {
+ if(rightChain->getVertex(k)[0] > leftMax) //no conflict
+ {
+ //update oldRightI if necessary
+ if(rightChain->getVertex(k)[0] < rightMin)
+ {
+ rightMin = rightChain->getVertex(k)[0];
+ oldRightI = k;
+ }
+ }
+ else //there is a conflict
+ break; //the for-loop. below right(k-1) is seperated: oldLeftI, oldRightI.
+ }
+ break; //the while loop
+ }
+ else if(j<rightStartIndex) //rightChain is done
+ {
+ for(k=i-1; k>= leftStartIndex; k--)
+ {
+ if(leftChain->getVertex(k)[0] < rightMin) //no conflict
+ {
+ //update oldLeftI if necessary
+ if(leftChain->getVertex(k)[0] > leftMax)
+ {
+ leftMax = leftChain->getVertex(k)[0];
+ oldLeftI = k;
+ }
+ }
+ else //there is a conflict
+ break; //the for loop
+ }
+ break; //the while loop
+ }
+ else if(leftChain->getVertex(i)[1] > rightChain->getVertex(j)[1]) //left hgiher
+ {
+ if(leftChain->getVertex(i)[0] > leftMax) //update leftMax and newLeftI.
+ {
+ leftMax = leftChain->getVertex(i)[0];
+ newLeftI = i;
+ }
+ for(k=j-1; k>= rightStartIndex; k--) //update rightMin and newRightI.
+ {
+ if(rightChain->getVertex(k)[1] > leftChain->getVertex(i)[1])
+ break;
+ if(rightChain->getVertex(k)[0] < rightMin)
+ {
+ rightMin = rightChain->getVertex(k)[0];
+ newRightI = k;
+ }
+ }
+ j = k; //next working j, since j will be higher than i in next loop
+ if(leftMax >= rightMin) //there is a conflict
+ break;
+ else //still no conflict
+ {
+ oldLeftI = newLeftI;
+ oldRightI = newRightI;
+ }
+ }
+ else //right higher
+ {
+ if(rightChain->getVertex(j)[0] < rightMin)
+ {
+ rightMin = rightChain->getVertex(j)[0];
+ newRightI = j;
+ }
+ for(k=i-1; k>= leftStartIndex; k--)
+ {
+ if(leftChain->getVertex(k)[1] > rightChain->getVertex(j)[1])
+ break;
+ if(leftChain->getVertex(k)[0] > leftMax)
+ {
+ leftMax = leftChain->getVertex(k)[0];
+ newLeftI = k;
+ }
+ }
+ i = k; //next working i, since i will be higher than j next loop
+
+ if(leftMax >= rightMin) //there is a conflict
+ break;
+ else //still no conflict
+ {
+ oldLeftI = newLeftI;
+ oldRightI = newRightI;
+ }
+ }
+ }//end of while loop
+ //now oldLeftI and oldRightI are the desired separeator index, notice that there are not necessarily valid
+ if(oldLeftI > leftEndIndex || oldRightI > rightEndIndex)
+ return 0;
+ else
+ {
+ ret_sep_left = oldLeftI;
+ ret_sep_right = oldRightI;
+ return 1;
+ }
+}
+
+
+void sampleCompTop(Real* topVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int up_rightCornerWhere,
+ Int up_rightCornerIndex,
+ primStream* pStream)
+{
+ if(up_leftCornerWhere == 1 && up_rightCornerWhere == 1) //the top is topVertex with possible grid points
+ {
+ leftGridChain->getGrid()->outputFanWithPoint(leftGridChain->getVlineIndex(gridIndex1),
+ leftGridChain->getUlineIndex(gridIndex1),
+ rightGridChain->getUlineIndex(gridIndex1),
+ topVertex,
+ pStream);
+ return;
+ }
+
+ else if(up_leftCornerWhere != 0)
+ {
+ Real* tempTop;
+ Int tempRightStart;
+ if(up_leftCornerWhere == 1){
+ tempRightStart = rightStartIndex;
+ tempTop = topVertex;
+ }
+ else
+ {
+ tempRightStart = up_leftCornerIndex+1;
+ tempTop = rightChain->getVertex(up_leftCornerIndex);
+ }
+ sampleTopRightWithGridLine(tempTop, rightChain, tempRightStart, up_rightCornerIndex,
+ rightGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex1),
+ leftGridChain->getUlineIndex(gridIndex1),
+ rightGridChain->getUlineIndex(gridIndex1),
+ pStream);
+ }
+ else if(up_rightCornerWhere != 2)
+ {
+ Real* tempTop;
+ Int tempLeftStart;
+ if(up_rightCornerWhere == 1)
+ {
+ tempLeftStart = leftStartIndex;
+ tempTop = topVertex;
+ }
+ else //0
+ {
+ tempLeftStart = up_rightCornerIndex+1;
+ tempTop = leftChain->getVertex(up_rightCornerIndex);
+ }
+/*
+ sampleTopLeftWithGridLine(tempTop, leftChain, tempLeftStart, up_leftCornerIndex,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex1),
+ leftGridChain->getUlineIndex(gridIndex1),
+ rightGridChain->getUlineIndex(gridIndex1),
+ pStream);
+*/
+ sampleCompTopSimple(topVertex,
+ leftChain,
+ leftStartIndex,
+ rightChain,
+ rightStartIndex,
+ leftGridChain,
+ rightGridChain,
+ gridIndex1,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ pStream);
+ }
+ else //up_leftCornerWhere == 0, up_rightCornerWhere == 2.
+ {
+ sampleCompTopSimple(topVertex,
+ leftChain,
+ leftStartIndex,
+ rightChain,
+ rightStartIndex,
+ leftGridChain,
+ rightGridChain,
+ gridIndex1,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ pStream);
+ return;
+#ifdef NOT_REACHABLE //code is not reachable, for test purpose only
+ //the following code is trying to do some optimization, but not quite working, also see sampleCompBot.C:
+ Int sep_left, sep_right;
+ if(findTopSeparator(leftChain,
+ leftStartIndex,
+ up_leftCornerIndex,
+ rightChain,
+ rightStartIndex,
+ up_rightCornerIndex,
+ sep_left,
+ sep_right)
+ ) //separator exists
+ {
+
+ if( leftChain->getVertex(sep_left)[0] >= leftGridChain->get_u_value(gridIndex1) &&
+ rightChain->getVertex(sep_right)[0] <= rightGridChain->get_u_value(gridIndex1))
+ {
+ Int gridSep;
+ Int segLeftSmall, segLeftLarge, segRightSmall, segRightLarge;
+ Int valid=1; //whether the gridStep is valid or not.
+ findTopLeftSegment(leftChain,
+ sep_left,
+ up_leftCornerIndex,
+ leftGridChain->get_u_value(gridIndex1),
+ segLeftSmall,
+ segLeftLarge);
+ findTopRightSegment(rightChain,
+ sep_right,
+ up_rightCornerIndex,
+ rightGridChain->get_u_value(gridIndex1),
+ segRightSmall,
+ segRightLarge);
+ if(leftChain->getVertex(segLeftSmall)[1] >= rightChain->getVertex(segRightSmall)[1])
+ {
+ gridSep = rightGridChain->getUlineIndex(gridIndex1);
+ while(leftGridChain->getGrid()->get_u_value(gridSep) > leftChain->getVertex(segLeftSmall)[0])
+ gridSep--;
+ if(segLeftSmall<segLeftLarge)
+ if(leftGridChain->getGrid()->get_u_value(gridSep) < leftChain->getVertex(segLeftSmall+1)[0])
+ {
+ valid = 0;
+ }
+ }
+ else
+ {
+ gridSep = leftGridChain->getUlineIndex(gridIndex1);
+ while(leftGridChain->getGrid()->get_u_value(gridSep) < rightChain->getVertex(segRightSmall)[0])
+ gridSep++;
+ if(segRightSmall<segRightLarge)
+ if(leftGridChain->getGrid()->get_u_value(gridSep) > rightChain->getVertex(segRightSmall+1)[0])
+ {
+ valid = 0;
+ }
+ }
+
+ if(! valid)
+ {
+ sampleCompTopSimple(topVertex,
+ leftChain,
+ leftStartIndex,
+ rightChain,
+ rightStartIndex,
+ leftGridChain,
+ rightGridChain,
+ gridIndex1,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ pStream);
+ }
+ else
+ {
+ sampleTopLeftWithGridLinePost(leftChain->getVertex(segLeftSmall),
+ leftChain,
+ segLeftSmall+1,
+ segLeftSmall+1,
+ segLeftLarge,
+ up_leftCornerIndex,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex1),
+ leftGridChain->getUlineIndex(gridIndex1),
+ gridSep,
+ pStream);
+ sampleTopRightWithGridLinePost(rightChain->getVertex(segRightSmall),
+ rightChain,
+ segRightSmall+1,
+ segRightSmall+1,
+ segRightLarge,
+ up_rightCornerIndex,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex1),
+ gridSep,
+ rightGridChain->getUlineIndex(gridIndex1),
+ pStream);
+ Real tempBot[2];
+ tempBot[0] = leftGridChain->getGrid()->get_u_value(gridSep);
+ tempBot[1] = leftGridChain->get_v_value(gridIndex1);
+ monoTriangulationRecGen(topVertex, tempBot,
+ leftChain, leftStartIndex, segLeftSmall,
+ rightChain, rightStartIndex, segRightSmall,
+ pStream);
+ }
+ }//end if both sides have vetices inside the gridboundary points
+ else if(leftChain->getVertex(sep_left)[0] >= leftGridChain->get_u_value(gridIndex1)) //left is in, right is nout
+ {
+
+ Int segLeftSmall, segLeftLarge;
+ findTopLeftSegment(leftChain,
+ sep_left,
+ up_leftCornerIndex,
+ leftGridChain->get_u_value(gridIndex1),
+ segLeftSmall,
+ segLeftLarge);
+ assert(segLeftLarge >= sep_left);
+ monoTriangulation2(leftChain->getVertex(segLeftLarge),
+ leftGridChain->get_vertex(gridIndex1),
+ leftChain,
+ segLeftLarge+1,
+ up_leftCornerIndex,
+ 1, //a increase chain,
+ pStream);
+
+ stripOfFanLeft(leftChain, segLeftLarge, segLeftSmall,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex1),
+ leftGridChain->getUlineIndex(gridIndex1),
+ rightGridChain->getUlineIndex(gridIndex1),
+ pStream, 0);
+
+
+ monoTriangulationRecGen(topVertex, rightGridChain->get_vertex(gridIndex1),
+ leftChain, leftStartIndex, segLeftSmall,
+ rightChain, rightStartIndex, up_rightCornerIndex,
+ pStream);
+ }//end left in right out
+ else if(rightChain->getVertex(sep_right)[0] <= rightGridChain->get_u_value(gridIndex1))
+ {
+ Int segRightSmall, segRightLarge;
+ findTopRightSegment(rightChain,
+ sep_right,
+ up_rightCornerIndex,
+ rightGridChain->get_u_value(gridIndex1),
+ segRightSmall,
+ segRightLarge);
+ assert(segRightLarge>=sep_right);
+ monoTriangulation2(rightChain->getVertex(segRightLarge),
+ rightGridChain->get_vertex(gridIndex1),
+ rightChain,
+ segRightLarge+1,
+ up_rightCornerIndex,
+ 0, //a decrease chain
+ pStream);
+ stripOfFanRight(rightChain, segRightLarge, segRightSmall,
+ rightGridChain->getGrid(),
+ rightGridChain->getVlineIndex(gridIndex1),
+ leftGridChain->getUlineIndex(gridIndex1),
+ rightGridChain->getUlineIndex(gridIndex1),
+ pStream, 0);
+
+
+ monoTriangulationRecGen(topVertex, leftGridChain->get_vertex(gridIndex1),
+ leftChain, leftStartIndex, up_leftCornerIndex,
+ rightChain, rightStartIndex,segRightSmall,
+ pStream);
+
+ }//end left out rigth in
+ else //left out , right out
+ {
+
+ sampleCompTopSimple(topVertex,
+ leftChain,
+ leftStartIndex,
+ rightChain,
+ rightStartIndex,
+ leftGridChain,
+ rightGridChain,
+ gridIndex1,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ pStream);
+ }//end leftout, right out
+ }//end if separator exixts.
+ else //no separator
+ {
+
+ sampleCompTopSimple(topVertex,
+ leftChain,
+ leftStartIndex,
+ rightChain,
+ rightStartIndex,
+ leftGridChain,
+ rightGridChain,
+ gridIndex1,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ pStream);
+ }
+#endif
+ }//end if 0,2
+}//end if the function
+
+
+static void sampleCompTopSimpleOpt(gridWrap* grid,
+ Int gridV,
+ Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream)
+{
+ if(gridV <= 0 || dec_end<dec_current || inc_end <inc_current)
+ {
+ monoTriangulationRecGenOpt(topVertex, botVertex,
+ inc_chain, inc_current, inc_end,
+ dec_chain, dec_current, dec_end,
+ pStream);
+ return;
+ }
+ if(grid->get_v_value(gridV+1) >= topVertex[1])
+ {
+ monoTriangulationRecGenOpt(topVertex, botVertex,
+ inc_chain, inc_current, inc_end,
+ dec_chain, dec_current, dec_end,
+ pStream);
+ return;
+ }
+ Int i,j,k;
+ Real currentV = grid->get_v_value(gridV+1);
+ if(inc_chain->getVertex(inc_end)[1] <= currentV &&
+ dec_chain->getVertex(dec_end)[1] < currentV)
+ {
+ //find i bottom up so that inc_chain[i]<= curentV and inc_chain[i-1] > currentV,
+ //find j botom up so that dec_chain[j] < currentV and dec_chain[j-1] >= currentV
+ for(i=inc_end; i >= inc_current; i--)
+ {
+ if(inc_chain->getVertex(i)[1] > currentV)
+ break;
+ }
+ i++;
+ for(j=dec_end; j >= dec_current; j--)
+ {
+ if(dec_chain->getVertex(j)[1] >= currentV)
+ break;
+ }
+ j++;
+ if(inc_chain->getVertex(i)[1] <= dec_chain->getVertex(j)[1])
+ {
+ //find the k so that dec_chain[k][1] < inc_chain[i][1]
+ for(k=j; k<=dec_end; k++)
+ {
+ if(dec_chain->getVertex(k)[1] < inc_chain->getVertex(i)[1])
+ break;
+ }
+ //we know that dec_chain[j][1] >= inc_chian[i][1]
+ //we know that dec_chain[k-1][1]>=inc_chain[i][1]
+ //we know that dec_chian[k][1] < inc_chain[i][1]
+ //find l in [j, k-1] so that dec_chain[l][0] 0 is closest to
+ // inc_chain[i]
+ int l;
+ Real tempI = Real(j);
+ Real tempMin = (Real)fabs(inc_chain->getVertex(i)[0] - dec_chain->getVertex(j)[0]);
+ for(l=j+1; l<= k-1; l++)
+ {
+ if(fabs(inc_chain->getVertex(i)[0] - dec_chain->getVertex(l)[0])
+ <= tempMin)
+ {
+ tempMin = (Real)fabs(inc_chain->getVertex(i)[0] - dec_chain->getVertex(l)[0]);
+ tempI = (Real)l;
+ }
+ }
+ //inc_chain[i] and dec_chain[tempI] are connected.
+ monoTriangulationRecGenOpt(dec_chain->getVertex((int)tempI),
+ botVertex,
+ inc_chain, i, inc_end,
+ dec_chain, (int)(tempI+1), dec_end,
+ pStream);
+ //recursively do the rest
+ sampleCompTopSimpleOpt(grid,
+ gridV+1,
+ topVertex, inc_chain->getVertex(i),
+ inc_chain, inc_current, i-1,
+ dec_chain, dec_current, (int)tempI,
+ pStream);
+ }
+ else
+ {
+ //find the k so that inc_chain[k][1] <= dec_chain[j][1]
+ for(k=i; k<=inc_end; k++)
+ {
+ if(inc_chain->getVertex(k)[1] <= dec_chain->getVertex(j)[1])
+ break;
+ }
+ //we know that inc_chain[i] > dec_chain[j]
+ //we know that inc_chain[k-1][1] > dec_chain[j][1]
+ //we know that inc_chain[k][1] <= dec_chain[j][1]
+ //so we find l between [i,k-1] so that
+ //inc_chain[l][0] is the closet to dec_chain[j][0]
+ int tempI = i;
+ int l;
+ Real tempMin = (Real)fabs(inc_chain->getVertex(i)[0] - dec_chain->getVertex(j)[0]);
+ for(l=i+1; l<=k-1; l++)
+ {
+ if(fabs(inc_chain->getVertex(l)[0] - dec_chain->getVertex(j)[0]) <= tempMin)
+ {
+ tempMin = (Real)fabs(inc_chain->getVertex(l)[0] - dec_chain->getVertex(j)[0]);
+ tempI = l;
+ }
+ }
+
+ //inc_chain[tempI] and dec_chain[j] are connected
+
+ monoTriangulationRecGenOpt(inc_chain->getVertex(tempI),
+ botVertex,
+ inc_chain, tempI+1, inc_end,
+ dec_chain, j, dec_end,
+ pStream);
+
+ //recurvesily do the rest
+ sampleCompTopSimpleOpt(grid, gridV+1,
+ topVertex, dec_chain->getVertex(j),
+ inc_chain, inc_current, tempI,
+ dec_chain, dec_current, j-1,
+ pStream);
+ }
+ }
+ else //go to the next higher gridV
+ {
+ sampleCompTopSimpleOpt(grid,
+ gridV+1,
+ topVertex, botVertex,
+ inc_chain, inc_current, inc_end,
+ dec_chain, dec_current, dec_end,
+ pStream);
+ }
+}
+
+void sampleCompTopSimple(Real* topVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int up_rightCornerWhere,
+ Int up_rightCornerIndex,
+ primStream* pStream)
+{
+ //the plan is to use monotriangulation algortihm.
+ Int i,k;
+ Real* ActualTop;
+ Real* ActualBot;
+ Int ActualLeftStart, ActualLeftEnd;
+ Int ActualRightStart, ActualRightEnd;
+
+ //creat an array to store the points on the grid line
+ gridWrap* grid = leftGridChain->getGrid();
+ Int gridV = leftGridChain->getVlineIndex(gridIndex1);
+ Int gridLeftU = leftGridChain->getUlineIndex(gridIndex1);
+ Int gridRightU = rightGridChain->getUlineIndex(gridIndex1);
+
+ Real2* gridPoints = (Real2*) malloc(sizeof(Real2) * (gridRightU - gridLeftU +1));
+ assert(gridPoints);
+
+ for(k=0, i=gridRightU; i>= gridLeftU; i--, k++)
+ {
+ gridPoints[k][0] = grid->get_u_value(i);
+ gridPoints[k][1] = grid->get_v_value(gridV);
+ }
+
+ if(up_leftCornerWhere != 2)
+ ActualRightStart = rightStartIndex;
+ else
+ ActualRightStart = up_leftCornerIndex+1; //up_leftCornerIndex will be the ActualTop
+
+ if(up_rightCornerWhere != 2) //right corner is not on right chain
+ ActualRightEnd = rightStartIndex-1; //meaning that there is no actual rigth section
+ else
+ ActualRightEnd = up_rightCornerIndex;
+
+ vertexArray ActualRightChain(max(0, ActualRightEnd-ActualRightStart+1) + gridRightU-gridLeftU+1);
+
+ for(i=ActualRightStart; i<= ActualRightEnd; i++)
+ ActualRightChain.appendVertex(rightChain->getVertex(i));
+ for(i=0; i<gridRightU-gridLeftU+1; i++)
+ ActualRightChain.appendVertex(gridPoints[i]);
+
+ //determine ActualLeftEnd
+ if(up_leftCornerWhere != 0)
+ ActualLeftEnd = leftStartIndex-1;
+ else
+ ActualLeftEnd = up_leftCornerIndex;
+
+ if(up_rightCornerWhere != 0)
+ ActualLeftStart = leftStartIndex;
+ else
+ ActualLeftStart = up_rightCornerIndex+1; //up_rightCornerIndex will be the actual top
+
+ if(up_leftCornerWhere == 0)
+ {
+ if(up_rightCornerWhere == 0)
+ ActualTop = leftChain->getVertex(up_rightCornerIndex);
+ else
+ ActualTop = topVertex;
+ }
+ else if(up_leftCornerWhere == 1)
+ ActualTop = topVertex;
+ else //up_leftCornerWhere == 2
+ ActualTop = rightChain->getVertex(up_leftCornerIndex);
+
+ ActualBot = gridPoints[gridRightU - gridLeftU];
+
+
+
+
+ if(leftChain->getVertex(ActualLeftEnd)[1] == ActualBot[1])
+ {
+/*
+ monoTriangulationRecGenOpt(ActualTop, leftChain->getVertex(ActualLeftEnd),
+ leftChain,
+ ActualLeftStart, ActualLeftEnd-1,
+ &ActualRightChain,
+ 0,
+ ActualRightChain.getNumElements()-1,
+ pStream);
+*/
+
+ sampleCompTopSimpleOpt(grid, gridV,
+ ActualTop, leftChain->getVertex(ActualLeftEnd),
+ leftChain,
+ ActualLeftStart, ActualLeftEnd-1,
+ &ActualRightChain,
+ 0,
+ ActualRightChain.getNumElements()-1,
+ pStream);
+
+ }
+ else
+ {
+/*
+ monoTriangulationRecGenOpt(ActualTop, ActualBot, leftChain,
+ ActualLeftStart, ActualLeftEnd,
+ &ActualRightChain,
+ 0, ActualRightChain.getNumElements()-2, //the last is the bot.
+ pStream);
+*/
+
+ sampleCompTopSimpleOpt(grid, gridV,
+ ActualTop, ActualBot, leftChain,
+ ActualLeftStart, ActualLeftEnd,
+ &ActualRightChain,
+ 0, ActualRightChain.getNumElements()-2, //the last is the bot.
+ pStream);
+
+
+ }
+
+ free(gridPoints);
+
+}
+
diff --git a/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.h b/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.h
new file mode 100644
index 00000000000..1d843ca8a37
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.h
@@ -0,0 +1,74 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#ifndef _SAMPLECOMPTOP_H
+#define _SAMPLECOMPTOP_H
+
+#include "sampleMonoPoly.h"
+
+void sampleCompTop(Real* topVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int up_rightCornerWhere,
+ Int up_rightCornerIndex,
+ primStream* pStream);
+
+void sampleCompTopSimple(Real* topVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int up_rightCornerWhere,
+ Int up_rightCornerIndex,
+ primStream* pStream);
+
+#endif
+
diff --git a/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.cc b/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.cc
new file mode 100644
index 00000000000..8502d83962c
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.cc
@@ -0,0 +1,2429 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2005/10/28 13:09:09 $ $Revision: 1.4.8.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.cc,v 1.4.8.1 2005/10/28 13:09:09 brianp Exp $
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#ifndef max
+#define max(a,b) ((a>b)? a:b)
+#endif
+#ifndef min
+#define min(a,b) ((a>b)? b:a)
+#endif
+
+#include <GL/gl.h>
+
+#include "glimports.h"
+#include "zlassert.h"
+#include "sampleMonoPoly.h"
+#include "sampleComp.h"
+#include "polyDBG.h"
+#include "partitionX.h"
+
+
+#define ZERO 0.00001
+
+//#define MYDEBUG
+
+//#define SHORTEN_GRID_LINE
+//see work/newtess/internal/test/problems
+
+
+/*split a polygon so that each vertex correcpond to one edge
+ *the head of the first edge of the returned plygon must be the head of the first
+ *edge of the origianl polygon. This is crucial for the code in sampleMonoPoly function
+ */
+ directedLine* polygonConvert(directedLine* polygon)
+{
+ int i;
+ directedLine* ret;
+ sampledLine* sline;
+ sline = new sampledLine(2);
+ sline->setPoint(0, polygon->getVertex(0));
+ sline->setPoint(1, polygon->getVertex(1));
+ ret=new directedLine(INCREASING, sline);
+ for(i=1; i<= polygon->get_npoints()-2; i++)
+ {
+ sline = new sampledLine(2);
+ sline->setPoint(0, polygon->getVertex(i));
+ sline->setPoint(1, polygon->getVertex(i+1));
+ ret->insert(new directedLine(INCREASING, sline));
+ }
+
+ for(directedLine *temp = polygon->getNext(); temp != polygon; temp = temp->getNext())
+ {
+ for(i=0; i<= temp->get_npoints()-2; i++)
+ {
+ sline = new sampledLine(2);
+ sline->setPoint(0, temp->getVertex(i));
+ sline->setPoint(1, temp->getVertex(i+1));
+ ret->insert(new directedLine(INCREASING, sline));
+ }
+ }
+ return ret;
+}
+
+void triangulateConvexPolyVertical(directedLine* topV, directedLine* botV, primStream *pStream)
+{
+ Int i,j;
+ Int n_leftVerts;
+ Int n_rightVerts;
+ Real** leftVerts;
+ Real** rightVerts;
+ directedLine* tempV;
+ n_leftVerts = 0;
+ for(tempV = topV; tempV != botV; tempV = tempV->getNext())
+ {
+ n_leftVerts += tempV->get_npoints();
+ }
+ n_rightVerts=0;
+ for(tempV = botV; tempV != topV; tempV = tempV->getNext())
+ {
+ n_rightVerts += tempV->get_npoints();
+ }
+
+ Real2* temp_leftVerts = (Real2 *) malloc(sizeof(Real2) * n_leftVerts);
+ assert(temp_leftVerts);
+ Real2* temp_rightVerts = (Real2 *) malloc(sizeof(Real2) * n_rightVerts);
+ assert(temp_rightVerts);
+
+ leftVerts = (Real**) malloc(sizeof(Real2*) * n_leftVerts);
+ assert(leftVerts);
+ rightVerts = (Real**) malloc(sizeof(Real2*) * n_rightVerts);
+ assert(rightVerts);
+ for(i=0; i<n_leftVerts; i++)
+ leftVerts[i] = temp_leftVerts[i];
+ for(i=0; i<n_rightVerts; i++)
+ rightVerts[i] = temp_rightVerts[i];
+
+ i=0;
+ for(tempV = topV; tempV != botV; tempV = tempV->getNext())
+ {
+ for(j=1; j<tempV->get_npoints(); j++)
+ {
+ leftVerts[i][0] = tempV->getVertex(j)[0];
+ leftVerts[i][1] = tempV->getVertex(j)[1];
+ i++;
+ }
+ }
+ n_leftVerts = i;
+ i=0;
+ for(tempV = topV->getPrev(); tempV != botV->getPrev(); tempV = tempV->getPrev())
+ {
+ for(j=tempV->get_npoints()-1; j>=1; j--)
+ {
+ rightVerts[i][0] = tempV->getVertex(j)[0];
+ rightVerts[i][1] = tempV->getVertex(j)[1];
+ i++;
+ }
+ }
+ n_rightVerts = i;
+ triangulateXYMonoTB(n_leftVerts, leftVerts, n_rightVerts, rightVerts, pStream);
+ free(leftVerts);
+ free(rightVerts);
+ free(temp_leftVerts);
+ free(temp_rightVerts);
+}
+
+void triangulateConvexPolyHoriz(directedLine* leftV, directedLine* rightV, primStream *pStream)
+{
+ Int i,j;
+ Int n_lowerVerts;
+ Int n_upperVerts;
+ Real2 *lowerVerts;
+ Real2 *upperVerts;
+ directedLine* tempV;
+ n_lowerVerts=0;
+ for(tempV = leftV; tempV != rightV; tempV = tempV->getNext())
+ {
+ n_lowerVerts += tempV->get_npoints();
+ }
+ n_upperVerts=0;
+ for(tempV = rightV; tempV != leftV; tempV = tempV->getNext())
+ {
+ n_upperVerts += tempV->get_npoints();
+ }
+ lowerVerts = (Real2 *) malloc(sizeof(Real2) * n_lowerVerts);
+ assert(n_lowerVerts);
+ upperVerts = (Real2 *) malloc(sizeof(Real2) * n_upperVerts);
+ assert(n_upperVerts);
+ i=0;
+ for(tempV = leftV; tempV != rightV; tempV = tempV->getNext())
+ {
+ for(j=0; j<tempV->get_npoints(); j++)
+ {
+ lowerVerts[i][0] = tempV->getVertex(j)[0];
+ lowerVerts[i][1] = tempV->getVertex(j)[1];
+ i++;
+ }
+ }
+ i=0;
+ for(tempV = leftV->getPrev(); tempV != rightV->getPrev(); tempV = tempV->getPrev())
+ {
+ for(j=tempV->get_npoints()-1; j>=0; j--)
+ {
+ upperVerts[i][0] = tempV->getVertex(j)[0];
+ upperVerts[i][1] = tempV->getVertex(j)[1];
+ i++;
+ }
+ }
+ triangulateXYMono(n_upperVerts, upperVerts, n_lowerVerts, lowerVerts, pStream);
+ free(lowerVerts);
+ free(upperVerts);
+}
+void triangulateConvexPoly(directedLine* polygon, Int ulinear, Int vlinear, primStream* pStream)
+{
+ /*find left, right, top , bot
+ */
+ directedLine* tempV;
+ directedLine* topV;
+ directedLine* botV;
+ directedLine* leftV;
+ directedLine* rightV;
+ topV = botV = polygon;
+
+ for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext())
+ {
+ if(compV2InY(topV->head(), tempV->head())<0) {
+
+ topV = tempV;
+ }
+ if(compV2InY(botV->head(), tempV->head())>0) {
+
+ botV = tempV;
+ }
+ }
+ //find leftV
+ for(tempV = topV; tempV != botV; tempV = tempV->getNext())
+ {
+ if(tempV->tail()[0] >= tempV->head()[0])
+ break;
+ }
+ leftV = tempV;
+ //find rightV
+ for(tempV = botV; tempV != topV; tempV = tempV->getNext())
+ {
+ if(tempV->tail()[0] <= tempV->head()[0])
+ break;
+ }
+ rightV = tempV;
+ if(vlinear)
+ {
+ triangulateConvexPolyHoriz( leftV, rightV, pStream);
+ }
+ else if(ulinear)
+ {
+ triangulateConvexPolyVertical(topV, botV, pStream);
+ }
+ else
+ {
+ if(DBG_is_U_direction(polygon))
+ {
+ triangulateConvexPolyHoriz( leftV, rightV, pStream);
+ }
+ else
+ triangulateConvexPolyVertical(topV, botV, pStream);
+ }
+}
+
+/*for debug purpose*/
+void drawCorners(
+ Real* topV, Real* botV,
+ vertexArray* leftChain,
+ vertexArray* rightChain,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1,
+ Int gridIndex2,
+ Int leftCornerWhere,
+ Int leftCornerIndex,
+ Int rightCornerWhere,
+ Int rightCornerIndex,
+ Int bot_leftCornerWhere,
+ Int bot_leftCornerIndex,
+ Int bot_rightCornerWhere,
+ Int bot_rightCornerIndex)
+{
+ Real* leftCornerV;
+ Real* rightCornerV;
+ Real* bot_leftCornerV;
+ Real* bot_rightCornerV;
+
+ if(leftCornerWhere == 1)
+ leftCornerV = topV;
+ else if(leftCornerWhere == 0)
+ leftCornerV = leftChain->getVertex(leftCornerIndex);
+ else
+ leftCornerV = rightChain->getVertex(leftCornerIndex);
+
+ if(rightCornerWhere == 1)
+ rightCornerV = topV;
+ else if(rightCornerWhere == 0)
+ rightCornerV = leftChain->getVertex(rightCornerIndex);
+ else
+ rightCornerV = rightChain->getVertex(rightCornerIndex);
+
+ if(bot_leftCornerWhere == 1)
+ bot_leftCornerV = botV;
+ else if(bot_leftCornerWhere == 0)
+ bot_leftCornerV = leftChain->getVertex(bot_leftCornerIndex);
+ else
+ bot_leftCornerV = rightChain->getVertex(bot_leftCornerIndex);
+
+ if(bot_rightCornerWhere == 1)
+ bot_rightCornerV = botV;
+ else if(bot_rightCornerWhere == 0)
+ bot_rightCornerV = leftChain->getVertex(bot_rightCornerIndex);
+ else
+ bot_rightCornerV = rightChain->getVertex(bot_rightCornerIndex);
+
+ Real topGridV = leftGridChain->get_v_value(gridIndex1);
+ Real topGridU1 = leftGridChain->get_u_value(gridIndex1);
+ Real topGridU2 = rightGridChain->get_u_value(gridIndex1);
+ Real botGridV = leftGridChain->get_v_value(gridIndex2);
+ Real botGridU1 = leftGridChain->get_u_value(gridIndex2);
+ Real botGridU2 = rightGridChain->get_u_value(gridIndex2);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(leftCornerV);
+ glVertex2f(topGridU1, topGridV);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(rightCornerV);
+ glVertex2f(topGridU2, topGridV);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(bot_leftCornerV);
+ glVertex2f(botGridU1, botGridV);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(bot_rightCornerV);
+ glVertex2f(botGridU2, botGridV);
+ glEnd();
+
+
+}
+
+void toVertexArrays(directedLine* topV, directedLine* botV, vertexArray& leftChain, vertexArray& rightChain)
+{
+ Int i;
+ directedLine* tempV;
+ for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
+ leftChain.appendVertex(topV->getVertex(i));
+ }
+ for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext())
+ {
+ for(i=0; i<=tempV->get_npoints()-2; i++){
+ leftChain.appendVertex(tempV->getVertex(i));
+ }
+ }
+
+ for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
+ {
+ for(i=tempV->get_npoints()-2; i>=0; i--){
+ rightChain.appendVertex(tempV->getVertex(i));
+ }
+ }
+ for(i=botV->get_npoints()-2; i>=1; i--){
+ rightChain.appendVertex(tempV->getVertex(i));
+ }
+}
+
+
+void findTopAndBot(directedLine* polygon, directedLine*& topV, directedLine*& botV)
+{
+ assert(polygon);
+ directedLine* tempV;
+ topV = botV = polygon;
+ for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext())
+ {
+ if(compV2InY(topV->head(), tempV->head())<0) {
+ topV = tempV;
+ }
+ if(compV2InY(botV->head(), tempV->head())>0) {
+ botV = tempV;
+ }
+ }
+}
+
+void findGridChains(directedLine* topV, directedLine* botV,
+ gridWrap* grid,
+ gridBoundaryChain*& leftGridChain,
+ gridBoundaryChain*& rightGridChain)
+{
+ /*find the first(top) and the last (bottom) grid line which intersect the
+ *this polygon
+ */
+ Int firstGridIndex; /*the index in the grid*/
+ Int lastGridIndex;
+
+ firstGridIndex = (Int) ((topV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1));
+
+ if(botV->head()[1] < grid->get_v_min())
+ lastGridIndex = 0;
+ else
+ lastGridIndex = (Int) ((botV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1)) + 1;
+
+ /*find the interval inside the polygon for each gridline*/
+ Int *leftGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(leftGridIndices);
+ Int *rightGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(rightGridIndices);
+ Int *leftGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(leftGridInnerIndices);
+ Int *rightGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(rightGridInnerIndices);
+
+ findLeftGridIndices(topV, firstGridIndex, lastGridIndex, grid, leftGridIndices, leftGridInnerIndices);
+
+ findRightGridIndices(topV, firstGridIndex, lastGridIndex, grid, rightGridIndices, rightGridInnerIndices);
+
+ leftGridChain = new gridBoundaryChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, leftGridIndices, leftGridInnerIndices);
+
+ rightGridChain = new gridBoundaryChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, rightGridIndices, rightGridInnerIndices);
+
+ free(leftGridIndices);
+ free(rightGridIndices);
+ free(leftGridInnerIndices);
+ free(rightGridInnerIndices);
+}
+
+void findDownCorners(Real *botVertex,
+ vertexArray *leftChain, Int leftChainStartIndex, Int leftChainEndIndex,
+ vertexArray *rightChain, Int rightChainStartIndex, Int rightChainEndIndex,
+ Real v,
+ Real uleft,
+ Real uright,
+ Int& ret_leftCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/
+ Int& ret_leftCornerIndex, /*useful when ret_leftCornerWhere == 0 or 2*/
+ Int& ret_rightCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/
+ Int& ret_rightCornerIndex /*useful when ret_leftCornerWhere == 0 or 2*/
+ )
+{
+#ifdef MYDEBUG
+printf("*************enter find donw corner\n");
+printf("finddownCorner: v=%f, uleft=%f, uright=%f\n", v, uleft, uright);
+printf("(%i,%i,%i,%i)\n", leftChainStartIndex, leftChainEndIndex,rightChainStartIndex, rightChainEndIndex);
+printf("left chain is\n");
+leftChain->print();
+printf("right chain is\n");
+rightChain->print();
+#endif
+
+ assert(v > botVertex[1]);
+ Real leftGridPoint[2];
+ leftGridPoint[0] = uleft;
+ leftGridPoint[1] = v;
+ Real rightGridPoint[2];
+ rightGridPoint[0] = uright;
+ rightGridPoint[1] = v;
+
+ Int i;
+ Int index1, index2;
+
+ index1 = leftChain->findIndexBelowGen(v, leftChainStartIndex, leftChainEndIndex);
+ index2 = rightChain->findIndexBelowGen(v, rightChainStartIndex, rightChainEndIndex);
+
+ if(index2 <= rightChainEndIndex) //index2 was found above
+ index2 = rightChain->skipEqualityFromStart(v, index2, rightChainEndIndex);
+
+ if(index1>leftChainEndIndex && index2 > rightChainEndIndex) /*no point below v on left chain or right chain*/
+ {
+
+ /*the botVertex is the only vertex below v*/
+ ret_leftCornerWhere = 1;
+ ret_rightCornerWhere = 1;
+ }
+ else if(index1>leftChainEndIndex ) /*index2 <= rightChainEndIndex*/
+ {
+
+ ret_rightCornerWhere = 2; /*on right chain*/
+ ret_rightCornerIndex = index2;
+
+
+ Real tempMin = rightChain->getVertex(index2)[0];
+ Int tempI = index2;
+ for(i=index2+1; i<= rightChainEndIndex; i++)
+ if(rightChain->getVertex(i)[0] < tempMin)
+ {
+ tempI = i;
+ tempMin = rightChain->getVertex(i)[0];
+ }
+
+
+ //we consider whether we can use botVertex as left corner. First check
+ //if (leftGirdPoint, botVertex) interesects right chian or not.
+ if(DBG_intersectChain(rightChain, rightChainStartIndex,rightChainEndIndex,
+ leftGridPoint, botVertex))
+ {
+ ret_leftCornerWhere = 2;//right
+ ret_leftCornerIndex = index2; //should use tempI???
+ }
+ else if(botVertex[0] < tempMin)
+ ret_leftCornerWhere = 1; //bot
+ else
+ {
+ ret_leftCornerWhere = 2; //right
+ ret_leftCornerIndex = tempI;
+ }
+ }
+ else if(index2> rightChainEndIndex) /*index1<=leftChainEndIndex*/
+ {
+ ret_leftCornerWhere = 0; /*left chain*/
+ ret_leftCornerIndex = index1;
+
+ /*find the vertex on the left chain with the maximum u,
+ *either this vertex or the botvertex can be used as the right corner
+ */
+
+ Int tempI;
+ //skip those points which are equal to v. (avoid degeneratcy)
+ for(tempI = index1; tempI <= leftChainEndIndex; tempI++)
+ if(leftChain->getVertex(tempI)[1] < v)
+ break;
+ if(tempI > leftChainEndIndex)
+ ret_rightCornerWhere = 1;
+ else
+ {
+ Real tempMax = leftChain->getVertex(tempI)[0];
+ for(i=tempI; i<= leftChainEndIndex; i++)
+ if(leftChain->getVertex(i)[0] > tempMax)
+ {
+ tempI = i;
+ tempMax = leftChain->getVertex(i)[0];
+ }
+
+
+
+ //we consider whether we can use botVertex as a corner. So first we check
+ //whether (rightGridPoint, botVertex) interescts the left chain or not.
+ if(DBG_intersectChain(leftChain, leftChainStartIndex,leftChainEndIndex,
+ rightGridPoint, botVertex))
+ {
+ ret_rightCornerWhere = 0;
+ ret_rightCornerIndex = index1; //should use tempI???
+ }
+ else if(botVertex[0] > tempMax)
+ {
+
+ ret_rightCornerWhere = 1;
+ }
+ else
+ {
+ ret_rightCornerWhere = 0;
+ ret_rightCornerIndex = tempI;
+ }
+ }
+
+ }
+ else /*index1<=leftChainEndIndex and index2 <=rightChainEndIndex*/
+ {
+ if(leftChain->getVertex(index1)[1] >= rightChain->getVertex(index2)[1]) /*left point above right point*/
+ {
+ ret_leftCornerWhere = 0; /*on left chain*/
+ ret_leftCornerIndex = index1;
+
+ Real tempMax;
+ Int tempI;
+
+ tempI = index1;
+ tempMax = leftChain->getVertex(index1)[0];
+
+ /*find the maximum u for all the points on the left above the right point index2*/
+ for(i=index1+1; i<= leftChainEndIndex; i++)
+ {
+ if(leftChain->getVertex(i)[1] < rightChain->getVertex(index2)[1])
+ break;
+
+ if(leftChain->getVertex(i)[0]>tempMax)
+ {
+ tempI = i;
+ tempMax = leftChain->getVertex(i)[0];
+ }
+ }
+ //we consider if we can use rightChain(index2) as right corner
+ //we check if (rightChain(index2), rightGidPoint) intersecs left chain or not.
+ if(DBG_intersectChain(leftChain, leftChainStartIndex,leftChainEndIndex, rightGridPoint, rightChain->getVertex(index2)))
+ {
+ ret_rightCornerWhere = 0;
+ ret_rightCornerIndex = index1; //should use tempI???
+ }
+ else if(tempMax >= rightChain->getVertex(index2)[0] ||
+ tempMax >= uright
+ )
+ {
+
+ ret_rightCornerWhere = 0; /*on left Chain*/
+ ret_rightCornerIndex = tempI;
+ }
+ else
+ {
+ ret_rightCornerWhere = 2; /*on right chain*/
+ ret_rightCornerIndex = index2;
+ }
+ }
+ else /*left below right*/
+ {
+ ret_rightCornerWhere = 2; /*on the right*/
+ ret_rightCornerIndex = index2;
+
+ Real tempMin;
+ Int tempI;
+
+ tempI = index2;
+ tempMin = rightChain->getVertex(index2)[0];
+
+ /*find the minimum u for all the points on the right above the left poitn index1*/
+ for(i=index2+1; i<= rightChainEndIndex; i++)
+ {
+ if( rightChain->getVertex(i)[1] < leftChain->getVertex(index1)[1])
+ break;
+ if(rightChain->getVertex(i)[0] < tempMin)
+ {
+ tempI = i;
+ tempMin = rightChain->getVertex(i)[0];
+ }
+ }
+
+ //we consider if we can use leftchain(index1) as left corner.
+ //we check if (leftChain(index1) intersects right chian or not
+ if(DBG_intersectChain(rightChain, rightChainStartIndex, rightChainEndIndex, leftGridPoint, leftChain->getVertex(index1)))
+ {
+ ret_leftCornerWhere = 2;
+ ret_leftCornerIndex = index2; //should use tempI???
+ }
+ else if(tempMin <= leftChain->getVertex(index1)[0] ||
+ tempMin <= uleft)
+ {
+ ret_leftCornerWhere = 2; /* on right chain*/
+ ret_leftCornerIndex = tempI;
+ }
+ else
+ {
+ ret_leftCornerWhere = 0; /*on left chain*/
+ ret_leftCornerIndex = index1;
+ }
+ }
+ }
+
+}
+
+
+void findUpCorners(Real *topVertex,
+ vertexArray *leftChain, Int leftChainStartIndex, Int leftChainEndIndex,
+ vertexArray *rightChain, Int rightChainStartIndex, Int rightChainEndIndex,
+ Real v,
+ Real uleft,
+ Real uright,
+ Int& ret_leftCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/
+ Int& ret_leftCornerIndex, /*useful when ret_leftCornerWhere == 0 or 2*/
+ Int& ret_rightCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/
+ Int& ret_rightCornerIndex /*useful when ret_leftCornerWhere == 0 or 2*/
+ )
+{
+#ifdef MYDEBUG
+printf("***********enter findUpCorners\n");
+#endif
+
+ assert(v < topVertex[1]);
+ Real leftGridPoint[2];
+ leftGridPoint[0] = uleft;
+ leftGridPoint[1] = v;
+ Real rightGridPoint[2];
+ rightGridPoint[0] = uright;
+ rightGridPoint[1] = v;
+
+ Int i;
+ Int index1, index2;
+
+ index1 = leftChain->findIndexFirstAboveEqualGen(v, leftChainStartIndex, leftChainEndIndex);
+
+
+ index2 = rightChain->findIndexFirstAboveEqualGen(v, rightChainStartIndex, rightChainEndIndex);
+
+ if(index2>= leftChainStartIndex) //index2 was found above
+ index2 = rightChain->skipEqualityFromStart(v, index2, rightChainEndIndex);
+
+ if(index1<leftChainStartIndex && index2 <rightChainStartIndex) /*no point above v on left chain or right chain*/
+ {
+ /*the topVertex is the only vertex above v*/
+ ret_leftCornerWhere = 1;
+ ret_rightCornerWhere = 1;
+ }
+ else if(index1<leftChainStartIndex ) /*index2 >= rightChainStartIndex*/
+ {
+ ret_rightCornerWhere = 2; /*on right chain*/
+ ret_rightCornerIndex = index2;
+
+ //find the minimum u on right top, either that, or top, or right[index2] is the left corner
+ Real tempMin = rightChain->getVertex(index2)[0];
+ Int tempI = index2;
+ for(i=index2-1; i>=rightChainStartIndex; i--)
+ if(rightChain->getVertex(i)[0] < tempMin)
+ {
+ tempMin = rightChain->getVertex(i)[0];
+ tempI = i;
+ }
+ //chech whether (leftGridPoint, top) intersects rightchai,
+ //if yes, use right corner as left corner
+ //if not, use top or right[tempI] as left corner
+ if(DBG_intersectChain(rightChain, rightChainStartIndex, rightChainEndIndex,
+ leftGridPoint, topVertex))
+ {
+ ret_leftCornerWhere = 2; //rightChain
+ ret_leftCornerIndex = index2;
+ }
+ else if(topVertex[0] < tempMin)
+ ret_leftCornerWhere = 1; /*topvertex*/
+ else
+ {
+ ret_leftCornerWhere = 2; //right chain
+ ret_leftCornerIndex = tempI;
+ }
+
+ }
+ else if(index2< rightChainStartIndex) /*index1>=leftChainStartIndex*/
+ {
+ ret_leftCornerWhere = 0; /*left chain*/
+ ret_leftCornerIndex = index1;
+
+ //find the maximum u on the left top section. either that or topvertex, or left[index1] is the right corner
+ Real tempMax = leftChain->getVertex(index1)[0];
+ Int tempI = index1;
+
+ for(i=index1-1; i>=leftChainStartIndex; i--){
+
+ if(leftChain->getVertex(i)[0] > tempMax)
+ {
+
+ tempMax = leftChain->getVertex(i)[0];
+ tempI = i;
+ }
+ }
+ //check whether (rightGridPoint, top) intersects leftChain or not
+ //if yes, we use leftCorner as the right corner
+ //if not, we use either top or left[tempI] as the right corner
+ if(DBG_intersectChain(leftChain, leftChainStartIndex,leftChainEndIndex,
+ rightGridPoint, topVertex))
+ {
+ ret_rightCornerWhere = 0; //left chan
+ ret_rightCornerIndex = index1;
+ }
+ else if(topVertex[0] > tempMax)
+ ret_rightCornerWhere = 1;//topVertex
+ else
+ {
+ ret_rightCornerWhere = 0;//left chain
+ ret_rightCornerIndex = tempI;
+ }
+ }
+ else /*index1>=leftChainStartIndex and index2 >=rightChainStartIndex*/
+ {
+ if(leftChain->getVertex(index1)[1] <= rightChain->getVertex(index2)[1]) /*left point below right point*/
+ {
+ ret_leftCornerWhere = 0; /*on left chain*/
+ ret_leftCornerIndex = index1;
+
+ Real tempMax;
+ Int tempI;
+
+ tempI = index1;
+ tempMax = leftChain->getVertex(index1)[0];
+
+ /*find the maximum u for all the points on the left below the right point index2*/
+ for(i=index1-1; i>= leftChainStartIndex; i--)
+ {
+ if(leftChain->getVertex(i)[1] > rightChain->getVertex(index2)[1])
+ break;
+
+ if(leftChain->getVertex(i)[0]>tempMax)
+ {
+ tempI = i;
+ tempMax = leftChain->getVertex(i)[0];
+ }
+ }
+ //chek whether (rightChain(index2), rightGridPoint) intersects leftchian or not
+ if(DBG_intersectChain(leftChain, leftChainStartIndex, leftChainEndIndex, rightGridPoint, rightChain->getVertex(index2)))
+ {
+ ret_rightCornerWhere = 0;
+ ret_rightCornerIndex = index1;
+ }
+ else if(tempMax >= rightChain->getVertex(index2)[0] ||
+ tempMax >= uright)
+ {
+ ret_rightCornerWhere = 0; /*on left Chain*/
+ ret_rightCornerIndex = tempI;
+ }
+ else
+ {
+ ret_rightCornerWhere = 2; /*on right chain*/
+ ret_rightCornerIndex = index2;
+ }
+ }
+ else /*left above right*/
+ {
+ ret_rightCornerWhere = 2; /*on the right*/
+ ret_rightCornerIndex = index2;
+
+ Real tempMin;
+ Int tempI;
+
+ tempI = index2;
+ tempMin = rightChain->getVertex(index2)[0];
+
+ /*find the minimum u for all the points on the right below the left poitn index1*/
+ for(i=index2-1; i>= rightChainStartIndex; i--)
+ {
+ if( rightChain->getVertex(i)[1] > leftChain->getVertex(index1)[1])
+ break;
+ if(rightChain->getVertex(i)[0] < tempMin)
+ {
+ tempI = i;
+ tempMin = rightChain->getVertex(i)[0];
+ }
+ }
+ //check whether (leftGRidPoint,left(index1)) interesect right chain
+ if(DBG_intersectChain(rightChain, rightChainStartIndex, rightChainEndIndex,
+ leftGridPoint, leftChain->getVertex(index1)))
+ {
+ ret_leftCornerWhere = 2; //right
+ ret_leftCornerIndex = index2;
+ }
+ else if(tempMin <= leftChain->getVertex(index1)[0] ||
+ tempMin <= uleft)
+ {
+ ret_leftCornerWhere = 2; /* on right chain*/
+ ret_leftCornerIndex = tempI;
+ }
+ else
+ {
+ ret_leftCornerWhere = 0; /*on left chain*/
+ ret_leftCornerIndex = index1;
+ }
+ }
+ }
+#ifdef MYDEBUG
+printf("***********leave findUpCorners\n");
+#endif
+}
+
+//return 1 if neck exists, 0 othewise
+Int findNeckF(vertexArray *leftChain, Int botLeftIndex,
+ vertexArray *rightChain, Int botRightIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridStartIndex,
+ Int& neckLeft,
+ Int& neckRight)
+{
+/*
+printf("enter findNeckF, botleft, botright=%i,%i,gstartindex=%i\n",botLeftIndex,botRightIndex,gridStartIndex);
+printf("leftChain is\n");
+leftChain->print();
+printf("rightChain is\n");
+rightChain->print();
+*/
+
+ Int lowerGridIndex; //the grid below leftChain and rightChian vertices
+ Int i;
+ Int n_vlines = leftGridChain->get_nVlines();
+ Real v;
+ if(botLeftIndex >= leftChain->getNumElements() ||
+ botRightIndex >= rightChain->getNumElements())
+ return 0; //no neck exists
+
+ v=min(leftChain->getVertex(botLeftIndex)[1], rightChain->getVertex(botRightIndex)[1]);
+
+
+
+
+ for(i=gridStartIndex; i<n_vlines; i++)
+ if(leftGridChain->get_v_value(i) <= v &&
+ leftGridChain->getUlineIndex(i)<= rightGridChain->getUlineIndex(i))
+ break;
+
+ lowerGridIndex = i;
+
+ if(lowerGridIndex == n_vlines) //the two trm vertex are higher than all gridlines
+ return 0;
+ else
+ {
+ Int botLeft2, botRight2;
+/*
+printf("leftGridChain->get_v_)value=%f\n",leftGridChain->get_v_value(lowerGridIndex), botLeftIndex);
+printf("leftChain->get_vertex(0)=(%f,%f)\n", leftChain->getVertex(0)[0],leftChain->getVertex(0)[1]);
+printf("leftChain->get_vertex(1)=(%f,%f)\n", leftChain->getVertex(1)[0],leftChain->getVertex(1)[1]);
+printf("leftChain->get_vertex(2)=(%f,%f)\n", leftChain->getVertex(2)[0],leftChain->getVertex(2)[1]);
+*/
+ botLeft2 = leftChain->findIndexFirstAboveEqualGen(leftGridChain->get_v_value(lowerGridIndex), botLeftIndex, leftChain->getNumElements()-1) -1 ;
+
+/*
+printf("botLeft2=%i\n", botLeft2);
+printf("leftChain->getNumElements=%i\n", leftChain->getNumElements());
+*/
+
+ botRight2 = rightChain->findIndexFirstAboveEqualGen(leftGridChain->get_v_value(lowerGridIndex), botRightIndex, rightChain->getNumElements()-1) -1;
+ if(botRight2 < botRightIndex) botRight2=botRightIndex;
+
+ if(botLeft2 < botLeftIndex) botLeft2 = botLeftIndex;
+
+ assert(botLeft2 >= botLeftIndex);
+ assert(botRight2 >= botRightIndex);
+ //find nectLeft so that it is th erightmost vertex on letChain
+
+ Int tempI = botLeftIndex;
+ Real temp = leftChain->getVertex(tempI)[0];
+ for(i=botLeftIndex+1; i<= botLeft2; i++)
+ if(leftChain->getVertex(i)[0] > temp)
+ {
+ temp = leftChain->getVertex(i)[0];
+ tempI = i;
+ }
+ neckLeft = tempI;
+
+ tempI = botRightIndex;
+ temp = rightChain->getVertex(tempI)[0];
+ for(i=botRightIndex+1; i<= botRight2; i++)
+ if(rightChain->getVertex(i)[0] < temp)
+ {
+ temp = rightChain->getVertex(i)[0];
+ tempI = i;
+ }
+ neckRight = tempI;
+ return 1;
+ }
+}
+
+
+
+/*find i>=botLeftIndex,j>=botRightIndex so that
+ *(leftChain[i], rightChain[j]) is a neck.
+ */
+void findNeck(vertexArray *leftChain, Int botLeftIndex,
+ vertexArray *rightChain, Int botRightIndex,
+ Int& leftLastIndex, /*left point of the neck*/
+ Int& rightLastIndex /*right point of the neck*/
+ )
+{
+ assert(botLeftIndex < leftChain->getNumElements() &&
+ botRightIndex < rightChain->getNumElements());
+
+ /*now the neck exists for sure*/
+
+ if(leftChain->getVertex(botLeftIndex)[1] <= rightChain->getVertex(botRightIndex)[1]) //left below right
+ {
+
+ leftLastIndex = botLeftIndex;
+
+ /*find i so that rightChain[i][1] >= leftchainbotverte[1], and i+1<
+ */
+ rightLastIndex=rightChain->findIndexAboveGen(leftChain->getVertex(botLeftIndex)[1], botRightIndex+1, rightChain->getNumElements()-1);
+ }
+ else //left above right
+ {
+
+ rightLastIndex = botRightIndex;
+
+ leftLastIndex = leftChain->findIndexAboveGen(rightChain->getVertex(botRightIndex)[1],
+ botLeftIndex+1,
+ leftChain->getNumElements()-1);
+ }
+}
+
+
+
+void findLeftGridIndices(directedLine* topEdge, Int firstGridIndex, Int lastGridIndex, gridWrap* grid, Int* ret_indices, Int* ret_innerIndices)
+{
+
+ Int i,k,isHoriz = 0;
+ Int n_ulines = grid->get_n_ulines();
+ Real uMin = grid->get_u_min();
+ Real uMax = grid->get_u_max();
+ /*
+ Real vMin = grid->get_v_min();
+ Real vMax = grid->get_v_max();
+ */
+ Real slop = 0.0, uinterc;
+
+#ifdef SHORTEN_GRID_LINE
+ //uintercBuf stores all the interction u value for each grid line
+ //notice that lastGridIndex<= firstGridIndex
+ Real *uintercBuf = (Real *) malloc (sizeof(Real) * (firstGridIndex-lastGridIndex+1));
+ assert(uintercBuf);
+#endif
+
+ /*initialization to make vtail bigger than grid->...*/
+ directedLine* dLine = topEdge;
+ Real vtail = grid->get_v_value(firstGridIndex) + 1.0;
+ Real tempMaxU = grid->get_u_min();
+
+
+ /*for each grid line*/
+ for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++)
+ {
+
+ Real grid_v_value = grid->get_v_value(i);
+
+ /*check whether this grid line is below the current trim edge.*/
+ if(vtail > grid_v_value)
+ {
+ /*since the grid line is below the trim edge, we
+ *find the trim edge which will contain the trim line
+ */
+ while( (vtail=dLine->tail()[1]) > grid_v_value){
+
+ tempMaxU = max(tempMaxU, dLine->tail()[0]);
+ dLine = dLine -> getNext();
+ }
+
+ if( fabs(dLine->head()[1] - vtail) < ZERO)
+ isHoriz = 1;
+ else
+ {
+ isHoriz = 0;
+ slop = (dLine->head()[0] - dLine->tail()[0]) / (dLine->head()[1]-vtail);
+ }
+ }
+
+ if(isHoriz)
+ {
+ uinterc = max(dLine->head()[0], dLine->tail()[0]);
+ }
+ else
+ {
+ uinterc = slop * (grid_v_value - vtail) + dLine->tail()[0];
+ }
+
+ tempMaxU = max(tempMaxU, uinterc);
+
+ if(uinterc < uMin && uinterc >= uMin - ZERO)
+ uinterc = uMin;
+ if(uinterc > uMax && uinterc <= uMax + ZERO)
+ uinterc = uMax;
+
+#ifdef SHORTEN_GRID_LINE
+ uintercBuf[k] = uinterc;
+#endif
+
+ assert(uinterc >= uMin && uinterc <= uMax);
+ if(uinterc == uMax)
+ ret_indices[k] = n_ulines-1;
+ else
+ ret_indices[k] = (Int)(((uinterc-uMin)/(uMax - uMin)) * (n_ulines-1)) + 1;
+ if(ret_indices[k] >= n_ulines)
+ ret_indices[k] = n_ulines-1;
+
+
+ ret_innerIndices[k] = (Int)(((tempMaxU-uMin)/(uMax - uMin)) * (n_ulines-1)) + 1;
+
+ /*reinitialize tempMaxU for next grdiLine*/
+ tempMaxU = uinterc;
+ }
+#ifdef SHORTEN_GRID_LINE
+ //for each grid line, compare the left grid point with the
+ //intersection point. If the two points are too close, then
+ //we should move the grid point one grid to the right
+ //and accordingly we should update the inner index.
+ for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++)
+ {
+ //check gridLine i
+ //check ret_indices[k]
+ Real a = grid->get_u_value(ret_indices[k]-1);
+ Real b = grid->get_u_value(ret_indices[k]);
+ assert(uintercBuf[k] >= a && uintercBuf < b);
+ if( (b-uintercBuf[k]) <= 0.2 * (b-a)) //interc is very close to b
+ {
+ ret_indices[k]++;
+ }
+
+ //check ret_innerIndices[k]
+ if(k>0)
+ {
+ if(ret_innerIndices[k] < ret_indices[k-1])
+ ret_innerIndices[k] = ret_indices[k-1];
+ if(ret_innerIndices[k] < ret_indices[k])
+ ret_innerIndices[k] = ret_indices[k];
+ }
+ }
+ //clean up
+ free(uintercBuf);
+#endif
+}
+
+void findRightGridIndices(directedLine* topEdge, Int firstGridIndex, Int lastGridIndex, gridWrap* grid, Int* ret_indices, Int* ret_innerIndices)
+{
+
+ Int i,k;
+ Int n_ulines = grid->get_n_ulines();
+ Real uMin = grid->get_u_min();
+ Real uMax = grid->get_u_max();
+ /*
+ Real vMin = grid->get_v_min();
+ Real vMax = grid->get_v_max();
+ */
+ Real slop = 0.0, uinterc;
+
+#ifdef SHORTEN_GRID_LINE
+ //uintercBuf stores all the interction u value for each grid line
+ //notice that firstGridIndex >= lastGridIndex
+ Real *uintercBuf = (Real *) malloc (sizeof(Real) * (firstGridIndex-lastGridIndex+1));
+ assert(uintercBuf);
+#endif
+
+ /*initialization to make vhead bigger than grid->v_value...*/
+ directedLine* dLine = topEdge->getPrev();
+ Real vhead = dLine->tail()[1];
+ Real tempMinU = grid->get_u_max();
+
+ /*for each grid line*/
+ for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++)
+ {
+
+ Real grid_v_value = grid->get_v_value(i);
+
+
+ /*check whether this grid line is below the current trim edge.*/
+ if(vhead >= grid_v_value)
+ {
+ /*since the grid line is below the tail of the trim edge, we
+ *find the trim edge which will contain the trim line
+ */
+ while( (vhead=dLine->head()[1]) > grid_v_value){
+ tempMinU = min(tempMinU, dLine->head()[0]);
+ dLine = dLine -> getPrev();
+ }
+
+ /*skip the equality in the case of degenerat case: horizontal */
+ while(dLine->head()[1] == grid_v_value)
+ dLine = dLine->getPrev();
+
+ assert( dLine->tail()[1] != dLine->head()[1]);
+ slop = (dLine->tail()[0] - dLine->head()[0]) / (dLine->tail()[1]-dLine->head()[1]);
+ /*
+ if(dLine->tail()[1] == vhead)
+ isHoriz = 1;
+ else
+ {
+ isHoriz = 0;
+ slop = (dLine->tail()[0] - dLine->head()[0]) / (dLine->tail()[1]-vhead);
+ }
+ */
+ }
+ uinterc = slop * (grid_v_value - dLine->head()[1]) + dLine->head()[0];
+
+ //in case unterc is outside of the grid due to floating point
+ if(uinterc < uMin)
+ uinterc = uMin;
+ else if(uinterc > uMax)
+ uinterc = uMax;
+
+#ifdef SHORTEN_GRID_LINE
+ uintercBuf[k] = uinterc;
+#endif
+
+ tempMinU = min(tempMinU, uinterc);
+
+ assert(uinterc >= uMin && uinterc <= uMax);
+
+ if(uinterc == uMin)
+ ret_indices[k] = 0;
+ else
+ ret_indices[k] = (int)ceil((((uinterc-uMin)/(uMax - uMin)) * (n_ulines-1))) -1;
+/*
+if(ret_indices[k] >= grid->get_n_ulines())
+ {
+ printf("ERROR3\n");
+ exit(0);
+}
+if(ret_indices[k] < 0)
+ {
+ printf("ERROR4\n");
+ exit(0);
+}
+*/
+ ret_innerIndices[k] = (int)ceil ((((tempMinU-uMin)/(uMax - uMin)) * (n_ulines-1))) -1;
+
+ tempMinU = uinterc;
+ }
+#ifdef SHORTEN_GRID_LINE
+ //for each grid line, compare the left grid point with the
+ //intersection point. If the two points are too close, then
+ //we should move the grid point one grid to the right
+ //and accordingly we should update the inner index.
+ for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++)
+ {
+ //check gridLine i
+ //check ret_indices[k]
+ Real a = grid->get_u_value(ret_indices[k]);
+ Real b = grid->get_u_value(ret_indices[k]+1);
+ assert(uintercBuf[k] > a && uintercBuf <= b);
+ if( (uintercBuf[k]-a) <= 0.2 * (b-a)) //interc is very close to a
+ {
+ ret_indices[k]--;
+ }
+
+ //check ret_innerIndices[k]
+ if(k>0)
+ {
+ if(ret_innerIndices[k] > ret_indices[k-1])
+ ret_innerIndices[k] = ret_indices[k-1];
+ if(ret_innerIndices[k] > ret_indices[k])
+ ret_innerIndices[k] = ret_indices[k];
+ }
+ }
+ //clean up
+ free(uintercBuf);
+#endif
+}
+
+
+void sampleMonoPoly(directedLine* polygon, gridWrap* grid, Int ulinear, Int vlinear, primStream* pStream, rectBlockArray* rbArray)
+{
+/*
+{
+grid->print();
+polygon->writeAllPolygons("zloutputFile");
+exit(0);
+}
+*/
+
+if(grid->get_n_ulines() == 2 ||
+ grid->get_n_vlines() == 2)
+{
+ if(ulinear && grid->get_n_ulines() == 2)
+ {
+ monoTriangulationFun(polygon, compV2InY, pStream);
+ return;
+ }
+ else if(DBG_isConvex(polygon) && polygon->numEdges() >=4)
+ {
+ triangulateConvexPoly(polygon, ulinear, vlinear, pStream);
+ return;
+ }
+ else if(vlinear || DBG_is_U_direction(polygon))
+ {
+ Int n_cusps;//num interior cusps
+ Int n_edges = polygon->numEdges();
+ directedLine** cusps = (directedLine**) malloc(sizeof(directedLine*) * n_edges);
+ assert(cusps);
+ findInteriorCuspsX(polygon, n_cusps, cusps);
+
+ if(n_cusps == 0) //u_monotone
+ {
+
+ monoTriangulationFun(polygon, compV2InX, pStream);
+
+ free(cusps);
+ return;
+ }
+ else if(n_cusps == 1) //one interior cusp
+ {
+
+ directedLine* new_polygon = polygonConvert(cusps[0]);
+
+ directedLine* other = findDiagonal_singleCuspX( new_polygon);
+
+
+
+ //<other> should NOT be null unless there are self-intersecting
+ //trim curves. In that case, we don't want to core dump, instead,
+ //we triangulate anyway, and print out error message.
+ if(other == NULL)
+ {
+ monoTriangulationFun(polygon, compV2InX, pStream);
+ free(cusps);
+ return;
+ }
+
+ directedLine* ret_p1;
+ directedLine* ret_p2;
+
+ new_polygon->connectDiagonal_2slines(new_polygon, other,
+ &ret_p1,
+ &ret_p2,
+ new_polygon);
+
+ monoTriangulationFun(ret_p1, compV2InX, pStream);
+ monoTriangulationFun(ret_p2, compV2InX, pStream);
+
+ ret_p1->deleteSinglePolygonWithSline();
+ ret_p2->deleteSinglePolygonWithSline();
+
+ free(cusps);
+ return;
+ }
+ free(cusps);
+ }
+}
+
+ /*find the top and bottom of the polygon. It is supposed to be
+ *a V-monotone polygon
+ */
+
+ directedLine* tempV;
+ directedLine* topV;
+ directedLine* botV;
+ topV = botV = polygon;
+
+ for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext())
+ {
+ if(compV2InY(topV->head(), tempV->head())<0) {
+
+ topV = tempV;
+ }
+ if(compV2InY(botV->head(), tempV->head())>0) {
+
+ botV = tempV;
+ }
+ }
+
+ /*find the first(top) and the last (bottom) grid line which intersect the
+ *this polygon
+ */
+ Int firstGridIndex; /*the index in the grid*/
+ Int lastGridIndex;
+ firstGridIndex = (Int) ((topV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1));
+ lastGridIndex = (Int) ((botV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1)) + 1;
+
+
+ /*find the interval inside the polygon for each gridline*/
+ Int *leftGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(leftGridIndices);
+ Int *rightGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(rightGridIndices);
+ Int *leftGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(leftGridInnerIndices);
+ Int *rightGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(rightGridInnerIndices);
+
+ findLeftGridIndices(topV, firstGridIndex, lastGridIndex, grid, leftGridIndices, leftGridInnerIndices);
+
+ findRightGridIndices(topV, firstGridIndex, lastGridIndex, grid, rightGridIndices, rightGridInnerIndices);
+
+ gridBoundaryChain leftGridChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, leftGridIndices, leftGridInnerIndices);
+
+ gridBoundaryChain rightGridChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, rightGridIndices, rightGridInnerIndices);
+
+
+
+// leftGridChain.draw();
+// leftGridChain.drawInner();
+// rightGridChain.draw();
+// rightGridChain.drawInner();
+ /*(1) determine the grid boundaries (left and right).
+ *(2) process polygon into two monotone chaines: use vertexArray
+ *(3) call sampleMonoPolyRec
+ */
+
+ /*copy the two chains into vertexArray datastructure*/
+ Int i;
+ vertexArray leftChain(20); /*this is a dynamic array*/
+ for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
+ leftChain.appendVertex(topV->getVertex(i));
+ }
+ for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext())
+ {
+ for(i=0; i<=tempV->get_npoints()-2; i++){
+ leftChain.appendVertex(tempV->getVertex(i));
+ }
+ }
+
+ vertexArray rightChain(20);
+ for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
+ {
+ for(i=tempV->get_npoints()-2; i>=0; i--){
+ rightChain.appendVertex(tempV->getVertex(i));
+ }
+ }
+ for(i=botV->get_npoints()-2; i>=1; i--){
+ rightChain.appendVertex(tempV->getVertex(i));
+ }
+
+ sampleMonoPolyRec(topV->head(),
+ botV->head(),
+ &leftChain,
+ 0,
+ &rightChain,
+ 0,
+ &leftGridChain,
+ &rightGridChain,
+ 0,
+ pStream,
+ rbArray);
+
+
+ /*cleanup space*/
+ free(leftGridIndices);
+ free(rightGridIndices);
+ free(leftGridInnerIndices);
+ free(rightGridInnerIndices);
+}
+
+void sampleMonoPolyRec(
+ Real* topVertex,
+ Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridStartIndex,
+ primStream* pStream,
+ rectBlockArray* rbArray)
+{
+
+ /*find the first connected component, and the four corners.
+ */
+ Int index1, index2; /*the first and last grid line of the first connected component*/
+
+ if(topVertex[1] <= botVertex[1])
+ return;
+
+ /*find i so that the grid line is below the top vertex*/
+ Int i=gridStartIndex;
+ while (i < leftGridChain->get_nVlines())
+ {
+ if(leftGridChain->get_v_value(i) < topVertex[1])
+ break;
+ i++;
+ }
+
+ /*find the first connected component starting with i*/
+ /*find index1 so that left_uline_index <= right_uline_index, that is, this
+ *grid line contains at least one inner grid point
+ */
+ index1=i;
+ int num_skipped_grid_lines=0;
+ while(index1 < leftGridChain->get_nVlines())
+ {
+ if(leftGridChain->getUlineIndex(index1) <= rightGridChain->getUlineIndex(index1))
+ break;
+ num_skipped_grid_lines++;
+ index1++;
+ }
+
+
+
+ if(index1 >= leftGridChain->get_nVlines()) /*no grid line exists which has inner point*/
+ {
+ /*stop recursion, ...*/
+ /*monotone triangulate it...*/
+// printf("no grid line exists\n");
+/*
+ monoTriangulationRecOpt(topVertex, botVertex, leftChain, leftStartIndex,
+ rightChain, rightStartIndex, pStream);
+*/
+
+if(num_skipped_grid_lines <2)
+ {
+ monoTriangulationRecGenOpt(topVertex, botVertex, leftChain, leftStartIndex,
+ leftChain->getNumElements()-1,
+ rightChain, rightStartIndex,
+ rightChain->getNumElements()-1,
+ pStream);
+ }
+else
+ {
+ //the optimum way to triangulate is top-down since this polygon
+ //is narrow-long.
+ monoTriangulationRec(topVertex, botVertex, leftChain, leftStartIndex,
+ rightChain, rightStartIndex, pStream);
+ }
+
+/*
+ monoTriangulationRec(topVertex, botVertex, leftChain, leftStartIndex,
+ rightChain, rightStartIndex, pStream);
+*/
+
+/* monoTriangulationRecGenTBOpt(topVertex, botVertex,
+ leftChain, leftStartIndex, leftChain->getNumElements()-1,
+ rightChain, rightStartIndex, rightChain->getNumElements()-1,
+ pStream);*/
+
+
+
+ }
+ else
+ {
+
+ /*find index2 so that left_inner_index <= right_inner_index holds until index2*/
+ index2=index1+1;
+ if(index2 < leftGridChain->get_nVlines())
+ while(leftGridChain->getInnerIndex(index2) <= rightGridChain->getInnerIndex(index2))
+ {
+ index2++;
+ if(index2 >= leftGridChain->get_nVlines())
+ break;
+ }
+
+ index2--;
+
+
+
+ /*the neck*/
+ Int neckLeftIndex;
+ Int neckRightIndex;
+
+ /*the four corners*/
+ Int up_leftCornerWhere;
+ Int up_leftCornerIndex;
+ Int up_rightCornerWhere;
+ Int up_rightCornerIndex;
+ Int down_leftCornerWhere;
+ Int down_leftCornerIndex;
+ Int down_rightCornerWhere;
+ Int down_rightCornerIndex;
+
+ Real* tempBotVertex; /*the bottom vertex for this component*/
+ Real* nextTopVertex=NULL; /*for the recursion*/
+ Int nextLeftStartIndex=0;
+ Int nextRightStartIndex=0;
+
+ /*find the points below the grid line index2 on both chains*/
+ Int botLeftIndex = leftChain->findIndexStrictBelowGen(
+ leftGridChain->get_v_value(index2),
+ leftStartIndex,
+ leftChain->getNumElements()-1);
+ Int botRightIndex = rightChain->findIndexStrictBelowGen(
+ rightGridChain->get_v_value(index2),
+ rightStartIndex,
+ rightChain->getNumElements()-1);
+ /*if either botLeftIndex>= numelements,
+ * or botRightIndex >= numelemnet,
+ *then there is no neck exists. the bottom vertex is botVertex,
+ */
+ if(! findNeckF(leftChain, botLeftIndex, rightChain, botRightIndex,
+ leftGridChain, rightGridChain, index2, neckLeftIndex, neckRightIndex))
+ /*
+ if(botLeftIndex == leftChain->getNumElements() ||
+ botRightIndex == rightChain->getNumElements())
+ */
+ {
+#ifdef MYDEBUG
+ printf("neck NOT exists, botRightIndex=%i\n", botRightIndex);
+#endif
+
+ tempBotVertex = botVertex;
+ nextTopVertex = botVertex;
+ botLeftIndex = leftChain->getNumElements()-1;
+ botRightIndex = rightChain->getNumElements()-1;
+ }
+ else /*neck exists*/
+ {
+#ifdef MYDEBUG
+ printf("neck exists\n");
+#endif
+
+ /*
+ findNeck(leftChain, botLeftIndex,
+ rightChain, botRightIndex,
+ neckLeftIndex,
+ neckRightIndex);
+ */
+#ifdef MYDEBUG
+printf("neck is found, neckLeftIndex=%i, neckRightIndex=%i\n", neckLeftIndex, neckRightIndex);
+glBegin(GL_LINES);
+glVertex2fv(leftChain->getVertex(neckLeftIndex));
+glVertex2fv(rightChain->getVertex(neckRightIndex));
+glEnd();
+#endif
+
+ if(leftChain->getVertex(neckLeftIndex)[1] <= rightChain->getVertex(neckRightIndex)[1])
+ {
+ tempBotVertex = leftChain->getVertex(neckLeftIndex);
+ botLeftIndex = neckLeftIndex-1;
+ botRightIndex = neckRightIndex;
+ nextTopVertex = rightChain->getVertex(neckRightIndex);
+ nextLeftStartIndex = neckLeftIndex;
+ nextRightStartIndex = neckRightIndex+1;
+ }
+ else
+ {
+ tempBotVertex = rightChain->getVertex(neckRightIndex);
+ botLeftIndex = neckLeftIndex;
+ botRightIndex = neckRightIndex-1;
+ nextTopVertex = leftChain->getVertex(neckLeftIndex);
+ nextLeftStartIndex = neckLeftIndex+1;
+ nextRightStartIndex = neckRightIndex;
+ }
+ }
+
+ findUpCorners(topVertex,
+ leftChain,
+ leftStartIndex, botLeftIndex,
+ rightChain,
+ rightStartIndex, botRightIndex,
+ leftGridChain->get_v_value(index1),
+ leftGridChain->get_u_value(index1),
+ rightGridChain->get_u_value(index1),
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex);
+
+ findDownCorners(tempBotVertex,
+ leftChain,
+ leftStartIndex, botLeftIndex,
+ rightChain,
+ rightStartIndex, botRightIndex,
+ leftGridChain->get_v_value(index2),
+ leftGridChain->get_u_value(index2),
+ rightGridChain->get_u_value(index2),
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex);
+#ifdef MYDEBUG
+ printf("find corners done, down_leftwhere=%i, down_righwhere=%i,\n",down_leftCornerWhere, down_rightCornerWhere );
+ printf("find corners done, up_leftwhere=%i, up_righwhere=%i,\n",up_leftCornerWhere, up_rightCornerWhere );
+ printf("find corners done, up_leftindex=%i, up_righindex=%i,\n",up_leftCornerIndex, up_rightCornerIndex );
+ printf("find corners done, down_leftindex=%i, down_righindex=%i,\n",down_leftCornerIndex, down_rightCornerIndex );
+#endif
+
+/*
+ drawCorners(topVertex,
+ tempBotVertex,
+ leftChain,
+ rightChain,
+ leftGridChain,
+ rightGridChain,
+ index1,
+ index2,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex);
+*/
+
+
+ sampleConnectedComp(topVertex, tempBotVertex,
+ leftChain,
+ leftStartIndex, botLeftIndex,
+ rightChain,
+ rightStartIndex, botRightIndex,
+ leftGridChain,
+ rightGridChain,
+ index1, index2,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex,
+ pStream,
+ rbArray
+ );
+
+ /*recursion*/
+
+ sampleMonoPolyRec(
+ nextTopVertex,
+ botVertex,
+ leftChain,
+ nextLeftStartIndex,
+ rightChain,
+ nextRightStartIndex,
+ leftGridChain,
+ rightGridChain,
+ index2+1,
+ pStream, rbArray);
+
+
+ }
+
+}
+
+void sampleLeftStrip(vertexArray* leftChain,
+ Int topLeftIndex,
+ Int botLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ Int leftGridChainEndIndex,
+ primStream* pStream
+ )
+{
+ assert(leftChain->getVertex(topLeftIndex)[1] > leftGridChain->get_v_value(leftGridChainStartIndex));
+ assert(leftChain->getVertex(topLeftIndex+1)[1] <= leftGridChain->get_v_value(leftGridChainStartIndex));
+ assert(leftChain->getVertex(botLeftIndex)[1] <= leftGridChain->get_v_value(leftGridChainEndIndex));
+ assert(leftChain->getVertex(botLeftIndex-1)[1] > leftGridChain->get_v_value(leftGridChainEndIndex));
+
+ /*
+ *(1)find the last grid line which doesn'; pass below
+ * this first edge, sample this region: one trim edge and
+ * possily multiple grid lines.
+ */
+ Real *upperVert, *lowerVert; /*the end points of the first trim edge*/
+ upperVert = leftChain->getVertex(topLeftIndex);
+ lowerVert = leftChain->getVertex(topLeftIndex+1);
+
+ Int index = leftGridChainStartIndex;
+ while(leftGridChain->get_v_value(index) >= lowerVert[1]){
+ index++;
+ if(index > leftGridChainEndIndex)
+ break;
+ }
+ index--;
+
+ sampleLeftSingleTrimEdgeRegion(upperVert, lowerVert,
+ leftGridChain,
+ leftGridChainStartIndex,
+ index,
+ pStream);
+ sampleLeftStripRec(leftChain, topLeftIndex+1, botLeftIndex,
+ leftGridChain, index, leftGridChainEndIndex,
+ pStream);
+
+}
+
+void sampleLeftStripRec(vertexArray* leftChain,
+ Int topLeftIndex,
+ Int botLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ Int leftGridChainEndIndex,
+ primStream* pStream
+ )
+{
+ /*now top left trim vertex is below the top grid line.
+ */
+ /*stop condition: if topLeftIndex >= botLeftIndex, then stop.
+ */
+ if(topLeftIndex >= botLeftIndex)
+ return;
+
+ /*find the last trim vertex which is above the second top grid line:
+ * index1.
+ *and sampleLeftOneGridStep(leftchain, topLeftIndex, index1, leftGridChain,
+ * leftGridChainStartIndex).
+ * index1 could be equal to topLeftIndex.
+ */
+ Real secondGridChainV = leftGridChain->get_v_value(leftGridChainStartIndex+1);
+ assert(leftGridChainStartIndex < leftGridChainEndIndex);
+ Int index1 = topLeftIndex;
+ while(leftChain->getVertex(index1)[1] > secondGridChainV)
+ index1++;
+ index1--;
+
+ sampleLeftOneGridStep(leftChain, topLeftIndex, index1, leftGridChain, leftGridChainStartIndex, pStream);
+
+
+ /*
+ * Let the next trim vertex be nextTrimVertIndex (which should be
+ * below the second grid line).
+ * Find the last grid line index2 which is above nextTrimVert.
+ * sampleLeftSingleTrimEdgeRegion(uppervert[2], lowervert[2],
+ * leftGridChain, leftGridChainStartIndex+1, index2).
+ */
+ Real *uppervert, *lowervert;
+ uppervert = leftChain->getVertex(index1);
+ lowervert = leftChain->getVertex(index1+1);
+ Int index2 = leftGridChainStartIndex+1;
+
+ while(leftGridChain->get_v_value(index2) >= lowervert[1])
+ {
+ index2++;
+ if(index2 > leftGridChainEndIndex)
+ break;
+ }
+ index2--;
+ sampleLeftSingleTrimEdgeRegion(uppervert, lowervert, leftGridChain, leftGridChainStartIndex+1, index2, pStream);
+
+ /* sampleLeftStripRec(leftChain,
+ nextTrimVertIndex,
+ botLeftIndex,
+ leftGridChain,
+ index2,
+ leftGridChainEndIndex
+ )
+ *
+ */
+ sampleLeftStripRec(leftChain, index1+1, botLeftIndex, leftGridChain, index2, leftGridChainEndIndex, pStream);
+
+}
+
+
+/***************begin RecF***********************/
+/* the gridlines from leftGridChainStartIndex to
+ * leftGridChainEndIndex are assumed to form a
+ * connected component.
+ * the trim vertex of topLeftIndex is assumed to
+ * be below the first gridline, and the tim vertex
+ * of botLeftIndex is assumed to be above the last
+ * grid line.
+ * If botLeftIndex < topLeftIndex, then no connected componeent exists, and this funcion returns without
+ * outputing any triangles.
+ * Otherwise botLeftIndex >= topLeftIndex, there is at least one triangle to output.
+ */
+void sampleLeftStripRecF(vertexArray* leftChain,
+ Int topLeftIndex,
+ Int botLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ Int leftGridChainEndIndex,
+ primStream* pStream
+ )
+{
+ /*now top left trim vertex is below the top grid line.
+ */
+ /*stop condition: if topLeftIndex > botLeftIndex, then stop.
+ */
+ if(topLeftIndex > botLeftIndex)
+ return;
+
+ /*if there is only one grid Line, return.*/
+
+ if(leftGridChainStartIndex>=leftGridChainEndIndex)
+ return;
+
+
+ assert(leftChain->getVertex(topLeftIndex)[1] <= leftGridChain->get_v_value(leftGridChainStartIndex) &&
+ leftChain->getVertex(botLeftIndex)[1] >= leftGridChain->get_v_value(leftGridChainEndIndex));
+
+ /*firs find the first trim vertex which is below or equal to the second top grid line:
+ * index1.
+ */
+ Real secondGridChainV = leftGridChain->get_v_value(leftGridChainStartIndex+1);
+
+
+ Int index1 = topLeftIndex;
+
+ while(leftChain->getVertex(index1)[1] > secondGridChainV){
+ index1++;
+ if(index1>botLeftIndex)
+ break;
+ }
+
+ /*now leftChain->getVertex(index-1)[1] > secondGridChainV and
+ * leftChain->getVertex(index)[1] <= secondGridChainV
+ *If equality holds, then we should include the vertex index1, otherwise we include only index1-1, to
+ *perform sampleOneGridStep.
+ */
+ if(index1>botLeftIndex)
+ index1--;
+ else if(leftChain->getVertex(index1)[1] < secondGridChainV)
+ index1--;
+
+ /*now we have leftChain->getVertex(index1)[1] >= secondGridChainV, and
+ * leftChain->getVertex(index1+1)[1] <= secondGridChainV
+ */
+
+
+ sampleLeftOneGridStep(leftChain, topLeftIndex, index1, leftGridChain, leftGridChainStartIndex, pStream);
+
+
+ /*if leftChain->getVertex(index1)[1] == secondGridChainV, then we can recursively do the rest.
+ */
+ if(leftChain->getVertex(index1)[1] == secondGridChainV)
+ {
+
+ sampleLeftStripRecF(leftChain, index1, botLeftIndex,leftGridChain, leftGridChainStartIndex+1, leftGridChainEndIndex, pStream);
+ }
+ else if(index1 < botLeftIndex)
+ {
+
+ /* Otherwise, we have leftChain->getVertex(index1)[1] > secondGridChainV,
+ * let the next trim vertex be nextTrimVertIndex (which should be strictly
+ * below the second grid line).
+ * Find the last grid line index2 which is above nextTrimVert.
+ * sampleLeftSingleTrimEdgeRegion(uppervert[2], lowervert[2],
+ * leftGridChain, leftGridChainStartIndex+1, index2).
+ */
+ Real *uppervert, *lowervert;
+ uppervert = leftChain->getVertex(index1);
+ lowervert = leftChain->getVertex(index1+1); //okay since index1<botLeftIndex
+ Int index2 = leftGridChainStartIndex+1;
+
+
+ while(leftGridChain->get_v_value(index2) >= lowervert[1])
+ {
+ index2++;
+ if(index2 > leftGridChainEndIndex)
+ break;
+ }
+ index2--;
+
+
+ sampleLeftSingleTrimEdgeRegion(uppervert, lowervert, leftGridChain, leftGridChainStartIndex+1, index2, pStream);
+
+ /*recursion*/
+
+ sampleLeftStripRecF(leftChain, index1+1, botLeftIndex, leftGridChain, index2, leftGridChainEndIndex, pStream);
+ }
+
+}
+
+/***************End RecF***********************/
+
+/*sample the left area in between one trim edge and multiple grid lines.
+ * all the grid lines should be in between the two end poins of the
+ *trim edge.
+ */
+void sampleLeftSingleTrimEdgeRegion(Real upperVert[2], Real lowerVert[2],
+ gridBoundaryChain* gridChain,
+ Int beginIndex,
+ Int endIndex,
+ primStream* pStream)
+{
+ Int i,j,k;
+
+ vertexArray vArray(endIndex-beginIndex+1);
+ vArray.appendVertex(gridChain->get_vertex(beginIndex));
+
+ for(k=1, i=beginIndex+1; i<=endIndex; i++, k++)
+ {
+ vArray.appendVertex(gridChain->get_vertex(i));
+
+ /*output the fan of the grid points of the (i)th and (i-1)th grid line.
+ */
+ if(gridChain->getUlineIndex(i) < gridChain->getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(gridChain->get_vertex(i-1));
+ for(j=gridChain->getUlineIndex(i); j<= gridChain->getUlineIndex(i-1); j++)
+ pStream->insert(gridChain->getGrid()->get_u_value(j), gridChain->get_v_value(i));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ else if(gridChain->getUlineIndex(i) > gridChain->getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(gridChain->get_vertex(i));
+ for(j=gridChain->getUlineIndex(i); j>= gridChain->getUlineIndex(i-1); j--)
+ pStream->insert(gridChain->getGrid()->get_u_value(j), gridChain->get_v_value(i-1));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ /*otherwisem, the two are equal, so there is no fan to outout*/
+ }
+
+ monoTriangulation2(upperVert, lowerVert, &vArray, 0, endIndex-beginIndex,
+ 0, /*decreasing chain*/
+ pStream);
+}
+
+/*return i, such that from begin to i-1 the chain is strictly u-monotone.
+ */
+Int findIncreaseChainFromBegin(vertexArray* chain, Int begin ,Int end)
+{
+ Int i=begin;
+ Real prevU = chain->getVertex(i)[0];
+ Real thisU;
+ for(i=begin+1; i<=end; i++){
+ thisU = chain->getVertex(i)[0];
+
+ if(prevU < thisU){
+ prevU = thisU;
+ }
+ else
+ break;
+ }
+ return i;
+}
+
+/*check whether there is a vertex whose v value is strictly
+ *inbetween vup vbelow
+ *if no middle exists return -1, else return the idnex.
+ */
+Int checkMiddle(vertexArray* chain, Int begin, Int end,
+ Real vup, Real vbelow)
+{
+ Int i;
+ for(i=begin; i<=end; i++)
+ {
+ if(chain->getVertex(i)[1] < vup && chain->getVertex(i)[1]>vbelow)
+ return i;
+ }
+ return -1;
+}
+
+/*the degenerat case of sampleLeftOneGridStep*/
+void sampleLeftOneGridStepNoMiddle(vertexArray* leftChain,
+ Int beginLeftIndex,
+ Int endLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ primStream* pStream)
+{
+ /*since there is no middle, there is at most one point which is on the
+ *second grid line, there could be multiple points on the first (top)
+ *grid line.
+ */
+
+ leftGridChain->leftEndFan(leftGridChainStartIndex+1, pStream);
+
+ monoTriangulation2(leftGridChain->get_vertex(leftGridChainStartIndex),
+ leftGridChain->get_vertex(leftGridChainStartIndex+1),
+ leftChain,
+ beginLeftIndex,
+ endLeftIndex,
+ 1, //is increase chain.
+ pStream);
+}
+
+
+
+/*sampling the left area in between two grid lines.
+ */
+void sampleLeftOneGridStep(vertexArray* leftChain,
+ Int beginLeftIndex,
+ Int endLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ primStream* pStream
+ )
+{
+ if(checkMiddle(leftChain, beginLeftIndex, endLeftIndex,
+ leftGridChain->get_v_value(leftGridChainStartIndex),
+ leftGridChain->get_v_value(leftGridChainStartIndex+1))<0)
+
+ {
+
+ sampleLeftOneGridStepNoMiddle(leftChain, beginLeftIndex, endLeftIndex, leftGridChain, leftGridChainStartIndex, pStream);
+ return;
+ }
+
+ //copy into a polygon
+ {
+ directedLine* poly = NULL;
+ sampledLine* sline;
+ directedLine* dline;
+ gridWrap* grid = leftGridChain->getGrid();
+ Real vert1[2];
+ Real vert2[2];
+ Int i;
+
+ Int innerInd = leftGridChain->getInnerIndex(leftGridChainStartIndex+1);
+ Int upperInd = leftGridChain->getUlineIndex(leftGridChainStartIndex);
+ Int lowerInd = leftGridChain->getUlineIndex(leftGridChainStartIndex+1);
+ Real upperV = leftGridChain->get_v_value(leftGridChainStartIndex);
+ Real lowerV = leftGridChain->get_v_value(leftGridChainStartIndex+1);
+
+ //the upper gridline
+ vert1[1] = vert2[1] = upperV;
+ for(i=innerInd; i>upperInd; i--)
+ {
+ vert1[0]=grid->get_u_value(i);
+ vert2[0]=grid->get_u_value(i-1);
+ sline = new sampledLine(vert1, vert2);
+ dline = new directedLine(INCREASING, sline);
+ if(poly == NULL)
+ poly = dline;
+ else
+ poly->insert(dline);
+ }
+
+ //the edge connecting upper grid with left chain
+ vert1[0] = grid->get_u_value(upperInd);
+ vert1[1] = upperV;
+ sline = new sampledLine(vert1, leftChain->getVertex(beginLeftIndex));
+ dline = new directedLine(INCREASING, sline);
+ if(poly == NULL)
+ poly = dline;
+ else
+ poly->insert(dline);
+
+ //the left chain
+ for(i=beginLeftIndex; i<endLeftIndex; i++)
+ {
+ sline = new sampledLine(leftChain->getVertex(i), leftChain->getVertex(i+1));
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+
+ //the edge connecting left chain with lower gridline
+ vert2[0] = grid->get_u_value(lowerInd);
+ vert2[1] = lowerV;
+ sline = new sampledLine(leftChain->getVertex(endLeftIndex), vert2);
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+
+ //the lower grid line
+ vert1[1] = vert2[1] = lowerV;
+ for(i=lowerInd; i<innerInd; i++)
+ {
+ vert1[0] = grid->get_u_value(i);
+ vert2[0] = grid->get_u_value(i+1);
+ sline = new sampledLine(vert1, vert2);
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+
+ //the vertical grid line segement
+ vert1[0]=vert2[0] = grid->get_u_value(innerInd);
+ vert2[1]=upperV;
+ vert1[1]=lowerV;
+ sline=new sampledLine(vert1, vert2);
+ dline=new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ monoTriangulationOpt(poly, pStream);
+ //cleanup
+ poly->deleteSinglePolygonWithSline();
+ return;
+ }
+
+
+
+
+
+ Int i;
+ if(1/*leftGridChain->getUlineIndex(leftGridChainStartIndex) >=
+ leftGridChain->getUlineIndex(leftGridChainStartIndex+1)*/
+ ) /*the second grid line is beyond the first one to the left*/
+ {
+ /*find the maximal U-monotone chain
+ * of endLeftIndex, endLeftIndex-1, ...,
+ */
+ i=endLeftIndex;
+ Real prevU = leftChain->getVertex(i)[0];
+ for(i=endLeftIndex-1; i>=beginLeftIndex; i--){
+ Real thisU = leftChain->getVertex(i)[0];
+ if( prevU < thisU){
+ prevU = thisU;
+ }
+ else
+ break;
+ }
+ /*from endLeftIndex to i+1 is strictly U- monotone */
+ /*if i+1==endLeftIndex and the vertex and leftchain is on the second gridline, then
+ *we should use 2 vertices on the leftchain. If we only use one (endLeftIndex), then we
+ *we would output degenerate triangles
+ */
+ if(i+1 == endLeftIndex && leftChain->getVertex(endLeftIndex)[1] == leftGridChain->get_v_value(1+leftGridChainStartIndex))
+ i--;
+
+ Int j = beginLeftIndex/*endLeftIndex*/+1;
+
+
+ if(leftGridChain->getInnerIndex(leftGridChainStartIndex+1) > leftGridChain->getUlineIndex(leftGridChainStartIndex))
+ {
+ j = findIncreaseChainFromBegin(leftChain, beginLeftIndex, i+1/*endLeftIndex*/);
+
+ Int temp = beginLeftIndex;
+ /*now from begin to j-1 is strictly u-monotone*/
+ /*if j-1 is on the first grid line, then we want to skip to the vertex which is strictly
+ *below the grid line. This vertexmust exist since there is a 'corner turn' inbetween the two grid lines
+ */
+ if(j-1 == beginLeftIndex)
+ {
+ while(leftChain->getVertex(j-1)[1] == leftGridChain->get_v_value(leftGridChainStartIndex))
+ j++;
+
+ Real vert[2];
+ vert[0] = leftGridChain->get_u_value(leftGridChainStartIndex);
+ vert[1] = leftGridChain->get_v_value(leftGridChainStartIndex);
+
+ monoTriangulation2(
+ vert/*leftChain->getVertex(beginLeftIndex)*/,
+ leftChain->getVertex(j-1),
+ leftChain,
+ beginLeftIndex,
+ j-2,
+ 1,
+ pStream //increase chain
+ );
+
+ temp = j-1;
+ }
+
+ stripOfFanLeft(leftChain, j-1, temp/*beginLeftIndex*/, leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(leftGridChainStartIndex),
+ leftGridChain->getUlineIndex(leftGridChainStartIndex),
+ leftGridChain->getInnerIndex(leftGridChainStartIndex+1),
+ pStream,
+ 1 /*the grid line is above the trim line*/
+ );
+ }
+
+ stripOfFanLeft(leftChain, endLeftIndex, i+1, leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(leftGridChainStartIndex+1),
+ leftGridChain->getUlineIndex(leftGridChainStartIndex+1),
+ leftGridChain->getInnerIndex(leftGridChainStartIndex+1),
+ pStream,
+ 0 /*the grid line is below the trim lines*/
+ );
+
+ /*monotone triangulate the remaining left chain togther with the
+ *two vertices on the two grid v-lines.
+ */
+ Real vert[2][2];
+ vert[0][0]=vert[1][0] = leftGridChain->getInner_u_value(leftGridChainStartIndex+1);
+ vert[0][1] = leftGridChain->get_v_value(leftGridChainStartIndex);
+ vert[1][1] = leftGridChain->get_v_value(leftGridChainStartIndex+1);
+
+// vertexArray right(vert, 2);
+
+ monoTriangulation2(
+ &vert[0][0], /*top vertex */
+ &vert[1][0], /*bottom vertex*/
+ leftChain,
+ /*beginLeftIndex*/j-1,
+ i+1,
+ 1, /*an increasing chain*/
+ pStream);
+ }
+ else /*the second one is shorter than the first one to the left*/
+ {
+ /*find the maximal U-monotone chain of beginLeftIndex, beginLeftIndex+1,...,
+ */
+ i=beginLeftIndex;
+ Real prevU = leftChain->getVertex(i)[0];
+ for(i=beginLeftIndex+1; i<=endLeftIndex; i++){
+ Real thisU = leftChain->getVertex(i)[0];
+
+ if(prevU < thisU){
+ prevU = thisU;
+ }
+ else
+ break;
+ }
+ /*from beginLeftIndex to i-1 is strictly U-monotone*/
+
+
+ stripOfFanLeft(leftChain, i-1, beginLeftIndex, leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(leftGridChainStartIndex),
+ leftGridChain->getUlineIndex(leftGridChainStartIndex),
+ leftGridChain->getUlineIndex(leftGridChainStartIndex+1),
+ pStream,
+ 1 /*the grid line is above the trim lines*/
+ );
+ /*monotone triangulate the remaining left chain together with the
+ *two vertices on the two grid v-lines.
+ */
+ Real vert[2][2];
+ vert[0][0]=vert[1][0] = leftGridChain->get_u_value(leftGridChainStartIndex+1);
+ vert[0][1] = leftGridChain->get_v_value(leftGridChainStartIndex);
+ vert[1][1] = leftGridChain->get_v_value(leftGridChainStartIndex+1);
+
+ vertexArray right(vert, 2);
+
+ monoTriangulation2(
+ &vert[0][0], //top vertex
+ &vert[1][0], //bottom vertex
+ leftChain,
+ i-1,
+ endLeftIndex,
+ 1, /*an increase chain*/
+ pStream);
+
+ }
+}
+
+/*n_upper>=1
+ *n_lower>=1
+ */
+void triangulateXYMono(Int n_upper, Real upperVerts[][2],
+ Int n_lower, Real lowerVerts[][2],
+ primStream* pStream)
+{
+ Int i,j,k,l;
+ Real* leftMostV;
+
+ assert(n_upper>=1 && n_lower>=1);
+ if(upperVerts[0][0] <= lowerVerts[0][0])
+ {
+ i=1;
+ j=0;
+ leftMostV = upperVerts[0];
+ }
+ else
+ {
+ i=0;
+ j=1;
+ leftMostV = lowerVerts[0];
+ }
+
+ while(1)
+ {
+ if(i >= n_upper) /*case1: no more in upper*/
+ {
+
+ if(j<n_lower-1) /*at least two vertices in lower*/
+ {
+ pStream->begin();
+ pStream->insert(leftMostV);
+ while(j<n_lower){
+ pStream->insert(lowerVerts[j]);
+ j++;
+ }
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+
+ break;
+ }
+ else if(j>= n_lower) /*case2: no more in lower*/
+ {
+
+ if(i<n_upper-1) /*at least two vertices in upper*/
+ {
+ pStream->begin();
+ pStream->insert(leftMostV);
+
+ for(k=n_upper-1; k>=i; k--)
+ pStream->insert(upperVerts[k]);
+
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+
+ break;
+ }
+ else /* case3: neither is empty, plus the leftMostV, there is at least one triangle to output*/
+ {
+
+ if(upperVerts[i][0] <= lowerVerts[j][0])
+ {
+ pStream->begin();
+ pStream->insert(lowerVerts[j]); /*the origin of this fan*/
+
+ /*find the last k>=i such that
+ *upperverts[k][0] <= lowerverts[j][0]
+ */
+ k=i;
+ while(k<n_upper)
+ {
+ if(upperVerts[k][0] > lowerVerts[j][0])
+ break;
+ k++;
+ }
+ k--;
+ for(l=k; l>=i; l--)/*the reverse is for two-face lighting*/
+ {
+ pStream->insert(upperVerts[l]);
+ }
+ pStream->insert(leftMostV);
+
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ //update i for next loop
+ i = k+1;
+ leftMostV = upperVerts[k];
+
+ }
+ else /*upperVerts[i][0] > lowerVerts[j][0]*/
+ {
+ pStream->begin();
+ pStream->insert(upperVerts[i]);/*the origion of this fan*/
+ pStream->insert(leftMostV);
+ /*find the last k>=j such that
+ *lowerverts[k][0] < upperverts[i][0]*/
+ k=j;
+ while(k< n_lower)
+ {
+ if(lowerVerts[k][0] >= upperVerts[i][0])
+ break;
+ pStream->insert(lowerVerts[k]);
+ k++;
+ }
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ j=k;
+ leftMostV = lowerVerts[j-1];
+ }
+ }
+ }
+}
+
+
+void stripOfFanLeft(vertexArray* leftChain,
+ Int largeIndex,
+ Int smallIndex,
+ gridWrap* grid,
+ Int vlineIndex,
+ Int ulineSmallIndex,
+ Int ulineLargeIndex,
+ primStream* pStream,
+ Int gridLineUp /*1 if the grid line is above the trim lines*/
+ )
+{
+ assert(largeIndex >= smallIndex);
+
+ Real grid_v_value;
+ grid_v_value = grid->get_v_value(vlineIndex);
+
+ Real2* trimVerts=(Real2*) malloc(sizeof(Real2)* (largeIndex-smallIndex+1));
+ assert(trimVerts);
+
+
+ Real2* gridVerts=(Real2*) malloc(sizeof(Real2)* (ulineLargeIndex-ulineSmallIndex+1));
+ assert(gridVerts);
+
+ Int k,i;
+ if(gridLineUp) /*trim line is below grid line, so trim vertices are going right when index increases*/
+ for(k=0, i=smallIndex; i<=largeIndex; i++, k++)
+ {
+ trimVerts[k][0] = leftChain->getVertex(i)[0];
+ trimVerts[k][1] = leftChain->getVertex(i)[1];
+ }
+ else
+ for(k=0, i=largeIndex; i>=smallIndex; i--, k++)
+ {
+ trimVerts[k][0] = leftChain->getVertex(i)[0];
+ trimVerts[k][1] = leftChain->getVertex(i)[1];
+ }
+
+ for(k=0, i=ulineSmallIndex; i<= ulineLargeIndex; i++, k++)
+ {
+ gridVerts[k][0] = grid->get_u_value(i);
+ gridVerts[k][1] = grid_v_value;
+ }
+
+ if(gridLineUp)
+ triangulateXYMono(
+ ulineLargeIndex-ulineSmallIndex+1, gridVerts,
+ largeIndex-smallIndex+1, trimVerts,
+ pStream);
+ else
+ triangulateXYMono(largeIndex-smallIndex+1, trimVerts,
+ ulineLargeIndex-ulineSmallIndex+1, gridVerts,
+ pStream);
+ free(trimVerts);
+ free(gridVerts);
+}
+
+
+
+
+
diff --git a/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.h b/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.h
new file mode 100644
index 00000000000..6f25a0311e1
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.h
@@ -0,0 +1,191 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#ifndef _SAMPLEMONOPOLY_H
+#define _SAMPLEMONOPOLY_H
+
+#include "monoTriangulation.h"
+#include "gridWrap.h"
+#include "rectBlock.h"
+
+
+void triangulateXYMono(Int n_upper, Real upperVerts[][2],
+ Int n_lower, Real lowerVerts[][2],
+ primStream* pStream);
+
+void stripOfFanLeft(vertexArray* leftChain,
+ Int largeIndex,
+ Int smallIndex,
+ gridWrap* grid,
+ Int vlineIndex,
+ Int ulineSmallIndex,
+ Int ulineLargeIndex,
+ primStream* pStream,
+ Int gridLineUp
+ );
+void sampleLeftOneGridStep(vertexArray* leftChain,
+ Int beginLeftIndex,
+ Int endLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ primStream* pStream
+ );
+
+void sampleLeftSingleTrimEdgeRegion(Real upperVert[2], Real lowerVert[2],
+ gridBoundaryChain* gridChain,
+ Int beginIndex,
+ Int endIndex,
+ primStream* pStream);
+
+void sampleLeftStripRec(vertexArray* leftChain,
+ Int topLeftIndex,
+ Int botLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ Int leftGridChainEndIndex,
+ primStream* pStream
+ );
+
+void sampleLeftStrip(vertexArray* leftChain,
+ Int topLeftIndex,
+ Int botLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ Int leftGridChainEndIndex,
+ primStream* pStream
+ );
+
+void findLeftGridIndices(directedLine* topEdge, Int firstGridIndex, Int lastGridIndex, gridWrap* grid, Int* ret_indices, Int* ret_inner);
+
+void findRightGridIndices(directedLine* topEdge, Int firstGridIndex, Int lastGridIndex, gridWrap* grid, Int* ret_indices, Int* ret_inner);
+
+void sampleMonoPoly(directedLine* polygon, gridWrap* grid, Int ulinear, Int vlinear, primStream *pStream, rectBlockArray* rbArray);
+
+void sampleMonoPolyRec(
+ Real* topVertex,
+ Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridStartIndex,
+ primStream* pStream,
+ rectBlockArray* rbArray
+ );
+
+void sampleLeftStripRecF(vertexArray* leftChain,
+ Int topLeftIndex,
+ Int botLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ Int leftGridChainEndIndex,
+ primStream* pStream
+ );
+
+void findUpCorners(Real *topVertex,
+ vertexArray *leftChain,
+ Int leftChainStartIndex, Int leftChainEndIndex,
+ vertexArray *rightChain,
+ Int rightChainStartIndex, Int rightChainEndIndex,
+ Real v,
+ Real uleft,
+ Real uright,
+ Int& ret_leftCornerWhere,
+ Int& ret_leftCornerIndex,
+ Int& ret_rightCornerWhere,
+ Int& ret_rightCornerIndex
+ );
+void findDownCorners(Real *botVertex,
+ vertexArray *leftChain, Int leftChainStartIndex, Int leftChainEndIndex,
+ vertexArray *rightChain, Int rightChainStartIndex, Int rightChainEndIndex,
+ Real v,
+ Real uleft,
+ Real uright,
+ Int& ret_leftCornerWhere,
+ Int& ret_leftCornerIndex,
+ Int& ret_rightCornerWhere,
+ Int& ret_rightCornerIndex
+ );
+void findNeck(vertexArray *leftChain, Int botLeftIndex,
+ vertexArray *rightChain, Int botRightIndex,
+ Int& leftLastIndex, /*left point of the neck*/
+ Int& rightLastIndex /*right point of the neck*/
+ );
+
+Int findNeckF(vertexArray *leftChain, Int botLeftIndex,
+ vertexArray *rightChain, Int botRightIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridStartIndex,
+ Int& neckLeft,
+ Int& neckRight);
+
+void findTopAndBot(directedLine* polygon,
+ directedLine*& topV,
+ directedLine*& botV);
+void findGridChains(directedLine* top, directedLine* bot,
+ gridWrap* grid,
+ gridBoundaryChain*& leftGridChain,
+ gridBoundaryChain*& rightGridChain);
+void toVertexArrays(directedLine* topV, directedLine* botV, vertexArray& leftChain, vertexArray& rightChain);
+
+void drawCorners(
+ Real* topV, Real* botV,
+ vertexArray* leftChain,
+ vertexArray* rightChain,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1,
+ Int gridIndex2,
+ Int leftCornerWhere,
+ Int leftCornerIndex,
+ Int rightCornerWhere,
+ Int rightCornerIndex,
+ Int bot_leftCornerWhere,
+ Int bot_leftCornerIndex,
+ Int bot_rightCornerWhere,
+ Int bot_rightCornerIndex);
+
+Int checkMiddle(vertexArray* chain, Int begin, Int end,
+ Real vup, Real vbelow);
+
+#endif
+
diff --git a/src/glu/sgi/libnurbs/nurbtess/sampledLine.cc b/src/glu/sgi/libnurbs/nurbtess/sampledLine.cc
new file mode 100644
index 00000000000..b7ca62e83e3
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/sampledLine.cc
@@ -0,0 +1,181 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/11/29 16:16:55 $ $Revision: 1.2 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/sampledLine.cc,v 1.2 2001/11/29 16:16:55 kschultz Exp $
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h> //for fabs()
+#include "glimports.h"
+#include "zlassert.h"
+#include "sampledLine.h"
+
+void sampledLine::setPoint(Int i, Real p[2])
+{
+ points[i][0]=p[0];
+ points[i][1]=p[1];
+}
+
+
+/*insert this single line in front of the oldList*/
+sampledLine* sampledLine::insert(sampledLine *oldList)
+{
+ next = oldList;
+ return this;
+}
+
+void sampledLine::deleteList()
+{
+ sampledLine *temp, *tempNext;
+ for(temp = this; temp != NULL; temp = tempNext)
+ {
+ tempNext = temp->next;
+ delete temp;
+ }
+}
+
+
+/*space of points[][2] is allocated*/
+sampledLine::sampledLine(Int n_points)
+{
+ npoints = n_points;
+ points = (Real2*) malloc(sizeof(Real2) * n_points);
+ assert(points);
+ next = NULL;
+}
+
+/*space of points[][2] is allocated and
+ *points are copied
+ */
+sampledLine::sampledLine(Int n_points, Real2 pts[])
+{
+ int i;
+ npoints = n_points;
+ points = (Real2*) malloc(sizeof(Real2) * n_points);
+ assert(points);
+ for(i=0; i<npoints; i++) {
+ points[i][0] = pts[i][0];
+ points[i][1] = pts[i][1];
+ }
+ next = NULL;
+}
+
+sampledLine::sampledLine(Real pt1[2], Real pt2[2])
+{
+ npoints = 2;
+ points = (Real2*) malloc(sizeof(Real2) * 2);
+ assert(points);
+ points[0][0] = pt1[0];
+ points[0][1] = pt1[1];
+ points[1][0] = pt2[0];
+ points[1][1] = pt2[1];
+ next = NULL;
+}
+
+//needs tp call init to setup
+sampledLine::sampledLine()
+{
+}
+
+//warning: ONLY pointer is copies!!!
+void sampledLine::init(Int n_points, Real2 *pts)
+{
+ npoints = n_points;
+ points = pts;
+}
+
+/*points[] is dealocated
+ */
+sampledLine::~sampledLine()
+{
+ free(points);
+}
+
+void sampledLine::print()
+{
+ int i;
+ printf("npoints=%i\n", npoints);
+
+ for(i=0; i<npoints; i++){
+ printf("(%f,%f)\n", points[i][0], points[i][1]);
+ }
+
+}
+
+void sampledLine::tessellate(Real u_reso, Real v_reso)
+{
+ int i;
+
+ Int nu, nv, n;
+ nu = 1+(Int) (fabs((points[npoints-1][0] - points[0][0])) * u_reso);
+ nv = 1+(Int) (fabs((points[npoints-1][1] - points[0][1])) * v_reso);
+
+ if(nu > nv) n = nu;
+ else
+ n = nv;
+ if(n<1)
+ n = 1;
+ //du dv could be negative
+ Real du = (points[npoints-1][0] - points[0][0])/n;
+ Real dv = (points[npoints-1][1] - points[0][1])/n;
+ Real2 *temp = (Real2*) malloc(sizeof(Real2) * (n+1));
+ assert(temp);
+
+ Real u,v;
+ for(i=0, u=points[0][0], v=points[0][1]; i<n; i++, u+=du, v+=dv)
+ {
+ temp[i][0] = u;
+ temp[i][1] = v;
+ }
+ temp[n][0] = points[npoints-1][0];
+ temp[n][1] = points[npoints-1][1];
+
+ free(points);
+
+ npoints = n+1;
+ points = temp;
+
+}
+
+void sampledLine::tessellateAll(Real u_reso, Real v_reso)
+{
+ sampledLine* temp;
+ for(temp = this; temp != NULL; temp = temp->next)
+ {
+ temp->tessellate(u_reso, v_reso);
+ }
+}
diff --git a/src/glu/sgi/libnurbs/nurbtess/sampledLine.h b/src/glu/sgi/libnurbs/nurbtess/sampledLine.h
new file mode 100644
index 00000000000..f9748669b8a
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/sampledLine.h
@@ -0,0 +1,78 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/sampledLine.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#ifndef _SAMPLEDLINE_H
+#define _SAMPLEDLINE_H
+
+#include "definitions.h"
+
+class sampledLine{
+ Int npoints;
+ Real2 *points;
+
+public:
+ sampledLine(Int n_points);
+ sampledLine(Int n_points, Real pts[][2]);
+ sampledLine(Real pt1[2], Real pt2[2]);
+ sampledLine(); //special, careful about memory
+ ~sampledLine();
+
+ void init(Int n_points, Real2 *pts);//special, careful about memory
+
+ void setPoint(Int i, Real p[2]) ;
+
+ sampledLine* insert(sampledLine *nline);
+ void deleteList();
+
+ Int get_npoints() {return npoints;}
+ Real2* get_points() {return points;}
+
+ //u_reso is number of segments (may not be integer) per unit u
+ void tessellate(Real u_reso, Real v_reso);//n segments
+ void tessellateAll(Real u_reso, Real v_reso);
+
+ void print();
+
+ sampledLine* next;
+};
+
+
+
+
+#endif
diff --git a/src/glu/sgi/libnurbs/nurbtess/searchTree.cc b/src/glu/sgi/libnurbs/nurbtess/searchTree.cc
new file mode 100644
index 00000000000..49133c5eabe
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/searchTree.cc
@@ -0,0 +1,284 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/searchTree.cc,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "zlassert.h"
+
+#include "searchTree.h"
+
+#define max(a,b) ((a>b)? a:b)
+
+treeNode* TreeNodeMake(void *key)
+{
+ treeNode *ret = (treeNode*) malloc(sizeof(treeNode));
+ assert(ret);
+ ret->key = key;
+ ret->parent = NULL;
+ ret->left = NULL;
+ ret->right = NULL;
+ return ret;
+}
+
+void TreeNodeDeleteSingleNode(treeNode* node)
+{
+ free(node);
+}
+
+void TreeNodeDeleteWholeTree(treeNode* node)
+{
+ if(node == NULL) return;
+ TreeNodeDeleteWholeTree(node->left);
+ TreeNodeDeleteWholeTree(node->right);
+ TreeNodeDeleteSingleNode(node);
+}
+
+void TreeNodePrint(treeNode* node,
+ void (*keyPrint) (void*))
+{
+ if(node ==NULL) return;
+ TreeNodePrint(node->left, keyPrint);
+ keyPrint(node->key);
+ TreeNodePrint(node->right, keyPrint);
+}
+
+int TreeNodeDepth(treeNode* root)
+{
+ if(root == NULL) return 0;
+ else{
+ int leftdepth = TreeNodeDepth(root->left);
+ int rightdepth = TreeNodeDepth(root->right);
+ return 1 + max(leftdepth, rightdepth);
+ }
+}
+
+/*return the node with the key.
+ *NULL is returned if not found
+ */
+treeNode* TreeNodeFind(treeNode* tree, void* key,
+ int (*compkey) (void*, void*))
+{
+ if(tree == NULL)
+ return NULL;
+ if(key == tree->key)
+ return tree;
+ else if(compkey(key, tree->key) < 0)
+ return TreeNodeFind(tree->left, key, compkey);
+ else
+ return TreeNodeFind(tree->right, key, compkey);
+}
+
+
+treeNode* TreeNodeInsert(treeNode* root, treeNode* newnode,
+ int (*compkey) (void *, void *))
+{
+ treeNode *y = NULL;
+ treeNode *x = root;
+ /*going down the tree from the root.
+ *x traces the path, y is the parent of x.
+ */
+ while (x != NULL){
+ y = x;
+ if(compkey(newnode->key,x->key) < 0) /*if newnode < x*/
+ x = x->left;
+ else
+ x = x->right;
+ }
+
+ /*now y has the property that
+ * if newnode < y, then y->left is NULL
+ * if newnode > y, then y->right is NULL.
+ *So we want to isnert newnode to be the child of y
+ */
+ newnode->parent = y;
+ if(y == NULL)
+ return newnode;
+ else if( compkey(newnode->key, y->key) <0)
+ {
+ y->left = newnode;
+ }
+ else
+ {
+ y->right = newnode;
+ }
+
+ return root;
+}
+
+treeNode* TreeNodeDeleteSingleNode(treeNode* tree, treeNode* node)
+{
+ treeNode* y;
+ treeNode* x;
+ treeNode* ret;
+ if(node==NULL) return tree;
+
+ if(node->left == NULL || node->right == NULL) {
+
+ y = node;
+ if(y->left != NULL)
+ x = y->left;
+ else
+ x = y->right;
+
+ if( x != NULL)
+ x->parent = y->parent;
+
+ if(y->parent == NULL) /*y is the root which has at most one child x*/
+ ret = x;
+ else /*y is not the root*/
+ {
+ if(y == y->parent->left)
+ y->parent->left = x;
+ else
+ y->parent->right = x;
+ ret = tree;
+ }
+ }
+ else { /*node has two children*/
+
+ y = TreeNodeSuccessor(node);
+ assert(y->left == NULL);
+
+ if(y == node->right) /*y is the right child if node*/
+ {
+ y->parent = node->parent;
+ y->left = node->left;
+ node->left->parent = y;
+
+ }
+ else /*y != node->right*/
+ {
+ x = y->right;
+ if(x!= NULL)
+ x->parent = y->parent;
+
+ assert(y->parent != NULL);
+ if(y == y->parent->left)
+ y->parent->left = x;
+ else
+ y->parent->right = x;
+ /*move y to the position of node*/
+ y->parent = node->parent;
+ y->left = node->left;
+ y->right = node->right;
+ node->left->parent = y;
+ node->right->parent = y;
+ }
+ if(node->parent != NULL) {
+ if(node->parent->left == node)
+ node->parent->left = y;
+ else
+ node->parent->right = y;
+ ret = tree; /*the root if the tree doesn't change*/
+ }
+ else /*node->parent is NULL: node is the root*/
+ ret = y;
+ }
+
+ /*finally free the node, and return the new root*/
+ TreeNodeDeleteSingleNode(node);
+ return ret;
+}
+
+
+/*the minimum node in the tree rooted by node
+ */
+treeNode* TreeNodeMinimum(treeNode* node)
+{
+ treeNode* temp = node;
+ if(temp == NULL) return NULL;
+ while(temp->left != NULL) {
+ temp = temp->left;
+ }
+ return temp;
+}
+
+/*the maximum node in the tree rooted by node
+ */
+treeNode* TreeNodeMaximum(treeNode* node)
+{
+ treeNode* temp = node;
+ if(temp == NULL) return NULL;
+ while(temp->right != NULL) {
+ temp = temp->right;
+ }
+ return temp;
+}
+
+/*return the first node (in sorted order) which is to the right of this node
+ */
+treeNode* TreeNodeSuccessor(treeNode* node)
+{
+ if(node == NULL) return NULL;
+ if(node->right != NULL)
+ return TreeNodeMinimum(node->right);
+ else{ /*node->right is NULL*/
+
+ /*find the first right-ancestor*/
+ treeNode *y = node->parent;
+ treeNode* x = node;
+ while(y != NULL && x == y->right) /*if y is a left parent of x*/
+ {
+
+ x = y;
+ y = y->parent;
+ }
+ return y;
+ }
+}
+
+/*return the first node (in sorted order) which is to the left of this node
+ */
+treeNode* TreeNodePredecessor(treeNode* node)
+{
+ if(node == NULL) return NULL;
+ if(node->left != NULL)
+ return TreeNodeMaximum(node->left);
+ else{ /*node->left is NULL*/
+ /*find the first left-ancestor*/
+ treeNode *y = node->parent;
+ treeNode *x = node;
+ while(y != NULL && x == y->left) /*if y is a right parent of x*/
+ {
+ x = y;
+ y = y->parent;
+ }
+ return y;
+ }
+}
diff --git a/src/glu/sgi/libnurbs/nurbtess/searchTree.h b/src/glu/sgi/libnurbs/nurbtess/searchTree.h
new file mode 100644
index 00000000000..7c8048296fd
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/searchTree.h
@@ -0,0 +1,68 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/searchTree.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+#ifndef _SEARCHTREE_H
+#define _SEARCHTREE_H
+
+typedef struct treeNode{
+ void *key;
+ struct treeNode* parent;
+ struct treeNode* left; /*children*/
+ struct treeNode* right;
+} treeNode;
+
+treeNode* TreeNodeMake(void *key);
+void TreeNodeDeleteSingleNode(treeNode* node);
+void TreeNodeDeleteWholeTree(treeNode* node);
+void TreeNodePrint(treeNode* node,
+ void (*keyPrint) (void*));
+int TreeNodeDepth(treeNode* root);
+treeNode* TreeNodeMinimum(treeNode* node);
+treeNode* TreeNodeMaximum(treeNode* node);
+treeNode* TreeNodePredecessor(treeNode* node);
+treeNode* TreeNodeSuccessor(treeNode* node);
+treeNode* TreeNodeFind(treeNode* tree, void* key,
+ int (*compkey) (void*, void*));
+
+treeNode* TreeNodeInsert(treeNode* root, treeNode* newnode,
+ int (*comp) (void *, void *));
+treeNode* TreeNodeDeleteSingleNode(treeNode* tree, treeNode* node);
+
+
+#endif
diff --git a/src/glu/sgi/libnurbs/nurbtess/zlassert.h b/src/glu/sgi/libnurbs/nurbtess/zlassert.h
new file mode 100644
index 00000000000..5af2f9b27bc
--- /dev/null
+++ b/src/glu/sgi/libnurbs/nurbtess/zlassert.h
@@ -0,0 +1,41 @@
+/*
+** 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.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+** $Date: 2001/03/17 00:25:41 $ $Revision: 1.1 $
+*/
+/*
+** $Header: /cvs/mesa/Mesa/src/glu/sgi/libnurbs/nurbtess/zlassert.h,v 1.1 2001/03/17 00:25:41 brianp Exp $
+*/
+
+/*XXXblythe this file should be deleted*/
+#include <assert.h>