curve.cc revision f220fa62
1/* 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: 9** 10** http://oss.sgi.com/projects/FreeB 11** 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. 17** 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. 23** 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. 33*/ 34 35/* 36 * curve.c++ 37 * 38 */ 39 40#include "glimports.h" 41#include "myassert.h" 42#include "mystdio.h" 43#include "mymath.h" 44#include "curve.h" 45#include "mapdesc.h" 46#include "types.h" 47#include "quilt.h" 48#include "nurbsconsts.h" 49 50/*-------------------------------------------------------------------------- 51 * Curve::Curve - copy curve from quilt and transform control points 52 *-------------------------------------------------------------------------- 53 */ 54 55Curve::Curve( Quilt_ptr geo, REAL pta, REAL ptb, Curve *c ) 56{ 57 mapdesc = geo->mapdesc; 58 next = c; 59 needsSampling = mapdesc->isRangeSampling() ? 1 : 0; 60 cullval = mapdesc->isCulling() ? CULL_ACCEPT : CULL_TRIVIAL_ACCEPT; 61 order = geo->qspec[0].order; 62 stride = MAXCOORDS; 63 for( int i = 0; i < MAXORDER * MAXCOORDS; i++ ) { 64 cpts[i] = 0; 65 spts[i] = 0; 66 } 67 stepsize = 0; 68 minstepsize = 0; 69 70 REAL *ps = geo->cpts; 71 Quiltspec_ptr qs = geo->qspec; 72 ps += qs->offset; 73 ps += qs->index * qs->order * qs->stride; 74 75 if( needsSampling ) 76 mapdesc->xformSampling( ps, qs->order, qs->stride, spts, stride ); 77 78 if( cullval == CULL_ACCEPT ) 79 mapdesc->xformCulling( ps, qs->order, qs->stride, cpts, stride ); 80 81 /* set untrimmed curve range */ 82 range[0] = qs->breakpoints[qs->index]; 83 range[1] = qs->breakpoints[qs->index+1]; 84 range[2] = range[1] - range[0]; 85 86 if( range[0] != pta ) { 87 Curve lower( *this, pta, 0 ); 88 lower.next = next; 89 *this = lower; 90 } 91 if( range[1] != ptb ) { 92 Curve lower( *this, ptb, 0 ); 93 } 94} 95 96/*-------------------------------------------------------------------------- 97 * Curve::Curve - subdivide a curve along an isoparametric line 98 *-------------------------------------------------------------------------- 99 */ 100 101Curve::Curve( Curve& upper, REAL value, Curve *c ) 102{ 103 Curve &lower = *this; 104 105 lower.next = c; 106 lower.mapdesc = upper.mapdesc; 107 lower.needsSampling = upper.needsSampling; 108 lower.order = upper.order; 109 lower.stride = upper.stride; 110 lower.cullval = upper.cullval; 111 112 REAL d = (value - upper.range[0]) / upper.range[2]; 113 114 if( needsSampling ) 115 mapdesc->subdivide( upper.spts, lower.spts, d, upper.stride, upper.order ); 116 117 if( cullval == CULL_ACCEPT ) 118 mapdesc->subdivide( upper.cpts, lower.cpts, d, upper.stride, upper.order ); 119 120 lower.range[0] = upper.range[0]; 121 lower.range[1] = value; 122 lower.range[2] = value - upper.range[0]; 123 upper.range[0] = value; 124 upper.range[2] = upper.range[1] - value; 125} 126 127 128/*-------------------------------------------------------------------------- 129 * Curve::clamp - clamp the sampling rate to a given maximum 130 *-------------------------------------------------------------------------- 131 */ 132 133void 134Curve::clamp( void ) 135{ 136 if( stepsize < minstepsize ) 137 stepsize = mapdesc->clampfactor * minstepsize; 138} 139 140void 141Curve::setstepsize( REAL max ) 142{ 143 stepsize = ( max >= 1.0 ) ? (range[2] / max) : range[2]; 144 minstepsize = stepsize; 145} 146 147void 148Curve::getstepsize( void ) 149{ 150 minstepsize= 0; 151 152 if( mapdesc->isConstantSampling() ) { 153 // fixed number of samples per patch in each direction 154 // maxrate is number of s samples per patch 155 setstepsize( mapdesc->maxrate ); 156 } else if( mapdesc->isDomainSampling() ) { 157 // maxrate is number of s samples per unit s length of domain 158 setstepsize( mapdesc->maxrate * range[2] ); 159 } else { 160 // upper bound on path length between sample points 161 162 assert( order <= MAXORDER ); 163 164 /* points have been transformed, therefore they are homogeneous */ 165 REAL tmp[MAXORDER][MAXCOORDS]; 166 const int tstride = sizeof(tmp[0]) / sizeof(REAL); 167 int val = mapdesc->project( spts, stride, &tmp[0][0], tstride, order ); 168 169 if( val == 0 ) { 170 // control points cross infinity, therefore derivatives are undefined 171 setstepsize( mapdesc->maxrate ); 172 } else { 173 REAL t = mapdesc->getProperty( N_PIXEL_TOLERANCE ); 174 if( mapdesc->isParametricDistanceSampling() ) { 175 REAL d = mapdesc->calcPartialVelocity( &tmp[0][0], tstride, order, 2, range[2] ); 176 stepsize = (d > 0.0) ? sqrtf( 8.0 * t / d ) : range[2]; 177 minstepsize = ( mapdesc->maxrate > 0.0 ) ? (range[2] / mapdesc->maxrate) : 0.0; 178 } else if( mapdesc->isPathLengthSampling() ) { 179 // t is upper bound on path (arc) length 180 REAL d = mapdesc->calcPartialVelocity( &tmp[0][0], tstride, order, 1, range[2] ); 181 stepsize = ( d > 0.0 ) ? (t / d) : range[2]; 182 minstepsize = ( mapdesc->maxrate > 0.0 ) ? (range[2] / mapdesc->maxrate) : 0.0; 183 } else { 184 // control points cross infinity, therefore partials are undefined 185 setstepsize( mapdesc->maxrate ); 186 } 187 } 188 } 189} 190 191int 192Curve::needsSamplingSubdivision( void ) 193{ 194 return ( stepsize < minstepsize ) ? 1 : 0; 195} 196 197int 198Curve::cullCheck( void ) 199{ 200 if( cullval == CULL_ACCEPT ) 201 cullval = mapdesc->cullCheck( cpts, order, stride ); 202 return cullval; 203} 204 205