1f220fa62Smrg/* 2f220fa62Smrg** License Applicability. Except to the extent portions of this file are 3f220fa62Smrg** made subject to an alternative license as permitted in the SGI Free 4f220fa62Smrg** Software License B, Version 1.1 (the "License"), the contents of this 5f220fa62Smrg** file are subject only to the provisions of the License. You may not use 6f220fa62Smrg** this file except in compliance with the License. You may obtain a copy 7f220fa62Smrg** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 8f220fa62Smrg** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: 9f220fa62Smrg** 10f220fa62Smrg** http://oss.sgi.com/projects/FreeB 11f220fa62Smrg** 12f220fa62Smrg** Note that, as provided in the License, the Software is distributed on an 13f220fa62Smrg** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS 14f220fa62Smrg** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND 15f220fa62Smrg** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A 16f220fa62Smrg** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. 17f220fa62Smrg** 18f220fa62Smrg** Original Code. The Original Code is: OpenGL Sample Implementation, 19f220fa62Smrg** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, 20f220fa62Smrg** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. 21f220fa62Smrg** Copyright in any portions created by third parties is as indicated 22f220fa62Smrg** elsewhere herein. All Rights Reserved. 23f220fa62Smrg** 24f220fa62Smrg** Additional Notice Provisions: The application programming interfaces 25f220fa62Smrg** established by SGI in conjunction with the Original Code are The 26f220fa62Smrg** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released 27f220fa62Smrg** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version 28f220fa62Smrg** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X 29f220fa62Smrg** Window System(R) (Version 1.3), released October 19, 1998. This software 30f220fa62Smrg** was created using the OpenGL(R) version 1.2.1 Sample Implementation 31f220fa62Smrg** published by SGI, but has not been independently verified as being 32f220fa62Smrg** compliant with the OpenGL(R) version 1.2.1 Specification. 33f220fa62Smrg*/ 34f220fa62Smrg 35f220fa62Smrg/* 36f220fa62Smrg * arctessellator.c++ 37f220fa62Smrg * 38f220fa62Smrg */ 39f220fa62Smrg 40f220fa62Smrg#include "glimports.h" 41f220fa62Smrg#include "mystdio.h" 42f220fa62Smrg#include "myassert.h" 43f220fa62Smrg#include "arctess.h" 44f220fa62Smrg#include "bufpool.h" 45f220fa62Smrg#include "simplemath.h" 46f220fa62Smrg#include "bezierarc.h" 47f220fa62Smrg#include "trimvertex.h" 48f220fa62Smrg#include "trimvertpool.h" 49f220fa62Smrg 50f220fa62Smrg#define NOELIMINATION 51f220fa62Smrg 52f220fa62Smrg#define steps_function(large, small, rate) (max(1, 1+ (int) ((large-small)/rate))); 53f220fa62Smrg 54f220fa62Smrg/*----------------------------------------------------------------------------- 55f220fa62Smrg * ArcTessellator - construct an ArcTessellator 56f220fa62Smrg *----------------------------------------------------------------------------- 57f220fa62Smrg */ 58f220fa62Smrg 59f220fa62SmrgArcTessellator::ArcTessellator( TrimVertexPool& t, Pool& p ) 60f220fa62Smrg : pwlarcpool(p), trimvertexpool(t) 61f220fa62Smrg{ 62f220fa62Smrg} 63f220fa62Smrg 64f220fa62Smrg/*----------------------------------------------------------------------------- 65f220fa62Smrg * ~ArcTessellator - destroy an ArcTessellator 66f220fa62Smrg *----------------------------------------------------------------------------- 67f220fa62Smrg */ 68f220fa62Smrg 69f220fa62SmrgArcTessellator::~ArcTessellator( void ) 70f220fa62Smrg{ 71f220fa62Smrg} 72f220fa62Smrg 73f220fa62Smrg/*----------------------------------------------------------------------------- 74f220fa62Smrg * bezier - construct a bezier arc and attach it to an Arc 75f220fa62Smrg *----------------------------------------------------------------------------- 76f220fa62Smrg */ 77f220fa62Smrg 78f220fa62Smrgvoid 79f220fa62SmrgArcTessellator::bezier( Arc *arc, REAL s1, REAL s2, REAL t1, REAL t2 ) 80f220fa62Smrg{ 81f220fa62Smrg assert( arc != 0 ); 82f220fa62Smrg assert( ! arc->isTessellated() ); 83f220fa62Smrg 84f220fa62Smrg#ifndef NDEBUG 85f220fa62Smrg switch( arc->getside() ) { 86f220fa62Smrg case arc_left: 87f220fa62Smrg assert( s1 == s2 ); 88f220fa62Smrg assert( t2 < t1 ); 89f220fa62Smrg break; 90f220fa62Smrg case arc_right: 91f220fa62Smrg assert( s1 == s2 ); 92f220fa62Smrg assert( t1 < t2 ); 93f220fa62Smrg break; 94f220fa62Smrg case arc_top: 95f220fa62Smrg assert( t1 == t2 ); 96f220fa62Smrg assert( s2 < s1 ); 97f220fa62Smrg break; 98f220fa62Smrg case arc_bottom: 99f220fa62Smrg assert( t1 == t2 ); 100f220fa62Smrg assert( s1 < s2 ); 101f220fa62Smrg break; 102f220fa62Smrg case arc_none: 103f220fa62Smrg (void) abort(); 104f220fa62Smrg break; 105f220fa62Smrg } 106f220fa62Smrg#endif 107f220fa62Smrg 108f220fa62Smrg TrimVertex *p = trimvertexpool.get(2); 109f220fa62Smrg arc->pwlArc = new(pwlarcpool) PwlArc( 2, p ); 110f220fa62Smrg p[0].param[0] = s1; 111f220fa62Smrg p[0].param[1] = t1; 112f220fa62Smrg p[1].param[0] = s2; 113f220fa62Smrg p[1].param[1] = t2; 114f220fa62Smrg assert( (s1 == s2) || (t1 == t2) ); 115f220fa62Smrg arc->setbezier(); 116f220fa62Smrg} 117f220fa62Smrg 118f220fa62Smrg 119f220fa62Smrg/*----------------------------------------------------------------------------- 120f220fa62Smrg * pwl_left - construct a left boundary pwl arc and attach it to an arc 121f220fa62Smrg *----------------------------------------------------------------------------- 122f220fa62Smrg */ 123f220fa62Smrg 124f220fa62Smrgvoid 125f220fa62SmrgArcTessellator::pwl_left( Arc *arc, REAL s, REAL t1, REAL t2, REAL rate ) 126f220fa62Smrg{ 127f220fa62Smrg assert( t2 < t1 ); 128f220fa62Smrg 129f220fa62Smrg/* if(rate <= 0.06) rate = 0.06;*/ 130f220fa62Smrg/* int nsteps = 1 + (int) ((t1 - t2) / rate ); */ 131f220fa62Smrg int nsteps = steps_function(t1, t2, rate); 132f220fa62Smrg 133f220fa62Smrg 134f220fa62Smrg REAL stepsize = (t1 - t2) / (REAL) nsteps; 135f220fa62Smrg 136f220fa62Smrg TrimVertex *newvert = trimvertexpool.get( nsteps+1 ); 137f220fa62Smrg int i; 138f220fa62Smrg for( i = nsteps; i > 0; i-- ) { 139f220fa62Smrg newvert[i].param[0] = s; 140f220fa62Smrg newvert[i].param[1] = t2; 141f220fa62Smrg t2 += stepsize; 142f220fa62Smrg } 143f220fa62Smrg newvert[i].param[0] = s; 144f220fa62Smrg newvert[i].param[1] = t1; 145f220fa62Smrg 146f220fa62Smrg arc->makeSide( new(pwlarcpool) PwlArc( nsteps+1, newvert ), arc_left ); 147f220fa62Smrg} 148f220fa62Smrg 149f220fa62Smrg/*----------------------------------------------------------------------------- 150f220fa62Smrg * pwl_right - construct a right boundary pwl arc and attach it to an arc 151f220fa62Smrg *----------------------------------------------------------------------------- 152f220fa62Smrg */ 153f220fa62Smrg 154f220fa62Smrgvoid 155f220fa62SmrgArcTessellator::pwl_right( Arc *arc, REAL s, REAL t1, REAL t2, REAL rate ) 156f220fa62Smrg{ 157f220fa62Smrg assert( t1 < t2 ); 158f220fa62Smrg 159f220fa62Smrg/* if(rate <= 0.06) rate = 0.06;*/ 160f220fa62Smrg 161f220fa62Smrg/* int nsteps = 1 + (int) ((t2 - t1) / rate ); */ 162f220fa62Smrg int nsteps = steps_function(t2,t1,rate); 163f220fa62Smrg REAL stepsize = (t2 - t1) / (REAL) nsteps; 164f220fa62Smrg 165f220fa62Smrg TrimVertex *newvert = trimvertexpool.get( nsteps+1 ); 166f220fa62Smrg int i; 167f220fa62Smrg for( i = 0; i < nsteps; i++ ) { 168f220fa62Smrg newvert[i].param[0] = s; 169f220fa62Smrg newvert[i].param[1] = t1; 170f220fa62Smrg t1 += stepsize; 171f220fa62Smrg } 172f220fa62Smrg newvert[i].param[0] = s; 173f220fa62Smrg newvert[i].param[1] = t2; 174f220fa62Smrg 175f220fa62Smrg arc->makeSide( new(pwlarcpool) PwlArc( nsteps+1, newvert ), arc_right ); 176f220fa62Smrg} 177f220fa62Smrg 178f220fa62Smrg 179f220fa62Smrg/*----------------------------------------------------------------------------- 180f220fa62Smrg * pwl_top - construct a top boundary pwl arc and attach it to an arc 181f220fa62Smrg *----------------------------------------------------------------------------- 182f220fa62Smrg */ 183f220fa62Smrg 184f220fa62Smrgvoid 185f220fa62SmrgArcTessellator::pwl_top( Arc *arc, REAL t, REAL s1, REAL s2, REAL rate ) 186f220fa62Smrg{ 187f220fa62Smrg assert( s2 < s1 ); 188f220fa62Smrg 189f220fa62Smrg/* if(rate <= 0.06) rate = 0.06;*/ 190f220fa62Smrg 191f220fa62Smrg/* int nsteps = 1 + (int) ((s1 - s2) / rate ); */ 192f220fa62Smrg int nsteps = steps_function(s1,s2,rate); 193f220fa62Smrg REAL stepsize = (s1 - s2) / (REAL) nsteps; 194f220fa62Smrg 195f220fa62Smrg TrimVertex *newvert = trimvertexpool.get( nsteps+1 ); 196f220fa62Smrg int i; 197f220fa62Smrg for( i = nsteps; i > 0; i-- ) { 198f220fa62Smrg newvert[i].param[0] = s2; 199f220fa62Smrg newvert[i].param[1] = t; 200f220fa62Smrg s2 += stepsize; 201f220fa62Smrg } 202f220fa62Smrg newvert[i].param[0] = s1; 203f220fa62Smrg newvert[i].param[1] = t; 204f220fa62Smrg 205f220fa62Smrg arc->makeSide( new(pwlarcpool) PwlArc( nsteps+1, newvert ), arc_top ); 206f220fa62Smrg} 207f220fa62Smrg 208f220fa62Smrg/*----------------------------------------------------------------------------- 209f220fa62Smrg * pwl_bottom - construct a bottom boundary pwl arc and attach it to an arc 210f220fa62Smrg *----------------------------------------------------------------------------- 211f220fa62Smrg */ 212f220fa62Smrg 213f220fa62Smrgvoid 214f220fa62SmrgArcTessellator::pwl_bottom( Arc *arc, REAL t, REAL s1, REAL s2, REAL rate ) 215f220fa62Smrg{ 216f220fa62Smrg assert( s1 < s2 ); 217f220fa62Smrg 218f220fa62Smrg/* if(rate <= 0.06) rate = 0.06;*/ 219f220fa62Smrg 220f220fa62Smrg/* int nsteps = 1 + (int) ((s2 - s1) / rate ); */ 221f220fa62Smrg int nsteps = steps_function(s2,s1,rate); 222f220fa62Smrg REAL stepsize = (s2 - s1) / (REAL) nsteps; 223f220fa62Smrg 224f220fa62Smrg TrimVertex *newvert = trimvertexpool.get( nsteps+1 ); 225f220fa62Smrg int i; 226f220fa62Smrg for( i = 0; i < nsteps; i++ ) { 227f220fa62Smrg newvert[i].param[0] = s1; 228f220fa62Smrg newvert[i].param[1] = t; 229f220fa62Smrg s1 += stepsize; 230f220fa62Smrg } 231f220fa62Smrg newvert[i].param[0] = s2; 232f220fa62Smrg newvert[i].param[1] = t; 233f220fa62Smrg 234f220fa62Smrg arc->makeSide( new(pwlarcpool) PwlArc( nsteps+1, newvert ), arc_bottom ); 235f220fa62Smrg} 236f220fa62Smrg 237f220fa62Smrg/*----------------------------------------------------------------------------- 238f220fa62Smrg * pwl - construct a pwl arc and attach it to an arc 239f220fa62Smrg *----------------------------------------------------------------------------- 240f220fa62Smrg */ 241f220fa62Smrg 242f220fa62Smrgvoid 243f220fa62SmrgArcTessellator::pwl( Arc *arc, REAL s1, REAL s2, REAL t1, REAL t2, REAL rate ) 244f220fa62Smrg{ 245f220fa62Smrg 246f220fa62Smrg/* if(rate <= 0.06) rate = 0.06;*/ 247f220fa62Smrg 248f220fa62Smrg int snsteps = 1 + (int) (glu_abs(s2 - s1) / rate ); 249f220fa62Smrg int tnsteps = 1 + (int) (glu_abs(t2 - t1) / rate ); 250f220fa62Smrg int nsteps = max(1,max( snsteps, tnsteps )); 251f220fa62Smrg 252f220fa62Smrg REAL sstepsize = (s2 - s1) / (REAL) nsteps; 253f220fa62Smrg REAL tstepsize = (t2 - t1) / (REAL) nsteps; 254f220fa62Smrg TrimVertex *newvert = trimvertexpool.get( nsteps+1 ); 255f220fa62Smrg long i; 256f220fa62Smrg for( i = 0; i < nsteps; i++ ) { 257f220fa62Smrg newvert[i].param[0] = s1; 258f220fa62Smrg newvert[i].param[1] = t1; 259f220fa62Smrg s1 += sstepsize; 260f220fa62Smrg t1 += tstepsize; 261f220fa62Smrg } 262f220fa62Smrg newvert[i].param[0] = s2; 263f220fa62Smrg newvert[i].param[1] = t2; 264f220fa62Smrg 265f220fa62Smrg /* arc->makeSide( new(pwlarcpool) PwlArc( nsteps+1, newvert ), arc_bottom ); */ 266f220fa62Smrg arc->pwlArc = new(pwlarcpool) PwlArc( nsteps+1, newvert ); 267f220fa62Smrg 268f220fa62Smrg arc->clearbezier(); 269f220fa62Smrg arc->clearside( ); 270f220fa62Smrg} 271f220fa62Smrg 272f220fa62Smrg 273f220fa62Smrg/*----------------------------------------------------------------------------- 274f220fa62Smrg * tessellateLinear - constuct a linear pwl arc and attach it to an Arc 275f220fa62Smrg *----------------------------------------------------------------------------- 276f220fa62Smrg */ 277f220fa62Smrg 278f220fa62Smrgvoid 279f220fa62SmrgArcTessellator::tessellateLinear( Arc *arc, REAL geo_stepsize, REAL arc_stepsize, int isrational ) 280f220fa62Smrg{ 281f220fa62Smrg assert( arc->pwlArc == NULL ); 282f220fa62Smrg REAL s1, s2, t1, t2; 283f220fa62Smrg 284f220fa62Smrg //we don't need to scale by arc_stepsize if the trim curve 285f220fa62Smrg //is piecewise linear. Reason: In pwl_right, pwl_left, pwl_top, pwl_left, 286f220fa62Smrg //and pwl, the nsteps is computed by deltaU (or V) /stepsize. 287f220fa62Smrg //The quantity deltaU/arc_stepsize doesn't have any meaning. And 288f220fa62Smrg //it causes problems: see bug 517641 289f220fa62Smrg REAL stepsize = geo_stepsize; /* * arc_stepsize*/; 290f220fa62Smrg 291f220fa62Smrg BezierArc *b = arc->bezierArc; 292f220fa62Smrg 293f220fa62Smrg if( isrational ) { 294f220fa62Smrg s1 = b->cpts[0] / b->cpts[2]; 295f220fa62Smrg t1 = b->cpts[1] / b->cpts[2]; 296f220fa62Smrg s2 = b->cpts[b->stride+0] / b->cpts[b->stride+2]; 297f220fa62Smrg t2 = b->cpts[b->stride+1] / b->cpts[b->stride+2]; 298f220fa62Smrg } else { 299f220fa62Smrg s1 = b->cpts[0]; 300f220fa62Smrg t1 = b->cpts[1]; 301f220fa62Smrg s2 = b->cpts[b->stride+0]; 302f220fa62Smrg t2 = b->cpts[b->stride+1]; 303f220fa62Smrg } 304f220fa62Smrg if( s1 == s2 ) 305f220fa62Smrg if( t1 < t2 ) 306f220fa62Smrg pwl_right( arc, s1, t1, t2, stepsize ); 307f220fa62Smrg else 308f220fa62Smrg pwl_left( arc, s1, t1, t2, stepsize ); 309f220fa62Smrg else if( t1 == t2 ) 310f220fa62Smrg if( s1 < s2 ) 311f220fa62Smrg pwl_bottom( arc, t1, s1, s2, stepsize ); 312f220fa62Smrg else 313f220fa62Smrg pwl_top( arc, t1, s1, s2, stepsize ); 314f220fa62Smrg else 315f220fa62Smrg pwl( arc, s1, s2, t1, t2, stepsize ); 316f220fa62Smrg} 317f220fa62Smrg 318f220fa62Smrg/*----------------------------------------------------------------------------- 319f220fa62Smrg * tessellateNonlinear - constuct a nonlinear pwl arc and attach it to an Arc 320f220fa62Smrg *----------------------------------------------------------------------------- 321f220fa62Smrg */ 322f220fa62Smrg 323f220fa62Smrgvoid 324f220fa62SmrgArcTessellator::tessellateNonlinear( Arc *arc, REAL geo_stepsize, REAL arc_stepsize, int isrational ) 325f220fa62Smrg{ 326f220fa62Smrg assert( arc->pwlArc == NULL ); 327f220fa62Smrg 328f220fa62Smrg REAL stepsize = geo_stepsize * arc_stepsize; 329f220fa62Smrg 330f220fa62Smrg BezierArc *bezierArc = arc->bezierArc; 331f220fa62Smrg 332f220fa62Smrg REAL size; //bounding box size of the curve in UV 333f220fa62Smrg { 334f220fa62Smrg int i,j; 335f220fa62Smrg REAL min_u, min_v, max_u,max_v; 336f220fa62Smrg min_u = max_u = bezierArc->cpts[0]; 337f220fa62Smrg min_v = max_v = bezierArc->cpts[1]; 338f220fa62Smrg for(i=1, j=bezierArc->stride; i<bezierArc->order; i++, j+= bezierArc->stride) 339f220fa62Smrg { 340f220fa62Smrg if(bezierArc->cpts[j] < min_u) 341f220fa62Smrg min_u = bezierArc->cpts[j]; 342f220fa62Smrg if(bezierArc->cpts[j] > max_u) 343f220fa62Smrg max_u = bezierArc->cpts[j]; 344f220fa62Smrg if(bezierArc->cpts[j+1] < min_v) 345f220fa62Smrg min_v = bezierArc->cpts[j+1]; 346f220fa62Smrg if(bezierArc->cpts[j+1] > max_v) 347f220fa62Smrg max_v = bezierArc->cpts[j+1]; 348f220fa62Smrg } 349f220fa62Smrg 350f220fa62Smrg size = max_u - min_u; 351f220fa62Smrg if(size < max_v - min_v) 352f220fa62Smrg size = max_v - min_v; 353f220fa62Smrg } 354f220fa62Smrg 355f220fa62Smrg /*int nsteps = 1 + (int) (1.0/stepsize);*/ 356f220fa62Smrg 357f220fa62Smrg int nsteps = (int) (size/stepsize); 358f220fa62Smrg if(nsteps <=0) 359f220fa62Smrg nsteps=1; 360f220fa62Smrg 361f220fa62Smrg TrimVertex *vert = trimvertexpool.get( nsteps+1 ); 362f220fa62Smrg REAL dp = 1.0/nsteps; 363f220fa62Smrg 364f220fa62Smrg 365f220fa62Smrg arc->pwlArc = new(pwlarcpool) PwlArc(); 366f220fa62Smrg arc->pwlArc->pts = vert; 367f220fa62Smrg 368f220fa62Smrg if( isrational ) { 369f220fa62Smrg REAL pow_u[MAXORDER], pow_v[MAXORDER], pow_w[MAXORDER]; 370f220fa62Smrg trim_power_coeffs( bezierArc, pow_u, 0 ); 371f220fa62Smrg trim_power_coeffs( bezierArc, pow_v, 1 ); 372f220fa62Smrg trim_power_coeffs( bezierArc, pow_w, 2 ); 373f220fa62Smrg 374f220fa62Smrg /* compute first point exactly */ 375f220fa62Smrg REAL *b = bezierArc->cpts; 376f220fa62Smrg vert->param[0] = b[0]/b[2]; 377f220fa62Smrg vert->param[1] = b[1]/b[2]; 378f220fa62Smrg 379f220fa62Smrg /* strength reduction on p = dp * step would introduce error */ 380f220fa62Smrg int step; 381f220fa62Smrg#ifndef NOELIMINATION 382f220fa62Smrg int ocanremove = 0; 383f220fa62Smrg#endif 384e7980a23Smrg long order = bezierArc->order; 385f220fa62Smrg for( step=1, ++vert; step<nsteps; step++, vert++ ) { 386e7980a23Smrg REAL p = dp * step; 387e7980a23Smrg REAL u = pow_u[0]; 388e7980a23Smrg REAL v = pow_v[0]; 389e7980a23Smrg REAL w = pow_w[0]; 390e7980a23Smrg for( int i = 1; i < order; i++ ) { 391f220fa62Smrg u = u * p + pow_u[i]; 392f220fa62Smrg v = v * p + pow_v[i]; 393f220fa62Smrg w = w * p + pow_w[i]; 394f220fa62Smrg } 395f220fa62Smrg vert->param[0] = u/w; 396f220fa62Smrg vert->param[1] = v/w; 397f220fa62Smrg#ifndef NOELIMINATION 398f220fa62Smrg REAL ds = glu_abs(vert[0].param[0] - vert[-1].param[0]); 399f220fa62Smrg REAL dt = glu_abs(vert[0].param[1] - vert[-1].param[1]); 400f220fa62Smrg int canremove = (ds<geo_stepsize && dt<geo_stepsize) ? 1 : 0; 401f220fa62Smrg REAL ods=0.0, odt=0.0; 402f220fa62Smrg 403f220fa62Smrg if( ocanremove && canremove ) { 404f220fa62Smrg REAL nds = ds + ods; 405f220fa62Smrg REAL ndt = dt + odt; 406f220fa62Smrg if( nds<geo_stepsize && ndt<geo_stepsize ) { 407f220fa62Smrg // remove previous point 408f220fa62Smrg --vert; 409f220fa62Smrg vert[0].param[0] = vert[1].param[0]; 410f220fa62Smrg vert[0].param[1] = vert[1].param[1]; 411f220fa62Smrg ods = nds; 412f220fa62Smrg odt = ndt; 413f220fa62Smrg ocanremove = 1; 414f220fa62Smrg } else { 415f220fa62Smrg ocanremove = canremove; 416f220fa62Smrg ods = ds; 417f220fa62Smrg odt = dt; 418f220fa62Smrg } 419f220fa62Smrg } else { 420f220fa62Smrg ocanremove = canremove; 421f220fa62Smrg ods = ds; 422f220fa62Smrg odt = dt; 423f220fa62Smrg } 424f220fa62Smrg#endif 425f220fa62Smrg } 426f220fa62Smrg 427f220fa62Smrg /* compute last point exactly */ 428f220fa62Smrg b += (order - 1) * bezierArc->stride; 429f220fa62Smrg vert->param[0] = b[0]/b[2]; 430f220fa62Smrg vert->param[1] = b[1]/b[2]; 431f220fa62Smrg 432f220fa62Smrg } else { 433f220fa62Smrg REAL pow_u[MAXORDER], pow_v[MAXORDER]; 434f220fa62Smrg trim_power_coeffs( bezierArc, pow_u, 0 ); 435f220fa62Smrg trim_power_coeffs( bezierArc, pow_v, 1 ); 436f220fa62Smrg 437f220fa62Smrg /* compute first point exactly */ 438f220fa62Smrg REAL *b = bezierArc->cpts; 439f220fa62Smrg vert->param[0] = b[0]; 440f220fa62Smrg vert->param[1] = b[1]; 441f220fa62Smrg 442f220fa62Smrg /* strength reduction on p = dp * step would introduce error */ 443f220fa62Smrg int step; 444f220fa62Smrg#ifndef NOELIMINATION 445f220fa62Smrg int ocanremove = 0; 446f220fa62Smrg#endif 447e7980a23Smrg long order = bezierArc->order; 448f220fa62Smrg for( step=1, ++vert; step<nsteps; step++, vert++ ) { 449e7980a23Smrg REAL p = dp * step; 450e7980a23Smrg REAL u = pow_u[0]; 451e7980a23Smrg REAL v = pow_v[0]; 452e7980a23Smrg for( int i = 1; i < bezierArc->order; i++ ) { 453f220fa62Smrg u = u * p + pow_u[i]; 454f220fa62Smrg v = v * p + pow_v[i]; 455f220fa62Smrg } 456f220fa62Smrg vert->param[0] = u; 457f220fa62Smrg vert->param[1] = v; 458f220fa62Smrg#ifndef NOELIMINATION 459f220fa62Smrg REAL ds = glu_abs(vert[0].param[0] - vert[-1].param[0]); 460f220fa62Smrg REAL dt = glu_abs(vert[0].param[1] - vert[-1].param[1]); 461f220fa62Smrg int canremove = (ds<geo_stepsize && dt<geo_stepsize) ? 1 : 0; 462f220fa62Smrg REAL ods=0.0, odt=0.0; 463f220fa62Smrg 464f220fa62Smrg if( ocanremove && canremove ) { 465f220fa62Smrg REAL nds = ds + ods; 466f220fa62Smrg REAL ndt = dt + odt; 467f220fa62Smrg if( nds<geo_stepsize && ndt<geo_stepsize ) { 468f220fa62Smrg // remove previous point 469f220fa62Smrg --vert; 470f220fa62Smrg vert[0].param[0] = vert[1].param[0]; 471f220fa62Smrg vert[0].param[1] = vert[1].param[1]; 472f220fa62Smrg ods = nds; 473f220fa62Smrg odt = ndt; 474f220fa62Smrg ocanremove = 1; 475f220fa62Smrg } else { 476f220fa62Smrg ocanremove = canremove; 477f220fa62Smrg ods = ds; 478f220fa62Smrg odt = dt; 479f220fa62Smrg } 480f220fa62Smrg } else { 481f220fa62Smrg ocanremove = canremove; 482f220fa62Smrg ods = ds; 483f220fa62Smrg odt = dt; 484f220fa62Smrg } 485f220fa62Smrg#endif 486f220fa62Smrg } 487f220fa62Smrg 488f220fa62Smrg /* compute last point exactly */ 489f220fa62Smrg b += (order - 1) * bezierArc->stride; 490f220fa62Smrg vert->param[0] = b[0]; 491f220fa62Smrg vert->param[1] = b[1]; 492f220fa62Smrg } 493f220fa62Smrg arc->pwlArc->npts = vert - arc->pwlArc->pts + 1; 494f220fa62Smrg/* 495f220fa62Smrg for( TrimVertex *vt=pwlArc->pts; vt != vert-1; vt++ ) { 496f220fa62Smrg if( tooclose( vt[0].param[0], vt[1].param[0] ) ) 497f220fa62Smrg vt[1].param[0] = vt[0].param[0]; 498f220fa62Smrg if( tooclose( vt[0].param[1], vt[1].param[1] ) ) 499f220fa62Smrg vt[1].param[1] = vt[0].param[1]; 500f220fa62Smrg } 501f220fa62Smrg*/ 502f220fa62Smrg} 503f220fa62Smrg 504f220fa62Smrgconst REAL ArcTessellator::gl_Bernstein[][MAXORDER][MAXORDER] = { 505f220fa62Smrg { 506f220fa62Smrg {1, 0, 0, 0, 0, 0, 0, 0 }, 507f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 }, 508f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 }, 509f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 }, 510f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 }, 511f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 }, 512f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 }, 513f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 } 514f220fa62Smrg }, 515f220fa62Smrg { 516f220fa62Smrg {-1, 1, 0, 0, 0, 0, 0, 0 }, 517f220fa62Smrg {1, 0, 0, 0, 0, 0, 0, 0 }, 518f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 }, 519f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 }, 520f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 }, 521f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 }, 522f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 }, 523f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 } 524f220fa62Smrg }, 525f220fa62Smrg { 526f220fa62Smrg {1, -2, 1, 0, 0, 0, 0, 0 }, 527f220fa62Smrg {-2, 2, 0, 0, 0, 0, 0, 0 }, 528f220fa62Smrg {1, 0, 0, 0, 0, 0, 0, 0 }, 529f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 }, 530f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 }, 531f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 }, 532f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 }, 533f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 } 534f220fa62Smrg }, 535f220fa62Smrg { 536f220fa62Smrg {-1, 3, -3, 1, 0, 0, 0, 0 }, 537f220fa62Smrg {3, -6, 3, 0, 0, 0, 0, 0 }, 538f220fa62Smrg {-3, 3, 0, 0, 0, 0, 0, 0 }, 539f220fa62Smrg {1, 0, 0, 0, 0, 0, 0, 0 }, 540f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 }, 541f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 }, 542f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 }, 543f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 } 544f220fa62Smrg }, 545f220fa62Smrg { 546f220fa62Smrg {1, -4, 6, -4, 1, 0, 0, 0 }, 547f220fa62Smrg {-4, 12, -12, 4, 0, 0, 0, 0 }, 548f220fa62Smrg {6, -12, 6, 0, 0, 0, 0, 0 }, 549f220fa62Smrg {-4, 4, 0, 0, 0, 0, 0, 0 }, 550f220fa62Smrg {1, 0, 0, 0, 0, 0, 0, 0 }, 551f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 }, 552f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 }, 553f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 } 554f220fa62Smrg }, 555f220fa62Smrg { 556f220fa62Smrg {-1, 5, -10, 10, -5, 1, 0, 0 }, 557f220fa62Smrg {5, -20, 30, -20, 5, 0, 0, 0 }, 558f220fa62Smrg {-10, 30, -30, 10, 0, 0, 0, 0 }, 559f220fa62Smrg {10, -20, 10, 0, 0, 0, 0, 0 }, 560f220fa62Smrg {-5, 5, 0, 0, 0, 0, 0, 0 }, 561f220fa62Smrg {1, 0, 0, 0, 0, 0, 0, 0 }, 562f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 }, 563f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 } 564f220fa62Smrg }, 565f220fa62Smrg { 566f220fa62Smrg {1, -6, 15, -20, 15, -6, 1, 0 }, 567f220fa62Smrg {-6, 30, -60, 60, -30, 6, 0, 0 }, 568f220fa62Smrg {15, -60, 90, -60, 15, 0, 0, 0 }, 569f220fa62Smrg {-20, 60, -60, 20, 0, 0, 0, 0 }, 570f220fa62Smrg {15, -30, 15, 0, 0, 0, 0, 0 }, 571f220fa62Smrg {-6, 6, 0, 0, 0, 0, 0, 0 }, 572f220fa62Smrg {1, 0, 0, 0, 0, 0, 0, 0 }, 573f220fa62Smrg {0, 0, 0, 0, 0, 0, 0, 0 } 574f220fa62Smrg }, 575f220fa62Smrg { 576f220fa62Smrg {-1, 7, -21, 35, -35, 21, -7, 1 }, 577f220fa62Smrg {7, -42, 105, -140, 105, -42, 7, 0 }, 578f220fa62Smrg {-21, 105, -210, 210, -105, 21, 0, 0 }, 579f220fa62Smrg {35, -140, 210, -140, 35, 0, 0, 0 }, 580f220fa62Smrg {-35, 105, -105, 35, 0, 0, 0, 0 }, 581f220fa62Smrg {21, -42, 21, 0, 0, 0, 0, 0 }, 582f220fa62Smrg {-7, 7, 0, 0, 0, 0, 0, 0 }, 583f220fa62Smrg {1, 0, 0, 0, 0, 0, 0, 0 } 584f220fa62Smrg }}; 585f220fa62Smrg 586f220fa62Smrg 587f220fa62Smrg/*----------------------------------------------------------------------------- 588f220fa62Smrg * trim_power_coeffs - compute power basis coefficients from bezier coeffients 589f220fa62Smrg *----------------------------------------------------------------------------- 590f220fa62Smrg */ 591f220fa62Smrgvoid 592f220fa62SmrgArcTessellator::trim_power_coeffs( BezierArc *bez_arc, REAL *p, int coord ) 593f220fa62Smrg{ 594e7980a23Smrg int stride = bez_arc->stride; 595e7980a23Smrg int order = bez_arc->order; 596e7980a23Smrg REAL *base = bez_arc->cpts + coord; 597f220fa62Smrg 598f220fa62Smrg REAL const (*mat)[MAXORDER][MAXORDER] = &gl_Bernstein[order-1]; 599f220fa62Smrg REAL const (*lrow)[MAXORDER] = &(*mat)[order]; 600f220fa62Smrg 601f220fa62Smrg /* WIN32 didn't like the following line within the for-loop */ 602f220fa62Smrg REAL const (*row)[MAXORDER] = &(*mat)[0]; 603f220fa62Smrg for( ; row != lrow; row++ ) { 604e7980a23Smrg REAL s = 0.0; 605e7980a23Smrg REAL *point = base; 606e7980a23Smrg REAL const *mlast = *row + order; 607f220fa62Smrg for( REAL const *m = *row; m != mlast; m++, point += stride ) 608f220fa62Smrg s += *(m) * (*point); 609f220fa62Smrg *(p++) = s; 610f220fa62Smrg } 611f220fa62Smrg} 612