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