diff options
Diffstat (limited to 'src/net')
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; + +} |