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