dri: Rework planar image interface
[mesa.git] / src / glu / sgi / libnurbs / internals / slicer.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 * slicer.c++
37 *
38 */
39
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <math.h>
43 #include "glimports.h"
44 #include "mystdio.h"
45 #include "myassert.h"
46 #include "bufpool.h"
47 #include "slicer.h"
48 #include "backend.h"
49 #include "arc.h"
50 #include "gridtrimvertex.h"
51 #include "simplemath.h"
52 #include "trimvertex.h"
53 #include "varray.h"
54
55 #include "polyUtil.h" //for area()
56
57 //static int count=0;
58
59 /*USE_OPTTT is initiated in trimvertex.h*/
60
61 #ifdef USE_OPTTT
62 #include <GL/gl.h>
63 #endif
64
65 //#define USE_READ_FLAG //whether to use new or old tesselator
66 //if defined, it reads "flagFile",
67 // if the number is 1, then use new tess
68 // otherwise, use the old tess.
69 //if not defined, then use new tess.
70 #ifdef USE_READ_FLAG
71 static Int read_flag(char* name);
72 Int newtess_flag = read_flag("flagFile");
73 #endif
74
75 //#define COUNT_TRIANGLES
76 #ifdef COUNT_TRIANGLES
77 Int num_triangles = 0;
78 Int num_quads = 0;
79 #endif
80
81 #define max(a,b) ((a>b)? a:b)
82 #define ZERO 0.00001 /*determing whether a loop is a rectngle or not*/
83 #define equalRect(a,b) ((glu_abs(a-b) <= ZERO)? 1:0) //only used in tessellating a rectangle
84
85 #if 0 // UNUSED
86 static Int is_Convex(Arc_ptr loop)
87 {
88 if(area(loop->tail(), loop->head(), loop->next->head()) <0 )
89 return 0;
90 for(Arc_ptr jarc = loop->next; jarc != loop; jarc = jarc->next)
91 {
92 if(area(jarc->tail(), jarc->head(), jarc->next->head()) < 0)
93 return 0;
94 }
95 return 1;
96 }
97 #endif
98
99 /******triangulate a monotone polygon**************/
100 #include "monoTriangulation.h"
101 #if 0 // UNUSED
102 static int is_U_monotone(Arc_ptr loop)
103 {
104 int n_changes=0;
105 int prev_sign;
106 int cur_sign;
107 Arc_ptr temp;
108
109 cur_sign = compV2InX(loop->head(), loop->tail());
110
111 n_changes = (compV2InX(loop->prev->head(), loop->prev->tail())
112 != cur_sign);
113
114 for(temp=loop->next; temp != loop; temp = temp->next)
115 {
116 prev_sign = cur_sign;
117 cur_sign = compV2InX(temp->head(), temp->tail());
118 if(cur_sign != prev_sign)
119 {
120 #ifdef DEBUG
121 printf("***change signe\n");
122 #endif
123 n_changes++;
124 }
125 }
126 if(n_changes == 2) return 1;
127 else
128 return 0;
129 }
130 #endif
131
132 inline int compInY(REAL a[2], REAL b[2])
133 {
134 if(a[1] < b[1])
135 return -1;
136 else if (a[1] > b[1])
137 return 1;
138 else if(a[0] > b[0])
139 return 1;
140 else return -1;
141 }
142
143 void monoTriangulationLoop(Arc_ptr loop, Backend& backend, primStream* pStream)
144 {
145 int i;
146 //find the top, bottom, increasing and decreasing chain
147 //then call monoTrianulation
148 Arc_ptr jarc, temp;
149 Arc_ptr top;
150 Arc_ptr bot;
151 top = bot = loop;
152 if(compInY(loop->tail(), loop->prev->tail()) < 0)
153 {
154 //first find bot
155 for(temp = loop->next; temp != loop; temp = temp->next)
156 {
157 if(compInY(temp->tail(), temp->prev->tail()) > 0)
158 break;
159 }
160 bot = temp->prev;
161 //then find top
162 for(temp=loop->prev; temp != loop; temp = temp->prev)
163 {
164 if(compInY(temp->tail(), temp->prev->tail()) > 0)
165 break;
166 }
167 top = temp;
168 }
169 else //loop > loop->prev
170 {
171 for(temp=loop->next; temp != loop; temp = temp->next)
172 {
173 if(compInY(temp->tail(), temp->prev->tail()) < 0)
174 break;
175 }
176 top = temp->prev;
177 for(temp=loop->prev; temp != loop; temp = temp->prev)
178 {
179 if(compInY(temp->tail(), temp->prev->tail()) < 0)
180 break;
181 }
182 bot = temp;
183 }
184 //creat increase and decrease chains
185 vertexArray inc_chain(50); //this is a dynamci array
186 for(i=1; i<=top->pwlArc->npts-2; i++)
187 {
188 //the first vertex is the top which doesn't below to inc_chain
189 inc_chain.appendVertex(top->pwlArc->pts[i].param);
190 }
191 for(jarc=top->next; jarc != bot; jarc = jarc->next)
192 {
193 for(i=0; i<=jarc->pwlArc->npts-2; i++)
194 {
195 inc_chain.appendVertex(jarc->pwlArc->pts[i].param);
196 }
197
198 }
199 vertexArray dec_chain(50);
200 for(jarc = top->prev; jarc != bot; jarc = jarc->prev)
201 {
202 for(i=jarc->pwlArc->npts-2; i>=0; i--)
203 {
204 dec_chain.appendVertex(jarc->pwlArc->pts[i].param);
205 }
206 }
207 for(i=bot->pwlArc->npts-2; i>=1; i--)
208 {
209 dec_chain.appendVertex(jarc->pwlArc->pts[i].param);
210 }
211
212 monoTriangulationRec(top->tail(), bot->tail(), &inc_chain, 0,
213 &dec_chain, 0, &backend);
214
215 }
216
217 /********tesselate a rectanlge (OPTIMIZATION**************/
218 static void triangulateRectGen(Arc_ptr loop, int n_ulines, int n_vlines, Backend& backend);
219
220 static Int is_rect(Arc_ptr loop)
221 {
222 Int nlines =1;
223 for(Arc_ptr jarc = loop->next; jarc != loop; jarc = jarc->next)
224 {
225 nlines++;
226 if(nlines == 5)
227 break;
228 }
229 if(nlines != 4)
230 return 0;
231
232
233 /*
234 printf("here1\n");
235 printf("loop->tail=(%f,%f)\n", loop->tail()[0], loop->tail()[1]);
236 printf("loop->head=(%f,%f)\n", loop->head()[0], loop->head()[1]);
237 printf("loop->next->tail=(%f,%f)\n", loop->next->tail()[0], loop->next->tail()[1]);
238 printf("loop->next->head=(%f,%f)\n", loop->next->head()[0], loop->next->head()[1]);
239 if(fglu_abs(loop->tail()[0] - loop->head()[0])<0.000001)
240 printf("equal 1\n");
241 if(loop->next->tail()[1] == loop->next->head()[1])
242 printf("equal 2\n");
243 */
244
245 if( (glu_abs(loop->tail()[0] - loop->head()[0])<=ZERO) &&
246 (glu_abs(loop->next->tail()[1] - loop->next->head()[1])<=ZERO) &&
247 (glu_abs(loop->prev->tail()[1] - loop->prev->head()[1])<=ZERO) &&
248 (glu_abs(loop->prev->prev->tail()[0] - loop->prev->prev->head()[0])<=ZERO)
249 )
250 return 1;
251 else if
252 ( (glu_abs(loop->tail()[1] - loop->head()[1]) <= ZERO) &&
253 (glu_abs(loop->next->tail()[0] - loop->next->head()[0]) <= ZERO) &&
254 (glu_abs(loop->prev->tail()[0] - loop->prev->head()[0]) <= ZERO) &&
255 (glu_abs(loop->prev->prev->tail()[1] - loop->prev->prev->head()[1]) <= ZERO)
256 )
257 return 1;
258 else
259 return 0;
260 }
261
262
263 //a line with the same u for opt
264 #ifdef USE_OPTTT
265 static void evalLineNOGE_BU(TrimVertex *verts, int n, Backend& backend)
266 {
267 int i;
268 backend.preEvaluateBU(verts[0].param[0]);
269 for(i=0; i<n; i++)
270 backend.tmeshvertNOGE_BU(&verts[i]);
271 }
272 #endif
273
274 //a line with the same v for opt
275 #ifdef USE_OPTTT
276 static void evalLineNOGE_BV(TrimVertex *verts, int n, Backend& backend)
277 {
278 int i;
279 backend.preEvaluateBV(verts[0].param[1]);
280
281 for(i=0; i<n; i++)
282 backend.tmeshvertNOGE_BV(&verts[i]);
283 }
284 #endif
285
286 #ifdef USE_OPTTT
287 static void evalLineNOGE(TrimVertex *verts, int n, Backend& backend)
288 {
289
290 if(verts[0].param[0] == verts[n-1].param[0]) //all u;s are equal
291 evalLineNOGE_BU(verts, n, backend);
292 else if(verts[0].param[1] == verts[n-1].param[1]) //all v's are equal
293 evalLineNOGE_BV(verts, n, backend);
294 else
295 {
296 int i;
297 for(i=0; i<n; i++)
298 backend.tmeshvertNOGE(&verts[i]);
299 }
300 }
301 #endif
302
303 inline void OPT_OUTVERT(TrimVertex& vv, Backend& backend)
304 {
305
306 #ifdef USE_OPTTT
307 glNormal3fv(vv.cache_normal);
308 glVertex3fv(vv.cache_point);
309 #else
310
311 backend.tmeshvert(&vv);
312
313 #endif
314
315 }
316
317 static void triangulateRectAux(PwlArc* top, PwlArc* bot, PwlArc* left, PwlArc* right, Backend& backend);
318
319 static void triangulateRect(Arc_ptr loop, Backend& backend, int TB_or_LR, int ulinear, int vlinear)
320 {
321 //we know the loop is a rectangle, but not sure which is top
322 Arc_ptr top, bot, left, right;
323 if(loop->tail()[1] == loop->head()[1])
324 {
325 if(loop->tail()[1] > loop->prev->prev->tail()[1])
326 {
327
328 top = loop;
329 }
330 else{
331
332 top = loop->prev->prev;
333 }
334 }
335 else
336 {
337 if(loop->tail()[0] > loop->prev->prev->tail()[0])
338 {
339 //loop is the right arc
340
341 top = loop->next;
342 }
343 else
344 {
345
346 top = loop->prev;
347 }
348 }
349 left = top->next;
350 bot = left->next;
351 right= bot->next;
352
353 //if u, v are both nonlinear, then if the
354 //boundary is tessellated dense, we also
355 //sample the inside to get a better tesslletant.
356 if( (!ulinear) && (!vlinear))
357 {
358 int nu = top->pwlArc->npts;
359 if(nu < bot->pwlArc->npts)
360 nu = bot->pwlArc->npts;
361 int nv = left->pwlArc->npts;
362 if(nv < right->pwlArc->npts)
363 nv = right->pwlArc->npts;
364 /*
365 if(nu > 2 && nv > 2)
366 {
367 triangulateRectGen(top, nu-2, nv-2, backend);
368 return;
369 }
370 */
371 }
372
373 if(TB_or_LR == 1)
374 triangulateRectAux(top->pwlArc, bot->pwlArc, left->pwlArc, right->pwlArc, backend);
375 else if(TB_or_LR == -1)
376 triangulateRectAux(left->pwlArc, right->pwlArc, bot->pwlArc, top->pwlArc, backend);
377 else
378 {
379 Int maxPointsTB = top->pwlArc->npts + bot->pwlArc->npts;
380 Int maxPointsLR = left->pwlArc->npts + right->pwlArc->npts;
381
382 if(maxPointsTB < maxPointsLR)
383 triangulateRectAux(left->pwlArc, right->pwlArc, bot->pwlArc, top->pwlArc, backend);
384 else
385 triangulateRectAux(top->pwlArc, bot->pwlArc, left->pwlArc, right->pwlArc, backend);
386 }
387 }
388
389 static void triangulateRectAux(PwlArc* top, PwlArc* bot, PwlArc* left, PwlArc* right, Backend& backend)
390 { //if(maxPointsTB >= maxPointsLR)
391 {
392
393 Int d, topd_left, topd_right, botd_left, botd_right, i,j;
394 d = left->npts /2;
395
396 #ifdef USE_OPTTT
397 evalLineNOGE(top->pts, top->npts, backend);
398 evalLineNOGE(bot->pts, bot->npts, backend);
399 evalLineNOGE(left->pts, left->npts, backend);
400 evalLineNOGE(right->pts, right->npts, backend);
401 #endif
402
403 if(top->npts == 2) {
404 backend.bgntfan();
405 OPT_OUTVERT(top->pts[0], backend);//the root
406 for(i=0; i<left->npts; i++){
407 OPT_OUTVERT(left->pts[i], backend);
408 }
409 for(i=1; i<= bot->npts-2; i++){
410 OPT_OUTVERT(bot->pts[i], backend);
411 }
412 backend.endtfan();
413
414 backend.bgntfan();
415 OPT_OUTVERT(bot->pts[bot->npts-2], backend);
416 for(i=0; i<right->npts; i++){
417 OPT_OUTVERT(right->pts[i], backend);
418 }
419 backend.endtfan();
420 }
421 else if(bot->npts == 2) {
422 backend.bgntfan();
423 OPT_OUTVERT(bot->pts[0], backend);//the root
424 for(i=0; i<right->npts; i++){
425 OPT_OUTVERT(right->pts[i], backend);
426 }
427 for(i=1; i<= top->npts-2; i++){
428 OPT_OUTVERT(top->pts[i], backend);
429 }
430 backend.endtfan();
431
432 backend.bgntfan();
433 OPT_OUTVERT(top->pts[top->npts-2], backend);
434 for(i=0; i<left->npts; i++){
435 OPT_OUTVERT(left->pts[i], backend);
436 }
437 backend.endtfan();
438 }
439 else { //both top and bot have >=3 points
440
441 backend.bgntfan();
442
443 OPT_OUTVERT(top->pts[top->npts-2], backend);
444
445 for(i=0; i<=d; i++)
446 {
447 OPT_OUTVERT(left->pts[i], backend);
448 }
449 backend.endtfan();
450
451 backend.bgntfan();
452
453 OPT_OUTVERT(bot->pts[1], backend);
454
455 OPT_OUTVERT(top->pts[top->npts-2], backend);
456
457 for(i=d; i< left->npts; i++)
458 {
459 OPT_OUTVERT(left->pts[i], backend);
460 }
461 backend.endtfan();
462
463 d = right->npts/2;
464 //output only when d<right->npts-1 and
465 //
466 if(d<right->npts-1)
467 {
468 backend.bgntfan();
469 // backend.tmeshvert(& top->pts[1]);
470 OPT_OUTVERT(top->pts[1], backend);
471 for(i=d; i< right->npts; i++)
472 {
473 // backend.tmeshvert(& right->pts[i]);
474
475 OPT_OUTVERT(right->pts[i], backend);
476
477 }
478 backend.endtfan();
479 }
480
481 backend.bgntfan();
482 // backend.tmeshvert(& bot->pts[bot->npts-2]);
483 OPT_OUTVERT( bot->pts[bot->npts-2], backend);
484 for(i=0; i<=d; i++)
485 {
486 // backend.tmeshvert(& right->pts[i]);
487 OPT_OUTVERT(right->pts[i], backend);
488
489 }
490
491 // backend.tmeshvert(& top->pts[1]);
492 OPT_OUTVERT(top->pts[1], backend);
493
494 backend.endtfan();
495
496
497 topd_left = top->npts-2;
498 topd_right = 1; //topd_left>= topd_right
499
500 botd_left = 1;
501 botd_right = bot->npts-2; //botd_left<= bot_dright
502
503
504 if(top->npts < bot->npts)
505 {
506 int delta=bot->npts - top->npts;
507 int u = delta/2;
508 botd_left = 1+ u;
509 botd_right = bot->npts-2-( delta-u);
510
511 if(botd_left >1)
512 {
513 backend.bgntfan();
514 // backend.tmeshvert(& top->pts[top->npts-2]);
515 OPT_OUTVERT(top->pts[top->npts-2], backend);
516 for(i=1; i<= botd_left; i++)
517 {
518 // backend.tmeshvert(& bot->pts[i]);
519 OPT_OUTVERT(bot->pts[i] , backend);
520 }
521 backend.endtfan();
522 }
523 if(botd_right < bot->npts-2)
524 {
525 backend.bgntfan();
526 OPT_OUTVERT(top->pts[1], backend);
527 for(i=botd_right; i<= bot->npts-2; i++)
528 OPT_OUTVERT(bot->pts[i], backend);
529 backend.endtfan();
530 }
531 }
532 else if(top->npts> bot->npts)
533 {
534 int delta=top->npts-bot->npts;
535 int u = delta/2;
536 topd_left = top->npts-2 - u;
537 topd_right = 1+delta-u;
538
539 if(topd_left < top->npts-2)
540 {
541 backend.bgntfan();
542 // backend.tmeshvert(& bot->pts[1]);
543 OPT_OUTVERT(bot->pts[1], backend);
544 for(i=topd_left; i<= top->npts-2; i++)
545 {
546 // backend.tmeshvert(& top->pts[i]);
547 OPT_OUTVERT(top->pts[i], backend);
548 }
549 backend.endtfan();
550 }
551 if(topd_right > 1)
552 {
553 backend.bgntfan();
554 OPT_OUTVERT(bot->pts[bot->npts-2], backend);
555 for(i=1; i<= topd_right; i++)
556 OPT_OUTVERT(top->pts[i], backend);
557 backend.endtfan();
558 }
559 }
560
561 if(topd_left <= topd_right)
562 return;
563
564 backend.bgnqstrip();
565 for(j=botd_left, i=topd_left; i>=topd_right; i--,j++)
566 {
567 // backend.tmeshvert(& top->pts[i]);
568 // backend.tmeshvert(& bot->pts[j]);
569 OPT_OUTVERT(top->pts[i], backend);
570 OPT_OUTVERT(bot->pts[j], backend);
571 }
572 backend.endqstrip();
573
574 }
575 }
576 }
577
578
579 static void triangulateRectCenter(int n_ulines, REAL* u_val,
580 int n_vlines, REAL* v_val,
581 Backend& backend)
582 {
583
584 // XXX this code was patched by Diego Santa Cruz <Diego.SantaCruz@epfl.ch>
585 // to fix a problem in which glMapGrid2f() was called with bad parameters.
586 // This has beens submitted to SGI but not integrated as of May 1, 2001.
587 if(n_ulines>1 && n_vlines>1) {
588 backend.surfgrid(u_val[0], u_val[n_ulines-1], n_ulines-1,
589 v_val[n_vlines-1], v_val[0], n_vlines-1);
590 backend.surfmesh(0,0,n_ulines-1,n_vlines-1);
591 }
592
593 return;
594
595 /*
596 for(i=0; i<n_vlines-1; i++)
597 {
598
599 backend.bgnqstrip();
600 for(j=0; j<n_ulines; j++)
601 {
602 trimVert.param[0] = u_val[j];
603 trimVert.param[1] = v_val[i+1];
604 backend.tmeshvert(& trimVert);
605
606 trimVert.param[1] = v_val[i];
607 backend.tmeshvert(& trimVert);
608 }
609 backend.endqstrip();
610
611 }
612 */
613 }
614
615 //it works for top, bot, left ad right, you need ot select correct arguments
616 static void triangulateRectTopGen(Arc_ptr arc, int n_ulines, REAL* u_val, Real v, int dir, int is_u, Backend& backend)
617 {
618
619 if(is_u)
620 {
621 int i,k;
622 REAL* upper_val = (REAL*) malloc(sizeof(REAL) * arc->pwlArc->npts);
623 assert(upper_val);
624 if(dir)
625 {
626 for(k=0,i=arc->pwlArc->npts-1; i>=0; i--,k++)
627 {
628 upper_val[k] = arc->pwlArc->pts[i].param[0];
629 }
630 backend.evalUStrip(arc->pwlArc->npts, arc->pwlArc->pts[0].param[1],
631 upper_val,
632 n_ulines, v, u_val);
633 }
634 else
635 {
636 for(k=0,i=0; i<arc->pwlArc->npts; i++,k++)
637 {
638 upper_val[k] = arc->pwlArc->pts[i].param[0];
639
640 }
641
642 backend.evalUStrip(
643 n_ulines, v, u_val,
644 arc->pwlArc->npts, arc->pwlArc->pts[0].param[1], upper_val
645 );
646 }
647
648 free(upper_val);
649 return;
650 }
651 else //is_v
652 {
653 int i,k;
654 REAL* left_val = (REAL*) malloc(sizeof(REAL) * arc->pwlArc->npts);
655 assert(left_val);
656 if(dir)
657 {
658 for(k=0,i=arc->pwlArc->npts-1; i>=0; i--,k++)
659 {
660 left_val[k] = arc->pwlArc->pts[i].param[1];
661 }
662 backend.evalVStrip(arc->pwlArc->npts, arc->pwlArc->pts[0].param[0],
663 left_val,
664 n_ulines, v, u_val);
665 }
666 else
667 {
668 for(k=0,i=0; i<arc->pwlArc->npts; i++,k++)
669 {
670 left_val[k] = arc->pwlArc->pts[i].param[1];
671 }
672 backend.evalVStrip(
673 n_ulines, v, u_val,
674 arc->pwlArc->npts, arc->pwlArc->pts[0].param[0], left_val
675 );
676 }
677 free(left_val);
678 return;
679 }
680
681 //the following is a different version of the above code. If you comment
682 //the above code, the following code will still work. The reason to leave
683 //the folliwng code here is purely for testing purpose.
684 /*
685 int i,j;
686 PwlArc* parc = arc->pwlArc;
687 int d1 = parc->npts-1;
688 int d2 = 0;
689 TrimVertex trimVert;
690 trimVert.nuid = 0;//????
691 REAL* temp_u_val = u_val;
692 if(dir ==0) //have to reverse u_val
693 {
694 temp_u_val = (REAL*) malloc(sizeof(REAL) * n_ulines);
695 assert(temp_u_val);
696 for(i=0; i<n_ulines; i++)
697 temp_u_val[i] = u_val[n_ulines-1-i];
698 }
699 u_val = temp_u_val;
700
701 if(parc->npts > n_ulines)
702 {
703 d1 = n_ulines-1;
704
705 backend.bgntfan();
706 if(is_u){
707 trimVert.param[0] = u_val[0];
708 trimVert.param[1] = v;
709 }
710 else
711 {
712 trimVert.param[1] = u_val[0];
713 trimVert.param[0] = v;
714 }
715
716 backend.tmeshvert(& trimVert);
717 for(i=d1; i< parc->npts; i++)
718 backend.tmeshvert(& parc->pts[i]);
719 backend.endtfan();
720
721
722 }
723 else if(parc->npts < n_ulines)
724 {
725 d2 = n_ulines-parc->npts;
726
727
728 backend.bgntfan();
729 backend.tmeshvert(& parc->pts[parc->npts-1]);
730 for(i=0; i<= d2; i++)
731 {
732 if(is_u){
733 trimVert.param[0] = u_val[i];
734 trimVert.param[1] = v;
735 }
736 else
737 {
738 trimVert.param[1] = u_val[i];
739 trimVert.param[0] = v;
740 }
741 backend.tmeshvert(&trimVert);
742 }
743 backend.endtfan();
744
745 }
746 if(d1>0){
747
748
749 backend.bgnqstrip();
750 for(i=d1, j=d2; i>=0; i--, j++)
751 {
752 backend.tmeshvert(& parc->pts[i]);
753
754 if(is_u){
755 trimVert.param[0] = u_val[j];
756 trimVert.param[1] = v;
757 }
758 else{
759 trimVert.param[1] = u_val[j];
760 trimVert.param[0] = v;
761 }
762 backend.tmeshvert(&trimVert);
763
764
765
766 }
767 backend.endqstrip();
768
769
770 }
771 if(dir == 0) //temp_u_val was mallocated
772 free(temp_u_val);
773 */
774 }
775
776 //n_ulines is the number of ulines inside, and n_vlines is the number of vlines
777 //inside, different from meanings elsewhere!!!
778 static void triangulateRectGen(Arc_ptr loop, int n_ulines, int n_vlines, Backend& backend)
779 {
780
781 int i;
782 //we know the loop is a rectangle, but not sure which is top
783 Arc_ptr top, bot, left, right;
784
785 if(equalRect(loop->tail()[1] , loop->head()[1]))
786 {
787
788 if(loop->tail()[1] > loop->prev->prev->tail()[1])
789 {
790
791 top = loop;
792 }
793 else{
794
795 top = loop->prev->prev;
796 }
797 }
798 else
799 {
800 if(loop->tail()[0] > loop->prev->prev->tail()[0])
801 {
802 //loop is the right arc
803
804 top = loop->next;
805 }
806 else
807 {
808
809 top = loop->prev;
810 }
811 }
812
813 left = top->next;
814 bot = left->next;
815 right= bot->next;
816
817 #ifdef COUNT_TRIANGLES
818 num_triangles += loop->pwlArc->npts +
819 left->pwlArc->npts +
820 bot->pwlArc->npts +
821 right->pwlArc->npts
822 + 2*n_ulines + 2*n_vlines
823 -8;
824 num_quads += (n_ulines-1)*(n_vlines-1);
825 #endif
826 /*
827 backend.surfgrid(left->tail()[0], right->tail()[0], n_ulines+1,
828 top->tail()[1], bot->tail()[1], n_vlines+1);
829 // if(n_ulines>1 && n_vlines>1)
830 backend.surfmesh(0,0,n_ulines+1,n_vlines+1);
831 return;
832 */
833 REAL* u_val=(REAL*) malloc(sizeof(REAL)*n_ulines);
834 assert(u_val);
835 REAL* v_val=(REAL*)malloc(sizeof(REAL) * n_vlines);
836 assert(v_val);
837 REAL u_stepsize = (right->tail()[0] - left->tail()[0])/( (REAL) n_ulines+1);
838 REAL v_stepsize = (top->tail()[1] - bot->tail()[1])/( (REAL) n_vlines+1);
839 Real temp=left->tail()[0]+u_stepsize;
840 for(i=0; i<n_ulines; i++)
841 {
842 u_val[i] = temp;
843 temp += u_stepsize;
844 }
845 temp = bot->tail()[1] + v_stepsize;
846 for(i=0; i<n_vlines; i++)
847 {
848 v_val[i] = temp;
849 temp += v_stepsize;
850 }
851
852 triangulateRectTopGen(top, n_ulines, u_val, v_val[n_vlines-1], 1,1, backend);
853 triangulateRectTopGen(bot, n_ulines, u_val, v_val[0], 0, 1, backend);
854 triangulateRectTopGen(left, n_vlines, v_val, u_val[0], 1, 0, backend);
855 triangulateRectTopGen(right, n_vlines, v_val, u_val[n_ulines-1], 0,0, backend);
856
857
858
859
860 //triangulate the center
861 triangulateRectCenter(n_ulines, u_val, n_vlines, v_val, backend);
862
863 free(u_val);
864 free(v_val);
865
866 }
867
868
869
870
871 /**********for reading newtess_flag from a file**********/
872 #ifdef USE_READ_FLAG
873 static Int read_flag(char* name)
874 {
875 Int ret;
876 FILE* fp = fopen(name, "r");
877 if(fp == NULL)
878 {
879 fprintf(stderr, "can't open file %s\n", name);
880 exit(1);
881 }
882 fscanf(fp, "%i", &ret);
883 fclose(fp);
884 return ret;
885 }
886 #endif
887
888 /***********nextgen tess****************/
889 #include "sampleMonoPoly.h"
890 directedLine* arcToDLine(Arc_ptr arc)
891 {
892 int i;
893 Real vert[2];
894 directedLine* ret;
895 sampledLine* sline = new sampledLine(arc->pwlArc->npts);
896 for(i=0; i<arc->pwlArc->npts; i++)
897 {
898 vert[0] = arc->pwlArc->pts[i].param[0];
899 vert[1] = arc->pwlArc->pts[i].param[1];
900 sline->setPoint(i, vert);
901 }
902 ret = new directedLine(INCREASING, sline);
903 return ret;
904 }
905
906 /*an pwlArc may not be a straight line*/
907 directedLine* arcToMultDLines(directedLine* original, Arc_ptr arc)
908 {
909 directedLine* ret = original;
910 int is_linear = 0;
911 if(arc->pwlArc->npts == 2 )
912 is_linear = 1;
913 else if(area(arc->pwlArc->pts[0].param, arc->pwlArc->pts[1].param, arc->pwlArc->pts[arc->pwlArc->npts-1].param) == 0.0)
914 is_linear = 1;
915
916 if(is_linear)
917 {
918 directedLine *dline = arcToDLine(arc);
919 if(ret == NULL)
920 ret = dline;
921 else
922 ret->insert(dline);
923 return ret;
924 }
925 else /*not linear*/
926 {
927 for(Int i=0; i<arc->pwlArc->npts-1; i++)
928 {
929 Real vert[2][2];
930 vert[0][0] = arc->pwlArc->pts[i].param[0];
931 vert[0][1] = arc->pwlArc->pts[i].param[1];
932 vert[1][0] = arc->pwlArc->pts[i+1].param[0];
933 vert[1][1] = arc->pwlArc->pts[i+1].param[1];
934
935 sampledLine *sline = new sampledLine(2, vert);
936 directedLine *dline = new directedLine(INCREASING, sline);
937 if(ret == NULL)
938 ret = dline;
939 else
940 ret->insert(dline);
941 }
942 return ret;
943 }
944 }
945
946
947
948 directedLine* arcLoopToDLineLoop(Arc_ptr loop)
949 {
950 directedLine* ret;
951
952 if(loop == NULL)
953 return NULL;
954 ret = arcToMultDLines(NULL, loop);
955 //ret->printSingle();
956 for(Arc_ptr temp = loop->next; temp != loop; temp = temp->next){
957 ret = arcToMultDLines(ret, temp);
958 //ret->printSingle();
959 }
960
961 return ret;
962 }
963
964 /*
965 void Slicer::evalRBArray(rectBlockArray* rbArray, gridWrap* grid)
966 {
967 TrimVertex *trimVert = (TrimVertex*)malloc(sizeof(TrimVertex));
968 trimVert -> nuid = 0;//????
969
970 Real* u_values = grid->get_u_values();
971 Real* v_values = grid->get_v_values();
972
973 Int i,j,k,l;
974
975 for(l=0; l<rbArray->get_n_elements(); l++)
976 {
977 rectBlock* block = rbArray->get_element(l);
978 for(k=0, i=block->get_upGridLineIndex(); i>block->get_lowGridLineIndex(); i--, k++)
979 {
980
981 backend.bgnqstrip();
982 for(j=block->get_leftIndices()[k+1]; j<= block->get_rightIndices()[k+1]; j++)
983 {
984 trimVert->param[0] = u_values[j];
985 trimVert->param[1] = v_values[i];
986 backend.tmeshvert(trimVert);
987
988 trimVert->param[1] = v_values[i-1];
989 backend.tmeshvert(trimVert);
990
991 }
992 backend.endqstrip();
993
994 }
995 }
996
997 free(trimVert);
998 }
999 */
1000
1001 void Slicer::evalRBArray(rectBlockArray* rbArray, gridWrap* grid)
1002 {
1003 Int i,j,k;
1004
1005 Int n_vlines=grid->get_n_vlines();
1006 //the reason to switch the position of v_max and v_min is because of the
1007 //the orientation problem. glEvalMesh generates quad_strip clockwise, but
1008 //we need counter-clockwise.
1009 backend.surfgrid(grid->get_u_min(), grid->get_u_max(), grid->get_n_ulines()-1,
1010 grid->get_v_max(), grid->get_v_min(), n_vlines-1);
1011
1012
1013 for(j=0; j<rbArray->get_n_elements(); j++)
1014 {
1015 rectBlock* block = rbArray->get_element(j);
1016 Int low = block->get_lowGridLineIndex();
1017 Int high = block->get_upGridLineIndex();
1018
1019 for(k=0, i=high; i>low; i--, k++)
1020 {
1021 backend.surfmesh(block->get_leftIndices()[k+1], n_vlines-1-i, block->get_rightIndices()[k+1]-block->get_leftIndices()[k+1], 1);
1022 }
1023 }
1024 }
1025
1026
1027 void Slicer::evalStream(primStream* pStream)
1028 {
1029 Int i,j,k;
1030 k=0;
1031 /* TrimVertex X;*/
1032 TrimVertex *trimVert =/*&X*/ (TrimVertex*)malloc(sizeof(TrimVertex));
1033 trimVert -> nuid = 0;//???
1034 Real* vertices = pStream->get_vertices(); //for efficiency
1035 for(i=0; i<pStream->get_n_prims(); i++)
1036 {
1037
1038 //ith primitive has #vertices = lengths[i], type=types[i]
1039 switch(pStream->get_type(i)){
1040 case PRIMITIVE_STREAM_FAN:
1041
1042 backend.bgntfan();
1043
1044 for(j=0; j<pStream->get_length(i); j++)
1045 {
1046 trimVert->param[0] = vertices[k];
1047 trimVert->param[1] = vertices[k+1];
1048 backend.tmeshvert(trimVert);
1049
1050 // backend.tmeshvert(vertices[k], vertices[k+1]);
1051 k += 2;
1052 }
1053 backend.endtfan();
1054 break;
1055
1056 default:
1057 fprintf(stderr, "evalStream: not implemented yet\n");
1058 exit(1);
1059
1060 }
1061 }
1062 free(trimVert);
1063 }
1064
1065
1066
1067
1068 void Slicer::slice_new(Arc_ptr loop)
1069 {
1070 //count++;
1071 //if(count == 78) count=1;
1072 //printf("count=%i\n", count);
1073 //if( ! (4<= count && count <=4)) return;
1074
1075
1076 Int num_ulines;
1077 Int num_vlines;
1078 Real uMin, uMax, vMin, vMax;
1079 Real mydu, mydv;
1080 uMin = uMax = loop->tail()[0];
1081 vMin = vMax = loop->tail()[1];
1082 mydu = (du>0)? du: -du;
1083 mydv = (dv>0)? dv: -dv;
1084
1085 for(Arc_ptr jarc=loop->next; jarc != loop; jarc = jarc->next)
1086 {
1087
1088 if(jarc->tail()[0] < uMin)
1089 uMin = jarc->tail()[0];
1090 if(jarc->tail()[0] > uMax)
1091 uMax = jarc->tail()[0];
1092 if(jarc->tail()[1] < vMin)
1093 vMin = jarc->tail()[1];
1094 if(jarc->tail()[1] > vMax)
1095 vMax = jarc->tail()[1];
1096 }
1097
1098 if (uMax == uMin)
1099 return; // prevent divide-by-zero. Jon Perry. 17 June 2002
1100
1101 if(mydu > uMax - uMin)
1102 num_ulines = 2;
1103 else
1104 {
1105 num_ulines = 3 + (Int) ((uMax-uMin)/mydu);
1106 }
1107 if(mydv>=vMax-vMin)
1108 num_vlines = 2;
1109 else
1110 {
1111 num_vlines = 2+(Int)((vMax-vMin)/mydv);
1112 }
1113
1114 Int isRect = is_rect(loop);
1115
1116 if(isRect && (num_ulines<=2 || num_vlines<=2))
1117 {
1118 if(vlinear)
1119 triangulateRect(loop, backend, 1, ulinear, vlinear);
1120 else if(ulinear)
1121 triangulateRect(loop, backend, -1, ulinear, vlinear);
1122 else
1123 triangulateRect(loop, backend, 0, ulinear, vlinear);
1124 }
1125
1126 else if(isRect)
1127 {
1128 triangulateRectGen(loop, num_ulines-2, num_vlines-2, backend);
1129 }
1130 else if( (num_ulines<=2 || num_vlines <=2) && ulinear)
1131 {
1132 monoTriangulationFunBackend(loop, compV2InY, &backend);
1133 }
1134 else if( (!ulinear) && (!vlinear) && (num_ulines == 2) && (num_vlines > 2))
1135 {
1136 monoTriangulationFunBackend(loop, compV2InY, &backend);
1137 }
1138 else
1139 {
1140 directedLine* poly = arcLoopToDLineLoop(loop);
1141
1142 gridWrap grid(num_ulines, num_vlines, uMin, uMax, vMin, vMax);
1143 primStream pStream(20, 20);
1144 rectBlockArray rbArray(20);
1145
1146 sampleMonoPoly(poly, &grid, ulinear, vlinear, &pStream, &rbArray);
1147
1148 evalStream(&pStream);
1149
1150 evalRBArray(&rbArray, &grid);
1151
1152 #ifdef COUNT_TRIANGLES
1153 num_triangles += pStream.num_triangles();
1154 num_quads += rbArray.num_quads();
1155 #endif
1156 poly->deleteSinglePolygonWithSline();
1157 }
1158
1159 #ifdef COUNT_TRIANGLES
1160 printf("num_triangles=%i\n", num_triangles);
1161 printf("num_quads = %i\n", num_quads);
1162 #endif
1163 }
1164
1165 void Slicer::slice(Arc_ptr loop)
1166 {
1167 #ifdef USE_READ_FLAG
1168 if(read_flag("flagFile"))
1169 slice_new(loop);
1170 else
1171 slice_old(loop);
1172
1173 #else
1174 slice_new(loop);
1175 #endif
1176
1177 }
1178
1179
1180
1181 Slicer::Slicer( Backend &b )
1182 : CoveAndTiler( b ), Mesher( b ), backend( b )
1183 {
1184 oneOverDu = 0;
1185 du = 0;
1186 dv = 0;
1187 isolines = 0;
1188 ulinear = 0;
1189 vlinear = 0;
1190 }
1191
1192 Slicer::~Slicer()
1193 {
1194 }
1195
1196 void
1197 Slicer::setisolines( int x )
1198 {
1199 isolines = x;
1200 }
1201
1202 void
1203 Slicer::setstriptessellation( REAL x, REAL y )
1204 {
1205 assert(x > 0 && y > 0);
1206 du = x;
1207 dv = y;
1208 setDu( du );
1209 }
1210
1211 void
1212 Slicer::slice_old( Arc_ptr loop )
1213 {
1214 loop->markverts();
1215
1216 Arc_ptr extrema[4];
1217 loop->getextrema( extrema );
1218
1219 unsigned int npts = loop->numpts();
1220 TrimRegion::init( npts, extrema[0] );
1221
1222 Mesher::init( npts );
1223
1224 long ulines = uarray.init( du, extrema[1], extrema[3] );
1225 //printf("ulines = %i\n", ulines);
1226 Varray varray;
1227 long vlines = varray.init( dv, extrema[0], extrema[2] );
1228 //printf("vlines = %i\n", vlines);
1229 long botv = 0;
1230 long topv;
1231 TrimRegion::init( varray.varray[botv] );
1232 getGridExtent( &extrema[0]->pwlArc->pts[0], &extrema[0]->pwlArc->pts[0] );
1233
1234 for( long quad=0; quad<varray.numquads; quad++ ) {
1235 backend.surfgrid( uarray.uarray[0],
1236 uarray.uarray[ulines-1],
1237 ulines-1,
1238 varray.vval[quad],
1239 varray.vval[quad+1],
1240 varray.voffset[quad+1] - varray.voffset[quad] );
1241
1242 for( long i=varray.voffset[quad]+1; i <= varray.voffset[quad+1]; i++ ) {
1243 topv = botv++;
1244 advance( topv - varray.voffset[quad],
1245 botv - varray.voffset[quad],
1246 varray.varray[botv] );
1247 if( i == vlines )
1248 getPts( extrema[2] );
1249 else
1250 getPts( backend );
1251 getGridExtent();
1252 if( isolines ) {
1253 outline();
1254 } else {
1255 if( canTile() )
1256 coveAndTile();
1257 else
1258 mesh();
1259 }
1260 }
1261 }
1262 }
1263
1264
1265 void
1266 Slicer::outline( void )
1267 {
1268 GridTrimVertex upper, lower;
1269 Hull::init( );
1270
1271 backend.bgnoutline();
1272 while( (nextupper( &upper )) ) {
1273 if( upper.isGridVert() )
1274 backend.linevert( upper.g );
1275 else
1276 backend.linevert( upper.t );
1277 }
1278 backend.endoutline();
1279
1280 backend.bgnoutline();
1281 while( (nextlower( &lower )) ) {
1282 if( lower.isGridVert() )
1283 backend.linevert( lower.g );
1284 else
1285 backend.linevert( lower.t );
1286 }
1287 backend.endoutline();
1288 }
1289
1290
1291 void
1292 Slicer::outline( Arc_ptr jarc )
1293 {
1294 jarc->markverts();
1295
1296 if( jarc->pwlArc->npts >= 2 ) {
1297 backend.bgnoutline();
1298 for( int j = jarc->pwlArc->npts-1; j >= 0; j-- )
1299 backend.linevert( &(jarc->pwlArc->pts[j]) );
1300 backend.endoutline();
1301 }
1302 }
1303
1304