2 ** License Applicability. Except to the extent portions of this file are
3 ** made subject to an alternative license as permitted in the SGI Free
4 ** Software License B, Version 1.1 (the "License"), the contents of this
5 ** file are subject only to the provisions of the License. You may not use
6 ** this file except in compliance with the License. You may obtain a copy
7 ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
8 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
10 ** http://oss.sgi.com/projects/FreeB
12 ** Note that, as provided in the License, the Software is distributed on an
13 ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
14 ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
15 ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
16 ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
18 ** Original Code. The Original Code is: OpenGL Sample Implementation,
19 ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
20 ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
21 ** Copyright in any portions created by third parties is as indicated
22 ** elsewhere herein. All Rights Reserved.
24 ** Additional Notice Provisions: The application programming interfaces
25 ** established by SGI in conjunction with the Original Code are The
26 ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
27 ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
28 ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
29 ** Window System(R) (Version 1.3), released October 19, 1998. This software
30 ** was created using the OpenGL(R) version 1.2.1 Sample Implementation
31 ** published by SGI, but has not been independently verified as being
32 ** compliant with the OpenGL(R) version 1.2.1 Specification.
38 * $Date: 2001/11/29 16:16:55 $ $Revision: 1.2 $
39 * $Header: /home/krh/git/sync/mesa-cvs-repo/Mesa/src/glu/sgi/libnurbs/internals/mapdesc.cc,v 1.2 2001/11/29 16:16:55 kschultz Exp $
43 #include "glimports.h"
49 #include "nurbsconsts.h"
52 Mapdesc::Mapdesc( long _type, int _israt, int _ncoords, Backend& b )
58 hcoords = _ncoords + (_israt ? 0 : 1 );
59 inhcoords = _ncoords - (_israt ? 1 : 0 );
60 mask = ((1<<(inhcoords*2))-1);
63 assert( hcoords <= MAXCOORDS );
64 assert( inhcoords >= 1 );
66 pixel_tolerance = 1.0;
67 error_tolerance = 1.0;
68 bbox_subdividing = N_NOBBOXSUBDIVISION;
69 culling_method = N_NOCULLING;
70 sampling_method = N_NOSAMPLING;
71 clampfactor = N_NOCLAMPING;
72 minsavings = N_NOSAVINGSSUBDIVISION;
75 maxrate = ( s_steps < 0.0 ) ? 0.0 : s_steps;
76 maxsrate = ( s_steps < 0.0 ) ? 0.0 : s_steps;
77 maxtrate = ( t_steps < 0.0 ) ? 0.0 : t_steps;
81 for( int i = 0; i != inhcoords; i++ )
86 Mapdesc::setBboxsize( INREAL *mat )
88 for( int i = 0; i != inhcoords; i++ )
89 bboxsize[i] = (REAL) mat[i];
93 Mapdesc::identify( REAL dest[MAXCOORDS][MAXCOORDS] )
95 memset( dest, 0, sizeof( dest ) );
96 for( int i=0; i != hcoords; i++ )
101 Mapdesc::surfbbox( REAL bb[2][MAXCOORDS] )
103 backend.surfbbox( type, bb[0], bb[1] );
107 Mapdesc::copy( REAL dest[MAXCOORDS][MAXCOORDS], long n, INREAL *src,
108 long rstride, long cstride )
111 for( int i=0; i != n; i++ )
112 for( int j=0; j != n; j++ )
113 dest[i][j] = src[i*rstride + j*cstride];
116 /*--------------------------------------------------------------------------
117 * copyPt - copy a homogeneous point
118 *--------------------------------------------------------------------------
121 Mapdesc::copyPt( REAL *d, REAL *s )
123 assert( hcoords > 0 );
151 memcpy( d, s, hcoords * sizeof( REAL ) );
156 /*--------------------------------------------------------------------------
157 * sumPt - compute affine combination of two homogeneous points
158 *--------------------------------------------------------------------------
161 Mapdesc::sumPt( REAL *dst, REAL *src1, REAL *src2, register REAL alpha, register REAL beta )
163 assert( hcoords > 0 );
166 dst[3] = src1[3] * alpha + src2[3] * beta;
167 dst[2] = src1[2] * alpha + src2[2] * beta;
168 dst[1] = src1[1] * alpha + src2[1] * beta;
169 dst[0] = src1[0] * alpha + src2[0] * beta;
172 dst[2] = src1[2] * alpha + src2[2] * beta;
173 dst[1] = src1[1] * alpha + src2[1] * beta;
174 dst[0] = src1[0] * alpha + src2[0] * beta;
177 dst[1] = src1[1] * alpha + src2[1] * beta;
178 dst[0] = src1[0] * alpha + src2[0] * beta;
181 dst[0] = src1[0] * alpha + src2[0] * beta;
184 dst[4] = src1[4] * alpha + src2[4] * beta;
185 dst[3] = src1[3] * alpha + src2[3] * beta;
186 dst[2] = src1[2] * alpha + src2[2] * beta;
187 dst[1] = src1[1] * alpha + src2[1] * beta;
188 dst[0] = src1[0] * alpha + src2[0] * beta;
191 for( int i = 0; i != hcoords; i++ )
192 dst[i] = src1[i] * alpha + src2[i] * beta;
198 /*--------------------------------------------------------------------------
199 * clipbits - compute bit-vector indicating point/window position
200 * of a (transformed) homogeneous point
201 *--------------------------------------------------------------------------
204 Mapdesc::clipbits( REAL *p )
206 assert( inhcoords >= 0 );
207 assert( inhcoords <= 3 );
209 register int nc = inhcoords;
210 register REAL pw = p[nc];
211 register REAL nw = -pw;
212 register unsigned int bits = 0;
214 if( pw == 0.0 ) return mask;
219 if( p[2] <= pw ) bits |= (1<<5);
220 if( p[2] >= nw ) bits |= (1<<4);
221 if( p[1] <= pw ) bits |= (1<<3);
222 if( p[1] >= nw ) bits |= (1<<2);
223 if( p[0] <= pw ) bits |= (1<<1);
224 if( p[0] >= nw ) bits |= (1<<0);
227 if( p[1] <= pw ) bits |= (1<<3);
228 if( p[1] >= nw ) bits |= (1<<2);
229 if( p[0] <= pw ) bits |= (1<<1);
230 if( p[0] >= nw ) bits |= (1<<0);
233 if( p[0] <= pw ) bits |= (1<<1);
234 if( p[0] >= nw ) bits |= (1<<0);
238 for( int i=0; i<nc; i++ ) {
239 if( p[i] >= nw ) bits |= bit;
241 if( p[i] <= pw ) bits |= bit;
251 if( p[2] <= nw ) bits |= (1<<5);
252 if( p[2] >= pw ) bits |= (1<<4);
253 if( p[1] <= nw ) bits |= (1<<3);
254 if( p[1] >= pw ) bits |= (1<<2);
255 if( p[0] <= nw ) bits |= (1<<1);
256 if( p[0] >= pw ) bits |= (1<<0);
259 if( p[1] <= nw ) bits |= (1<<3);
260 if( p[1] >= pw ) bits |= (1<<2);
261 if( p[0] <= nw ) bits |= (1<<1);
262 if( p[0] >= pw ) bits |= (1<<0);
265 if( p[0] <= nw ) bits |= (1<<1);
266 if( p[0] >= pw ) bits |= (1<<0);
270 for( int i=0; i<nc; i++ ) {
271 if( p[i] >= pw ) bits |= bit;
273 if( p[i] <= nw ) bits |= bit;
284 /*--------------------------------------------------------------------------
285 * xformRational - transform a homogeneous point
286 *--------------------------------------------------------------------------
289 Mapdesc::xformRational( Maxmatrix mat, REAL *d, REAL *s )
291 assert( hcoords >= 0 );
297 d[0] = x*mat[0][0]+y*mat[1][0]+z*mat[2][0];
298 d[1] = x*mat[0][1]+y*mat[1][1]+z*mat[2][1];
299 d[2] = x*mat[0][2]+y*mat[1][2]+z*mat[2][2];
300 } else if( hcoords == 4 ) {
305 d[0] = x*mat[0][0]+y*mat[1][0]+z*mat[2][0]+w*mat[3][0];
306 d[1] = x*mat[0][1]+y*mat[1][1]+z*mat[2][1]+w*mat[3][1];
307 d[2] = x*mat[0][2]+y*mat[1][2]+z*mat[2][2]+w*mat[3][2];
308 d[3] = x*mat[0][3]+y*mat[1][3]+z*mat[2][3]+w*mat[3][3];
310 for( int i=0; i != hcoords; i++ ) {
312 for( int j = 0; j != hcoords; j++ )
313 d[i] += s[j] * mat[j][i];
318 /*--------------------------------------------------------------------------
319 * xformNonrational - transform a inhomogeneous point to a homogeneous point
320 *--------------------------------------------------------------------------
323 Mapdesc::xformNonrational( Maxmatrix mat, REAL *d, REAL *s )
325 if( inhcoords == 2 ) {
328 d[0] = x*mat[0][0]+y*mat[1][0]+mat[2][0];
329 d[1] = x*mat[0][1]+y*mat[1][1]+mat[2][1];
330 d[2] = x*mat[0][2]+y*mat[1][2]+mat[2][2];
331 } else if( inhcoords == 3 ) {
335 d[0] = x*mat[0][0]+y*mat[1][0]+z*mat[2][0]+mat[3][0];
336 d[1] = x*mat[0][1]+y*mat[1][1]+z*mat[2][1]+mat[3][1];
337 d[2] = x*mat[0][2]+y*mat[1][2]+z*mat[2][2]+mat[3][2];
338 d[3] = x*mat[0][3]+y*mat[1][3]+z*mat[2][3]+mat[3][3];
340 assert( inhcoords >= 0 );
341 for( int i=0; i != hcoords; i++ ) {
342 d[i] = mat[inhcoords][i];
343 for( int j = 0; j < inhcoords; j++ )
344 d[i] += s[j] * mat[j][i];
349 /*--------------------------------------------------------------------------
350 * xformAndCullCheck - transform a set of points that may be EITHER
351 * homogeneous or inhomogeneous depending on the map description and
352 * check if they are either completely inside, completely outside,
353 * or intersecting the viewing frustrum.
354 *--------------------------------------------------------------------------
357 Mapdesc::xformAndCullCheck(
358 REAL *pts, int uorder, int ustride, int vorder, int vstride )
360 assert( uorder > 0 );
361 assert( vorder > 0 );
363 unsigned int inbits = mask;
364 unsigned int outbits = 0;
367 for( REAL *pend = p + uorder * ustride; p != pend; p += ustride ) {
369 for( REAL *qend = q + vorder * vstride; q != qend; q += vstride ) {
370 REAL cpts[MAXCOORDS];
371 xformCulling( cpts, q );
372 unsigned int bits = clipbits( cpts );
375 if( ( outbits == (unsigned int)mask ) && ( inbits != (unsigned int)mask ) ) return CULL_ACCEPT;
379 if( outbits != (unsigned int)mask ) {
380 return CULL_TRIVIAL_REJECT;
381 } else if( inbits == (unsigned int)mask ) {
382 return CULL_TRIVIAL_ACCEPT;
388 /*--------------------------------------------------------------------------
389 * cullCheck - check if a set of homogeneous transformed points are
390 * either completely inside, completely outside,
391 * or intersecting the viewing frustrum.
392 *--------------------------------------------------------------------------
395 Mapdesc::cullCheck( REAL *pts, int uorder, int ustride, int vorder, int vstride )
397 unsigned int inbits = mask;
398 unsigned int outbits = 0;
401 for( REAL *pend = p + uorder * ustride; p != pend; p += ustride ) {
403 for( REAL *qend = q + vorder * vstride; q != qend; q += vstride ) {
404 unsigned int bits = clipbits( q );
407 if( ( outbits == (unsigned int)mask ) && ( inbits != (unsigned int)mask ) ) return CULL_ACCEPT;
411 if( outbits != (unsigned int)mask ) {
412 return CULL_TRIVIAL_REJECT;
413 } else if( inbits == (unsigned int)mask ) {
414 return CULL_TRIVIAL_ACCEPT;
420 /*--------------------------------------------------------------------------
421 * cullCheck - check if a set of homogeneous transformed points are
422 * either completely inside, completely outside,
423 * or intersecting the viewing frustrum.
424 *--------------------------------------------------------------------------
427 Mapdesc::cullCheck( REAL *pts, int order, int stride )
429 unsigned int inbits = mask;
430 unsigned int outbits = 0;
433 for( REAL *pend = p + order * stride; p != pend; p += stride ) {
434 unsigned int bits = clipbits( p );
437 if( ( outbits == (unsigned int)mask ) && ( inbits != (unsigned int)mask ) ) return CULL_ACCEPT;
440 if( outbits != (unsigned int)mask ) {
441 return CULL_TRIVIAL_REJECT;
442 } else if( inbits == (unsigned int)mask ) {
443 return CULL_TRIVIAL_ACCEPT;
449 /*--------------------------------------------------------------------------
450 * xformSampling - transform a set of points that may be EITHER
451 * homogeneous or inhomogeneous depending on the map description
452 * into sampling space
453 *--------------------------------------------------------------------------
456 Mapdesc::xformSampling( REAL *pts, int order, int stride, REAL *sp, int outstride )
458 xformMat( smat, pts, order, stride, sp, outstride );
462 Mapdesc::xformBounding( REAL *pts, int order, int stride, REAL *sp, int outstride )
464 xformMat( bmat, pts, order, stride, sp, outstride );
467 /*--------------------------------------------------------------------------
468 * xformCulling - transform a set of points that may be EITHER
469 * homogeneous or inhomogeneous depending on the map description
471 *--------------------------------------------------------------------------
474 Mapdesc::xformCulling( REAL *pts, int order, int stride, REAL *cp, int outstride )
476 xformMat( cmat, pts, order, stride, cp, outstride );
479 /*--------------------------------------------------------------------------
480 * xformCulling - transform a set of points that may be EITHER
481 * homogeneous or inhomogeneous depending on the map description
483 *--------------------------------------------------------------------------
486 Mapdesc::xformCulling( REAL *pts,
487 int uorder, int ustride,
488 int vorder, int vstride,
489 REAL *cp, int outustride, int outvstride )
491 xformMat( cmat, pts, uorder, ustride, vorder, vstride, cp, outustride, outvstride );
494 /*--------------------------------------------------------------------------
495 * xformSampling - transform a set of points that may be EITHER
496 * homogeneous or inhomogeneous depending on the map description
497 * into sampling space
498 *--------------------------------------------------------------------------
501 Mapdesc::xformSampling( REAL *pts,
502 int uorder, int ustride,
503 int vorder, int vstride,
504 REAL *sp, int outustride, int outvstride )
506 xformMat( smat, pts, uorder, ustride, vorder, vstride, sp, outustride, outvstride );
510 Mapdesc::xformBounding( REAL *pts,
511 int uorder, int ustride,
512 int vorder, int vstride,
513 REAL *sp, int outustride, int outvstride )
515 xformMat( bmat, pts, uorder, ustride, vorder, vstride, sp, outustride, outvstride );
528 REAL *pend = pts + order * stride;
529 for( REAL *p = pts ; p != pend; p += stride ) {
530 xformRational( mat, cp, p );
534 REAL *pend = pts + order * stride;
535 for( REAL *p = pts ; p != pend; p += stride ) {
536 xformNonrational( mat, cp, p );
543 Mapdesc::xformMat( Maxmatrix mat, REAL *pts,
544 int uorder, int ustride,
545 int vorder, int vstride,
546 REAL *cp, int outustride, int outvstride )
549 REAL *pend = pts + uorder * ustride;
550 for( REAL *p = pts ; p != pend; p += ustride ) {
552 REAL *qend = p + vorder * vstride;
553 for( REAL *q = p; q != qend; q += vstride ) {
554 xformRational( mat, cpts2, q );
560 REAL *pend = pts + uorder * ustride;
561 for( REAL *p = pts ; p != pend; p += ustride ) {
563 REAL *qend = p + vorder * vstride;
564 for( REAL *q = p; q != qend; q += vstride ) {
565 xformNonrational( mat, cpts2, q );
573 /*--------------------------------------------------------------------------
574 * subdivide - subdivide a curve along an isoparametric line
575 *--------------------------------------------------------------------------
579 Mapdesc::subdivide( REAL *src, REAL *dst, REAL v, int stride, int order )
583 for( REAL *send=src+stride*order; src!=send; send-=stride, dst+=stride ) {
585 REAL *qpnt = src + stride;
586 for( REAL *qp=src; qpnt!=send; qp=qpnt, qpnt+=stride )
587 sumPt( qp, qp, qpnt, mv, v );
591 /*--------------------------------------------------------------------------
592 * subdivide - subdivide a patch along an isoparametric line
593 *--------------------------------------------------------------------------
597 Mapdesc::subdivide( REAL *src, REAL *dst, REAL v,
598 int so, int ss, int to, int ts )
602 for( REAL *slast = src+ss*so; src != slast; src += ss, dst += ss ) {
605 for( REAL *send = src+ts*to; sp != send; send -= ts, dp += ts ) {
608 for( REAL *qpnt = sp+ts; qpnt != send; qp = qpnt, qpnt += ts )
609 sumPt( qp, qp, qpnt, mv, v );
615 #define sign(x) ((x > 0) ? 1 : ((x < 0.0) ? -1 : 0))
617 /*--------------------------------------------------------------------------
618 * project - project a set of homogeneous coordinates into inhomogeneous ones
619 *--------------------------------------------------------------------------
622 Mapdesc::project( REAL *src, int rstride, int cstride,
623 REAL *dest, int trstride, int tcstride,
624 int nrows, int ncols )
626 int s = sign( src[inhcoords] );
627 REAL *rlast = src + nrows * rstride;
629 for( REAL *rptr=src; rptr != rlast; rptr+=rstride, trptr+=trstride ) {
630 REAL *clast = rptr + ncols * cstride;
632 for( REAL *cptr = rptr; cptr != clast; cptr+=cstride, tcptr+=tcstride ) {
633 REAL *coordlast = cptr + inhcoords;
634 if( sign( *coordlast ) != s ) return 0;
635 REAL *tcoord = tcptr;
636 for( REAL *coord = cptr; coord != coordlast; coord++, tcoord++ ) {
637 *tcoord = *coord / *coordlast;
644 /*--------------------------------------------------------------------------
645 * project - project a set of homogeneous coordinates into inhomogeneous ones
646 *--------------------------------------------------------------------------
649 Mapdesc::project( REAL *src, int stride, REAL *dest, int tstride, int ncols )
651 int s = sign( src[inhcoords] );
653 REAL *clast = src + ncols * stride;
654 for( REAL *cptr = src, *tcptr = dest; cptr != clast; cptr+=stride, tcptr+=tstride ) {
655 REAL *coordlast = cptr + inhcoords;
656 if( sign( *coordlast ) != s ) return 0;
657 for( REAL *coord = cptr, *tcoord = tcptr; coord != coordlast; coord++, tcoord++ )
658 *tcoord = *coord / *coordlast;
671 REAL bb[2][MAXCOORDS] )
673 REAL bbpts[MAXORDER][MAXORDER][MAXCOORDS];
674 const int trstride = sizeof(bbpts[0]) / sizeof(REAL);
675 const int tcstride = sizeof(bbpts[0][0]) / sizeof(REAL);
677 // points have been transformed, therefore they are homogeneous
679 int val = project( p, rstride, cstride,
680 &bbpts[0][0][0], trstride, tcstride, nrows, ncols );
681 if( val == 0 ) return -1;
683 // compute bounding box
684 bbox( bb, &bbpts[0][0][0], trstride, tcstride, nrows, ncols );
686 // find out if bounding box can't fit in unit cube
687 if( bbox_subdividing == N_BBOXROUND ) {
688 for( int k=0; k != inhcoords; k++ )
689 if( ceilf(bb[1][k]) - floorf(bb[0][k]) > bboxsize[k] ) return 1;
691 for( int k=0; k != inhcoords; k++ )
692 if( bb[1][k] - bb[0][k] > bboxsize[k] ) return 1;
699 REAL bb[2][MAXCOORDS],
707 for( k=0; k != inhcoords; k++ )
708 bb[0][k] = bb[1][k] = p[k];
710 for( int i=0; i != nrows; i++ )
711 for( int j=0; j != ncols; j++ )
712 for( k=0; k != inhcoords; k++ ) {
713 REAL x = p[i*rstride + j*cstride + k];
714 if( x < bb[0][k] ) bb[0][k] = x;
715 else if( x > bb[1][k] ) bb[1][k] = x;
719 /*--------------------------------------------------------------------------
720 * calcVelocityRational - calculate upper bound on first partial derivative
721 * of a homogeneous set of points and bounds on each row of points.
722 *--------------------------------------------------------------------------
725 Mapdesc::calcVelocityRational( REAL *p, int stride, int ncols )
727 REAL tmp[MAXORDER][MAXCOORDS];
729 assert( ncols <= MAXORDER );
731 const int tstride = sizeof(tmp[0]) / sizeof(REAL);
733 if( project( p, stride, &tmp[0][0], tstride, ncols ) ) {
734 return calcPartialVelocity( &tmp[0][0], tstride, ncols, 1, 1.0 );
736 return calcPartialVelocity( &tmp[0][0], tstride, ncols, 1, 1.0 );
740 /*--------------------------------------------------------------------------
741 * calcVelocityNonrational - calculate upper bound on first partial
742 * derivative of a inhomogeneous set of points.
743 *--------------------------------------------------------------------------
746 Mapdesc::calcVelocityNonrational( REAL *pts, int stride, int ncols )
748 return calcPartialVelocity( pts, stride, ncols, 1, 1.0 );
752 Mapdesc::isProperty( long property )
754 switch ( property ) {
755 case N_PIXEL_TOLERANCE:
756 case N_ERROR_TOLERANCE:
758 case N_BBOX_SUBDIVIDING:
761 case N_SAMPLINGMETHOD:
771 Mapdesc::getProperty( long property )
773 switch ( property ) {
774 case N_PIXEL_TOLERANCE:
775 return pixel_tolerance;
776 case N_ERROR_TOLERANCE:
777 return error_tolerance;
779 return culling_method;
780 case N_BBOX_SUBDIVIDING:
781 return bbox_subdividing;
786 case N_SAMPLINGMETHOD:
787 return sampling_method;
794 return -1; //not necessary, needed to shut up compiler
799 Mapdesc::setProperty( long property, REAL value )
802 switch ( property ) {
803 case N_PIXEL_TOLERANCE:
804 pixel_tolerance = value;
806 case N_ERROR_TOLERANCE:
807 error_tolerance = value;
810 culling_method = value;
812 case N_BBOX_SUBDIVIDING:
813 if( value <= 0.0 ) value = N_NOBBOXSUBDIVISION;
814 bbox_subdividing = value;
817 if( value < 0.0 ) value = 0.0;
819 maxrate = ( value < 0.0 ) ? 0.0 : value;
820 maxsrate = ( value < 0.0 ) ? 0.0 : value;
823 if( value < 0.0 ) value = 0.0;
825 maxtrate = ( value < 0.0 ) ? 0.0 : value;
827 case N_SAMPLINGMETHOD:
828 sampling_method = value;
831 if( value <= 0.0 ) value = N_NOCLAMPING;
835 if( value <= 0.0 ) value = N_NOSAVINGSSUBDIVISION;