Home | History | Annotate | Line # | Download | only in internals
      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 (at) 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 
   1305