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