summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenneth Russel <[email protected]>2004-12-20 20:04:27 +0000
committerKenneth Russel <[email protected]>2004-12-20 20:04:27 +0000
commit167641d406619ba710e2d50005b6886d2874a251 (patch)
treed080e059fa1d034f63946ae68937dd3f97f6943c
parent494740e563ead19828cc44a03230eb066bf84a02 (diff)
Initial incomplete GLU NURBS port under net.java.games.jogl.impl.nurbs
and a small README about the procedures being used during the port git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/trunk@180 232f8b59-042b-4e1e-8c03-345bb8c30851
-rwxr-xr-xsrc/net/java/games/jogl/impl/nurbs/README-PORTING.txt40
-rwxr-xr-xsrc/net/java/games/jogl/impl/nurbs/internals/Arc.java274
-rwxr-xr-xsrc/net/java/games/jogl/impl/nurbs/internals/ArcTesselator.java449
-rwxr-xr-xsrc/net/java/games/jogl/impl/nurbs/internals/Backend.java377
-rwxr-xr-xsrc/net/java/games/jogl/impl/nurbs/internals/BasicCurveEvaluator.java50
-rwxr-xr-xsrc/net/java/games/jogl/impl/nurbs/internals/BasicSurfaceEvaluator.java76
-rwxr-xr-xsrc/net/java/games/jogl/impl/nurbs/internals/BezierArc.java42
-rwxr-xr-xsrc/net/java/games/jogl/impl/nurbs/internals/Bin.java147
-rwxr-xr-xsrc/net/java/games/jogl/impl/nurbs/internals/CachingEvaluator.java56
-rwxr-xr-xsrc/net/java/games/jogl/impl/nurbs/internals/Defines.java46
-rwxr-xr-xsrc/net/java/games/jogl/impl/nurbs/internals/NurbsConsts.java117
-rwxr-xr-xsrc/net/java/games/jogl/impl/nurbs/internals/NurbsException.java30
-rwxr-xr-xsrc/net/java/games/jogl/impl/nurbs/internals/Subdivider.java1781
13 files changed, 3485 insertions, 0 deletions
diff --git a/src/net/java/games/jogl/impl/nurbs/README-PORTING.txt b/src/net/java/games/jogl/impl/nurbs/README-PORTING.txt
new file mode 100755
index 000000000..df5f41782
--- /dev/null
+++ b/src/net/java/games/jogl/impl/nurbs/README-PORTING.txt
@@ -0,0 +1,40 @@
+This is a currently incomplete port of SGI's GLU NURBS library from
+C++ to Java. There are a few reasons for doing such a port:
+
+ - The C interface is structured around function pointers. It is
+ generally difficult to bind such interfaces up to Java.
+
+ - Some people have reported crashes on certain Linux distributions
+ when trying to use any routines out of the C GLU library. To date
+ we have not been able to diagnose the root cause of these failures.
+ Porting the code involved from C++ to Java has solved these
+ problems.
+
+The port so far has been started in the internals/ directory. The C++
+sources have been gone through roughly alphabetically and
+transliterated into the appropriate files. The large Subdivider class
+was the current focus of attention at the time of this writing, and a
+closer look indicates that at least a few classes were skipped on the
+way down to some of the Subdivider's sources like intersect.cc. It may
+be a good idea to continue the port in this directory first, since it
+looks like the other directories' sources are built on top of these
+and it would be good to firm up the Java interfaces for the internals
+(and perhaps get the sources to compile) before porting lots of code
+built on top of them.
+
+A couple of notes on the translation:
+
+ - All object pool classes have been removed. The intention is to have
+ a static allocate() method on the appropriate classes which will
+ instantiate populated arrays of these types (not just arrays of
+ null references). See uses of TrimVertex.allocate().
+
+ - There are a significant number of places in the original C++ code
+ where pointer arithmetic is used. Some of these are not obvious
+ until the code has been ported and examined. Bin.java was a good
+ example of this where the algorithms needed some restructuring. At
+ the time of this writing intersect.cc was in the process of being
+ ported and it wasn't clear whether we would need to change some of
+ the APIs or add more utility routines to be able to do pointer
+ arithmetic on, for example, the TrimVertex arrays returned from the
+ allocate() routine.
diff --git a/src/net/java/games/jogl/impl/nurbs/internals/Arc.java b/src/net/java/games/jogl/impl/nurbs/internals/Arc.java
new file mode 100755
index 000000000..076c68b72
--- /dev/null
+++ b/src/net/java/games/jogl/impl/nurbs/internals/Arc.java
@@ -0,0 +1,274 @@
+/*
+** 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.
+*/
+
+/* an arc, in two list, the trim list and bin */
+public class Arc {
+ public static final int SIDE_NONE = 0;
+ public static final int SIDE_RIGHT = 1;
+ public static final int SIDE_TOP = 2;
+ public static final int SIDE_LEFT = 3;
+ public static final int SIDE_BOTTOM = 4;
+
+ public static final int bezier_tag = (1 << 13);
+ public static final int arc_tag = (1 << 3);
+ public static final int tail_tag = (1 << 6);
+ public Arc prev; /* trim list pointer */
+ public Arc next; /* trim list pointer */
+ public Arc link; /* bin pointers */
+ public BezierArc bezierArc; /* associated bezier arc */
+ public PwlArc pwlArc; /* associated pwl arc */
+ public long type; /* curve type */
+ public long nuid;
+
+ private static final float ZERO = 0.00001f;
+
+ public Arc(Arc j, PwlArc p) {
+ pwlArc = p;
+ type = j.type;
+ nuid = j.nuid;
+ }
+
+ public Arc(int arcSide, long nuid) {
+ type = 0;
+ setside(arcSide);
+ this.nuid = nuid;
+ }
+
+ public Arc append(Arc jarc) {
+ if ( jarc != null ) {
+ next = jarc.next;
+ prev = jarc;
+ next.prev = prev.next = this;
+ } else {
+ next = prev = this;
+ }
+ return this;
+ }
+
+ public boolean check() {
+ Arc jarc = this;
+ do {
+ assert( (jarc.pwlArc != null) || (jarc.bezierArc != null) );
+
+ if (jarc.prev == 0 || jarc.next == 0) {
+ System.out.println( "checkjarc:null next/prev pointer");
+ jarc.print( );
+ return false;
+ }
+
+ if (jarc.next.prev != jarc) {
+ System.out.println( "checkjarc: pointer linkage screwed up");
+ jarc.print( );
+ return false;
+ }
+
+ if( jarc.pwlArc != null ) {
+ assert( jarc.pwlArc.npts >= 1 );
+ assert( jarc.pwlArc.npts < 100000 );
+ if( jarc.prev.pwlArc != null ) {
+ if( jarc.tail()[1] != jarc.prev.rhead()[1] ) {
+ System.out.println( "checkjarc: geometric linkage screwed up 1");
+ jarc.prev.show();
+ jarc.show();
+ return false;
+ }
+ if( jarc.tail()[0] != jarc.prev.rhead()[0] ) {
+ System.out.println( "checkjarc: geometric linkage screwed up 2");
+ jarc.prev.show();
+ jarc.show();
+ return false;
+ }
+ }
+ if( jarc.next.pwlArc ) {
+ if( jarc.next.tail()[0] != jarc.rhead()[0] ) {
+ System.out.println( "checkjarc: geometric linkage screwed up 3");
+ jarc.show();
+ jarc.next.show();
+ return false;
+ }
+ if( jarc.next.tail()[1] != jarc.rhead()[1] ) {
+ System.out.println( "checkjarc: geometric linkage screwed up 4");
+ jarc.show();
+ jarc.next.show();
+ return false;
+ }
+ }
+ 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 true;
+ }
+
+ /**
+ * Checks if tail of arc and head of prev meet.
+ */
+ public boolean isDisconnected() {
+ if( pwlArc == 0 ) return 0;
+ if( prev.pwlArc == 0 ) return 0;
+
+ float[] p0 = tail();
+ float[] p1 = prev.rhead();
+
+ if( ((p0[0] - p1[0]) > ZERO) || ((p1[0] - p0[0]) > ZERO) ||
+ ((p0[1] - p1[1]) > ZERO) || ((p1[1] - p0[1]) > ZERO) ) {
+ return true;
+ } else {
+ /* average two points together */
+ p0[0] = p1[0] = (p1[0] + p0[0]) * 0.5f;
+ p0[1] = p1[1] = (p1[1] + p0[1]) * 0.5f;
+ return false;
+ }
+ }
+
+ /**
+ * Counts number of points on arc loop.
+ */
+ public int numpts( ) {
+ Arc jarc = this;
+ int npts = 0;
+ do {
+ npts += jarc.pwlArc.npts;
+ jarc = jarc.next;
+ } while( jarc != this );
+ return npts;
+ }
+
+ /**
+ * Marks each point with id of arc.
+ */
+ public void markverts( void ) {
+ Arc 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 );
+ }
+
+ /**
+ * Finds axis extrema on arc loop.
+ */
+ public void getextrema( Arc[4] ) {
+ float 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 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;
+ }
+ }
+ }
+
+ /**
+ * Prints out the vertices of all pwl arcs on a loop.
+ */
+ public void print( ) {
+ Arc jarc = this;
+
+ do {
+ jarc.show( );
+ jarc = jarc.next;
+ } while (jarc != this);
+ }
+
+ public void show( ) {
+ System.out.println( "\tPWLARC NP: " + pwlArc.npts + " FL: 1");
+ for( int i = 0; i < pwlArc.npts; i++ ) {
+ System.out.println( "\t\tVERTEX " + pwlArc.pts[i].param[0] + " " +
+ pwlArc.pts[i].param[1] );
+ }
+ }
+
+ /**
+ * Attaches a pwl arc to an arc and mark it as a border arc.
+ */
+ public void makeSide( PwlArc pwl, int arcSide ) {
+ assert( pwl != 0);
+ assert( pwlArc == 0 );
+ assert( pwl.npts > 0 );
+ assert( pwl.pts != 0);
+ pwlArc = pwl;
+ clearbezier();
+ setside( arcSide );
+ }
+
+ public boolean isTessellated() { return (pwlArc != null); }
+ public boolean isbezier() { return (type & bezier_tag) != 0; }
+ public void setbezier() { type |= bezier_tag; }
+ public void clearbezier() { type &= ~bezier_tag; }
+ public long npts() { return pwlArc.npts; }
+ public TrimVertex[] pts() { return pwlArc.pts; }
+ public float[] tail() { return pwlArc.pts[0].param; }
+ public float[] head() { return next.pwlArc.pts[0].param; }
+ public float[] rhead() { return pwlArc.pts[pwlArc.npts-1].param; }
+ public long ismarked() { return type & arc_tag; }
+ public void setmark() { type |= arc_tag; }
+ public void clearmark() { type &= (~arc_tag); }
+ public void clearside() { type &= ~(0x7 << 8); }
+ public void setside( int arcSide ) { clearside(); type |= (((long)arcSide)<<8); }
+ public int getside() { return ((type>>8) & 0x7); }
+ public int getitail() { return type & tail_tag; }
+ public void setitail() { type |= tail_tag; }
+ public void clearitail() { type &= (~tail_tag); }
+}
diff --git a/src/net/java/games/jogl/impl/nurbs/internals/ArcTesselator.java b/src/net/java/games/jogl/impl/nurbs/internals/ArcTesselator.java
new file mode 100755
index 000000000..cb77dfbd0
--- /dev/null
+++ b/src/net/java/games/jogl/impl/nurbs/internals/ArcTesselator.java
@@ -0,0 +1,449 @@
+/*
+** 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.
+*/
+
+public class ArcTessellator {
+ /**
+ * Constructs a bezier arc and attaches it to an Arc.
+ */
+ public void bezier( Arc arc, float s1, float s2, float t1, float t2 ) {
+ assert( arc != null );
+ assert( ! arc.isTessellated() );
+
+ switch( arc.getside() ) {
+ case Arc.SIDE_LEFT:
+ assert( s1 == s2 );
+ assert( t2 < t1 );
+ break;
+ case Arc.SIDE_RIGHT:
+ assert( s1 == s2 );
+ assert( t1 < t2 );
+ break;
+ case Arc.SIDE_TOP:
+ assert( t1 == t2 );
+ assert( s2 < s1 );
+ break;
+ case Arc.SIDE_BOTTOM:
+ assert( t1 == t2 );
+ assert( s1 < s2 );
+ break;
+ case Arc.SIDE_NONE:
+ throw new InternalError();
+ break;
+ }
+
+ TrimVertex[] p = TrimVertex.allocate(2);
+ arc.pwlArc = new PwlArc( 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();
+ }
+
+ /**
+ * Constructs a pwl arc and attaches it to an arc.
+ */
+ public void pwl( Arc arc, float s1, float s2, float t1, float t2, float rate ) {
+ int snsteps = 1 + (int) (Math.abs(s2 - s1) / rate );
+ int tnsteps = 1 + (int) (Math.abs(t2 - t1) / rate );
+ int nsteps = (int) Math.max(1, Math.max( snsteps, tnsteps ));
+
+ float sstepsize = (s2 - s1) / (float) nsteps;
+ float tstepsize = (t2 - t1) / (float) nsteps;
+ TrimVertex[] newvert = TrimVertex.allocate( 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.pwlArc = new PwlArc( newvert );
+
+ arc.clearbezier();
+ arc.clearside( );
+ }
+
+ /**
+ * Constructs a left boundary pwl arc and attaches it to an arc.
+ */
+ public void pwl_left( Arc arc, float s, float t1, float t2, float rate ) {
+ assert( t2 < t1 );
+
+ int nsteps = steps_function(t1, t2, rate);
+
+ float stepsize = (t1 - t2) / (float) nsteps;
+
+ TrimVertex[] newvert = TrimVertex.allocate( 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 PwlArc( newvert ), Arc.SIDE_LEFT );
+ }
+
+ /**
+ * Constructs a right boundary pwl arc and attaches it to an arc.
+ */
+ public void pwl_right( Arc arc, float s, float t1, float t2, float rate ) {
+ assert( t1 < t2 );
+
+ int nsteps = steps_function(t2,t1,rate);
+ float stepsize = (t2 - t1) / (float) nsteps;
+
+ TrimVertex[] newvert = TrimVertex.allocate( 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 PwlArc( newvert ), Arc.SIDE_RIGHT );
+ }
+
+ /**
+ * Constructs a top boundary pwl arc and attaches it to an arc.
+ */
+ public void pwl_top( Arc arc, float t, float s1, float s2, float rate ) {
+ assert( s2 < s1 );
+
+ int nsteps = steps_function(s1,s2,rate);
+ float stepsize = (s1 - s2) / (float) nsteps;
+
+ TrimVertex[] newvert = TrimVertex.allocate( 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 PwlArc( newvert ), Arc.SIDE_TOP );
+ }
+
+ /**
+ * Constructs a bottom boundary pwl arc and attaches it to an arc.
+ */
+ public void pwl_bottom( Arc arc, float t, float s1, float s2, float rate ) {
+ assert( s1 < s2 );
+
+ int nsteps = steps_function(s2,s1,rate);
+ float stepsize = (s2 - s1) / (float) nsteps;
+
+ TrimVertex[] newvert = TrimVertex.allocate( 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 PwlArc( newvert ), Arc.SIDE_BOTTOM );
+ }
+
+ /**
+ * Constucts a linear pwl arc and attaches it to an Arc.
+ */
+ public void tessellateLinear( Arc arc, float geo_stepsize, float arc_stepsize, boolean isrational ) {
+ assert( arc.pwlArc == null );
+ float 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
+ float 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 );
+ }
+
+ /**
+ * Constucts a nonlinear pwl arc and attaches it to an Arc.
+ */
+ public void tessellateNonlinear( Arc arc, float geo_stepsize, float arc_stepsize, int isrational ) {
+ assert( arc.pwlArc == null );
+
+ float stepsize = geo_stepsize * arc_stepsize;
+
+ BezierArc *bezierArc = arc.bezierArc;
+
+ float size; //bounding box size of the curve in UV
+ {
+ int i,j;
+ float 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 = TrimVertex.allocate( nsteps+1 );
+ float dp = 1.0/nsteps;
+ int vi = 0; // vertIdx
+
+ arc.pwlArc = new PwlArc();
+ arc.pwlArc.pts = vert;
+
+ if( isrational ) {
+ float[] pow_u = new float[Defines.MAXORDER];
+ float[] pow_v = new float[Defines.MAXORDER];
+ float[] pow_w = new float[Defines.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 */
+ float[] b = bezierArc.cpts;
+ vert[vi].param[0] = b[0]/b[2];
+ vert[vi].param[1] = b[1]/b[2];
+
+ /* strength reduction on p = dp * step would introduce error */
+ long order = bezierArc.order;
+ for( int step=1, ++vi; step<nsteps; step++, vi++ ) {
+ float p = dp * step;
+ float u = pow_u[0];
+ float v = pow_v[0];
+ float w = pow_w[0];
+ for( 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[vi].param[0] = u/w;
+ vert[vi].param[1] = v/w;
+ }
+
+ /* compute last point exactly */
+ b += (order - 1) * bezierArc.stride;
+ vert[vi].param[0] = b[0]/b[2];
+ vert[vi].param[1] = b[1]/b[2];
+
+ } else {
+ float[] pow_u = new float[Defines.MAXORDER];
+ float[] pow_v = new float[Defines.MAXORDER];
+ trim_power_coeffs( bezierArc, pow_u, 0 );
+ trim_power_coeffs( bezierArc, pow_v, 1 );
+
+ /* compute first point exactly */
+ float[] b = bezierArc.cpts;
+ vert[vi].param[0] = b[0];
+ vert[vi].param[1] = b[1];
+
+ /* strength reduction on p = dp * step would introduce error */
+ long order = bezierArc.order;
+ for( int step=1, ++vi; step<nsteps; step++, vi++ ) {
+ float p = dp * step;
+ float u = pow_u[0];
+ float v = pow_v[0];
+ for( int i = 1; i < bezierArc.order; i++ ) {
+ u = u * p + pow_u[i];
+ v = v * p + pow_v[i];
+ }
+ vert[vi].param[0] = u;
+ vert[vi].param[1] = v;
+ }
+
+ /* compute last point exactly */
+ b += (order - 1) * bezierArc.stride;
+ vert[vi].param[0] = b[0];
+ vert[vi].param[1] = b[1];
+ }
+ arc.pwlArc.npts = vi + 1;
+ }
+
+ private static final float gl_Bernstein[][Defines.MAXORDER][Defines.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 }
+ }
+ };
+
+ /**
+ * Computes power basis coefficients from bezier coeffients.
+ */
+ private static void trim_power_coeffs( BezierArc bez_arc, float[] p, int coord ) {
+ int stride = bez_arc.stride;
+ int order = bez_arc.order;
+ float[] base = bez_arc.cpts;
+ int baseIdx = coord;
+
+ float[][] mat = gl_Bernstein[order-1];
+
+ for (int i = 0; i < order; i++) {
+ float[] row = mat[i];
+ float s = 0.0f;
+ int pointIdx = baseIdx;
+ for (int j = 0; j < order; j++, pointIdx += stride) {
+ s += row[j] * base[pointIdx];
+ }
+ p[i] = s;
+ }
+ }
+}
diff --git a/src/net/java/games/jogl/impl/nurbs/internals/Backend.java b/src/net/java/games/jogl/impl/nurbs/internals/Backend.java
new file mode 100755
index 000000000..e99822f0b
--- /dev/null
+++ b/src/net/java/games/jogl/impl/nurbs/internals/Backend.java
@@ -0,0 +1,377 @@
+/*
+** 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.
+*/
+
+public class Backend {
+ private BasicCurveEvaluator curveEvaluator;
+ private BasicSurfaceEvaluator surfaceEvaluator;
+
+ public Backend( BasicCurveEvaluator c, BasicSurfaceEvaluator e ) {
+ this.c = c;
+ this.e = e;
+ }
+
+ /* surface backend routines */
+
+ /**
+ * bgnsurf - preamble to surface definition and evaluations
+ */
+ public void bgnsurf( boolean wiretris, boolean wirequads, long nuid ) {
+ wireframetris = wiretris;
+ wireframequads = wirequads;
+
+ /*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);
+ }
+
+ public void patch( float ulo, float uhi, float vlo, float vhi ) {
+ surfaceEvaluator.domain2f( ulo, uhi, vlo, vhi );
+ }
+
+ /**
+ * surfpts - pass a desription of a surface map
+ */
+ public void surfpts(long type, /* geometry, color, texture, normal */
+ float[] 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 */
+ float ulo, /* u lower bound */
+ float uhi, /* u upper bound */
+ float vlo, /* v lower bound */
+ float vhi /* v upper bound */ ) {
+ surfaceEvaluator.map2f( type,ulo,uhi,ustride,uorder,vlo,vhi,vstride,vorder,pts );
+ surfaceEvaluator.enable( type );
+ }
+ public void surfbbox( long type, float[] from, float[] to ) {
+ surfaceEvaluator.range2f( type, from, to );
+ }
+ /**
+ * surfgrid - define a lattice of points with origin and offset
+ */
+ public void surfgrid( float u0, float u1, long nu, float v0, float v1, long nv ) {
+ surfaceEvaluator.mapgrid2f( nu, u0, u1, nv, v0, v1 );
+ }
+ /**
+ * surfmesh - evaluate a mesh of points on lattice
+ */
+ public void surfmesh( long u, long v, long n, long m ) {
+ 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 );
+ }
+ }
+ /**
+ * bgntmesh - preamble to a triangle mesh
+ */
+ public void bgntmesh() {
+ meshindex = 0; /* I think these need to be initialized to zero */
+ npts = 0;
+
+ if( !wireframetris ) {
+ surfaceEvaluator.bgntmesh();
+ }
+ }
+ /**
+ * endtmesh - postamble to triangle mesh
+ */
+ public void endtmesh( ) {
+ if( ! wireframetris )
+ surfaceEvaluator.endtmesh();
+ }
+ /**
+ * swaptmesh - perform a swap of the triangle mesh pointers
+ */
+ public void swaptmesh( ) {
+ if( wireframetris ) {
+ meshindex = 1 - meshindex;
+ } else {
+ surfaceEvaluator.swaptmesh();
+ }
+ }
+ public void tmeshvert( GridTrimVertex v ) {
+ if( v.isGridVert() ) {
+ tmeshvert( v.g );
+ } else {
+ tmeshvert( v.t );
+ }
+ }
+ /**
+ * tmeshvert - evaluate a point on a triangle mesh
+ */
+ public void tmeshvert( TrimVertex t ) {
+ long nuid = t.nuid;
+ float u = t.param[0];
+ float v = t.param[1];
+
+ 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 );
+ }
+ }
+ /**
+ * tmeshvert - evaluate a grid point of a triangle mesh
+ */
+ public void tmeshvert( GridVertex g ) {
+ long u = g->gparam[0];
+ long v = g->gparam[1];
+
+ 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 );
+ }
+ }
+ /** the same as tmeshvert(trimvertex), for efficiency purpose */
+ public void tmeshvert( float u, float v ) {
+ 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 );
+ }
+ }
+ /**
+ * linevert - evaluate a point on an outlined contour
+ */
+ public void linevert( TrimVertex t ) {
+ surfaceEvaluator.evalcoord2f( t.nuid, t.param[0], t.param[1] );
+ }
+ /**
+ * linevert - evaluate a grid point of an outlined contour
+ */
+ public void linevert( GridVertex g ) {
+ surfaceEvaluator.evalpoint2i( g.gparam[0], g.gparam[1] );
+ }
+ /**
+ * bgnoutline - preamble to outlined rendering
+ */
+ public void bgnoutline( ) {
+ surfaceEvaluator.bgnline();
+ }
+ /**
+ * endoutline - postamble to outlined rendering
+ */
+ public void endoutline( ) {
+ surfaceEvaluator.endline();
+ }
+ /**
+ * endsurf - postamble to surface
+ */
+ public void endsurf( ) {
+ surfaceEvaluator.endmap2f();
+ }
+ /**
+ * triangle - output a triangle
+ */
+ public void triangle( TrimVertex a, TrimVertex b, TrimVertex c ) {
+ bgntfan();
+ tmeshvert( a );
+ tmeshvert( b );
+ tmeshvert( c );
+ endtfan();
+ }
+
+ public void bgntfan() {
+ surfaceEvaluator.bgntfan();
+ }
+ public void endtfan() {
+ surfaceEvaluator.endtfan();
+ }
+ public void bgnqstrip() {
+ surfaceEvaluator.bgnqstrip();
+ }
+ public void endqstrip() {
+ surfaceEvaluator.endqstrip();
+ }
+ public void evalUStrip(int n_upper, float v_upper, float[] upper_val,
+ int n_lower, float v_lower, float[] lower_val) {
+ surfaceEvaluator.evalUStrip(n_upper, v_upper, upper_val,
+ n_lower, v_lower, lower_val);
+ }
+ public void evalVStrip(int n_left, float u_left, float[] left_val,
+ int n_right, float v_right, float[] right_val) {
+ surfaceEvaluator.evalVStrip(n_left, u_left, left_val,
+ n_right, u_right, right_val);
+ }
+ public void tmeshvertNOGE(TrimVertex *t) {
+ // NOTE: under undefined USE_OPTTT #ifdef
+ }
+ public void tmeshvertNOGE_BU(TrimVertex *t) {
+ // NOTE: under undefined USE_OPTTT #ifdef
+ }
+ public void tmeshvertNOGE_BV(TrimVertex *t) {
+ // NOTE: under undefined USE_OPTTT #ifdef
+ }
+ public void preEvaluateBU(float u) {
+ surfaceEvaluator.inPreEvaluateBU_intfac(u);
+ }
+ public void preEvaluateBV(float v) {
+ surfaceEvaluator.inPreEvaluateBV_intfac(v);
+ }
+
+ /* curve backend routines */
+ public void bgncurv( void ) {
+ curveEvaluator.bgnmap1f( 0 );
+ }
+ public void segment( float ulo, float uhi ) {
+ curveEvaluator.domain1f( ulo, uhi );
+ }
+ public void curvpts(long type, /* geometry, color, texture, normal */
+ float[] pts, /* control points */
+ long stride, /* distance to next point */
+ int order, /* parametric order */
+ float ulo, /* lower parametric bound */
+ float uhi ) /* upper parametric bound */ {
+ curveEvaluator.map1f( type, ulo, uhi, stride, order, pts );
+ curveEvaluator.enable( type );
+ }
+ public void curvgrid( float u0, float u1, long nu ) {
+ curveEvaluator.mapgrid1f( nu, u0, u1 );
+ }
+ public void curvmesh( long from, long n ) {
+ curveEvaluator.mapmesh1f( N_MESHFILL, from, from+n );
+ }
+ public void curvpt( float u ) {
+ curveEvaluator.evalcoord1f( 0, u );
+ }
+ public void bgnline( ) {
+ curveEvaluator.bgnline();
+ }
+ public void endline( ) {
+ curveEvaluator.endline();
+ }
+ public void endcurv( ) {
+ curveEvaluator.endmap1f();
+ }
+
+ private boolean wireframetris;
+ private boolean wireframequads;
+ private int npts;
+ private float[][] mesh = new float[3][4];
+ private int meshindex;
+}
diff --git a/src/net/java/games/jogl/impl/nurbs/internals/BasicCurveEvaluator.java b/src/net/java/games/jogl/impl/nurbs/internals/BasicCurveEvaluator.java
new file mode 100755
index 000000000..3aae3674b
--- /dev/null
+++ b/src/net/java/games/jogl/impl/nurbs/internals/BasicCurveEvaluator.java
@@ -0,0 +1,50 @@
+/*
+** 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.
+*/
+
+public class BasicCurveEvaluator extends CachingEvaluator {
+ public void domain1f(float ulo, float uhi) {}
+ public void range1f(long type, float[] from, float[] to) {}
+
+ public void enable(long type) {}
+ public void disable(long type) {}
+ public void bgnmap1f(long type) {}
+ public void map1f(long type, float ulo, float uhi, long stride, long order, float[] pts) {}
+ public void mapgrid1f(long nu, float u0, float u1) {}
+ public void mapmesh1f(long style, long from, long to) {}
+ public void evalcoord1f(long type, float u) {}
+ public void endmap1f() {}
+
+ public void bgnline() {}
+ public void endline() {}
+}
diff --git a/src/net/java/games/jogl/impl/nurbs/internals/BasicSurfaceEvaluator.java b/src/net/java/games/jogl/impl/nurbs/internals/BasicSurfaceEvaluator.java
new file mode 100755
index 000000000..f2b4a6679
--- /dev/null
+++ b/src/net/java/games/jogl/impl/nurbs/internals/BasicSurfaceEvaluator.java
@@ -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.
+*/
+
+public abstract class BasicSurfaceEvaluator extends CachingEvaluator {
+ public void range2f(long, float[] from, float[] to) {}
+ public void domain2f(float ulo, float uhi, float vlo, float vhi) {}
+
+ public void enable(long type) {}
+ public void disable(long type) {}
+ public void bgnmap2f(long type) {}
+ public void map2f(long type, float ulower, float uupper, long ustride, long uorder,
+ float vlower, float vupper, long vstride, long vorder,
+ float[] pts) {}
+ public void mapgrid2f(long nu, float u0, float u1,
+ long nv, float v0, float v1) {}
+ public void mapmesh2f(long style, long umin, long umax,
+ long vmin, long vmax) {}
+ public void evalcoord2f(long type, float u, float v) {}
+ public void evalpoint2i(long u, long v) {}
+ public void endmap2f() {}
+
+ public void polymode(long style) {}
+ public void bgnline() {}
+ public void endline() {}
+ public void bgnclosedline() {}
+ public void endclosedline() {}
+ public void bgntmesh() {}
+ public void swaptmesh() {}
+ public void endtmesh() {}
+ public void bgnqstrip() {}
+ public void endqstrip() {}
+
+ public void bgntfan() {}
+ public void endtfan() {}
+
+ public abstract void evalUStrip(int n_upper, float v_upper, float[] upper_val,
+ int n_lower, float v_lower, float[] lower_val);
+ public abstract void evalVStrip(int n_left, float u_left, float[] left_val,
+ int n_right, float u_right, float[] right_val);
+ public abstract void inDoEvalCoord2NOGE(float u, float v, float[] ret_point, float[] ret_normal);
+ public abstract void inDoEvalCoord2NOGE_BU(float u, float v, float[] ret_point, float[] ret_normal);
+ public abstract void inDoEvalCoord2NOGE_BV(float u, float v, float[] ret_point, float[] ret_normal);
+ public abstract void inPreEvaluateBV_intfac(float v);
+ public abstract void inPreEvaluateBU_intfac(float u);
+}
diff --git a/src/net/java/games/jogl/impl/nurbs/internals/BezierArc.java b/src/net/java/games/jogl/impl/nurbs/internals/BezierArc.java
new file mode 100755
index 000000000..feac7d544
--- /dev/null
+++ b/src/net/java/games/jogl/impl/nurbs/internals/BezierArc.java
@@ -0,0 +1,42 @@
+/*
+** 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.
+*/
+
+/** A bezier arc. */
+class BezierArc {
+ public float[] cpts; /* control points of arc */
+ public int order; /* order of arc */
+ public int stride; /* REAL distance between points */
+ public long type; /* curve type */
+ public Mapdesc mapdesc;
+}
diff --git a/src/net/java/games/jogl/impl/nurbs/internals/Bin.java b/src/net/java/games/jogl/impl/nurbs/internals/Bin.java
new file mode 100755
index 000000000..55bec5eae
--- /dev/null
+++ b/src/net/java/games/jogl/impl/nurbs/internals/Bin.java
@@ -0,0 +1,147 @@
+/*
+** 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.
+*/
+
+public class Bin {
+ private Arc head; /*first arc on list */
+ private Arc current; /* current arc on list */
+
+ /**
+ * Sets current arc to first arc of bin; advances to next arc.
+ */
+ public Arc firstarc( ) {
+ current = head;
+ return nextarc( );
+ }
+ /**
+ * Returns current arc in bin and advances pointer to next arc.
+ */
+ public Arc nextarc( ) {
+ Arc jarc = current;
+
+ assert( (jarc == null) || jarc.check() );
+
+ if( jarc != null ) current = jarc.link;
+ return jarc;
+ }
+ /**
+ * Removes first Arc from bin.
+ */
+ public Arc removearc( ) {
+ Arc jarc = head;
+
+ if( jarc != null ) head = jarc.link;
+ return jarc;
+ }
+ public boolean isnonempty( ) { return (head != null); }
+ /**
+ * Adds an Arc to head of the linked list of Arcs.
+ */
+ public void addarc( Arc jarc ) {
+ jarc.link = head;
+ head = jarc;
+ }
+ /**
+ * Removes given Arc from bin.
+ */
+ public void remove_this_arc( Arc arc ) {
+ Arc j, prev;
+ for( j = head; (j != null) && (j != arc); prev = j, j = j.link );
+
+ if( j != null ) {
+ if( j == current )
+ current = j.link;
+ if ( prev != null )
+ prev.link = j.link;
+ }
+ }
+ /**
+ * Counts number of arcs in bin.
+ */
+ public int numarcs( ) {
+ long count = 0;
+ for( Arc jarc = firstarc(); jarc != null; jarc = nextarc() )
+ count++;
+ return count;
+ }
+ /**
+ * Places an orphaned arc into its new parent's bin.
+ */
+ public void adopt( ) {
+ markall();
+
+ Arc orphan;
+ while( (orphan = removearc()) != null ) {
+ for( Arc parent = orphan.next; parent != orphan; parent = parent.next ) {
+ if (! parent.ismarked() ) {
+ orphan.link = parent.link;
+ parent.link = orphan;
+ orphan.clearmark();
+ break;
+ }
+ }
+ }
+ }
+ /**
+ * Marks all arcs with an identifying tag.
+ */
+ public void markall( ) {
+ for( Arc jarc = firstarc(); jarc != null; jarc = nextarc() )
+ jarc.setmark();
+ }
+ /**
+ * Prints out descriptions of the arcs in the bin.
+ */
+ public void show( String name ) {
+ System.out.println( name );
+ for( Arc jarc = firstarc(); jarc != null; jarc = nextarc() )
+ jarc.show( );
+ }
+ /**
+ * Prints out all arcs that are untessellated border arcs.
+ */
+ public void listBezier( ) {
+ for( Arc jarc = firstarc(); jarc != null; jarc = nextarc() ) {
+ if( jarc.isbezier( ) ) {
+ assert( jarc.pwlArc.npts == 2 );
+ TrimVertex[] pts = jarc.pwlArc.pts;
+ float s1 = pts[0].param[0];
+ float t1 = pts[0].param[1];
+ float s2 = pts[1].param[0];
+ float t2 = pts[1].param[1];
+ System.out.println( "arc ( " + s1 + "," + t1 + ") (" +
+ s2 + "," + t2 + ")");
+ }
+ }
+ }
+}
diff --git a/src/net/java/games/jogl/impl/nurbs/internals/CachingEvaluator.java b/src/net/java/games/jogl/impl/nurbs/internals/CachingEvaluator.java
new file mode 100755
index 000000000..c9c8c5cf9
--- /dev/null
+++ b/src/net/java/games/jogl/impl/nurbs/internals/CachingEvaluator.java
@@ -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.
+*/
+
+public class CachingEvaluator {
+ public int ServiceModePlay = 0;
+ public int ServiceModeRecord = 1;
+ public int ServiceModePlayAndRecord = 2;
+
+ public int canRecord() {
+ return 0;
+ }
+
+ public int canPlayAndRecord() {
+ return 0;
+ }
+
+ public int createHandle( int handle ) {
+ return 0;
+ }
+
+ public void beginOutput( int serviceMode, int handle ) {}
+ public void endOutput() {}
+ public void discardRecording(int handle) {}
+ public void playRecording(int handle) {}
+}
diff --git a/src/net/java/games/jogl/impl/nurbs/internals/Defines.java b/src/net/java/games/jogl/impl/nurbs/internals/Defines.java
new file mode 100755
index 000000000..fc284abbd
--- /dev/null
+++ b/src/net/java/games/jogl/impl/nurbs/internals/Defines.java
@@ -0,0 +1,46 @@
+/*
+** 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.
+*/
+
+public class Defines {
+ /* culling constants */
+ public static final int CULL_TRIVIAL_REJECT = 0;
+ public static final int CULL_TRIVIAL_ACCEPT = 1;
+ public static final int CULL_ACCEPT = 2;
+
+ /* maximum order of a B-Spline */
+ public static final int MAXORDER = 24;
+
+ /* maximum dimension of any B-spline range space */
+ public static final int MAXCOORDS = 5;
+}
diff --git a/src/net/java/games/jogl/impl/nurbs/internals/NurbsConsts.java b/src/net/java/games/jogl/impl/nurbs/internals/NurbsConsts.java
new file mode 100755
index 000000000..74c9c150c
--- /dev/null
+++ b/src/net/java/games/jogl/impl/nurbs/internals/NurbsConsts.java
@@ -0,0 +1,117 @@
+/*
+** 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.
+*/
+
+public class NurbsConsts {
+ /* NURBS Properties - one set per map,
+ each takes a single INREAL arg */
+ public static final int N_SAMPLING_TOLERANCE = 1;
+ public static final int N_S_RATE = 6;
+ public static final int N_T_RATE = 7;
+ public static final int N_CLAMPFACTOR = 13;
+ public static final float N_NOCLAMPING = 0.0f;
+ public static final int N_MINSAVINGS = 14;
+ public static final float N_NOSAVINGSSUBDIVISION = 0.0f;
+
+ /* NURBS Properties - one set per map,
+ each takes an enumerated value */
+ public static final int N_CULLING = 2;
+ public static final float N_NOCULLING = 0.0f;
+ public static final float N_CULLINGON = 1.0f;
+ public static final int N_SAMPLINGMETHOD 10;
+ public static final float N_NOSAMPLING = 0.0f;
+ public static final float N_FIXEDRATE = 3.0f;
+ public static final float N_DOMAINDISTANCE = 2.0f;
+ public static final float N_PARAMETRICDISTANCE = 5.0f;
+ public static final float N_PATHLENGTH = 6.0f;
+ public static final float N_SURFACEAREA = 7.0f;
+ public static final float N_OBJECTSPACE_PARA = 8.0f;
+ public static final float N_OBJECTSPACE_PATH = 9.0f;
+ public static final int N_BBOX_SUBDIVIDING = 17;
+ public static final float N_NOBBOXSUBDIVISION = 0.0f;
+ public static final float N_BBOXTIGHT = 1.0f;
+ public static final float N_BBOXROUND = 2.0f;
+
+ /* NURBS Rendering Properties - one set per renderer
+ each takes an enumerated value */
+public static final int N_DISPLAY 3
+public static final int N_FILL 1.0
+public static final int N_OUTLINE_POLY 2.0
+public static final int N_OUTLINE_TRI 3.0
+public static final int N_OUTLINE_QUAD 4.0
+public static final int N_OUTLINE_PATCH 5.0
+public static final int N_OUTLINE_PARAM 6.0
+public static final int N_OUTLINE_PARAM_S 7.0
+public static final int N_OUTLINE_PARAM_ST 8.0
+public static final int N_OUTLINE_SUBDIV 9.0
+public static final int N_OUTLINE_SUBDIV_S 10.0
+public static final int N_OUTLINE_SUBDIV_ST 11.0
+public static final int N_ISOLINE_S 12.0
+public static final int N_ERRORCHECKING 4
+public static final int N_NOMSG 0.0
+public static final int N_MSG 1.0
+
+/* GL 4.0 propeties not defined above */
+#ifndef N_PIXEL_TOLERANCE
+public static final int N_PIXEL_TOLERANCE N_SAMPLING_TOLERANCE
+public static final int N_ERROR_TOLERANCE 20
+public static final int N_SUBDIVISIONS 5
+public static final int N_TILES 8
+public static final int N_TMP1 9
+public static final int N_TMP2 N_SAMPLINGMETHOD
+public static final int N_TMP3 11
+public static final int N_TMP4 12
+public static final int N_TMP5 N_CLAMPFACTOR
+public static final int N_TMP6 N_MINSAVINGS
+public static final int N_S_STEPS N_S_RATE
+public static final int N_T_STEPS N_T_RATE
+#endif
+
+/* NURBS Rendering Properties - one set per map,
+ each takes an INREAL matrix argument */
+public static final int N_CULLINGMATRIX 1
+public static final int N_SAMPLINGMATRIX 2
+public static final int N_BBOXMATRIX 3
+
+
+/* NURBS Rendering Properties - one set per map,
+ each takes an INREAL vector argument */
+public static final int N_BBOXSIZE 4
+
+/* type argument for trimming curves */
+#ifndef N_P2D
+public static final int N_P2D 0x8
+public static final int N_P2DR 0xd
+#endif
+
+}
diff --git a/src/net/java/games/jogl/impl/nurbs/internals/NurbsException.java b/src/net/java/games/jogl/impl/nurbs/internals/NurbsException.java
new file mode 100755
index 000000000..5453807cd
--- /dev/null
+++ b/src/net/java/games/jogl/impl/nurbs/internals/NurbsException.java
@@ -0,0 +1,30 @@
+/** Encapsulates functionality of the C GLU NURBS implementation's
+ setjmp/longjmp wrappers. */
+
+public class NurbsException extends RuntimeException {
+ private int errorCode;
+
+ public NurbsException(int code) {
+ super();
+ errorCode = code;
+ }
+
+ public NurbsException(String message, int code) {
+ super(message);
+ errorCode = code;
+ }
+
+ public NurbsException(String message, Throwable cause, int code) {
+ super(message, cause);
+ errorCode = code;
+ }
+
+ public NurbsException(Throwable cause, int code) {
+ super(cause);
+ errorCode = code;
+ }
+
+ public int errorCode() {
+ return errorCode;
+ }
+}
diff --git a/src/net/java/games/jogl/impl/nurbs/internals/Subdivider.java b/src/net/java/games/jogl/impl/nurbs/internals/Subdivider.java
new file mode 100755
index 000000000..155b6b7ac
--- /dev/null
+++ b/src/net/java/games/jogl/impl/nurbs/internals/Subdivider.java
@@ -0,0 +1,1781 @@
+/*
+** 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.
+*/
+
+public class Subdivider {
+
+ /**
+ * Constructs a subdivider.
+ */
+ public Subdivider(RenderHints hints, Backend b) {
+ renderhints = hints;
+ arctessellator = new ArcTesselator();
+ backend = b;
+ slicer = new Slicer(b);
+ }
+
+ /**
+ * Resets all state after possible error condition.
+ */
+ public void clear() {
+ // FIXME: looks like nothing to do given that we have no object pools
+ }
+ public void beginTrims() {}
+ public void beginLoop() {
+ pjarc = 0;
+ }
+
+ /**
+ * Adds a bezier arc to a trim loop and to a bin.
+ */
+ public void addArc(float[] cpts, Quilt quilt, long _nuid) {
+ BezierArc bezierArc = new BezierArc();
+ Arc jarc = new Arc(Arc.SIDE_NONE, _nuid);
+ 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 );
+ }
+
+ /**
+ * Adds a pwl arc to a trim loop and to a bin.
+ */
+ public void addArc(int npts, TrimVertex[] pts, long _nuid) {
+ Arc jarc = new Arc( Arc.SIDE_NONE, _nuid );
+ jarc.pwlArc = new PwlArc( npts, pts );
+ initialbin.addarc( jarc );
+ pjarc = jarc.append( pjarc );
+ }
+ public void endLoop() {}
+ public void endTrims() {}
+
+ public void beginQuilts() {
+ qlist = null;
+ }
+ public void addQuilt( Quilt quilt ) {
+ quilt.next = qlist;
+ qlist = quilt;
+ }
+ public void endQuilts() {}
+
+ /**
+ * Main curve rendering entry point
+ */
+ public void drawCurves() {
+ float[] from = new float[1];
+ float[] to = new float[1];
+ Flist bpts = new Flist();
+ qlist.getRange( from, to, bpts );
+
+ renderhints.init( );
+
+ backend.bgncurv();
+ float[] pta = new float[0];
+ float[] ptb = new float[1];
+ for( int i=bpts.start; i<bpts.end-1; i++ ) {
+ pta[0] = bpts.pts[i];
+ ptb[0] = bpts.pts[i+1];
+
+ qlist.downloadAll( pta, ptb, backend );
+
+ Curvelist curvelist = new Curvelist( qlist, pta, ptb );
+ samplingSplit( curvelist, renderhints.maxsubdivisions );
+ }
+ backend.endcurv();
+ }
+ public void drawSurfaces(long nuid) {
+ renderhints.init( );
+
+ if (qlist == null) {
+ //initialbin could be nonempty due to some errors
+ freejarcs(initialbin);
+ return;
+ }
+
+ for( Quilt q = qlist; q != null; q = q.next ) {
+ if( q.isCulled( ) == Defines.CULL_TRIVIAL_REJECT ) {
+ freejarcs( initialbin );
+ return;
+ }
+ }
+
+
+ float[] from = new float[2];
+ float[] to = new float[2];
+ qlist.getRange( from, to, spbrkpts, tpbrkpts );
+ //perform optimization only when the samplng method is
+ //DOMAIN_DISTANCE and the display methdo is either
+ //fill or outline_polygon.
+ bool optimize = (is_domain_distance_sampling && (renderhints.display_method != N_OUTLINE_PATCH));
+
+ if( ! initialbin.isnonempty() ) {
+ if(! optimize )
+ {
+ makeBorderTrim( from, to );
+ }
+ } else {
+ float[] rate = new float[2];
+ qlist.findRates( spbrkpts, tpbrkpts, rate );
+
+ if( decompose( initialbin, Math.min(rate[0], rate[1]) ) )
+ throw new NurbsException( 31 );
+ }
+
+ backend.bgnsurf( renderhints.wiretris, renderhints.wirequads, nuid );
+
+ 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++){
+ float[] pta = new float[2];
+ float[] ptb = new float[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;
+ }
+ }
+ }
+ else
+ subdivideInS( initialbin );
+
+ backend.endsurf();
+ }
+
+ public int ccwTurn_sl(Arc j1, Arc j2 ) {
+ int v1i = j1.pwlArc.npts-1;
+ int v1lasti = 0;
+ int v2i = 0;
+ int v2lasti = j2.pwlArc.npts-1;
+ int v1nexti = v1i-1;
+ int v2nexti = v2i+1;
+ TrimVertex v1 = j1.pwlArc.pts[v1i];
+ TrimVertex v1last = j1.pwlArc.pts[v1lasti];
+ TrimVertex v2 = j2.pwlArc.pts[v2i];
+ TrimVertex v2last = j2.pwlArc.pts[v2lasti];
+ TrimVertex v1next = j1.pwlArc.pts[v1nexti];
+ TrimVertex v2next = j2.pwlArc.pts[v2nexti];
+ int sgn;
+
+ assert( v1 != v1last );
+ assert( v2 != v2last );
+
+ // 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] )
+ throw new NurbsException(28);
+
+ if( v1.param[1] < v2.param[1] )
+ return 1;
+ else if( v1.param[1] > v2.param[1] )
+ return 0;
+
+ while( true ) {
+ if( v1next.param[0] > v2next.param[0] ) {
+ 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 {
+ v1i = v1nexti--;
+ v1 = j1.pwlArc.pts[v1i];
+ v1next = j1.pwlArc.pts[v1nexti];
+ if( v1 == v1last ) {
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 0;
+ }
+ } else if( v1next.param[0] < v2next.param[0] ) {
+ 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 {
+ v2i = v2nexti++;
+ v2 = j2.pwlArc.pts[v2i];
+ v2next = j2.pwlArc.pts[v2nexti];
+ if( v2 == v2last ) {
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 1;
+ }
+ } else {
+ if( v1next.param[1] < v2next.param[1] )
+ return 1;
+ else if( v1next.param[1] > v2next.param[1] )
+ return 0;
+ else {
+ v2i = v2nexti++;
+ v2 = j2.pwlArc.pts[v2i];
+ v2next = j2.pwlArc.pts[v2nexti];
+ if( v2 == v2last ) {
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ }
+ }
+ }
+
+ public int ccwTurn_sr(Arc j1, Arc j2 ) {
+ // dir = 1
+ int v1i = j1.pwlArc.npts-1;
+ int v1lasti = 0;
+ int v2i = 0;
+ int v2lasti = j2.pwlArc.npts-1;
+ int v1nexti = v1i-1;
+ int v2nexti = v2i+1;
+ TrimVertex v1 = j1.pwlArc.pts[v1i];
+ TrimVertex v1last = j1.pwlArc.pts[v1lasti];
+ TrimVertex v2 = j2.pwlArc.pts[v2i];
+ TrimVertex v2last = j2.pwlArc.pts[v2lasti];
+ TrimVertex v1next = j1.pwlArc.pts[v1nexti];
+ TrimVertex v2next = j2.pwlArc.pts[v2nexti];
+ int sgn;
+
+ assert( v1 != v1last );
+ assert( v2 != v2last );
+
+ // 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] )
+ throw new NurbsException(28);
+
+ if( v1.param[1] < v2.param[1] )
+ return 0;
+ else if( v1.param[1] > v2.param[1] )
+ return 1;
+
+ while( true ) {
+ if( v1next.param[0] < v2next.param[0] ) {
+ 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 {
+ v1i = v1nexti--;
+ v1 = j1.pwlArc.pts[v1i];
+ v1next = j1.pwlArc.pts[v1nexti];
+ if( v1 == v1last ) {
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 1;
+ }
+ } else if( v1next.param[0] > v2next.param[0] ) {
+ 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 {
+ v2i = v2nexti++;
+ v2 = j2.pwlArc.pts[v2i];
+ v2next = j2.pwlArc.pts[v2nexti];
+ if( v2 == v2last ) {
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 0;
+ }
+ } else {
+ if( v1next.param[1] < v2next.param[1] )
+ return 0;
+ else if( v1next.param[1] > v2next.param[1] )
+ return 1;
+ else {
+ v2i = v2nexti++;
+ v2 = j2.pwlArc.pts[v2i];
+ v2next = j2.pwlArc.pts[v2nexti];
+ if( v2 == v2last ) {
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ }
+ }
+ }
+
+ public int ccwTurn_tl(Arc j1, Arc j2 ) {
+ int v1i = j1.pwlArc.npts-1;
+ int v1lasti = 0;
+ int v2i = 0;
+ int v2lasti = j2.pwlArc.npts-1;
+ int v1nexti = v1i-1;
+ int v2nexti = v2i+1;
+ TrimVertex v1 = j1.pwlArc.pts[v1i];
+ TrimVertex v1last = j1.pwlArc.pts[v1lasti];
+ TrimVertex v2 = j2.pwlArc.pts[v2i];
+ TrimVertex v2last = j2.pwlArc.pts[v2lasti];
+ TrimVertex v1next = j1.pwlArc.pts[v1nexti];
+ TrimVertex v2next = j2.pwlArc.pts[v2nexti];
+ int sgn;
+
+ assert( v1 != v1last );
+ assert( v2 != v2last );
+
+ // 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] )
+ throw new NurbsException(28 );
+
+ if( v1.param[0] < v2.param[0] )
+ return 0;
+ else if( v1.param[0] > v2.param[0] )
+ return 1;
+
+ while( true ) {
+ if( v1next.param[1] > v2next.param[1] ) {
+ 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 {
+ v1i = v1nexti--;
+ v1 = j1.pwlArc.pts[v1i];
+ v1next = j1.pwlArc.pts[v1nexti];
+ if( v1 == v1last ) {
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 1;
+ }
+ } else if( v1next.param[1] < v2next.param[1] ) {
+ switch( bbox( v1next, v1, v2next, 0 ) ) {
+ case -1:
+ return 1;
+ case 0:
+ sgn = ccw( v1next, v1, v2next );
+ if( sgn != -1 )
+ return sgn;
+ else {
+ v2i = v2nexti++;
+ v2 = j2.pwlArc.pts[v2i];
+ v2next = j2.pwlArc.pts[v2nexti];
+ if( v2 == v2last ) {
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 0;
+ }
+ } else {
+ if( v1next.param[0] < v2next.param[0] )
+ return 0;
+ else if( v1next.param[0] > v2next.param[0] )
+ return 1;
+ else {
+ v2i = v2nexti++;
+ v2 = j2.pwlArc.pts[v2i];
+ v2next = j2.pwlArc.pts[v2nexti];
+ if( v2 == v2last ) {
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ }
+ }
+ }
+
+ public int ccwTurn_tr(Arc j1, Arc j2) {
+ int v1i = j1.pwlArc.npts-1;
+ int v1lasti = 0;
+ int v2i = 0;
+ int v2lasti = j2.pwlArc.npts-1;
+ int v1nexti = v1i-1;
+ int v2nexti = v2i+1;
+ TrimVertex v1 = j1.pwlArc.pts[v1i];
+ TrimVertex v1last = j1.pwlArc.pts[v1lasti];
+ TrimVertex v2 = j2.pwlArc.pts[v2i];
+ TrimVertex v2last = j2.pwlArc.pts[v2lasti];
+ TrimVertex v1next = j1.pwlArc.pts[v1nexti];
+ TrimVertex v2next = j2.pwlArc.pts[v2nexti];
+ int sgn;
+
+ assert( v1 != v1last );
+ assert( v2 != v2last );
+
+ // 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] )
+ throw new NurbsException( 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] ) {
+ 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 {
+ v1i = v1nexti--;
+ v1 = j1.pwlArc.pts[v1i];
+ v1next = j1.pwlArc.pts[v1nexti];
+ if( v1 == v1last ) {
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 0;
+ }
+ } else if( v1next.param[1] > v2next.param[1] ) {
+ 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 {
+ v2i = v2nexti++;
+ v2 = j2.pwlArc.pts[v2i];
+ v2next = j2.pwlArc.pts[v2nexti];
+ if( v2 == v2last ) {
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 1;
+ }
+ } else {
+ if( v1next.param[0] < v2next.param[0] )
+ return 1;
+ else if( v1next.param[0] > v2next.param[0] )
+ return 0;
+ else {
+ v2i = v2nexti++;
+ v2 = j2.pwlArc.pts[v2i];
+ v2next = j2.pwlArc.pts[v2nexti];
+ if( v2 == v2last ) {
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ }
+ }
+ }
+
+ public void set_domain_distance_u_rate(float u_rate) {
+ domain_distance_u_rate = u_rate;
+ }
+
+ public void set_domain_distance_v_rate(float v_rate) {
+ domain_distance_v_rate = v_rate;
+ }
+
+ public void set_is_domain_distance_sampling(int flag) {
+ is_domain_distance_sampling = flag;
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only below this point
+ //
+
+ /**
+ * Determine which side of a line a jarc lies (for debugging only)
+ */
+ private int arc_classify( Arc jarc, int param, float value )
+ {
+ float 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;
+ }
+ }
+ }
+
+ private void classify_headonleft_s( Bin bin, Bin in, Bin out, float val ) {
+ /* tail on line, head at left */
+ Arc j;
+
+ while( (j = bin.removearc()) != null ) {
+ assert( arc_classify( j, 0, val ) == 0x20 );
+
+ j.setitail();
+
+ float diff = j.prev.tail()[0] - val;
+ if( diff > 0.0 ) {
+ out.addarc( j );
+ } else if( diff < 0.0 ) {
+ if( ccwTurn_sl( j.prev, j ) != 0 )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ } else {
+ if( j.prev.tail()[1] > j.prev.head()[1] )
+ in.addarc( j );
+ else
+ out.addarc( j );
+ }
+ }
+ }
+
+ private void classify_tailonleft_s( Bin bin, Bin in, Bin out, float val ) {
+ /* tail at left, head on line */
+ Arc j;
+
+ while( (j = bin.removearc()) != null ) {
+ assert( arc_classify( j, 1, val ) == 0x02 );
+ j.clearitail();
+
+ float diff = j.next.head()[1] - val;
+ if( diff > 0.0 ) {
+ in.addarc( j );
+ } else if( diff < 0.0 ) {
+ if( ccwTurn_tl( j, j.next ) != 0 )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ } else {
+ if (j.next.tail()[0] > j.next.head()[0] )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ }
+ }
+ }
+
+ private void classify_headonright_s( Bin bin, Bin in, Bin out, float val ) {
+ /* tail on line, head at right */
+ Arc j;
+
+ while( (j = bin.removearc()) != null ) {
+ assert( arc_classify( j, 0, val ) == 0x21 );
+
+ j.setitail();
+
+ float diff = j.prev.tail()[0] - val;
+ if( diff > 0.0 ) {
+ if( ccwTurn_sr( j.prev, j ) != 0 )
+ 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 );
+ }
+ }
+ }
+
+ private void classify_tailonright_s( Bin bin, Bin in, Bin out, float val ) {
+ /* tail at right, head on line */
+ Arc j;
+
+ while( (j = bin.removearc()) != null ) {
+ assert( arc_classify( j, 0, val ) == 0x12);
+
+ j.clearitail();
+
+ float diff = j.next.head()[0] - val;
+ if( diff > 0.0 ) {
+ if( ccwTurn_sr( j, j.next ) != 0 )
+ 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 );
+ }
+ }
+ }
+
+ private void classify_headonleft_t( Bin bin, Bin in, Bin out, float val ) {
+ /* tail on line, head at left */
+ Arc j;
+
+ while( (j = bin.removearc()) != null ) {
+ assert( arc_classify( j, 1, val ) == 0x20 );
+ j.setitail();
+
+ float diff = j.prev.tail()[1] - val;
+ if( diff > 0.0 ) {
+ out.addarc( j );
+ } else if( diff < 0.0 ) {
+ if( ccwTurn_tl( j.prev, j ) != 0 )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ } else {
+ if( j.prev.tail()[0] > j.prev.head()[0] )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ }
+ }
+ }
+
+ private void classify_tailonleft_t( Bin bin, Bin in, Bin out, float val ) {
+ /* tail at left, head on line */
+ Arc j;
+
+ while( (j = bin.removearc()) != null ) {
+ assert( arc_classify( j, 1, val ) == 0x02 );
+ j.clearitail();
+
+ float diff = j.next.head()[1] - val;
+ if( diff > 0.0 ) {
+ in.addarc( j );
+ } else if( diff < 0.0 ) {
+ if( ccwTurn_tl( j, j.next ) != 0 )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ } else {
+ if (j.next.tail()[0] > j.next.head()[0] )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ }
+ }
+ }
+
+ private void classify_headonright_t( Bin bin, Bin in, Bin out, float val ) {
+ /* tail on line, head at right */
+ Arc j;
+
+ while( (j = bin.removearc()) != null ) {
+ assert( arc_classify( j, 1, val ) == 0x21 );
+
+ j.setitail();
+
+ float diff = j.prev.tail()[1] - val;
+ if( diff > 0.0 ) {
+ if( ccwTurn_tr( j.prev, j ) != 0 )
+ 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 );
+ }
+ }
+ }
+
+ private void classify_tailonright_t( Bin bin, Bin in, Bin out, float val ) {
+ /* tail at right, head on line */
+ Arc j;
+
+ while( (j = bin.removearc()) != null ) {
+ assert( arc_classify( j, 1, val ) == 0x12);
+
+ j.clearitail();
+
+ float diff = j.next.head()[1] - val;
+ if( diff > 0.0 ) {
+ if( ccwTurn_tr( j, j.next ) != 0 )
+ 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 );
+ }
+ }
+ }
+
+ private int DIR_DOWN = 0;
+ private int DIR_SAME = 1;
+ private int DIR_UP = 2;
+ private int DIR_NONE = 3;
+
+ private void tessellate( Arc_ptr, float );
+ private void monotonize( Arc_ptr , Bin & );
+ private int isMonotone( Arc_ptr );
+ private int decompose( Bin &, float );
+
+
+ private Slicer slicer;
+ private ArcTessellator arctessellator;
+ // private Pool arcpool;
+ // private Pool bezierarcpool;
+ // private Pool pwlarcpool;
+ // private TrimVertexPool trimvertexpool;
+
+ private JumpBuffer* jumpbuffer;
+ private Renderhints& renderhints;
+ private Backend& backend;
+
+ private Bin initialbin;
+ private Arc pjarc;
+ private int s_index;
+ private int t_index;
+ private Quilt *qlist;
+ private Flist spbrkpts;
+ private Flist tpbrkpts;
+ private Flist smbrkpts;
+ private Flist tmbrkpts;
+ private float stepsizes[4];
+ private int showDegenerate;
+ private int isArcTypeBezier;
+
+ // FIXME: NOT FINISHED
+ private void samplingSplit( Curvelist&, int );
+
+ private void subdivideInS( Bin source ) {
+ if( renderhints.display_method == N_OUTLINE_PARAM ) {
+ outline( source );
+ freejarcs( source );
+ } else {
+ setArcTypeBezier();
+ setNonDegenerate();
+ splitInS( source, spbrkpts.start, spbrkpts.end );
+ }
+ }
+
+ /**
+ * Splits a patch and a bin by an isoparametric line.
+ */
+ private void splitInS( Bin source, int start, int end ) {
+ if( source.isnonempty() ) {
+ if( start != end ) {
+ int i = start + (end - start) / 2;
+ Bin left = new Bin();
+ Bin right = new Bin();
+ 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 == NurbsConsts.N_OUTLINE_PARAM_S ) {
+ outline( source );
+ freejarcs( source );
+ } else {
+ setArcTypeBezier();
+ setNonDegenerate();
+ s_index = start;
+ splitInT( source, tpbrkpts.start, tpbrkpts.end );
+ }
+ }
+ }
+ }
+
+ /**
+ * Splits a patch and a bin by an isoparametric line.
+ */
+ private void splitInT( Bin source, int start, int end ) {
+ if( source.isnonempty() ) {
+ if( start != end ) {
+ int i = start + (end - start) / 2;
+ Bin left = new Bin();
+ Bin right = new Bin();
+ 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 == NurbsConsts.N_OUTLINE_PARAM_ST ) {
+ outline( source );
+ freejarcs( source );
+ } else {
+ t_index = start;
+ setArcTypeBezier();
+ setDegenerate();
+
+ float[] pta = new float[2];
+ float[] ptb = new float[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 = new Patchlist( qlist, pta, ptb );
+ /*
+ printf("-------samplingSplit-----\n");
+ source.show("samplingSplit source");
+ */
+ samplingSplit( source, patchlist, renderhints.maxsubdivisions, 0 );
+ setNonDegenerate();
+ setArcTypeBezier();
+ }
+ }
+ }
+ }
+
+ /**
+ * Recursively subdivides patch, cull checks each subpatch
+ */
+ private void samplingSplit( Bin source, Patchlist patchlist, int subdivisions, int param ) {
+ if( ! source.isnonempty() ) return;
+
+ if( patchlist.cullCheck() == Defines.CULL_TRIVIAL_REJECT ) {
+ freejarcs( source );
+ return;
+ }
+
+ patchlist.getstepsize();
+
+ if( renderhints.display_method == NurbsConsts.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 = new Bin();
+ Bin right = new Bin();
+ float mid = ( patchlist.pspec[param].range[0] +
+ patchlist.pspec[param].range[1] ) * 0.5;
+ split( source, left, right, param, mid );
+ Patchlist subpatchlist = new Patchlist( 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();
+ }
+ }
+
+ private void nonSamplingSplit( Bin source, Patchlist patchlist, int subdivisions, int param ) {
+ if( patchlist.needsNonSamplingSubdivision() && (subdivisions > 0) ) {
+ param = 1 - param;
+
+ Bin left = new Bin();
+ Bin right = new Bin();
+ float mid = ( patchlist.pspec[param].range[0] +
+ patchlist.pspec[param].range[1] ) * 0.5;
+ split( source, left, right, param, mid );
+ Patchlist subpatchlist = new Patchlist( patchlist, param, mid );
+ if( left.isnonempty() )
+ if( subpatchlist.cullCheck() == Defines.CULL_TRIVIAL_REJECT )
+ freejarcs( left );
+ else
+ nonSamplingSplit( left, subpatchlist, subdivisions-1, param );
+ if( right.isnonempty() )
+ if( patchlist.cullCheck() == Defines.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 == NurbsConsts.N_OUTLINE_SUBDIV ) {
+ outline( source );
+ freejarcs( source );
+ } else {
+ setArcTypePwl();
+ setDegenerate();
+ findIrregularS( source );
+ monosplitInS( source, smbrkpts.start, smbrkpts.end );
+ }
+ }
+ }
+
+ /**
+ * Sets tessellation of interior and boundary of patch.
+ */
+ private void 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;
+ }
+
+ /**
+ * Splits a patch and a bin by an isoparametric line.
+ */
+ private void monosplitInS( Bin source, int start, int end ) {
+ if( source.isnonempty() ) {
+ if( start != end ) {
+ int i = start + (end - start) / 2;
+ Bin left = new Bin();
+ Bin right = new Bin();
+ split( source, left, right, 0, smbrkpts.pts[i] );
+ monosplitInS( left, start, i );
+ monosplitInS( right, i+1, end );
+ } else {
+ if( renderhints.display_method == NurbsConsts.N_OUTLINE_SUBDIV_S ) {
+ outline( source );
+ freejarcs( source );
+ } else {
+ setArcTypePwl();
+ setDegenerate();
+ findIrregularT( source );
+ monosplitInT( source, tmbrkpts.start, tmbrkpts.end );
+ }
+ }
+ }
+ }
+
+ /**
+ * Splits a patch and a bin by an isoparametric line.
+ */
+ private void monosplitInT( Bin source, int start, int end ) {
+ if( source.isnonempty() ) {
+ if( start != end ) {
+ int i = start + (end - start) / 2;
+ Bin left = new Bin();
+ Bin right = new Bin();
+ split( source, left, right, 1, tmbrkpts.pts[i] );
+ monosplitInT( left, start, i );
+ monosplitInT( right, i+1, end );
+ } else {
+ if( renderhints.display_method == NurbsConsts.N_OUTLINE_SUBDIV_ST ) {
+ outline( source );
+ freejarcs( source );
+ } else {
+ /*
+ printf("*******render\n");
+ source.show("source\n");
+ */
+ render( source );
+ freejarcs( source );
+ }
+ }
+ }
+ }
+
+ /**
+ * Renders the trimmed patch by outlining the boundary .
+ */
+ private void outline( Bin bin ) {
+ bin.markall();
+ for( Arc jarc=bin.firstarc(); jarc != null; jarc=bin.nextarc() ) {
+ if( jarc.ismarked() ) {
+ assert( jarc.check( ) );
+ Arc jarchead = jarc;
+ do {
+ slicer.outline( jarc );
+ jarc.clearmark();
+ jarc = jarc.prev;
+ } while (jarc != jarchead);
+ }
+ }
+ }
+
+ /**
+ * Frees all arcs in a bin.
+ */
+ private void freejarcs( Bin & ) {
+ bin.adopt(); /* XXX - should not be necessary */
+
+ Arc jarc;
+ while( (jarc = bin.removearc()) != null ) {
+ if( jarc.pwlArc != null ) jarc.pwlArc.deleteMe( ); jarc.pwlArc = null;
+ if( jarc.bezierArc != null) jarc.bezierArc.deleteMe( ); jarc.bezierArc = null;
+ jarc.deleteMe( );
+ }
+ }
+
+ /**
+ * Renders all monotone regions in a bin and frees the bin.
+ */
+ private void render( Bin bin ) {
+ bin.markall();
+
+ slicer.setisolines( ( renderhints.display_method == N_ISOLINE_S ) ? 1 : 0 );
+
+ for( Arc jarc=bin.firstarc(); jarc != null; jarc=bin.nextarc() ) {
+ if( jarc.ismarked() ) {
+ assert( jarc.check( ) != 0 );
+ Arc jarchead = jarc;
+ do {
+ jarc.clearmark();
+ jarc = jarc.next;
+ } while (jarc != jarchead);
+ slicer.slice( jarc );
+ }
+ }
+ }
+
+ private void split( Bin &, Bin &, Bin &, int, float );
+
+ /**
+ * Tessellates all Bezier arcs in a bin.
+ * <ol>
+ * <li> only accepts linear Bezier arcs as input
+ * <li> the Bezier arcs are stored in the pwlArc structure
+ * <li> only vertical or horizontal lines work
+ * </ol>
+ * should:
+ * <ol>
+ * <li> represent Bezier arcs in BezierArc structure
+ * (this requires a multitude of changes to the code)
+ * <li> accept high degree Bezier arcs (hard)
+ * <il> map the curve onto the surface to determine tessellation
+ * <li> work for curves of arbitrary geometry
+ * </ol>
+ *----------------------------------------------------------------------------
+ */
+ private void tessellate( Bin bin, float rrate, float trate, float lrate, float brate ) {
+ for( Arc jarc=bin.firstarc(); jarc != null; jarc=bin.nextarc() ) {
+ if( jarc.isbezier( ) ) {
+ assert( jarc.pwlArc.npts == 2 );
+ TrimVertex[] pts = jarc.pwlArc.pts;
+ float s1 = pts[0].param[0];
+ float t1 = pts[0].param[1];
+ float s2 = pts[1].param[0];
+ float t2 = pts[1].param[1];
+
+ jarc.pwlArc.deleteMe( );
+ jarc.pwlArc = null;
+
+ switch( jarc.getside() ) {
+ case Arc.SIDE_LEFT:
+ assert( s1 == s2 );
+ arctessellator.pwl_left( jarc, s1, t1, t2, lrate );
+ break;
+ case Arc.SIDE_RIGHT:
+ assert( s1 == s2 );
+ arctessellator.pwl_right( jarc, s1, t1, t2, rrate );
+ break;
+ case Arc.SIDE_TOP:
+ assert( t1 == t2 );
+ arctessellator.pwl_top( jarc, t1, s1, s2, trate );
+ break;
+ case Arc.SIDE_BOTTOM:
+ assert( t1 == t2 );
+ arctessellator.pwl_bottom( jarc, t1, s1, s2, brate );
+ break;
+ case Arc.SIDE_NONE:
+ throw new InternalError("Incorrect tesselation state");
+ break;
+ }
+ assert( ! jarc.isbezier() );
+ assert( jarc.check() != 0 );
+ }
+ }
+ }
+
+ private inline void setDegenerate( void ) { showDegenerate = 1; }
+ private inline void setNonDegenerate( void ) { showDegenerate = 0; }
+ private inline int showingDegenerate( void ) { return showDegenerate; }
+ private inline void setArcTypeBezier( void ) { isArcTypeBezier = 1; }
+ private inline void setArcTypePwl( void ) { isArcTypeBezier = 0; }
+ private inline int isBezierArcType( void ) { return isArcTypeBezier; }
+
+ /**
+ * 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.
+ */
+ private void makeBorderTrim( float[] from, float[] to ) {
+ float smin = from[0];
+ float smax = to[0];
+ float tmin = from[1];
+ float tmax = to[1];
+
+ pjarc = null;
+
+ Arc jarc = new Arc( Arc.SIDE_BOTTOM, 0 );
+ arctessellator.bezier( jarc, smin, smax, tmin, tmin );
+ initialbin.addarc( jarc );
+ pjarc = jarc.append( pjarc );
+
+ jarc = new Arc( Arc.SIDE_RIGHT, 0 );
+ arctessellator.bezier( jarc, smax, smax, tmin, tmax );
+ initialbin.addarc( jarc );
+ pjarc = jarc.append( pjarc );
+
+ jarc = new Arc( Arc.SIDE_TOP, 0 );
+ arctessellator.bezier( jarc, smax, smin, tmax, tmax );
+ initialbin.addarc( jarc );
+ pjarc = jarc.append( pjarc );
+
+ jarc = new Arc( Arc.SIDE_LEFT, 0 );
+ arctessellator.bezier( jarc, smin, smin, tmax, tmin );
+ initialbin.addarc( jarc );
+ jarc.append( pjarc );
+
+ assert( jarc.check() );
+ }
+
+ private void split( Bin &, int, const float *, int, int );
+ private void partition( Bin bin, Bin left, Bin intersections, Bin right, Bin unknown, int param, float value ) {
+ Bin headonleft = new Bin();
+ Bin headonright = new Bin();
+ Bin tailonleft = new Bin();
+ Bin tailonright = new Bin();
+
+ for( Arc jarc = bin.removearc(); jarc != null; jarc = bin.removearc() ) {
+
+ float tdiff = jarc.tail()[param] - value;
+ float 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 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 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 );
+ }
+ }
+
+ /**
+ * Determine points of non-monotonicity in s direction.
+ */
+ private void findIrregularS( Bin bin ) {
+ assert( bin.firstarc() == null || bin.firstarc().check() );
+
+ smbrkpts.grow( bin.numarcs() );
+
+ for( Arc jarc=bin.firstarc(); jarc != null; jarc=bin.nextarc() ) {
+ float[] a = jarc.prev.tail();
+ float[] b = jarc.tail();
+ float[] 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();
+ }
+
+ /**
+ * Determines points of non-monotonicity in t direction where one
+ * arc is parallel to the s axis.
+ */
+ private void findIrregularT( Bin bin ) {
+ assert( bin.firstarc() == null || bin.firstarc().check() );
+
+ tmbrkpts.grow( bin.numarcs() );
+
+ for( Arc jarc=bin.firstarc(); jarc != null; jarc=bin.nextarc() ) {
+ float[] a = jarc.prev.tail();
+ float[] b = jarc.tail();
+ float[] 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 ) == 0)
+ 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 ) == 0)
+ tmbrkpts.add( b[1] );
+ }
+ }
+ tmbrkpts.filter( );
+ }
+
+
+ private int 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] );
+ }
+
+ private static int bbox( float sa, float sb, float sc, float ta, float tb, float tc ) {
+ assert( tc >= ta );
+ assert( tc <= tb );
+
+ 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;
+ }
+ }
+ }
+ /**
+ * Determines 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.
+ */
+ private static int ccw( TrimVertex a, TrimVertex b, TrimVertex c ) {
+ float d = TrimVertex.det3( a, b, c );
+ if( Math.abs(d) < 0.0001 ) return -1;
+ return (d < 0.0) ? 0 : 1;
+ }
+ private void join_s( Bin &, Bin &, Arc_ptr, Arc_ptr );
+ private void join_t( Bin &, Bin &, Arc_ptr , Arc_ptr );
+
+ private static void vert_interp( TrimVertex n, TrimVertex l, TrimVertex r, int p, float 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] ) {
+ float 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];
+ }
+ }
+
+ private static final int INTERSECT_VERTEX = 1;
+ private static final int INTERSECT_EDGE = 2;
+
+ /**
+ * Finds intersection of pwlArc and isoparametric line.
+ */
+ private static int pwlarc_intersect( PwlArc pwlArc, int param, float value, int dir, int[] loc ) {
+ assert( pwlArc.npts > 0 );
+
+ if( dir != 0 ) {
+ 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;
+ }
+ }
+
+ private int arc_split( Arc jarc , int param, float value, int dir ) {
+ int maxvertex = jarc.pwlArc.npts;
+ Arc jarc1, jarc2, jarc3;
+ TrimVertex v = jarc.pwlArc.pts;
+
+ int[] loc = new int[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 Arc( jarc, new PwlArc( maxvertex-loc[1], /* &v[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());
+ 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];
+ }
+
+ // 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 = TrimVertex.allocate(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 = TrimVertex.allocate(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 Arc( jarc,
+ new 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());
+
+ return 2;
+
+ /***
+ // JEB: This is the original version:
+
+ TrimVertex[] newjunk = TrimVertex.allocate(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;
+ }
+ ***/
+ }
+ default:
+ return -1; //picked -1 since it's not used
+ }
+ }
+
+ private void check_s( Arc_ptr , Arc_ptr );
+ private void check_t( Arc_ptr , Arc_ptr );
+ private inline void link( Arc_ptr , Arc_ptr , Arc_ptr , Arc_ptr );
+ private inline void simple_link( Arc_ptr , Arc_ptr );
+
+ private Bin makePatchBoundary( const float[] from, const float[] to ) {
+ Bin ret = new Bin();
+ float smin = from[0];
+ float smax = to[0];
+ float tmin = from[1];
+ float tmax = to[1];
+
+ pjarc = 0;
+
+ Arc jarc = new 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;
+ }
+
+ /*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_..().
+ */
+ private float domain_distance_u_rate;
+ private float domain_distance_v_rate;
+ private int is_domain_distance_sampling;
+
+}