FreeWRL/FreeX3D  3.0.0
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  ulinear = 0;
1185  vlinear = 0;
1186 }
1187 
1188 Slicer::~Slicer()
1189 {
1190 }
1191 
1192 void
1193 Slicer::setisolines( int x )
1194 {
1195  isolines = x;
1196 }
1197 
1198 void
1199 Slicer::setstriptessellation( REAL x, REAL y )
1200 {
1201  assert(x > 0 && y > 0);
1202  du = x;
1203  dv = y;
1204  setDu( du );
1205 }
1206 
1207 void
1208 Slicer::slice_old( Arc_ptr loop )
1209 {
1210  loop->markverts();
1211 
1212  Arc_ptr extrema[4];
1213  loop->getextrema( extrema );
1214 
1215  unsigned int npts = loop->numpts();
1216  TrimRegion::init( npts, extrema[0] );
1217 
1218  Mesher::init( npts );
1219 
1220  long ulines = uarray.init( du, extrema[1], extrema[3] );
1221 //printf("ulines = %i\n", ulines);
1222  Varray varray;
1223  long vlines = varray.init( dv, extrema[0], extrema[2] );
1224 //printf("vlines = %i\n", vlines);
1225  long botv = 0;
1226  long topv;
1227  TrimRegion::init( varray.varray[botv] );
1228  getGridExtent( &extrema[0]->pwlArc->pts[0], &extrema[0]->pwlArc->pts[0] );
1229 
1230  for( long quad=0; quad<varray.numquads; quad++ ) {
1231  backend.surfgrid( uarray.uarray[0],
1232  uarray.uarray[ulines-1],
1233  ulines-1,
1234  varray.vval[quad],
1235  varray.vval[quad+1],
1236  varray.voffset[quad+1] - varray.voffset[quad] );
1237 
1238  for( long i=varray.voffset[quad]+1; i <= varray.voffset[quad+1]; i++ ) {
1239  topv = botv++;
1240  advance( topv - varray.voffset[quad],
1241  botv - varray.voffset[quad],
1242  varray.varray[botv] );
1243  if( i == vlines )
1244  getPts( extrema[2] );
1245  else
1246  getPts( backend );
1247  getGridExtent();
1248  if( isolines ) {
1249  outline();
1250  } else {
1251  if( canTile() )
1252  coveAndTile();
1253  else
1254  mesh();
1255  }
1256  }
1257  }
1258 }
1259 
1260 
1261 void
1262 Slicer::outline( void )
1263 {
1264  GridTrimVertex upper, lower;
1265  Hull::init( );
1266 
1267  backend.bgnoutline();
1268  while( (nextupper( &upper )) ) {
1269  if( upper.isGridVert() )
1270  backend.linevert( upper.g );
1271  else
1272  backend.linevert( upper.t );
1273  }
1274  backend.endoutline();
1275 
1276  backend.bgnoutline();
1277  while( (nextlower( &lower )) ) {
1278  if( lower.isGridVert() )
1279  backend.linevert( lower.g );
1280  else
1281  backend.linevert( lower.t );
1282  }
1283  backend.endoutline();
1284 }
1285 
1286 
1287 void
1288 Slicer::outline( Arc_ptr jarc )
1289 {
1290  jarc->markverts();
1291 
1292  if( jarc->pwlArc->npts >= 2 ) {
1293  backend.bgnoutline();
1294  for( int j = jarc->pwlArc->npts-1; j >= 0; j-- )
1295  backend.linevert( &(jarc->pwlArc->pts[j]) );
1296  backend.endoutline();
1297  }
1298 }
1299 
1300 
Definition: pwlarc.h:44
Definition: varray.h:43
Definition: mesher.h:47