41a78120c1777f920893357bce5b73c41f4c68ba
[reactos.git] / reactos / dll / glu32 / libnurbs / internals / nurbstess.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 * nurbstess.c++
37 *
38 * $Date$ $Revision: 1.1 $
39 * $Header: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/glu32/libnurbs/internals/nurbstess.cc,v 1.1 2004/02/02 16:39:12 navaraf Exp $
40 */
41
42 #include "glimports.h"
43 #include "myassert.h"
44 #include "mysetjmp.h"
45 #include "mystdio.h"
46 #include "nurbsconsts.h"
47 #include "nurbstess.h"
48 #include "bufpool.h"
49 #include "quilt.h"
50 #include "knotvector.h"
51 #include "mapdesc.h"
52 #include "maplist.h"
53
54 void
55 NurbsTessellator::set_domain_distance_u_rate(REAL u_rate)
56 {
57 subdivider.set_domain_distance_u_rate(u_rate);
58 }
59
60 void
61 NurbsTessellator::set_domain_distance_v_rate(REAL v_rate)
62 {
63 subdivider.set_domain_distance_v_rate(v_rate);
64 }
65
66 void
67 NurbsTessellator::set_is_domain_distance_sampling(int flag)
68 {
69 subdivider.set_is_domain_distance_sampling(flag);
70 }
71
72 void
73 NurbsTessellator::resetObjects( void )
74 {
75 subdivider.clear();
76 }
77
78 void
79 NurbsTessellator::makeobj( int )
80 {
81 #ifndef NDEBUG
82 dprintf( "makeobj\n" );
83 #endif
84 }
85
86 void
87 NurbsTessellator::closeobj( void )
88 {
89 #ifndef NDEBUG
90 dprintf( "closeobj\n" );
91 #endif
92 }
93
94 void
95 NurbsTessellator::bgnrender( void )
96 {
97 #ifndef NDEBUG
98 dprintf( "bgnrender\n" );
99 #endif
100 }
101
102 void
103 NurbsTessellator::endrender( void )
104 {
105 #ifndef NDEBUG
106 dprintf( "endrender\n" );
107 #endif
108 }
109
110 /*-----------------------------------------------------------------------------
111 * do_freebgnsurface - free o_surface structure
112 *
113 * Client: do_freeall(), bgnsurface()
114 *-----------------------------------------------------------------------------
115 */
116 void
117 NurbsTessellator::do_freebgnsurface( O_surface *o_surface )
118 {
119 o_surface->deleteMe( o_surfacePool );
120 }
121
122
123 /*-----------------------------------------------------------------------------
124 * do_bgnsurface - begin the display of a surface
125 *
126 * Client: bgnsurface()
127 *-----------------------------------------------------------------------------
128 */
129 void
130 NurbsTessellator::do_bgnsurface( O_surface *o_surface )
131 {
132 if( inSurface ) {
133 do_nurbserror( 27 );
134 endsurface();
135 }
136 inSurface = 1;
137
138 if( ! playBack ) bgnrender();
139
140 isTrimModified = 0;
141 isSurfaceModified = 0;
142 isDataValid = 1;
143 numTrims = 0;
144 currentSurface = o_surface;
145 nextTrim = &( currentSurface->o_trim );
146 nextNurbssurface = &( currentSurface->o_nurbssurface );
147 }
148
149 /*-----------------------------------------------------------------------------
150 * do_bgncurve - begin the display of a curve
151 *
152 * Client: bgncurve()
153 *-----------------------------------------------------------------------------
154 */
155 void
156 NurbsTessellator::do_bgncurve( O_curve *o_curve )
157 {
158 if ( inCurve ) {
159 do_nurbserror( 6 );
160 endcurve();
161 }
162
163 inCurve = 1;
164 currentCurve = o_curve;
165 currentCurve->curvetype = ct_none;
166
167 if( inTrim ) {
168 if( *nextCurve != o_curve ) {
169 isCurveModified = 1;
170 *nextCurve = o_curve;
171 }
172 } else {
173 if( ! playBack ) bgnrender();
174 isDataValid = 1;
175 }
176 nextCurve = &(o_curve->next);
177 nextPwlcurve = &(o_curve->curve.o_pwlcurve);
178 nextNurbscurve = &(o_curve->curve.o_nurbscurve);
179 }
180
181 /*-----------------------------------------------------------------------------
182 * do_endcurve -
183 *
184 * Client: endcurve()
185 *-----------------------------------------------------------------------------
186 */
187
188 void
189 NurbsTessellator::do_endcurve( void )
190 {
191 if( ! inCurve ) {
192 do_nurbserror( 7 );
193 return;
194 }
195 inCurve = 0;
196
197 *nextCurve = 0;
198 if (currentCurve->curvetype == ct_nurbscurve)
199 *nextNurbscurve = 0;
200 else
201 *nextPwlcurve = 0;
202
203 if ( ! inTrim ) {
204 if( ! isDataValid ) {
205 do_freecurveall( currentCurve );
206 return;
207 }
208
209 int errval;
210 errval = ::mysetjmp( jumpbuffer );
211 if( errval == 0 ) {
212 if( currentCurve->curvetype == ct_nurbscurve ) {
213 subdivider.beginQuilts();
214 for( O_nurbscurve *n = currentCurve->curve.o_nurbscurve; n != 0; n = n->next )
215 subdivider.addQuilt( n->bezier_curves );
216 subdivider.endQuilts();
217 subdivider.drawCurves();
218 if( ! playBack ) endrender();
219 } else {
220 /* XXX */
221 if( ! playBack ) endrender();
222 /*do_draw_pwlcurve( currentCurve->curve.o_pwlcurve ) */;
223 do_nurbserror( 9 );
224 }
225 } else {
226 if( ! playBack ) endrender();
227 do_nurbserror( errval );
228 }
229 do_freecurveall( currentCurve );
230 resetObjects();
231 }
232 }
233
234 /*-----------------------------------------------------------------------------
235 * do_endsurface - mark end of surface, display surface, free immediate data
236 *
237 * Client:
238 *-----------------------------------------------------------------------------
239 */
240 void
241 NurbsTessellator::do_endsurface( void )
242 {
243 if( inTrim ) {
244 do_nurbserror( 12 );
245 endtrim();
246 }
247
248 if( ! inSurface ) {
249 do_nurbserror( 13 );
250 return;
251 }
252 inSurface = 0;
253
254 *nextNurbssurface = 0;
255
256 if( ! isDataValid ) {
257 do_freeall( );
258 return;
259 }
260
261 if( *nextTrim != 0 ) {
262 isTrimModified = 1;
263 *nextTrim = 0;
264 }
265
266 int errval;
267
268 errval = ::mysetjmp( jumpbuffer );
269 if( errval == 0 ) {
270 if( numTrims > 0 ) {
271
272 subdivider.beginTrims();
273 for( O_trim *trim = currentSurface->o_trim; trim; trim = trim->next ) {
274 subdivider.beginLoop();
275 for( O_curve *curve = trim->o_curve; curve; curve = curve->next ) {
276 curve->used = 0;
277 assert( curve->curvetype != ct_none );
278 if (curve->curvetype == ct_pwlcurve) {
279 O_pwlcurve *c = curve->curve.o_pwlcurve;
280 subdivider.addArc( c->npts, c->pts, curve->nuid );
281 } else {
282 Quilt *quilt = curve->curve.o_nurbscurve->bezier_curves;
283 Quiltspec *qspec = quilt->qspec;
284 REAL *cpts = quilt->cpts + qspec->offset;
285 REAL *cptsend = cpts + (qspec->width * qspec->order * qspec->stride);
286 for( ; cpts != cptsend; cpts += qspec->order*qspec->stride )
287 subdivider.addArc( cpts, quilt, curve->nuid );
288 }
289 }
290 subdivider.endLoop();
291 }
292 subdivider.endTrims();
293 }
294
295 subdivider.beginQuilts();
296 for( O_nurbssurface *n = currentSurface->o_nurbssurface; n; n = n->next )
297 subdivider.addQuilt( n->bezier_patches );
298 subdivider.endQuilts();
299 subdivider.drawSurfaces( currentSurface->nuid );
300 if( ! playBack ) endrender();
301 } else {
302 if( ! playBack ) endrender();
303 do_nurbserror( errval );
304 }
305
306 do_freeall( );
307 resetObjects();
308 }
309
310 /*-----------------------------------------------------------------------------
311 * do_freeall - free all data allocated in immediate mode
312 *
313 * Client:
314 *-----------------------------------------------------------------------------
315 */
316 void
317 NurbsTessellator::do_freeall( void )
318 {
319 for( O_trim *o_trim = currentSurface->o_trim; o_trim; ) {
320 O_trim *next_o_trim = o_trim->next;
321 for( O_curve *curve = o_trim->o_curve; curve; ) {
322 O_curve *next_o_curve = curve->next;
323 do_freecurveall( curve );
324 curve = next_o_curve;
325 }
326 if( o_trim->save == 0 ) do_freebgntrim( o_trim );
327 o_trim = next_o_trim;
328 }
329
330 O_nurbssurface *nurbss, *next_nurbss;
331 for( nurbss= currentSurface->o_nurbssurface; nurbss; nurbss = next_nurbss) {
332 next_nurbss = nurbss->next;
333 if( nurbss->save == 0 )
334 do_freenurbssurface( nurbss );
335 else
336 nurbss->used = 0;
337 }
338
339 if( currentSurface->save == 0 ) do_freebgnsurface( currentSurface );
340 }
341
342 void
343 NurbsTessellator::do_freecurveall( O_curve *curve )
344 {
345 assert( curve->curvetype != ct_none );
346
347 if( curve->curvetype == ct_nurbscurve ) {
348 O_nurbscurve *ncurve, *next_ncurve;
349 for( ncurve=curve->curve.o_nurbscurve; ncurve; ncurve=next_ncurve ) {
350 next_ncurve = ncurve->next;
351 if( ncurve->save == 0 )
352 do_freenurbscurve( ncurve );
353 else
354 ncurve->used = 0;
355 }
356 } else {
357 O_pwlcurve *pcurve, *next_pcurve;
358 for( pcurve=curve->curve.o_pwlcurve; pcurve; pcurve=next_pcurve ) {
359 next_pcurve = pcurve->next;
360 if( pcurve->save == 0 )
361 do_freepwlcurve( pcurve );
362 else
363 pcurve->used = 0;
364 }
365 }
366 if( curve->save == 0 )
367 do_freebgncurve( curve );
368 }
369
370
371 /*-----------------------------------------------------------------------------
372 * do_freebgntrim - free the space allocated for a trim loop
373 *
374 * Client:
375 *-----------------------------------------------------------------------------
376 */
377 void
378 NurbsTessellator::do_freebgntrim( O_trim *o_trim )
379 {
380 o_trim->deleteMe( o_trimPool );
381 }
382
383
384 /*-----------------------------------------------------------------------------
385 * do_bgntrim - link in a trim loop to the current trimmed surface description
386 *
387 * Client: bgntrim()
388 *-----------------------------------------------------------------------------
389 */
390 void
391 NurbsTessellator::do_bgntrim( O_trim *o_trim )
392 {
393
394 if( ! inSurface ) {
395 do_nurbserror( 15 );
396 bgnsurface( 0 );
397 inSurface = 2;
398 }
399
400 if( inTrim ) {
401 do_nurbserror( 16 );
402 endtrim();
403 }
404 inTrim = 1;
405
406 if( *nextTrim != o_trim ) {
407 isTrimModified = 1;
408 *nextTrim = o_trim;
409 }
410
411 currentTrim = o_trim;
412 nextTrim = &(o_trim->next);
413 nextCurve = &(o_trim->o_curve);
414 }
415
416
417 /*-----------------------------------------------------------------------------
418 * do_endtrim - mark the end of the current trim loop
419 *
420 * Client: endtrim()
421 *-----------------------------------------------------------------------------
422 */
423 void
424 NurbsTessellator::do_endtrim( void )
425 {
426 if( ! inTrim ) {
427 do_nurbserror( 17 );
428 return;
429 }
430 inTrim = 0;
431
432 if( currentTrim->o_curve == 0 ) {
433 do_nurbserror( 18 );
434 isDataValid = 0;
435 }
436
437 numTrims++;
438
439 if( *nextCurve != 0 ) {
440 isTrimModified = 1;
441 *nextCurve = 0;
442 }
443 }
444
445 /*-----------------------------------------------------------------------------
446 * do_freepwlcurve -
447 *
448 * Client:
449 *-----------------------------------------------------------------------------
450 */
451 void
452 NurbsTessellator::do_freepwlcurve( O_pwlcurve *o_pwlcurve )
453 {
454 o_pwlcurve->deleteMe( o_pwlcurvePool );
455 }
456
457 void
458 NurbsTessellator::do_freebgncurve( O_curve *o_curve )
459 {
460 o_curve->deleteMe( o_curvePool );
461 }
462
463 /*-----------------------------------------------------------------------------
464 * do_pwlcurve - link in pwl trim loop to the current surface description
465 *
466 * Client: pwlcurve()
467 *-----------------------------------------------------------------------------
468 */
469 void
470 NurbsTessellator::do_pwlcurve( O_pwlcurve *o_pwlcurve )
471 {
472 if( ! inTrim ) {
473 do_nurbserror( 19 );
474 if( o_pwlcurve->save == 0 )
475 do_freepwlcurve(o_pwlcurve );
476 return;
477 }
478
479 if( ! inCurve ) {
480 bgncurve( 0 );
481 inCurve = 2;
482 }
483
484 if( o_pwlcurve->used ) {
485 do_nurbserror( 20 );
486 isDataValid = 0;
487 return;
488 } else
489 o_pwlcurve->used = 1;
490
491 if( currentCurve->curvetype == ct_none ) {
492 currentCurve->curvetype = ct_pwlcurve;
493 } else if( currentCurve->curvetype != ct_pwlcurve ) {
494 do_nurbserror( 21 );
495 isDataValid = 0;
496 return;
497 }
498
499 if( *nextPwlcurve != o_pwlcurve ) {
500 isCurveModified = 1;
501 *nextPwlcurve = o_pwlcurve;
502 }
503 nextPwlcurve = &(o_pwlcurve->next);
504
505 if( o_pwlcurve->owner != currentCurve ) {
506 isCurveModified = 1;
507 o_pwlcurve->owner = currentCurve;
508 }
509
510 if( (inCurve == 2) )
511 endcurve();
512 }
513
514
515 /*-----------------------------------------------------------------------------
516 * do_freenurbscurve -
517 *
518 * Client:
519 *-----------------------------------------------------------------------------
520 */
521 void
522 NurbsTessellator::do_freenurbscurve( O_nurbscurve *o_nurbscurve )
523 {
524 o_nurbscurve->bezier_curves->deleteMe( quiltPool );
525 o_nurbscurve->deleteMe( o_nurbscurvePool );
526 }
527
528
529 /*-----------------------------------------------------------------------------
530 * do_nurbscurve -
531 *
532 * Client: nurbscurve()
533 *-----------------------------------------------------------------------------
534 */
535 void
536 NurbsTessellator::do_nurbscurve( O_nurbscurve *o_nurbscurve )
537 {
538 if ( ! inCurve ) {
539 bgncurve( 0 );
540 inCurve = 2;
541 }
542
543 if( o_nurbscurve->used ) {
544 /* error - curve was already called in current surface */
545 do_nurbserror( 23 );
546 isDataValid = 0;
547 return;
548 } else
549 o_nurbscurve->used = 1;
550
551 if( currentCurve->curvetype == ct_none ) {
552 currentCurve->curvetype = ct_nurbscurve;
553 } else if( currentCurve->curvetype != ct_nurbscurve ) {
554 do_nurbserror( 24 );
555 isDataValid = 0;
556 return;
557 }
558
559 if( *nextNurbscurve != o_nurbscurve ) {
560 isCurveModified = 1;
561 *nextNurbscurve = o_nurbscurve;
562 }
563
564 nextNurbscurve = &(o_nurbscurve->next);
565
566 if( o_nurbscurve->owner != currentCurve ) {
567 isCurveModified = 1;
568 o_nurbscurve->owner = currentCurve;
569 }
570
571 if( o_nurbscurve->owner == 0 )
572 isCurveModified = 1;
573
574 if( inCurve == 2 )
575 endcurve();
576 }
577
578
579 /*-----------------------------------------------------------------------------
580 * do_freenurbssurface -
581 *
582 * Client:
583 *-----------------------------------------------------------------------------
584 */
585
586 void
587 NurbsTessellator::do_freenurbssurface( O_nurbssurface *o_nurbssurface )
588 {
589 o_nurbssurface->bezier_patches->deleteMe( quiltPool );
590 o_nurbssurface->deleteMe( o_nurbssurfacePool );
591 }
592
593 /*-----------------------------------------------------------------------------
594 * do_nurbssurface -
595 *
596 * Client: nurbssurface()
597 *-----------------------------------------------------------------------------
598 */
599 void
600 NurbsTessellator::do_nurbssurface( O_nurbssurface *o_nurbssurface )
601 {
602 if( ! inSurface ) {
603 bgnsurface( 0 );
604 inSurface = 2;
605 }
606
607 if( o_nurbssurface->used ) {
608 /* error - surface was already called in current block */
609 do_nurbserror( 25 );
610 isDataValid = 0;
611 return;
612 } else
613 o_nurbssurface->used = 1;
614
615 if( *nextNurbssurface != o_nurbssurface ) {
616 isSurfaceModified = 1;
617 *nextNurbssurface = o_nurbssurface;
618 }
619
620 if( o_nurbssurface->owner != currentSurface ) {
621 isSurfaceModified = 1;
622 o_nurbssurface->owner = currentSurface;
623 }
624 nextNurbssurface = &(o_nurbssurface->next);
625
626 if( inSurface == 2 )
627 endsurface();
628 }
629
630
631 /*-----------------------------------------------------------------------------
632 * do_freenurbsproperty
633 *
634 *-----------------------------------------------------------------------------
635 */
636
637 void
638 NurbsTessellator::do_freenurbsproperty( Property *prop )
639 {
640 prop->deleteMe( propertyPool );
641 }
642
643
644 /*-----------------------------------------------------------------------------
645 * do_setnurbsproperty -
646 *
647 *-----------------------------------------------------------------------------
648 */
649
650 void
651 NurbsTessellator::do_setnurbsproperty( Property *prop )
652 {
653 renderhints.setProperty( prop->tag, prop->value );
654 if( prop->save == 0 )
655 do_freenurbsproperty( prop );
656 }
657
658 void
659 NurbsTessellator::do_setnurbsproperty2( Property *prop )
660 {
661 Mapdesc *mapdesc = maplist.find( prop->type );
662
663 mapdesc->setProperty( prop->tag, prop->value );
664 if( prop->save == 0 )
665 do_freenurbsproperty( prop );
666 }
667
668 void
669 NurbsTessellator::errorHandler( int )
670 {
671 }
672
673 void
674 NurbsTessellator::do_nurbserror( int msg )
675 {
676 errorHandler( msg );
677 }
678
679 int
680 NurbsTessellator::do_check_knots( Knotvector *knots, char *msg )
681 {
682 int status = knots->validate();
683 if( status ) {
684 do_nurbserror( status );
685 if( renderhints.errorchecking != N_NOMSG ) knots->show( msg );
686 }
687 return status;
688 }
689
690
691
692
693