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  * nurbsinterfac.c++
37  *
38  */
39 
40 //#include "glimports.h"
41 //#include "mystdio.h"
42 //#include "nurbsconsts.h"
43 #include "nurbstess.h"
44 //#include "bufpool.h"
45 #include "quilt.h"
46 #include "displaylist.h"
47 #include "knotvector.h"
48 #include "mapdesc.h"
49 
50 #define THREAD( work, arg, cleanup ) \
51 	if( dl ) {\
52 	    arg->save = 1;\
53 	    dl->append( (PFVS)&NurbsTessellator::work, (void *) arg, (PFVS)&NurbsTessellator::cleanup );\
54  	} else {\
55 	    arg->save = 0;\
56 	    work( arg );\
57 	}
58 
59 #define THREAD2( work ) \
60 	if( dl ) {\
61 	    dl->append( (PFVS)&NurbsTessellator::work, 0, 0 );\
62  	} else {\
63 	    work( );\
64 	}
65 
NurbsTessellator(BasicCurveEvaluator & c,BasicSurfaceEvaluator & e)66 NurbsTessellator::NurbsTessellator( BasicCurveEvaluator &c, BasicSurfaceEvaluator& e)
67 	: maplist( backend ),
68 	  backend( c, e ),
69           subdivider( renderhints, backend ),
70 	  o_pwlcurvePool( sizeof( O_pwlcurve ), 32, "o_pwlcurvePool" ),
71 	  o_nurbscurvePool( sizeof( O_nurbscurve ), 32, "o_nurbscurvePool"),
72 	  o_curvePool( sizeof( O_curve ), 32,  "o_curvePool" ),
73 	  o_trimPool( sizeof( O_trim ), 32,  "o_trimPool" ),
74 	  o_surfacePool( sizeof( O_surface ), 1, "o_surfacePool" ),
75 	  o_nurbssurfacePool( sizeof( O_nurbssurface ), 4, "o_nurbssurfacePool" ),
76 	  propertyPool( sizeof( Property ), 32, "propertyPool" ),
77           quiltPool( sizeof( Quilt  ), 32, "quiltPool" )
78 {
79     dl		= 0;
80     inSurface	= 0;
81     inCurve	= 0;
82     inTrim	= 0;
83     playBack	= 0;
84     jumpbuffer  = newJumpbuffer();
85     subdivider.setJumpbuffer( jumpbuffer );
86 }
87 
~NurbsTessellator(void)88 NurbsTessellator::~NurbsTessellator( void )
89 {
90     if( inTrim ) {
91 	do_nurbserror( 12 );
92 	endtrim();
93     }
94 
95     if( inSurface ) {
96         *nextNurbssurface = 0;
97         do_freeall();
98     }
99 
100     if (jumpbuffer) {
101         deleteJumpbuffer(jumpbuffer);
102 	jumpbuffer= 0;
103     }
104 }
105 
106 /*-----------------------------------------------------------------------------
107  * bgnsurface - allocate and initialize an o_surface structure
108  *
109  * Client: GL user
110  *-----------------------------------------------------------------------------
111  */
112 void
bgnsurface(long nuid)113 NurbsTessellator::bgnsurface( long nuid )
114 {
115     O_surface *o_surface = new(o_surfacePool) O_surface;
116     o_surface->nuid = nuid;
117     THREAD( do_bgnsurface, o_surface, do_freebgnsurface );
118 }
119 
120 /*-----------------------------------------------------------------------------
121  * bgncurve - allocate an initialize an o_curve structure
122  *
123  * Client: GL user
124  *-----------------------------------------------------------------------------
125  */
126 void
bgncurve(long nuid)127 NurbsTessellator::bgncurve( long nuid )
128 {
129     O_curve *o_curve = new(o_curvePool) O_curve;
130     o_curve->nuid = nuid;
131     THREAD( do_bgncurve, o_curve, do_freebgncurve );
132 }
133 /*-----------------------------------------------------------------------------
134  * endcurve -
135  *
136  * Client:
137  *-----------------------------------------------------------------------------
138  */
139 
140 void
endcurve(void)141 NurbsTessellator::endcurve( void )
142 {
143     THREAD2( do_endcurve );
144 }
145 
146 /*-----------------------------------------------------------------------------
147  * endsurface - user level end of surface call
148  *
149  * Client: GL user
150  *-----------------------------------------------------------------------------
151  */
152 void
endsurface(void)153 NurbsTessellator::endsurface( void )
154 {
155     THREAD2( do_endsurface );
156 }
157 
158 
159 /*-----------------------------------------------------------------------------
160  * bgntrim - allocate and initialize a new trim loop structure (o_trim )
161  *
162  * Client: GL user
163  *-----------------------------------------------------------------------------
164  */
165 void
bgntrim(void)166 NurbsTessellator::bgntrim( void )
167 {
168     O_trim *o_trim = new(o_trimPool) O_trim;
169     THREAD( do_bgntrim, o_trim, do_freebgntrim );
170 }
171 
172 /*-----------------------------------------------------------------------------
173  * endtrim -
174  *
175  * Client: GL user
176  *-----------------------------------------------------------------------------
177  */
178 void
endtrim(void)179 NurbsTessellator::endtrim( void )
180 {
181     THREAD2( do_endtrim );
182 }
183 
184 
185 /*-----------------------------------------------------------------------------
186  * pwlcurve -
187  *
188  *      count        - number of points on curve
189  *      array        - array of points on curve
190  *      byte_stride  - distance between points in bytes
191  *      type         - valid data flag
192  *
193  * Client: Gl user
194  *-----------------------------------------------------------------------------
195  */
196 void
pwlcurve(long count,INREAL array[],long byte_stride,long type)197 NurbsTessellator::pwlcurve( long count, INREAL array[], long byte_stride, long type )
198 {
199     Mapdesc *mapdesc = maplist.locate( type );
200 
201     if( mapdesc == 0 ) {
202 	do_nurbserror( 35 );
203 	isDataValid = 0;
204 	return;
205     }
206 
207     if ( (type != N_P2D) && (type != N_P2DR) ) {
208 	do_nurbserror( 22 );
209 	isDataValid = 0;
210 	return;
211     }
212     if( count < 0 ) {
213 	do_nurbserror( 33 );
214 	isDataValid = 0;
215 	return;
216     }
217     if( byte_stride < 0 ) {
218 	do_nurbserror( 34 );
219 	isDataValid = 0;
220 	return;
221     }
222 
223 #ifdef NOTDEF
224     if( mapdesc->isRational() ) {
225 	INREAL *p = array;
226 	INREAL x = p[0]; INREAL y = p[1]; INREAL w = p[2];
227 	p = (INREAL *) (((char *) p) + byte_stride);
228 	for( long i = 1; i != count; i++ ) {
229 	    if( p[0] == x && p[1] == y && p[2] == w ) break;
230 	    x = p[0]; y = p[1]; w = p[2];
231 	    p = (INREAL *) (((char *) p) + byte_stride);
232 	}
233 	if( i != count ) {
234 	    do_nurbserror( 37 );
235 	    _glu_dprintf( "point %d (%f,%f)\n", i, x, y );
236 	    isDataValid = 0;
237 	    return;
238 	}
239     } else {
240 	INREAL *p = array;
241 	INREAL x = p[0]; INREAL y = p[1];
242 	p = (INREAL *) (((char *) p) + byte_stride);
243 	for( long i = 1; i != count; i++ ) {
244 	    if( p[0] == x && p[1] == y ) break;
245 	    x = p[0]; y = p[1];
246 	    p = (INREAL *) (((char *) p) + byte_stride);
247 	}
248 	if( i != count ) {
249 	    do_nurbserror( 37 );
250 	    _glu_dprintf( "point %d (%f,%f)\n", i, x, y );
251 	    isDataValid = 0;
252 	    return;
253 	}
254     }
255 #endif
256 
257     O_pwlcurve	*o_pwlcurve = new(o_pwlcurvePool) O_pwlcurve( type, count, array, byte_stride, extTrimVertexPool.get((int)count) );
258     THREAD( do_pwlcurve, o_pwlcurve, do_freepwlcurve );
259 }
260 
261 
262 /*-----------------------------------------------------------------------------
263  * nurbscurve -
264  *
265  * Client: GL user
266  *-----------------------------------------------------------------------------
267  */
268 void
nurbscurve(long nknots,INREAL knot[],long byte_stride,INREAL ctlarray[],long order,long type)269 NurbsTessellator::nurbscurve(
270     long nknots, 		/* number of p knots */
271     INREAL knot[], 		/* nondecreasing knot values in p */
272     long byte_stride,		/* distance in bytes between control points */
273     INREAL ctlarray[], 		/* pointer to first control point */
274     long order,			/* order of spline */
275     long type )			/* description of range space */
276 {
277 
278     Mapdesc *mapdesc = maplist.locate( type );
279 
280     if( mapdesc == 0 ) {
281 	do_nurbserror( 35 );
282 	isDataValid = 0;
283 	return;
284     }
285 
286     if( ctlarray == 0 ) {
287 	do_nurbserror( 36 );
288 	isDataValid = 0;
289 	return;
290     }
291 
292     if( byte_stride < 0 ) {
293 	do_nurbserror( 34 );
294 	isDataValid = 0;
295 	return;
296     }
297 
298     Knotvector knots;
299 
300     knots.init( nknots, byte_stride, order, knot );
301     if( do_check_knots( &knots, "curve" ) ) return;
302 
303     O_nurbscurve *o_nurbscurve = new(o_nurbscurvePool) O_nurbscurve(type);
304     o_nurbscurve->bezier_curves = new(quiltPool) Quilt(mapdesc);
305     o_nurbscurve->bezier_curves->toBezier( knots,ctlarray, mapdesc->getNcoords() );
306 
307     THREAD( do_nurbscurve, o_nurbscurve, do_freenurbscurve );
308 }
309 
310 
311 /*-----------------------------------------------------------------------------
312  * nurbssurface -
313  *
314  * Client: User routine
315  *-----------------------------------------------------------------------------
316  */
317 void
nurbssurface(long sknot_count,INREAL sknot[],long tknot_count,INREAL tknot[],long s_byte_stride,long t_byte_stride,INREAL ctlarray[],long sorder,long torder,long type)318 NurbsTessellator::nurbssurface(
319     long sknot_count,		/* number of s knots */
320     INREAL sknot[],		/* nondecreasing knot values in s */
321     long tknot_count, 		/* number of t knots */
322     INREAL tknot[],		/* nondecreasing knot values in t */
323     long s_byte_stride,		/* s step size in memory bytes */
324     long t_byte_stride,		/* t step size in memory bytes */
325     INREAL ctlarray[],		/* pointer to first control point */
326     long sorder,		/* order of the spline in s parameter */
327     long torder,		/* order of the spline in t parameter */
328     long type)			/* description of range space */
329 {
330     Mapdesc *mapdesc = maplist.locate( type );
331 
332     if( mapdesc == 0 ) {
333 	do_nurbserror( 35 );
334 	isDataValid = 0;
335 	return;
336     }
337 
338     if( s_byte_stride < 0 ) {
339 	do_nurbserror( 34 );
340 	isDataValid = 0;
341 	return;
342     }
343 
344     if( t_byte_stride < 0 ) {
345 	do_nurbserror( 34 );
346 	isDataValid = 0;
347 	return;
348     }
349 
350     Knotvector sknotvector, tknotvector;
351 
352     sknotvector.init( sknot_count, s_byte_stride, sorder, sknot );
353     if( do_check_knots( &sknotvector, "surface" ) ) return;
354 
355     tknotvector.init( tknot_count, t_byte_stride, torder, tknot );
356     if( do_check_knots( &tknotvector, "surface" ) ) return;
357 
358     O_nurbssurface *o_nurbssurface = new(o_nurbssurfacePool) O_nurbssurface(type);
359     o_nurbssurface->bezier_patches = new(quiltPool) Quilt(mapdesc);
360 
361     o_nurbssurface->bezier_patches->toBezier( sknotvector, tknotvector,
362 	ctlarray, mapdesc->getNcoords() );
363     THREAD( do_nurbssurface, o_nurbssurface, do_freenurbssurface );
364 }
365 
366 
367 /*-----------------------------------------------------------------------------
368  * setnurbsproperty -
369  *
370  *-----------------------------------------------------------------------------
371  */
372 void
setnurbsproperty(long tag,INREAL value)373 NurbsTessellator::setnurbsproperty( long tag, INREAL value )
374 {
375     if( ! renderhints.isProperty( tag ) ) {
376 	do_nurbserror( 26 );
377     } else {
378 	Property *prop = new(propertyPool) Property( tag, value );
379 	THREAD( do_setnurbsproperty, prop, do_freenurbsproperty );
380     }
381 }
382 
383 /*-----------------------------------------------------------------------------
384  * setnurbsproperty -
385  *
386  *-----------------------------------------------------------------------------
387  */
388 void
setnurbsproperty(long type,long tag,INREAL value)389 NurbsTessellator::setnurbsproperty( long type, long tag, INREAL value )
390 {
391     Mapdesc *mapdesc = maplist.locate( type );
392 
393     if( mapdesc == 0 ) {
394 	do_nurbserror( 35 );
395 	return;
396     }
397 
398     if( ! mapdesc->isProperty( tag ) ) {
399 	do_nurbserror( 26 );
400 	return;
401     }
402 
403     Property *prop = new(propertyPool) Property( type, tag, value );
404     THREAD( do_setnurbsproperty2, prop, do_freenurbsproperty );
405 }
406 
407 
408 /*-----------------------------------------------------------------------------
409  * getnurbsproperty -
410  *
411  *-----------------------------------------------------------------------------
412  */
413 
414 void
getnurbsproperty(long tag,INREAL * value)415 NurbsTessellator::getnurbsproperty( long tag, INREAL *value )
416 {
417     if( renderhints.isProperty( tag ) ) {
418 	*value = renderhints.getProperty( tag );
419     } else {
420 	do_nurbserror( 26 );
421     }
422 }
423 
424 /*-----------------------------------------------------------------------------
425  * getnurbsproperty -
426  *
427  *-----------------------------------------------------------------------------
428  */
429 
430 void
getnurbsproperty(long type,long tag,INREAL * value)431 NurbsTessellator::getnurbsproperty( long type, long tag, INREAL *value )
432 {
433     Mapdesc *mapdesc = maplist.locate( type );
434 
435     if( mapdesc == 0 )
436 	do_nurbserror( 35 );
437 
438     if( mapdesc->isProperty( tag  ) ) {
439 	*value = mapdesc->getProperty( tag );
440     } else {
441 	do_nurbserror( 26 );
442     }
443 }
444 
445 /*--------------------------------------------------------------------------
446  * setnurbsproperty - accept a user supplied matrix as culling or sampling mat
447  *--------------------------------------------------------------------------
448  */
449 
450 void
setnurbsproperty(long type,long purpose,INREAL * mat)451 NurbsTessellator::setnurbsproperty( long type, long purpose, INREAL *mat )
452 {
453     // XXX - cannot be put in display list
454     Mapdesc *mapdesc = maplist.locate( type );
455 
456     if( mapdesc == 0 ) {
457 	do_nurbserror( 35 );
458 	isDataValid = 0;
459     } else if( purpose == N_BBOXSIZE ) {
460 	mapdesc->setBboxsize( mat );
461     } else {
462 #ifndef NDEBUG
463         _glu_dprintf( "ERRORRORRORR!!!\n");
464 #endif
465     }
466 }
467 
468 /*--------------------------------------------------------------------------
469  * setnurbsproperty - accept a user supplied matrix as culling or sampling mat
470  *--------------------------------------------------------------------------
471  */
472 
473 void
setnurbsproperty(long type,long purpose,INREAL * mat,long rstride,long cstride)474 NurbsTessellator::setnurbsproperty( long type, long purpose, INREAL *mat,
475     long rstride, long cstride )
476 {
477     // XXX - cannot be put in display list
478     Mapdesc *mapdesc = maplist.locate( type );
479 
480     if( mapdesc == 0 ) {
481 	do_nurbserror( 35 );
482 	isDataValid = 0;
483     } else if( purpose == N_CULLINGMATRIX ) {
484 	mapdesc->setCmat( mat, rstride, cstride );
485     } else if( purpose == N_SAMPLINGMATRIX ) {
486 	mapdesc->setSmat( mat, rstride, cstride );
487     } else if( purpose == N_BBOXMATRIX ) {
488 	mapdesc->setBmat( mat, rstride, cstride );
489     } else {
490 #ifndef NDEBUG
491         _glu_dprintf( "ERRORRORRORR!!!\n");
492 #endif
493     }
494 }
495 
496 void
redefineMaps(void)497 NurbsTessellator::redefineMaps( void )
498 {
499     maplist.initialize();
500 }
501 
502 void
defineMap(long type,long rational,long ncoords)503 NurbsTessellator::defineMap( long type, long rational, long ncoords )
504 {
505     maplist.define( type, (int) rational, (int) ncoords );
506 }
507 
508 void
discardRecording(void * _dl)509 NurbsTessellator::discardRecording( void *_dl )
510 {
511     delete (DisplayList *) _dl;
512 }
513 
514 void *
beginRecording(void)515 NurbsTessellator::beginRecording( void )
516 {
517     dl = new DisplayList( this );
518     return (void *) dl;
519 }
520 
521 void
endRecording(void)522 NurbsTessellator::endRecording( void )
523 {
524     dl->endList();
525     dl = 0;
526 }
527 
528 void
playRecording(void * _dl)529 NurbsTessellator::playRecording( void *_dl )
530 {
531     playBack = 1;
532     bgnrender();
533     ((DisplayList *)_dl)->play();
534     endrender();
535     playBack = 0;
536 }
537 
538