source: GTP/trunk/Lib/Geom/shared/GTGeometry/src/GeoMeshStripifier.cpp @ 1070

Revision 1070, 236.8 KB checked in by gumbau, 18 years ago (diff)
Line 
1/*      ==========================================================================
2 *      (C) 2005 Universitat Jaume I
3 *      ==========================================================================
4 *      PROYECT:        GAME TOOLS
5 *      ==========================================================================*/
6/**     CONTENT:        Make triangle strip meshes from triangle list meshes.
7        *
8        *
9        *       @file   GeoMeshStripifier.cpp
10/*===========================================================================*/
11
12#include "GeoMeshStripifier.h"
13
14using namespace Geometry;
15using   namespace       std;
16
17//-----------------------------------------------------------------------------
18//      Private.
19//-----------------------------------------------------------------------------
20
21//-----------------------------------------------------------------------------
22///     InitList.
23//-----------------------------------------------------------------------------
24BOOL CustomStripifier::InitList(PLISTHEAD LHead)
25{
26        if (LHead == NULL)
27        {
28                return  FALSE;
29        }
30
31        LHead->LHeaders[LISTHEAD] = LHead->LHeaders[LISTTAIL] = NULL;
32        LHead->NumList = 0;
33
34        return  TRUE;
35}
36
37//-----------------------------------------------------------------------------
38//      AddHead.
39//-----------------------------------------------------------------------------
40BOOL CustomStripifier::AddHead(PLISTHEAD LHead, PLISTINFO LInfo)
41{
42        if (LHead == NULL || LInfo == NULL)
43        {
44                return(FALSE);
45        }
46
47        if (EMPTYLIST(LHead))
48        {
49                LHead->LHeaders[LISTTAIL] = LInfo;
50        }
51        else
52        {
53                LHead->LHeaders[LISTHEAD]->ListNode.Previous = (void  *) LInfo;
54        }
55
56        LInfo->ListNode.Next                    =       (void  *) LHead->LHeaders[LISTHEAD];
57        LHead->LHeaders[LISTHEAD]       =       LInfo;
58        LInfo->ListNode.Previous        =       NULL;
59        LHead->NumList++;
60
61        return(TRUE);
62}
63
64///     AddTail
65BOOL  CustomStripifier::AddTail(PLISTHEAD LHead, PLISTINFO LInfo)
66{
67        if (LHead == NULL || LInfo == NULL)
68        {
69                return  FALSE;
70        }
71
72        if (EMPTYLIST(LHead))
73        {
74                LHead->LHeaders[LISTHEAD] = LInfo;
75        }
76        else
77        {
78                LHead->LHeaders[LISTTAIL]->ListNode.Next = (void *) LInfo;
79        }
80
81        LInfo->ListNode.Previous        = (void  *) LHead->LHeaders[LISTTAIL];
82        LHead->LHeaders[LISTTAIL] = LInfo;
83        LInfo->ListNode.Next                    = NULL;
84        LHead->NumList++;
85
86        return  TRUE;
87}
88
89///     InsertNode
90BOOL  CustomStripifier::InsertNode( PLISTHEAD LHead, int nPos, PLISTINFO LInfo )
91{
92        PLISTINFO add_node;
93
94  if ( LHead == NULL || LInfo == NULL || nPos > NumOnList( LHead ) )
95        {
96                return  FALSE;
97        }
98
99        if ( nPos == 0 )
100        {
101                AddHead( LHead, LInfo );
102        }
103        else if ( nPos == NumOnList( LHead ) )
104        {
105                AddTail( LHead, LInfo );
106        }
107        else
108        {
109                if ( (add_node = PeekList( LHead, LISTHEAD, nPos - 1 )) == NULL )
110                {
111                        return  FALSE;
112                }
113 
114                ((PLISTINFO)add_node->ListNode.Next)->ListNode.Previous = LInfo;
115
116                LInfo->ListNode.Next      = add_node->ListNode.Next;
117                LInfo->ListNode.Previous  = add_node;
118                add_node->ListNode.Next   = LInfo;
119                LHead->NumList++;
120        }
121
122        return  TRUE;
123}
124
125///     RemHead:
126PLISTINFO  CustomStripifier::RemHead(PLISTHEAD LHead)
127{
128        PLISTINFO t, t1;
129
130        if ( LHead == NULL || EMPTYLIST(LHead) )
131        {
132                return  NULL;
133        }
134
135        t                                                                                                       =       LHead->LHeaders[LISTHEAD];
136        LHead->LHeaders[LISTHEAD] = (PLISTINFO) t->ListNode.Next;
137
138        if (LHead->LHeaders[LISTHEAD] != NULL)
139        {
140                t1                                                                              = (PLISTINFO) t->ListNode.Next;
141                t1->ListNode.Previous = NULL;
142        }
143        else
144        {
145                LHead->LHeaders[LISTTAIL] = NULL;
146        }
147       
148        LHead->NumList--;
149
150        return  t;
151}
152
153///     RemTail:
154PLISTINFO CustomStripifier::RemTail(PLISTHEAD   LHead)
155{
156        PLISTINFO   t, t1;
157
158        if ( LHead == NULL || EMPTYLIST(LHead) )
159        {
160                return  NULL;
161        }
162
163        t                                                                                                       = LHead->LHeaders[LISTTAIL];
164        LHead->LHeaders[LISTTAIL] = (PLISTINFO) t->ListNode.Previous;
165
166        if (LHead->LHeaders[LISTTAIL] != NULL)
167        {
168                t1 = (PLISTINFO) t->ListNode.Previous;
169                t1->ListNode.Next = NULL;
170        }
171        else
172        {
173                LHead->LHeaders[LISTHEAD] = NULL;
174        }
175
176        LHead->NumList--;
177
178        return  t;
179}
180
181///     PeekList:
182PLISTINFO CustomStripifier::PeekList(PLISTHEAD LHead, int wch, int index )
183{
184        PLISTINFO  t;
185
186        if (LHead == NULL)
187        {
188                return  NULL;
189        }
190
191        if ( (t = LHead->LHeaders[wch]) == NULL )
192        {
193                return  NULL;
194        }
195
196        for (; t != NULL && index > 0; index-- )
197        {
198                t = (wch == LISTHEAD)   ?       (PLISTINFO) t->ListNode.Next 
199                                                                                                        :       (PLISTINFO) t->ListNode.Previous;
200        }
201
202        return  t;
203}
204
205///     RemoveList:
206PLISTINFO CustomStripifier::RemoveList(PLISTHEAD LHead, PLISTINFO LInfo )
207{
208        PLISTINFO       t;
209        PLISTINFO       t1;
210
211        t       =       LInfo;
212
213        if (LHead == NULL)
214        {
215                return  NULL;
216        }
217
218        if (LHead->LHeaders[LISTHEAD] == t)
219        {
220                t       =       (PLISTINFO) RemHead(LHead);
221        }
222        else if (LHead->LHeaders[LISTTAIL] == t)
223        {
224                t = (PLISTINFO) RemTail(LHead);
225        }
226        else
227        {
228                t1                    = (PLISTINFO) t->ListNode.Previous;
229                t1->ListNode.Next     = t->ListNode.Next;
230                t1                    = (PLISTINFO) t->ListNode.Next;
231                t1->ListNode.Previous = t->ListNode.Previous;
232                LHead->NumList--;
233        }
234
235        return  t;
236}
237
238///     SearchList:
239///                     Try to find a specific node in the queue whose key matches with
240///                     searching key. Return the pointer to that node if found, return NULL
241///                     otherwise
242///     @param  lpHashTbl       => a far pointer to the hash table.
243///     @param  lpKey           => a far poniter to searching key.
244///     @param  CompareCallBack => comparision function.
245///     @return a far pointer to the node to be found.
246PLISTINFO CustomStripifier::SearchList(
247                        PLISTHEAD listHead,
248                        PVOID lpSKey,
249                        int (* CompareCallBack) ( PVOID, PVOID ) )
250{
251        PLISTINFO list_info;
252
253        list_info = PeekList( listHead, LISTHEAD, 0);
254
255        while ( list_info != NULL )
256        {
257                if ( CompareCallBack( list_info, lpSKey ) )
258                {
259                        break;
260                }
261
262                list_info       =       (PLISTINFO) GetNextNode( list_info );
263        }
264
265        return  list_info;
266}
267
268///     init_vert_norms:
269void CustomStripifier::init_vert_norms(int num_vert)
270{
271  /*   Initialize vertex/normal array to have all zeros to
272       start with.
273  */
274  register int x;
275 
276  for (x = 0; x < num_vert; x++)
277        {
278                *(vert_norms + x) = 0;
279        }
280}
281
282///     init_vert_texture:
283void CustomStripifier::init_vert_texture(int num_vert)
284{
285  /*   Initialize vertex/normal array to have all zeros to
286       start with.
287  */
288  register int x;
289 
290  for (x = 0; x < num_vert; x++)
291        {
292    *(vert_texture + x) = 0;
293        }
294}
295
296///     InitVertexTable:
297BOOL CustomStripifier::InitVertexTable( int size )
298{
299  register int index;
300 
301  /*     Initialize the face table */
302  Vertices      =       (ListHead**) malloc(sizeof(ListHead*) * size );
303 
304  if (Vertices)
305        {
306                for (index      =       0; index < size; index++)
307                {
308                        Vertices[index] = NULL;
309                }
310
311                return  TRUE;
312
313        }
314
315        return  FALSE;
316}
317
318///     InitFaceTable:
319BOOL CustomStripifier::InitFaceTable( int size )
320{
321  register int index;
322 
323  /*     Initialize the face table */
324  PolFaces = (ListHead**) malloc(sizeof(ListHead*) * size);
325 
326  if (PolFaces)
327  {
328        for (index      =       0; index < size; index++)
329                {
330                        PolFaces[index] = NULL;
331                }
332
333                return  TRUE;
334        }
335
336        return  FALSE;
337}
338
339///     InitEdgeTable:
340BOOL CustomStripifier::InitEdgeTable( int size )
341{
342  register int index;
343 
344  /*     Initialize the edge table */
345  PolEdges      =       (ListHead**) malloc(sizeof(ListHead*) * size );
346
347  if (PolEdges)
348        {
349                for (index=0; index < size; index++)
350                {
351                        PolEdges[index] =       NULL;
352                }
353
354                return  TRUE;
355        }
356
357        return  FALSE;
358}
359
360///     InitStripTable:
361void CustomStripifier::InitStripTable( )
362{
363 
364  PLISTHEAD list_head;
365 
366  /*   Initialize the strip table */
367  list_head = (PLISTHEAD) malloc(sizeof(ListHead));
368
369  if (list_head)
370  {
371    InitList(list_head);
372
373    strips[0] = list_head;
374  }
375  else
376  {
377    printf("Out of memory !\n");
378
379    exit(0);
380  }
381 
382}
383
384///     Init_Table_SGI:
385void CustomStripifier::Init_Table_SGI(int numFaces)
386{
387  PLISTHEAD                     list_head;
388  int                                           max_adj         = 60;
389  register                      int     x;
390 
391  /*   This routine will initialize the table that will
392       have the faces sorted by the number of adjacent polygons
393       to it.
394  */
395 
396  for (x=0; x< max_adj; x++)
397  {
398                /*      We are allowing the max number of sides of a polygon
399                                to be max_adj.
400    */                     
401    list_head = (PLISTHEAD) malloc(sizeof(ListHead));
402
403    if (list_head)
404                {
405                        InitList(list_head);
406
407                        array[x]        =       list_head;
408                }
409    else
410                {
411                        printf("Out of memory !\n");
412                        exit(0);
413                }
414        }
415 
416  if (face_array != NULL) /* It seems this function is called more than */
417        {
418    free(face_array);     /* once so we'll free up the old stuff */
419        }
420 
421  face_array = (P_FACE_ADJACENCIES) malloc (sizeof(FACE_ADJACENCIES) * numFaces);
422
423  if (face_array == NULL)
424        {
425    printf("Out of memory !!\n");
426    exit(0);
427  }
428 
429}
430
431///     BuildVertexTable:
432void CustomStripifier::BuildVertexTable(int size)
433{
434  register int  index;
435  PLISTHEAD                     list_head;
436 
437  for (index    =       0; index < size; index++)
438  {
439    list_head   =       (PLISTHEAD) malloc(sizeof(ListHead));
440
441    if (list_head)
442                {
443                        InitList(list_head);
444
445                        Vertices[index] =       list_head;
446                }
447    else
448                {
449                        return;
450                }
451     
452        }
453}
454
455///     BuildFaceTable:
456void CustomStripifier::BuildFaceTable( int size )
457{
458  register int  index;
459  PLISTHEAD                     list_head;
460 
461  for (index    =       0; index < size; index++)
462  {
463    list_head   =       (PLISTHEAD) malloc(sizeof(ListHead));
464
465    if (list_head)
466                {
467                        InitList(list_head);
468
469                        PolFaces[index] =       list_head;
470                }
471                else
472                {
473                        return;
474                }
475        }
476}
477
478///     BuildEdgeTable:
479void CustomStripifier::BuildEdgeTable( int size )
480{
481  register int  index;
482  PLISTHEAD                     list_head;
483 
484  for (index    =       0; index < size; index++)
485  {
486        list_head       =       (PLISTHEAD) malloc(sizeof(ListHead));
487
488                if (list_head)
489                {
490                InitList(list_head);
491
492                PolEdges[index] =       list_head;
493                }
494    else
495                {
496                        return;
497                }
498        }
499}
500
501///     Start_Vertex_Struct:
502void CustomStripifier::Start_Vertex_Struct(int numVerts)
503{
504  if (InitVertexTable(numVerts))
505  {
506    BuildVertexTable(numVerts);
507  }
508}
509
510///     Start_Face_Struct:
511void CustomStripifier::Start_Face_Struct(int numFaces)
512{
513  if (InitFaceTable(numFaces))
514  {
515    BuildFaceTable(numFaces);
516  }
517}
518
519///     Start_Edge_Struct:
520void CustomStripifier::Start_Edge_Struct(int numVerts)
521{
522  if (InitEdgeTable(numVerts))
523  {
524    BuildEdgeTable(numVerts);
525  }
526}
527
528///     switch_lower:
529void CustomStripifier::switch_lower (int *x, int *y)
530{
531  register int temp;
532 
533  /*    Put lower value in x */
534  if (*y < *x)
535  {
536    temp        =       *x;
537    *x          =       *y;
538    *y          =       temp;
539  }
540}
541
542///     member:
543BOOL CustomStripifier::member(int x , int id1, int id2, int id3)
544{
545  /*  Is x in the triangle specified by id1,id2,id3 */
546  if ((x != id1) && (x != id2) && (x != id3))
547        {
548    return      FALSE;
549        }
550
551  return        TRUE;
552}
553
554///     Exist:
555BOOL CustomStripifier::Exist(int faceId, int id1, int id2)
556{
557  /*    Does the edge specified by id1 and id2 exist in this
558        face currently? Maybe we deleted in partial triangulation
559  */
560  ListHead                      *list_head;
561  PF_FACES                      temp;
562  register int  x,size;
563  BOOL                                  a       =       FALSE;
564        BOOL                                    b =     FALSE;
565 
566  list_head     =       PolFaces[faceId];
567
568  temp  =       (PF_FACES) PeekList(list_head, LISTHEAD, 0);
569  size  =       temp->nPolSize;
570
571  for (x=0; x<size; x++)
572  {
573    if (*(temp->pPolygon+x) == id1)
574                {
575                        a = TRUE;
576                }
577     
578                if (*(temp->pPolygon+x) == id2)
579                {
580                        b = TRUE;
581                }
582
583    if (a && b)
584                {
585                        return  TRUE;
586                }
587  }
588
589  return        FALSE;
590}
591
592///     Different:
593int CustomStripifier::Different(int id1,int id2,int id3,int id4,int id5, int id6, int *x, int *y)
594{
595  /*    Find the vertex in the first 3 numbers that does not exist in
596        the last three numbers
597  */
598  if ((id1 != id4) && (id1 != id5) && (id1 != id6))
599    {
600      *x = id2;
601      *y = id3;
602      return id1;
603    }
604  if ((id2 != id4) && (id2 != id5) && (id2 != id6))
605    {
606      *x = id1;
607      *y = id3;
608      return id2;
609    }
610  if ((id3 != id4) && (id3 != id5) && (id3 != id6))
611    {
612      *x = id1;
613      *y = id2;
614      return id3;
615    }
616 
617  /*  Because there are degeneracies in the data, this might occur */
618  *x = id5;
619  *y = id6;
620  return id4;
621}
622
623///     Return_Other:
624int CustomStripifier::Return_Other(int *index,int e1,int e2)
625{
626  /*   We have a triangle and want to know the third vertex of it */
627  register int x;
628 
629  for (x=0;x<3;x++)
630    {
631      if ((*(index+x) != e1) && (*(index+x) != e2))
632        return *(index+x);
633    }
634  /*   If there is a degenerate triangle return arbitrary */
635  return e1;
636}
637
638///     Get_Other_Vertex:
639int CustomStripifier::Get_Other_Vertex(int id1,int id2,int id3,int *index)
640{
641  /*    We have a list index of 4 numbers and we wish to
642        return the number that is not id1,id2 or id3
643  */
644  register int x;
645 
646  for (x=0; x<4; x++)
647    {
648      if ((*(index+x) != id1) && (*(index+x) != id2) &&
649          (*(index+x) != id3))
650        return *(index+x);
651    }
652  /*   If there is some sort of degeneracy this might occur,
653       return arbitrary
654  */
655//  if (x==4)
656    return id1;
657}
658
659///     Done:
660PLISTINFO CustomStripifier::Done(int face_id, int *bucket)
661{
662  /*    Check to see whether the polygon with face_id was used
663        already, return NULL if it was, otherwise return a pointer to the face.
664  */
665 
666  PLISTINFO lpListInfo;
667 
668  lpListInfo = (PLISTINFO) face_array[face_id].pfNode;
669  if (lpListInfo != NULL) {
670    *bucket = face_array[face_id].bucket;
671    return lpListInfo;
672  }
673  else
674    return lpListInfo;
675}
676
677///     First_Edge:
678void CustomStripifier::First_Edge(int *id1,int *id2, int *id3)
679{
680  /*  Get the first triangle in the strip we just found, we will use this to
681      try to extend backwards in the strip
682  */
683 
684  ListHead *pListHead;
685  register int num;
686  P_STRIPS temp1,temp2,temp3;
687 
688  pListHead = strips[0];
689  num = NumOnList(pListHead);
690 
691  /*    Did not have a strip */
692  if (num < 3)
693    return;
694 
695  temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 0);
696  temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 1);
697  temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 2);
698  *id1 = temp1->face_id;
699  *id2 = temp2->face_id;
700  *id3 = temp3->face_id;
701 
702}
703
704///     Last_Edge:
705void CustomStripifier::Last_Edge(int *id1, int *id2, int *id3, BOOL save)
706{
707  /*   We need the last edge that we had  */
708  static int v1, v2, v3;
709 
710  if (save)
711    {
712      v1 = *id1;
713      v2 = *id2;
714      v3 = *id3;
715    }
716  else
717    {
718      *id1 = v1;
719      *id2 = v2;
720      *id3 = v3;
721    }
722}
723
724///     find_triangle_orientation:
725void CustomStripifier::find_triangle_orientation(int vertex1,int vertex2,int vertex3,
726                                      int *original_vertex)                                 
727{
728  int vertices,index;
729  PF_VERTICES verts;
730 
731  /* Search through face to match orignal vertices */
732 
733  /* Start with vertex1's Vertices struct */ 
734  verts = (PF_VERTICES) PeekList(Vertices[vertex1-1],LISTHEAD,0);
735  do { 
736    index = 0;
737    for (vertices = 0; vertices < verts->face->nOrgSize;vertices++) {
738      if (vertex1 == verts->face->pPolygon[vertices]+1 ||
739          vertex2 == verts->face->pPolygon[vertices]+1 ||
740          vertex3 == verts->face->pPolygon[vertices]+1 )
741        original_vertex[index++] = verts->face->pPolygon[vertices]+1;     
742      if (index == 3)
743        break;
744    }
745    if (index == 3)
746      break;
747  } while ((verts = (PF_VERTICES) GetNextNode(verts)) != NULL);
748 
749  if (index != 3) {
750    /* Search vertex2's Vertices struct */ 
751    verts = (PF_VERTICES) PeekList(Vertices[vertex2-1],LISTHEAD,0);
752    do {
753      index = 0;
754      for (vertices = 0; vertices < verts->face->nOrgSize;vertices++) {
755        if (vertex1 == verts->face->pPolygon[vertices]+1 ||
756            vertex2 == verts->face->pPolygon[vertices]+1 ||
757            vertex3 == verts->face->pPolygon[vertices]+1 )
758          original_vertex[index++] = verts->face->pPolygon[vertices]+1;     
759        if (index == 3)
760          break;
761      }
762      if (index == 3)
763        break;
764    } while ((verts = (PF_VERTICES) GetNextNode(verts)) != NULL);
765  }
766 
767  if (index != 3) {
768    /* Search vertex3's Vertices struct */ 
769    verts = (PF_VERTICES) PeekList(Vertices[vertex3-1],LISTHEAD,0);
770    do {   
771      index = 0;
772      for (vertices = 0; vertices < verts->face->nOrgSize;vertices++) {
773        if (vertex1 == verts->face->pPolygon[vertices]+1 ||
774            vertex2 == verts->face->pPolygon[vertices]+1 ||
775            vertex3 == verts->face->pPolygon[vertices]+1 )
776          original_vertex[index++] = verts->face->pPolygon[vertices]+1;     
777        if (index == 3)
778          break;
779      }
780      if (index == 3)
781        break;
782    } while ((verts = (PF_VERTICES) GetNextNode(verts)) != NULL);
783  }
784 
785  /*  if (index !=3 )
786      printf("Warning: Didn't find a triangle for %d %d %d\n",
787      vertex1,vertex2,vertex3);
788  */
789}
790
791///     preserve_strip_orientation_with_normal:
792void CustomStripifier::preserve_strip_orientation_with_normal(FILE *output, int vertex1, int normal1, int vertex2, int normal2, int vertex3, int normal3)
793{
794  int original_vertex[3];
795 
796  find_triangle_orientation(vertex1,vertex2,vertex3, original_vertex);
797 
798  if ( ( original_vertex[0] == vertex3 && original_vertex[1] == vertex2 && original_vertex[2] == vertex1) ||
799       ( original_vertex[0] == vertex2 && original_vertex[1] == vertex1 && original_vertex[2] == vertex3   ) ||
800       ( original_vertex[0] == vertex1 && original_vertex[1] == vertex3 && original_vertex[2] == vertex2   ))  {
801        // New Triangle is in an opposite orientation.  Add vertex2 to correct it
802        fprintf(output," %d//%d",vertex2,normal2);
803  }
804
805}
806
807///     preserve_strip_orientation_with_texture:
808void CustomStripifier::preserve_strip_orientation_with_texture(FILE *output,
809                                             int vertex1, int texture1,
810                                             int vertex2, int texture2,
811                                             int vertex3, int texture3)
812{
813  int original_vertex[3];
814 
815  find_triangle_orientation(vertex1,vertex2,vertex3,                   
816                            original_vertex);
817 
818  if ( ( original_vertex[0] == vertex3 &&
819         original_vertex[1] == vertex2 &&
820         original_vertex[2] == vertex1   ) ||
821       ( original_vertex[0] == vertex2 &&
822         original_vertex[1] == vertex1 &&
823         original_vertex[2] == vertex3   ) ||
824       ( original_vertex[0] == vertex1 &&
825         original_vertex[1] == vertex3 &&
826         original_vertex[2] == vertex2   ) ) {
827    /* New Triangle is in an opposite orientation */
828    /* Add vertex2 to correct it */
829    fprintf(output," %d/%d",vertex2,texture2);
830  }
831}
832
833///     preserve_strip_orientation_with_texture_and_normal:
834void  CustomStripifier::preserve_strip_orientation_with_texture_and_normal(FILE *output,
835                                                         int vertex1, int texture1, int normal1,
836                                                         int vertex2, int texture2, int normal2,
837                                                         int vertex3, int texture3, int normal3)
838{
839  int original_vertex[3];
840 
841  find_triangle_orientation(vertex1,vertex2,vertex3,
842                            original_vertex);
843 
844  if ( ( original_vertex[0] == vertex3 &&
845         original_vertex[1] == vertex2 &&
846         original_vertex[2] == vertex1   ) ||
847       ( original_vertex[0] == vertex2 &&
848         original_vertex[1] == vertex1 &&
849         original_vertex[2] == vertex3   ) ||
850       ( original_vertex[0] == vertex1 &&
851         original_vertex[1] == vertex3 &&
852         original_vertex[2] == vertex2   ) ) {
853    /* New Triangle is in an opposite orientation */
854    /* Add vertex2 to correct it */
855    fprintf(output," %d/%d/%d",vertex2,texture2,normal2);
856  }
857}
858
859///     preserve_strip_orientation:
860void CustomStripifier::preserve_strip_orientation(FILE *output,int vertex1, int vertex2,int vertex3)
861{
862  int original_vertex[3];
863 
864  find_triangle_orientation(vertex1,vertex2,vertex3,
865                            original_vertex);
866 
867  if ( ( original_vertex[0] == vertex3 &&
868         original_vertex[1] == vertex2 &&
869         original_vertex[2] == vertex1   ) ||
870       ( original_vertex[0] == vertex2 &&
871         original_vertex[1] == vertex1 &&
872         original_vertex[2] == vertex3   ) ||
873       ( original_vertex[0] == vertex1 &&
874         original_vertex[1] == vertex3 &&
875         original_vertex[2] == vertex2   ))  {
876    /* New Triangle is in an opposite orientation */
877    /* Add vertex2 to correct it */
878    fprintf(output," %d",vertex2);
879        mi_vector[num_tiras].push_back(vertex2-1);
880  }
881}
882
883///     Output_TriEx:
884void CustomStripifier::Output_TriEx(int id1, int id2, int id3, FILE *output,
885                  int flag, int where)
886{
887  /*   We will save everything into a list, rather than output at once,
888       as was done in the old routine. This way for future modifications
889       we can change the strips later on if we want to.
890  */
891 
892  int swap,temp1,temp2,temp3;
893  static int total=0;
894  static int tri=0;
895  static int strips = 0;
896  static int cost = 0;
897 
898  if (flag == -20)
899    {
900      cost = cost + where+total+tri+strips+strips;
901      printf("We will need to send %d vertices to the renderer\n",cost);
902      total = 0;
903      tri = 0;
904      strips = 0;
905      return ;
906    }
907 
908 
909  if (flag == -10)
910    /*    We are finished, now is time to output the triangle list
911     */
912  {
913                fprintf(output,"\nt");
914          mi_vector_tipo nada;
915          mi_vector.push_back(nada);
916          num_tiras++;
917    tri = tri + Finished(&swap,output,1);
918    total = total + swap;
919    strips++;
920      /*printf("There are %d swaps %d tri %d strips\n",total,tri,strips);*/
921  }
922  else
923  {
924      Last_Edge(&temp1,&temp2,&temp3,0);
925      Add_Id_Strips(id1,where);
926      Add_Id_Strips(id2,where);
927      Add_Id_Strips(id3,where);
928      Last_Edge(&id1,&id2,&id3,1);
929  }
930}
931
932///     Extend_BackwardsEx:
933void CustomStripifier::Extend_BackwardsEx(int face_id, FILE *output, int *ties,
934                        int tie, int triangulate,
935                        int swaps,int *next_id)
936{
937  /*  We just made a strip, now we are going to see if we can extend
938      backwards from the starting face, which had 2 or more adjacencies
939      to start with.
940  */
941 
942  int bucket,next_face,num,x,y,z,c,max,f;             
943  ListHead *pListFace;
944  PF_FACES face;
945  P_ADJACENCIES temp;
946 
947  /*  Get the first triangle that we have saved the the strip data
948      structure, so we can see if there are any polygons adjacent
949      to this edge or a neighboring one
950  */
951  First_Edge(&x,&y,&z);
952 
953  pListFace  = PolFaces[face_id];
954  face = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
955 
956  num = face->nPolSize;
957 
958  /*  Go through the edges to see if there is an adjacency
959      with a vertex in common to the first triangle that was
960      outputted in the strip. (maybe edge was deleted....)
961  */
962  for (c=0; c<num ; c++)
963    {
964     
965      if ( (c != (num-1)) &&
966           (( (*(face->pPolygon+c) == x) && (*(face->pPolygon+c+1) == y)) ||
967            (*(face->pPolygon+c) == y) && (*(face->pPolygon+c+1) == x)))
968        {
969          /*  Input edge is still there see if there is an adjacency */
970          next_face = Find_Face(face_id, x, y, &bucket);
971          if (next_face == -1)
972            /*  Could not find a face adjacent to the edge */
973            break;
974          pListFace = array[bucket];
975          max = NumOnList(pListFace);
976          for (f=0;;f++)
977            {
978              temp = (P_ADJACENCIES) PeekList(pListFace,LISTHEAD,f);   
979              if (temp->face_id == next_face)
980                {
981                  Last_Edge(&z,&y,&x,1);
982                  Polygon_OutputEx(temp,temp->face_id,bucket,pListFace,
983                                   output,ties,tie,triangulate,
984                                   swaps,next_id,0);
985                  return;
986                }
987             
988              if (temp == NULL)
989                {
990                  printf("Error in the new buckets%d %d %d\n",bucket,max,0);
991                  exit(0);
992                }
993            }
994         
995        }
996      else if ( (c == (num -1)) &&
997                ( ((*(face->pPolygon) == x) && (*(face->pPolygon+num-1) == y)) ||
998                  (*(face->pPolygon) == y) && (*(face->pPolygon+num-1) == x)))
999        {
1000          next_face = Find_Face(face_id,x,y,&bucket);
1001          if (next_face == -1)
1002            /*  Could not find a face adjacent to the edge */
1003            break;
1004          pListFace = array[bucket];
1005          max = NumOnList(pListFace);
1006          for (f=0;;f++)
1007            {
1008              temp = (P_ADJACENCIES) PeekList(pListFace,LISTHEAD,f);
1009              if (temp->face_id == next_face)
1010                {
1011                  Last_Edge(&z,&y,&x,1);
1012                  Polygon_OutputEx(temp,temp->face_id,bucket,pListFace,
1013                                   output,ties,tie,triangulate,
1014                                   swaps,next_id,0);
1015                  return;
1016                }
1017             
1018              if (temp == NULL)
1019                {
1020                  printf("Error in the new buckets%d %d %d\n",bucket,max,0);
1021                  exit(0);
1022                }
1023            }
1024        }
1025    }
1026}
1027
1028///     Polygon_OutputEx:
1029void CustomStripifier::Polygon_OutputEx(P_ADJACENCIES temp,int face_id,int bucket,
1030                      ListHead *pListHead, FILE *output,
1031                      int *ties, int tie,
1032                      int triangulate, int swaps,
1033                      int *next_id, int where)
1034{
1035  ListHead *pListFace;
1036  PF_FACES face;
1037  static BOOL begin = TRUE;
1038  int old_face,next_face_id,next_bucket,e1,e2,e3,other1,other2,other3;
1039  P_ADJACENCIES lpListInfo;
1040 
1041  /*      We have a polygon to output, the id is face id, and the number
1042          of adjacent polygons to it is bucket.
1043  */
1044 
1045  Last_Edge(&e1,&e2,&e3,0);
1046 
1047  /*  Get the polygon with id face_id */
1048  pListFace  = PolFaces[face_id];
1049  face = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
1050 
1051  if (face->nPolSize == 3)
1052    {
1053      /*      It is already a triangle */
1054      if (bucket == 0)
1055        {
1056          /*      It is not adjacent to anything so we do not have to
1057                  worry about the order of the sides or updating adjacencies
1058          */
1059         
1060          Last_Edge(&e1,&e2,&e3,0);
1061          next_face_id = Different(*(face->pPolygon),*(face->pPolygon+1),
1062                                   *(face->pPolygon+2),
1063                                   e1,e2,e3,&other1,&other2);
1064          /*  No input edge, at the start */
1065          if ((e2 ==0) && (e3 == 0))
1066            {
1067              e2 = other1;
1068              e3 = other2;
1069            }
1070         
1071          Output_TriEx(e2,e3,next_face_id,NULL,begin,where);
1072          if (face_array[temp->face_id].head == pListHead)
1073            face_array[temp->face_id].pfNode = NULL;
1074          RemoveList(pListHead,(PLISTINFO) temp);
1075          /*      We will be at the beginning of the next strip. */
1076          begin = TRUE;
1077        }
1078      /*      It is a triangle with adjacencies. This means that we
1079              have to:
1080              1. Update the adjacencies in the list, because we are
1081              using this polygon and it will be deleted.
1082              2. Get the next polygon.
1083      */
1084      else
1085        {
1086          /*   Return the face_id of the next polygon we will be using,
1087               while updating the adjacency list by decrementing the
1088               adjacencies of everything adjacent to the current triangle.
1089          */
1090         
1091          next_face_id = Update_AdjacenciesEx(face_id,&next_bucket, &e1,&e2,ties);
1092          old_face = next_face_id;
1093         
1094          /*  Break the tie,  if there was one */
1095          if (tie != FIRST)
1096            old_face = Get_Next_Face(tie,face_id,triangulate);
1097         
1098          if (next_face_id == -1)
1099            {
1100              Polygon_OutputEx(temp,face_id,0,pListHead,output,ties,tie,
1101                               triangulate,swaps,next_id,where);
1102              return;
1103            }
1104         
1105         
1106          /*  We are using a different face */
1107          if ((tie != FIRST) && (old_face != next_face_id) && (swaps == ON))
1108            {
1109              next_face_id = old_face;
1110              /*  Get the new output edge, since e1 and e2 are for the
1111                  original next face that we got.
1112              */
1113              e3 = Get_EdgeEx(&e1,&e2,face->pPolygon,next_face_id,
1114                              face->nPolSize,0,0);
1115            }
1116         
1117          /*      Find the other vertex to transmit in the triangle */
1118          e3 = Return_Other(face->pPolygon,e1,e2);
1119          Last_Edge(&other1,&other2,&other3,0);
1120         
1121          if ((other1 != 0) && (other2 != 0))
1122            {
1123              /*   See which vertex in the output edge is not in the input edge */
1124              if ((e1 != other2) && (e1 != other3))
1125                e3 = e1;
1126              else if ((e2 != other2) && (e2 != other3))
1127                e3 = e2;
1128              /* can happen with > 2 polys on an edge but won't
1129                 form a good strip so stop the strip here
1130              */
1131              else
1132                {
1133                  Polygon_OutputEx(temp,face_id,0,pListHead,output,
1134                                   ties,tie,triangulate,swaps,next_id,where);
1135                  return;
1136                }
1137             
1138              /*   See which vertex of the input edge is not in the output edge */
1139              if ((other2 != e1) && (other2 != e2))
1140                {
1141                  other1 = other2;
1142                  other2 = other3;
1143                }
1144              else if ((other3 != e1) && (other3 != e2))
1145                other1 = other3;
1146              else
1147                {
1148                  /* Degenerate triangle just return*/
1149                  Output_TriEx(other1,other2,e3,NULL,begin,where);
1150                  if (face_array[temp->face_id].head == pListHead)
1151                    face_array[temp->face_id].pfNode = NULL;
1152                  RemoveList(pListHead,(PLISTINFO) temp);
1153                  begin = FALSE;
1154                  return;
1155                }
1156             
1157            }
1158         
1159          /*  There was not an input edge, we are the first triangle in a strip */
1160          else
1161            {
1162              /*   Find the correct order to transmit the triangle, what is
1163                   the output edge that we want ?
1164              */
1165              other1 = e3;
1166              e3 = e2;
1167              other2 = e1;
1168            }
1169         
1170          /*   At this point the adjacencies have been updated  and we
1171               have the next polygon id
1172          */
1173          Output_TriEx(other1,other2,e3,NULL,begin,where);
1174          if (face_array[temp->face_id].head == pListHead)
1175            face_array[temp->face_id].pfNode = NULL;
1176          RemoveList(pListHead,(PLISTINFO) temp);
1177          begin = FALSE;
1178         
1179          if (Done(next_face_id,&next_bucket) == NULL)
1180            return;
1181         
1182          pListHead = array[next_bucket];
1183          lpListInfo = face_array[next_face_id].pfNode;
1184          if (lpListInfo == NULL)
1185            {
1186              printf("There is an error finding the next polygon3 %d\n",
1187                     next_face_id);
1188              exit(0);
1189            }
1190          Polygon_OutputEx(lpListInfo,next_face_id,next_bucket,
1191                           pListHead, output,ties,tie,
1192                           triangulate,swaps,next_id,where);
1193         
1194        }
1195    }
1196 
1197  else
1198    {
1199      /*      It is not a triangle, we have to triangulate it .
1200              Since it is not adjacent to anything we can triangulate it
1201              blindly
1202      */
1203      if (bucket == 0)
1204        {
1205          /*  Check to see if there is not an input edge */
1206          Last_Edge(&other1,&other2,&other3,0);
1207          if ((other1 == 0) && (other2 ==0))
1208            Blind_TriangulateEx(face->nPolSize,face->pPolygon,
1209                                TRUE,where);
1210          else
1211            Blind_TriangulateEx(face->nPolSize,face->pPolygon,
1212                                FALSE,where);
1213         
1214          if (face_array[temp->face_id].head == pListHead)       
1215            face_array[temp->face_id].pfNode = NULL;
1216          RemoveList(pListHead,(PLISTINFO) temp);
1217          /*      We will be at the beginning of the next strip. */
1218          begin = TRUE;
1219        }
1220     
1221      /*  If we have specified PARTIAL triangulation then
1222          we will go to special routines that will break the
1223          polygon and update the data structure. Else everything
1224          below will simply triangulate the whole polygon
1225      */
1226      else if (triangulate == PARTIAL)
1227        {
1228         
1229          /*  Return the face_id of the next polygon we will be using,
1230           */
1231          next_face_id = Min_Face_AdjEx(face_id,&next_bucket,ties);
1232         
1233         
1234          /* Don't do it partially, because we can go inside and get
1235             less adjacencies, for a quad we can do the whole thing.
1236          */
1237          if ((face_id == next_face_id) && (face->nPolSize == 4) && (swaps == ON))
1238            {
1239              next_face_id = Update_AdjacenciesEx(face_id, &next_bucket,
1240                                                  &e1,&e2,ties);
1241              if (next_face_id == -1)
1242                {
1243                  /*  There is no sequential face to go to, end the strip */
1244                  Polygon_OutputEx(temp,face_id,0,pListHead,output,
1245                                   ties,tie,triangulate,swaps,next_id,where);
1246                  return;
1247                }
1248             
1249              /* Break the tie,  if there was one */
1250              if (tie != FIRST)
1251                next_face_id = Get_Next_Face(tie,face_id,triangulate);
1252              Non_Blind_TriangulateEx(face->nPolSize,face->pPolygon,
1253                                      output,next_face_id,face_id,where);
1254             
1255              if (face_array[temp->face_id].head == pListHead)         
1256                face_array[temp->face_id].pfNode = NULL;
1257              RemoveList(pListHead,(PLISTINFO) temp);
1258            }
1259         
1260          /*   Was not a quad but we still do not want to do it partially for
1261               now, since we want to only do one triangle at a time
1262          */
1263          else if ((face_id == next_face_id) && (swaps == ON))
1264            Inside_Polygon(face->nPolSize,face->pPolygon,
1265                           face_id,pListHead,where);
1266         
1267          else
1268            {
1269              if ((tie != FIRST) && (swaps == ON))
1270                next_face_id = Get_Next_Face(tie,face_id,triangulate);
1271              Partial_Triangulate(face->nPolSize,face->pPolygon,
1272                                  output,next_face_id,face_id,next_id,
1273                                  pListHead,temp,where);
1274              /*    Check the next bucket again ,maybe it changed
1275                    We calculated one less, but that might not be the case
1276              */
1277            }
1278         
1279          if (Done(next_face_id,&next_bucket) == NULL)
1280            {
1281              /*  Check to see if there is not an input edge */
1282              Last_Edge(&other1,&other2,&other3,0);
1283              if ((other1 == 0) && (other2 ==0))
1284                Blind_TriangulateEx(face->nPolSize,face->pPolygon,
1285                                    TRUE,where);
1286              else
1287                Blind_TriangulateEx(face->nPolSize,face->pPolygon,
1288                                    FALSE,where);
1289             
1290              if (Done(face_id,&bucket) != NULL)
1291                {
1292                  pListHead = array[bucket];
1293                  lpListInfo = face_array[face_id].pfNode;
1294                  if (face_array[temp->face_id].head == pListHead)
1295                    face_array[lpListInfo->face_id].pfNode = NULL;
1296                  RemoveList(pListHead,(PLISTINFO)lpListInfo);
1297                }
1298              begin = TRUE;
1299              return;
1300            }
1301         
1302          begin = FALSE;
1303          pListHead = array[next_bucket];
1304          lpListInfo = face_array[next_face_id].pfNode;
1305          if (lpListInfo == NULL)
1306            {
1307              printf("There is an error finding the next polygon1 %d %d\n",
1308                     next_face_id,next_bucket);
1309              exit(0);
1310            }
1311          Polygon_OutputEx(lpListInfo,next_face_id,next_bucket,
1312                           pListHead, output,ties,tie,
1313                           triangulate,swaps,next_id,where);
1314        }
1315     
1316     
1317      else
1318        {
1319          /*  WHOLE triangulation */
1320          /*  It is not a triangle and has adjacencies.
1321              This means that we have to:
1322              1. TriangulateEx this polygon, not blindly because
1323              we have an edge that we want to come out on, that
1324              is the edge that is adjacent to a polygon with the
1325              least number of adjacencies. Also we must come in
1326              on the last seen edge.
1327              2. Update the adjacencies in the list, because we are
1328              using this polygon .
1329              3. Get the next polygon.
1330          */
1331          /*   Return the face_id of the next polygon we will be using,
1332               while updating the adjacency list by decrementing the
1333               adjacencies of everything adjacent to the current polygon.
1334          */
1335         
1336          next_face_id = Update_AdjacenciesEx(face_id,&next_bucket, &e1,&e2,ties);
1337         
1338          if (Done(next_face_id,&next_bucket) == NULL)
1339            {
1340              Polygon_OutputEx(temp,face_id,0,pListHead,output,ties,tie,
1341                               triangulate,swaps,next_id,where);
1342              /*    Because maybe there was more than 2 polygons on the edge */
1343              return;
1344            }
1345         
1346          /*      Break the tie,  if there was one */
1347          else if (tie != FIRST)
1348            next_face_id = Get_Next_Face(tie,face_id,triangulate);
1349         
1350          Non_Blind_TriangulateEx(face->nPolSize,face->pPolygon,
1351                                  output,next_face_id,face_id,where);
1352         
1353          if (face_array[temp->face_id].head == pListHead)
1354            face_array[temp->face_id].pfNode = NULL;
1355          RemoveList(pListHead,(PLISTINFO) temp);
1356          begin = FALSE;
1357          pListHead = array[next_bucket];
1358          lpListInfo = face_array[next_face_id].pfNode;
1359         
1360          if (lpListInfo == NULL)
1361            {
1362              printf("There is an error finding the next polygon2 %d %d\n",
1363                     next_face_id,next_bucket);
1364              exit(0);
1365            }
1366          Polygon_OutputEx(lpListInfo,next_face_id,next_bucket,
1367                           pListHead, output,ties,tie,
1368                           triangulate,swaps,next_id,where);
1369        }
1370     
1371    }
1372  Last_Edge(&e1,&e2,&e3,0);
1373}
1374
1375///     Adjacent:
1376int CustomStripifier::Adjacent(int id2,int id1, int *list, int size)
1377{
1378  /*    Return the vertex that is adjacent to id1,
1379        but is not id2, in the list of integers.
1380  */
1381 
1382  register int x=0;
1383 
1384  while (x < size)
1385    {
1386      if (*(list+x) == id1)
1387        {
1388          if ((x != (size -1)) && (x != 0))
1389            {
1390              if ( *(list+x+1) != id2)
1391                return *(list+x+1);
1392              else
1393                return *(list+x-1);
1394            }
1395          else if (x == (size -1))
1396            {
1397              if (*(list) != id2)
1398                return *(list);
1399              else
1400                return *(list+x-1);
1401            }
1402          else
1403            {
1404              if (*(list+size-1) != id2)
1405                return *(list+size-1);
1406              else
1407                return *(list+x+1);
1408            }
1409        }
1410      x++;
1411    }
1412  /*   if there are degeneracies */
1413  return id1;
1414}
1415
1416///     Rearrange_Index:
1417void CustomStripifier::Rearrange_Index(int *index, int size)
1418{
1419  /*    If we are in the middle of a strip we must find the
1420        edge to start on, which is the last edge that we had
1421        transmitted.
1422  */
1423  int x,f,y,e1,e2,e3;
1424  register int increment = 1;
1425  int *temp;
1426 
1427  /*    Find where the input edge is in the input list */
1428  Last_Edge(&e1,&e2,&e3,0);
1429  for (y = 0; y < size; y++)
1430    {
1431      if (*(index+y) == e2)
1432        {
1433          if ((y != (size - 1)) && (*(index+y+1) == e3))
1434            break;
1435          else if ((y == (size - 1)) && (*(index) == e3))
1436            break;
1437          else if ((y != 0) && (*(index+y-1) == e3))
1438            {
1439              increment = -1;
1440              break;
1441            }
1442          else if ((y==0) && (*(index+size-1) == e3))
1443            {
1444              increment = -1;
1445              break;
1446            }
1447        }
1448      if (*(index+y) == e3)
1449        {
1450          if ((y != (size - 1)) && (*(index+y+1) == e2))
1451            break;
1452          else if ((y == (size - 1)) && (*(index) == e2))
1453            break;
1454          else if ((y != 0) && (*(index+y-1) == e2))
1455            {
1456              increment = -1;
1457              break;
1458            }
1459          else if ((y==0) && (*(index+size-1) == e2))
1460            {
1461              increment = -1;
1462              break;
1463            }
1464        }
1465      /*        Edge is not here, we are at the beginning */
1466      if ((y == (size-1)) && (increment != -1))
1467        return;
1468    }
1469 
1470  /*    Now put the list into a new list, starting with the
1471        input edge. Increment tells us whether we have to go
1472        forward or backward.
1473  */
1474  /*    Was in good position already */
1475  if ((y == 0) && (increment == 1))
1476    return;
1477 
1478  temp = (int *) malloc(sizeof(int) * size);
1479  memcpy(temp,index,sizeof(int)*size);
1480 
1481  if (increment == 1)
1482    {
1483      x=0;
1484      for (f = y ; f< size; f++)
1485        {
1486          *(index+x) = *(temp+f);
1487          x++;
1488        }
1489      /*        Finish the rest of the list */ 
1490      for(f = 0; f < y ; f++)
1491        {
1492          *(index+x) = *(temp+f);
1493          x++;
1494        }
1495    }
1496  else
1497    {
1498      x=0;
1499      for (f = y ; f >= 0; f--)
1500        {
1501          *(index+x) = *(temp+f);
1502          x++;
1503        }
1504      /*        Finish the rest of the list */ 
1505      for(f = (size - 1); f > y ; f--)
1506        {
1507          *(index+x) = *(temp+f);
1508          x++;
1509        }
1510    }
1511}
1512
1513///     Delete_From_List:
1514void CustomStripifier::Delete_From_List(int id,int *list, int *size)
1515{
1516  /*    Delete the occurence of id in the list.
1517        (list has size size)
1518  */
1519 
1520  int *temp;
1521  register int x,y=0;
1522 
1523  temp = (int *) malloc(sizeof(int) * (*size));
1524  for (x=0; x<(*size); x++)
1525    {
1526      if (*(list+x) != id)
1527        {
1528          *(temp+y) = *(list+x);
1529          y++;
1530        }
1531    }
1532  *(temp+y) = -1;
1533  *size = *size - (*size - y - 1);
1534  memcpy(list,temp,sizeof(int)*(*size));
1535}
1536
1537///     Build_SGI_Table:
1538void CustomStripifier::Build_SGI_Table(int num_faces)
1539{
1540  /*      Build a table that has the polygons sorted by the
1541          number of adjacent polygons.
1542  */
1543  int x,y,size,tally=0;
1544  ListHead *pListHead;
1545  PF_FACES temp = NULL;
1546 
1547  /* For each face....*/
1548  for (x=0;x < num_faces;x++)
1549    {
1550      pListHead = PolFaces[x];
1551      temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
1552      /*   Check each edge of the face and tally the number of adjacent
1553           polygons to this face.
1554      */                     
1555      if ( temp != NULL )
1556        {
1557          /*      Size of the polygon */
1558          size = temp->nPolSize;
1559          if (size != 1)
1560            {
1561              for (y = 0; y< size; y++)
1562                {
1563                  if (y != (size-1))
1564                    tally += Num_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1));
1565                  else
1566                    tally+= Num_Adj(*(temp->pPolygon),*(temp->pPolygon+(size-1)));
1567                }
1568             
1569              /*   Tally is the number of polygons that is adjacent to
1570                   the current polygon.
1571              */
1572              /*      Now put the face in the proper bucket depending on tally. */
1573              Add_Sgi_Adj(tally,x);
1574              temp = NULL;
1575              tally=0;
1576            }
1577        }
1578    }
1579}
1580
1581///     Triangulate_Quad:
1582void CustomStripifier::Triangulate_Quad(int out_edge1,int out_edge2,int in_edge1,
1583                             int in_edge2,int size,int *index,
1584                             int reversed,int where)
1585{
1586  int vertex4,vertex5;
1587 
1588  /*    This routine will nonblindly triangulate a quad, meaning
1589        that there is a definite input and a definite output
1590        edge that we must adhere to. Reversed will tell the orientation
1591        of the input edge. (Reversed is -1 is we do not have an input
1592        edge, in other words we are at the beginning of a strip.)
1593        Out_edge* is the output edge, and in_edge* is the input edge.
1594        Index are the edges of the polygon
1595        and size is the size of the polygon. Begin is whether we are
1596        at the start of a new strip.
1597  */
1598 
1599  /*    If we do not have an input edge, then we can make our input
1600        edge whatever we like, therefore it will be easier to come
1601        out on the output edge.
1602  */
1603  if (reversed == -1)
1604    {
1605      vertex4 = Adjacent(out_edge1,out_edge2,index,size);
1606      vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index);
1607      Output_Tri(vertex5,vertex4,out_edge1,where);
1608      Output_Tri(vertex4,out_edge1,out_edge2,where);
1609      return;
1610    }
1611 
1612  /*    These are the 5 cases that we can have for the output edge */
1613 
1614  /*  Are they consecutive so that we form a triangle to
1615      peel off, but cannot use the whole quad?
1616  */
1617 
1618  if (in_edge2 == out_edge1)
1619    {
1620      /*        Output the triangle that comes out the correct
1621                edge last. First output the triangle that comes out
1622                the wrong edge.
1623      */
1624      vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index);
1625      Output_Tri(in_edge1,in_edge2,vertex4,where);
1626      Output_Tri(vertex4,in_edge2,out_edge2,where);
1627      return;
1628    }
1629  /*    The next case is where it is impossible to come out the
1630        edge that we want. So we will have to start a new strip to
1631        come out on that edge. We will output the one triangle
1632        that we can, and then start the new strip with the triangle
1633        that comes out on the edge that we want to come out on.
1634  */
1635  else if (in_edge1 == out_edge1)
1636    {
1637      /*        We want to output the first triangle (whose output
1638                edge is not the one that we want.
1639                We have to find the vertex that we need, which is
1640                the other vertex which we do not have.
1641      */
1642      vertex4 = Get_Other_Vertex(in_edge2,in_edge1,out_edge2,index);
1643      Output_Tri(in_edge2,in_edge1,vertex4,where);
1644      Output_Tri(vertex4,in_edge1,out_edge2,where);
1645      return;
1646    }
1647 
1648  /*    Consecutive cases again, but with the output edge reversed */
1649  else if (in_edge1 == out_edge2)
1650    {
1651      vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
1652      Output_Tri(in_edge2,in_edge1,vertex4,where);
1653      Output_Tri(vertex4,in_edge1,out_edge1,where);
1654      return;
1655    }
1656  else if (in_edge2 == out_edge2)
1657    {
1658      vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
1659      Output_Tri(in_edge1,in_edge2,vertex4,where);
1660      Output_Tri(vertex4,in_edge2,out_edge1,where);
1661      return;
1662    }
1663 
1664  /*    The final case is where we want to come out the opposite
1665        edge.
1666  */
1667  else
1668    {
1669      if( ((!reversed) &&
1670           (out_edge1 == (Adjacent(in_edge1,in_edge2,index,size)))) ||
1671          ((reversed) &&
1672           (out_edge2 == (Adjacent(in_edge2,in_edge1,index,size)))))
1673        {
1674          /*    We need to know the orientation of the input
1675                edge, so we know which way to put the diagonal.
1676                And also the output edge, so that we triangulate
1677                correctly.
1678          */
1679          Output_Tri(in_edge1,in_edge2,out_edge2,where);
1680          Output_Tri(in_edge2,out_edge2,out_edge1,where);
1681        }
1682      else
1683        {
1684          /*      Input and output orientation was reversed, so diagonal will
1685                  be reversed from above.
1686          */
1687          Output_Tri(in_edge1,in_edge2,out_edge1,where);
1688          Output_Tri(in_edge2,out_edge1,out_edge2,where);
1689        }
1690      return;
1691    }
1692}
1693
1694///     Triangulate_Polygon:
1695void CustomStripifier::Triangulate_Polygon(     int out_edge1,int out_edge2,
1696                                                                                                                                                                                int in_edge1,   int in_edge2,
1697                                                                                                                                                                                int size,                       int *index,
1698                                                                                                                                                                                FILE *output,   int reversed,
1699                                                                                                                                                                                int face_id,    int where,
1700                                                                                                                                                                                int color1,             int color2,
1701                                                                                                                                                                                int color3)
1702{
1703  /*    We have a polygon that we need to nonblindly triangulate.
1704        We will recursively try to triangulate it, until we are left
1705        with a polygon of size 4, which can use the quad routine
1706        from above. We will be taking off a triangle at a time
1707        and outputting it. We will have 3 cases similar to the
1708        cases for the quad above. The inputs to this routine
1709        are the same as for the quad routine.
1710  */
1711 
1712  int vertex4;
1713  int *temp;
1714 
1715 
1716  /*    Since we are calling this recursively, we have to check whether
1717        we are down to the case of the quad.
1718  */
1719 
1720  if (size == 4)
1721    {
1722      Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size,
1723                       index,reversed,where);
1724      return;
1725    }
1726 
1727 
1728 
1729  /*    We do not have a specified input edge, and therefore we
1730        can make it anything we like, as long as we still come out
1731        the output edge that we want.
1732  */
1733  if (reversed  == -1)
1734    {
1735      /*        Get the vertex for the last triangle, which is
1736                the one coming out the output edge, before we do
1737                any deletions to the list. We will be doing this
1738                bottom up.
1739      */
1740      vertex4 = Adjacent(out_edge1,out_edge2,index,size);
1741      temp = (int *) malloc(sizeof(int) * size);
1742      memcpy(temp,index,sizeof(int)*size);
1743      Delete_From_List(out_edge2,index,&size);
1744      Triangulate_Polygon(out_edge1,vertex4,in_edge2,
1745                          vertex4,size-1,index,output,reversed,face_id,
1746                          where,color1,color2,color3);
1747      memcpy(index,temp,sizeof(int)*size);
1748      /*        Lastly do the triangle that comes out the output
1749                edge.
1750      */
1751      Output_Tri(vertex4,out_edge1,out_edge2,where);
1752      return;
1753    }
1754 
1755  /*    These are the 5 cases that we can have for the output edge */
1756 
1757  /*  Are they consecutive so that we form a triangle to
1758      peel off that comes out the correct output edge,
1759      but we cannot use the whole polygon?
1760  */
1761  if (in_edge2 == out_edge1)
1762    {
1763      /*        Output the triangle that comes out the correct
1764                edge last. First recursively do the rest of the
1765                polygon.
1766      */
1767      /*        Do the rest of the polygon without the triangle.
1768                We will be doing a fan triangulation.
1769      */
1770      /*        Get the vertex adjacent to in_edge1, but is not
1771                in_edge2.
1772      */
1773      vertex4 = Adjacent(in_edge2,in_edge1,index,size);
1774      Output_Tri(in_edge1,in_edge2,vertex4,where);
1775      /*        Create a new edgelist without the triangle that
1776                was just outputted.
1777      */
1778      temp = (int *) malloc(sizeof(int) * size);
1779      memcpy(temp,index,sizeof(int)*size);
1780      Delete_From_List(in_edge1,index,&size);
1781      Triangulate_Polygon(out_edge1,out_edge2,in_edge2,
1782                          vertex4,size-1,index,output,!reversed,face_id,
1783                          where,color1,color2,color3);
1784      memcpy(index,temp,sizeof(int)*size);
1785      return;
1786    }
1787 
1788  /*    Next case is where it is again consecutive, but the triangle
1789        formed by the consecutive edges do not come out of the
1790        correct output edge. For this case, we can not do much to
1791        keep it sequential. Try and do the fan.
1792  */
1793  else if (in_edge1 == out_edge1)
1794    {
1795      /*        Get vertex adjacent to in_edge2, but is not in_edge1 */
1796      vertex4 = Adjacent(in_edge1,in_edge2,index,size);
1797      Output_Tri(in_edge1,in_edge2,vertex4,where);
1798      /*        Since that triangle goes out of the polygon (the
1799                output edge of it), we can make our new input edge
1800                anything we like, so we will try to make it good for
1801                the strip. (This will be like starting a new strip,
1802                all so that we can go out the correct output edge.)
1803      */
1804      temp = (int *) malloc(sizeof(int) * size);
1805      memcpy(temp,index,sizeof(int)*size);
1806      Delete_From_List(in_edge2,index,&size);
1807      Triangulate_Polygon(out_edge1,out_edge2,in_edge1,
1808                          vertex4,size-1,index,output,reversed,face_id,
1809                          where,color1,color2,color3);
1810      memcpy(index,temp,sizeof(int)*size);
1811      return;
1812    }
1813  /*    Consecutive cases again, but with the output edge reversed */
1814  else if (in_edge1 == out_edge2)
1815    {
1816      /*        Get vertex adjacent to in_edge2, but is not in_edge1 */
1817      vertex4 = Adjacent(in_edge1,in_edge2,index,size);
1818      Output_Tri(in_edge2,in_edge1,vertex4,where);
1819      temp = (int *) malloc(sizeof(int) * size);
1820      memcpy(temp,index,sizeof(int)*size);
1821      Delete_From_List(in_edge2,index,&size);
1822      Triangulate_Polygon(out_edge1,out_edge2,in_edge1,
1823                          vertex4,size-1,index,output,reversed,face_id,
1824                          where,color1,color2,color3);
1825      memcpy(index,temp,sizeof(int)*size);
1826      return;
1827    }
1828  else if (in_edge2 == out_edge2)
1829    {
1830      /*        Get vertex adjacent to in_edge2, but is not in_edge1 */
1831      vertex4 = Adjacent(in_edge2,in_edge1,index,size);
1832      Output_Tri(in_edge1,in_edge2,vertex4,where);
1833      temp = (int *) malloc(sizeof(int) * size);
1834      memcpy(temp,index,sizeof(int)*size);
1835      Delete_From_List(in_edge1,index,&size);
1836      Triangulate_Polygon(out_edge1,out_edge2,vertex4,
1837                          in_edge2,size-1,index,output,reversed,face_id,
1838                          where,color1,color2,color3);
1839      memcpy(index,temp,sizeof(int)*size);
1840      return;
1841    }
1842 
1843  /*    Else the edge is not consecutive, and it is sufficiently
1844        far away, for us not to make a conclusion at this time.
1845        So we can take off a triangle and recursively call this
1846        function.
1847  */
1848  else
1849    {
1850      vertex4 = Adjacent(in_edge2,in_edge1,index,size);
1851      Output_Tri(in_edge1,in_edge2,vertex4,where);
1852      temp = (int *) malloc(sizeof(int) * size);
1853      memcpy(temp,index,sizeof(int)*size);
1854      Delete_From_List(in_edge1,index,&size);
1855      Triangulate_Polygon(out_edge1,out_edge2,in_edge2,
1856                          vertex4,size-1,index,output,!reversed,face_id,
1857                          where,color1,color2,color3);
1858      memcpy(index,temp,sizeof(int)*size);
1859      return;
1860    }
1861}
1862
1863///     Triangulate:
1864void CustomStripifier::Triangulate(int out_edge1,int out_edge2,int in_edge1,
1865                        int in_edge2,int size,int *index,
1866                        FILE *output,int reversed,int face_id, int where,
1867                        int color1, int color2,int color3)
1868{
1869  /*    We have the info we need to triangulate a polygon */
1870 
1871  if (size == 4)
1872    Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size,
1873                     index,reversed,where);
1874  else
1875    Triangulate_Polygon(out_edge1,out_edge2,in_edge1,in_edge2,size,
1876                        index,output,reversed,face_id,where,color1,color2,color3);
1877}
1878
1879///     Non_Blind_Triangulate:
1880void CustomStripifier::Non_Blind_Triangulate(int size,int *index,
1881                           FILE *output,int next_face_id,int face_id,int where,
1882                           int color1,int color2,int color3)
1883{
1884  int id1,id2,id3;
1885  int nedge1,nedge2;
1886  int reversed;
1887  /*    We have a polygon that has to be triangulated and we cannot
1888        do it blindly, ie we will try to come out on the edge that
1889        has the least number of adjacencies
1890  */
1891 
1892  Last_Edge(&id1,&id2,&id3,0);
1893  /*    Find the edge that is adjacent to the new face ,
1894        also return whether the orientation is reversed in the
1895        face of the input edge, which is id2 and id3.
1896  */
1897  if (next_face_id == -1)
1898    {
1899      printf("The face is -1 and the size is %d\n",size);
1900      exit(0);
1901    }
1902 
1903  reversed = Get_Edge(&nedge1,&nedge2,index,next_face_id,size,id2,id3);
1904  /* Do the triangulation */
1905 
1906  /* If reversed is -1, the input edge is not in the polygon,
1907     therefore we can have the input edge to be anything we like,
1908     since we are at the beginning of a strip
1909  */
1910  Triangulate(nedge1,nedge2,id2,id3,size,index,output,reversed,
1911              face_id, where,color1,color2,color3);
1912}
1913
1914///     Blind_Triangulate:
1915void CustomStripifier::Blind_Triangulate(int size, int *index, BOOL begin, int where)
1916{
1917  /*    save sides in temp array, we need it so we know
1918        about swaps.
1919  */
1920  int mode, decreasing,increasing,e1,e2,e3;
1921 
1922  /*    Rearrange the index list so that the input edge is first
1923   */
1924  if (!begin)
1925    Rearrange_Index(index,size);
1926 
1927  /*    We are given a polygon of more than 3 sides
1928        and want to triangulate it. We will output the
1929        triangles to the output file.
1930  */
1931 
1932  /*    Find where the input edge is in the input list */
1933  Last_Edge(&e1,&e2,&e3,0);
1934  if (( (!begin) && (*(index) == e2) ) || (begin))
1935    {
1936      Output_Tri(*(index+0),*(index+1),*(index+size-1),where);
1937      /*        If we have a quad, (chances are yes), then we know that
1938                we can just add one diagonal and be done. (divide the
1939                quad into 2 triangles.
1940      */
1941      if (size == 4)
1942        {
1943          Output_Tri(*(index+1),*(index+size-1),*(index+2),where);
1944          return;
1945        }
1946      increasing = 1;
1947      mode = 1;
1948     
1949    }
1950  else if (!begin)
1951    {
1952      Output_Tri(*(index+1),*(index+0),*(index+size-1),where);
1953      if (size == 4)
1954        {
1955          Output_Tri(*(index+0),*(index+size-1),*(index+2),where);
1956          return;
1957        }
1958      Output_Tri(*(index+0),*(index+size-1),*(index+2),where);
1959      increasing = 2;
1960      mode = 0;
1961    }
1962  if (size != 4)
1963    {
1964      /*        We do not have a quad, we have something bigger. */
1965      decreasing = size - 1;           
1966      do
1967        {
1968          /*    Will be alternating diagonals, so we will be increasing
1969                and decreasing around the polygon.
1970          */
1971          if (mode)
1972            {
1973              Output_Tri(*(index+increasing),*(index+decreasing),
1974                         *(index+increasing+1),where);
1975              increasing++;
1976            }
1977          else
1978            {
1979              Output_Tri(*(index+decreasing),*(index+increasing),
1980                         *(index+decreasing-1),where);
1981              decreasing--;
1982            }
1983          mode = !mode;
1984        } while ((decreasing - increasing) >= 2);
1985     
1986    }
1987}
1988
1989///     Get_Edge:
1990int CustomStripifier::Get_Edge(int *edge1,int *edge2,int *index,int face_id,
1991             int size, int id1, int id2)
1992{
1993  /*    Put the edge that is adjacent to face_id into edge1
1994        and edge2. For each edge see if it is adjacent to
1995        face_id. Id1 and id2 is the input edge, so see if
1996        the orientation is reversed, and save it in reversed.
1997  */
1998  register int x;
1999  int reversed = -1;
2000  BOOL set = FALSE;
2001 
2002  for (x=0; x< size; x++)
2003    {
2004      if (x == (size-1))
2005        {
2006          if ((*(index) == id1) && (*(index+size-1)==id2))
2007            {
2008              if (set)
2009                return 1;
2010              reversed = 1;
2011            }
2012          else if ((*(index) == id2) && (*(index+size-1)==id1))
2013            {
2014              if (set)
2015                return 0;
2016              reversed = 0;
2017            }
2018         
2019          if (Look_Up(*(index),*(index+size-1),face_id))
2020            {
2021              if ( (out1 != -1) &&
2022                   ( (out1 == *(index)) ||
2023                     (out1 == *(index+size-1)) ) &&
2024                   ( (out2 == *(index)) ||
2025                     (out2 == *(index+size-1)) ))
2026                {
2027                  set = TRUE;
2028                  *edge1 = *(index);
2029                  *edge2 = *(index+size-1);
2030                }
2031              else if (out1 == -1)
2032                {
2033                  set = TRUE;
2034                  *edge1 = *(index);
2035                  *edge2 = *(index+size-1);
2036                }
2037              if ((reversed != -1) && (set)) 
2038                return reversed;
2039            }
2040        }               
2041      else
2042        {
2043          if ((*(index+x) == id1) && (*(index+x+1)==id2))
2044            {
2045              if (set)
2046                return 0;
2047              reversed = 0;
2048            }
2049          else if ((*(index+x) == id2) && (*(index+x+1)==id1))
2050            {
2051              if (set)
2052                return 1;
2053              reversed = 1;
2054            }
2055         
2056          if (Look_Up(*(index+x),*(index+x+1),face_id))
2057            {
2058              if ( (out1 != -1) &&
2059                   ( (out1 == *(index+x)) ||
2060                     (out1 == *(index+x+1)) ) &&
2061                   ((out2 == *(index+x)) ||
2062                    (out2 == *(index+x+1))))
2063                {
2064                  set = TRUE;
2065                  *edge1 = *(index+x);
2066                  *edge2 = *(index+x+1);
2067                }
2068              else if (out1 == -1)
2069                {
2070                  set = TRUE;
2071                  *edge1 = *(index+x);
2072                  *edge2 = *(index+x + 1);
2073                }
2074              if ((reversed != -1) && (set))
2075                return reversed;
2076            }
2077        }
2078    }                   
2079  if ((x == size) && (reversed != -1))
2080    {
2081      /*        Could not find the output edge */
2082      printf("Error in the Lookup %d %d %d %d %d %d %d %d\n",
2083             face_id,id1,id2,reversed,*edge1,*edge2,out1,out2);
2084      exit(0);
2085    }
2086  return reversed;
2087}
2088
2089///     Udate_Face:
2090void CustomStripifier::Update_Face(int *next_bucket, int *min_face, int face_id, int *e1,
2091                        int *e2,int temp1,int temp2,int *ties)
2092{
2093  /*    We have a face id that needs to be decremented.
2094        We have to determine where it is in the structure,
2095        so that we can decrement it.
2096  */
2097  /*    The number of adjacencies may have changed, so to locate
2098        it may be a little tricky. However we know that the number
2099        of adjacencies is less than or equal to the original number
2100        of adjacencies,
2101  */
2102  int y,size;
2103  ListHead *pListHead;
2104  PF_FACES temp = NULL;
2105  PLISTINFO lpListInfo;
2106  static int each_poly = 0;
2107  BOOL there = FALSE;
2108 
2109  pListHead = PolFaces[face_id];
2110  temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
2111  /*    Check each edge of the face and tally the number of adjacent
2112        polygons to this face.
2113  */                   
2114  if ( temp != NULL )
2115    {
2116      /*        Size of the polygon */
2117      size = temp->nPolSize;
2118      /*  We did it already */
2119      if (size == 1)
2120        return;
2121      for (y = 0; y< size; y++)
2122        {
2123          /*    If we are doing partial triangulation, we must check
2124                to see whether the edge is still there in the polygon,
2125                since we might have done a portion of the polygon
2126                and saved the rest for later.
2127          */
2128          if (y != (size-1))
2129            {
2130              if( ((temp1 == *(temp->pPolygon+y)) &&
2131                   (temp2 ==*(temp->pPolygon+y+1))) ||
2132                  ((temp2 == *(temp->pPolygon+y)) &&
2133                   (temp1 ==*(temp->pPolygon+y+1))))
2134                /*      edge is still there we are ok */
2135                there = TRUE;
2136            }
2137          else
2138            {
2139              if( ((temp1 == *(temp->pPolygon)) &&
2140                   (temp2 == *(temp->pPolygon+size-1))) ||
2141                  ((temp2 == *(temp->pPolygon)) &&
2142                   (temp1 ==*(temp->pPolygon+size-1))))
2143                /*      edge is still there we are ok */
2144                there = TRUE;
2145            }
2146        }
2147     
2148      if (!there)
2149        /*      Original edge was already used, we cannot use this polygon */
2150        return;
2151     
2152      /*        We have a starting point to start our search to locate
2153                this polygon.
2154      */
2155     
2156      /*        Check to see if this polygon was done */
2157      lpListInfo = Done(face_id,&y);
2158     
2159      if (lpListInfo == NULL)
2160        return;
2161     
2162      /*  Was not done, but there is an error in the adjacency calculations */
2163      if (y == 0)
2164        {
2165          printf("There is an error in finding the adjacencies\n");
2166          exit(0);
2167        }
2168     
2169      /*        Now put the face in the proper bucket depending on tally. */
2170      /*        First add it to the new bucket, then remove it from the old */
2171      Add_Sgi_Adj(y-1,face_id);
2172      RemoveList(array[y],lpListInfo);
2173     
2174      /*        Save it if it was the smallest seen so far since then
2175                it will be the next face
2176                Here we will have different options depending on
2177                what we want for resolving ties:
2178                1) First one we see we will use
2179                2) Random resolving
2180                3) Look ahead
2181                4) Alternating direction
2182      */
2183      /*        At a new strip */
2184      if (*next_bucket == 60)
2185        *ties = *ties + each_poly;
2186      /*        Have a tie */
2187      if (*next_bucket == (y-1))
2188        {
2189          Add_Ties(face_id);
2190          each_poly++;
2191        }
2192      /*        At a new minimum */
2193      if (*next_bucket > (y-1))
2194        {
2195          *next_bucket = y-1;
2196          *min_face = face_id;
2197          *e1 = temp1;
2198          *e2 = temp2;
2199          each_poly = 0;
2200          Clear_Ties();
2201          Add_Ties(face_id);
2202        }
2203    }
2204}
2205
2206///     Delete_Adj:
2207void CustomStripifier::Delete_Adj(int id1, int id2,int *next_bucket,int *min_face,
2208                       int current_face,int *e1,int *e2,int *ties)
2209{
2210  /*    Find the face that is adjacent to the edge and is not the
2211        current face. Delete one adjacency from it. Save the min
2212        adjacency seen so far.
2213  */
2214  register int count=0;
2215  PF_EDGES temp = NULL;
2216  ListHead *pListHead;
2217  int next_face;
2218 
2219  /*    Always want smaller id first */
2220  switch_lower(&id1,&id2);
2221 
2222  pListHead = PolEdges[id1];
2223  temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
2224  if (temp == NULL)
2225    /*  It could be a new edge that we created. So we can
2226        exit, since there is not a face adjacent to it.
2227    */
2228    return;
2229  while (temp->edge[0] != id2)
2230    {
2231      count++;
2232      temp = ( PF_EDGES )GetNextNode(temp);                                       
2233     
2234      if (temp == NULL)
2235        /*      Was a new edge that was created and therefore
2236                does not have anything adjacent to it
2237        */
2238        return;
2239    }
2240  /*    Was not adjacent to anything else except itself */
2241  if (temp->edge[2] == -1)
2242    return;
2243 
2244  /*    Was adjacent to something */
2245  else
2246    {
2247      if (temp->edge[2] == current_face)
2248        next_face =  temp->edge[1];
2249      else
2250        next_face = temp->edge[2];
2251    }
2252  /*    We have the other face adjacent to this edge, it is
2253        next_face. Now we need to decrement this faces' adjacencies.
2254  */
2255  Update_Face(next_bucket, min_face, next_face,e1,e2,id1,id2,ties);
2256}
2257
2258///     Update_Adjacencies:
2259int CustomStripifier::Update_Adjacencies(int face_id, int *next_bucket, int *e1, int *e2,
2260                       int *ties)
2261{
2262  /*    Give the face with id face_id, we want to decrement
2263        all the faces that are adjacent to it, since we will
2264        be deleting face_id from the data structure.
2265        We will return the face that has the least number
2266        of adjacencies.
2267  */
2268  PF_FACES temp = NULL;
2269  ListHead *pListHead;
2270  int size,y,min_face = -1;
2271 
2272  *next_bucket = 60;
2273  pListHead = PolFaces[face_id];
2274  temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
2275 
2276  if ( temp == NULL )
2277    {
2278      printf("The face was already deleted, there is an error\n");
2279      exit(0);
2280    }
2281 
2282  /*    Size of the polygon */
2283  size = temp->nPolSize;
2284  for (y = 0; y< size; y++)
2285    {
2286      if (y != (size-1))
2287        Delete_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),
2288                   next_bucket,&min_face,face_id,e1,e2,ties);
2289      else
2290        Delete_Adj(*(temp->pPolygon),*(temp->pPolygon+(size-1)),
2291                   next_bucket,&min_face,face_id,e1,e2,ties);
2292    }
2293  return (min_face);
2294}
2295
2296///     Old_Adj:
2297int CustomStripifier::Old_Adj(int face_id)
2298{
2299  /*    Find the bucket that the face_id is currently in,
2300        because maybe we will be deleting it.
2301  */
2302  PF_FACES temp = NULL;
2303  ListHead *pListHead;
2304  int y;
2305 
2306  pListHead = PolFaces[face_id];
2307  temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
2308  if ( temp == NULL )
2309    {
2310      printf("The face was already deleted, there is an error\n");
2311      exit(0);
2312    }
2313 
2314  if (Done(face_id,&y) == NULL)
2315    {
2316      printf("There is an error in finding the face\n");
2317      exit(0);
2318    }
2319  return y;
2320}
2321
2322///     Number_Adj:
2323int CustomStripifier::Number_Adj(int id1, int id2, int curr_id)
2324{
2325  /*    Given edge whose endpoints are specified by id1 and id2,
2326        determine how many polygons share this edge and return that
2327        number minus one (since we do not want to include the polygon
2328        that the caller has already).
2329  */
2330 
2331  int size,y,count=0;
2332  PF_EDGES temp = NULL;
2333  PF_FACES temp2 = NULL;
2334  ListHead *pListHead;
2335  BOOL there= FALSE;
2336 
2337  /*    Always want smaller id first */
2338  switch_lower(&id1,&id2);
2339 
2340  pListHead = PolEdges[id1];
2341  temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
2342  if (temp == NULL)
2343    /*  new edge that was created might not be here */
2344    return 0;
2345  while (temp->edge[0] != id2)
2346    {
2347      count++;
2348      temp = ( PF_EDGES )GetNextNode(temp);                               
2349     
2350      if (temp == NULL)
2351        /*      This edge was not there in the original, which
2352                mean that we created it in the partial triangulation.
2353                So it is adjacent to nothing.
2354        */
2355        return 0;
2356    }
2357  /*    Was not adjacent to anything else except itself */
2358  if (temp->edge[2] == -1)
2359    return 0;
2360  else
2361    {
2362      /* It was adjacent to another polygon, but maybe we did this
2363         polygon already, and it was done partially so that this edge
2364         could have been done
2365      */
2366      if (curr_id != temp->edge[1])
2367        {
2368          /* Did we use this polygon already?and it was deleted
2369             completely from the structure
2370          */
2371          pListHead = PolFaces[temp->edge[1]];
2372          temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
2373          if (Done(temp->edge[1],&size) == NULL)
2374            return 0;
2375        }
2376      else
2377        {
2378          pListHead = PolFaces[temp->edge[2]];
2379          temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
2380          if (Done(temp->edge[2],&size)== NULL)
2381            return 0;
2382        }
2383     
2384      /* Now we have to check whether it was partially done, before
2385         we can say definitely if it is adjacent.
2386         Check each edge of the face and tally the number of adjacent
2387         polygons to this face.
2388      */                       
2389      if ( temp2 != NULL )
2390        {
2391          /* Size of the polygon */
2392          size = temp2->nPolSize;
2393          for (y = 0; y< size; y++)
2394            {
2395              /* If we are doing partial triangulation, we must check
2396                 to see whether the edge is still there in the polygon,
2397                 since we might have done a portion of the polygon
2398                 and saved the rest for later.
2399              */
2400              if (y != (size-1))
2401                {
2402                  if(((id1 == *(temp2->pPolygon+y)) &&
2403                      (id2 ==*(temp2->pPolygon+y+1))) ||
2404                     ((id2 == *(temp2->pPolygon+y)) &&
2405                      (id1 ==*(temp2->pPolygon+y+1))))
2406                    /*  edge is still there we are ok */
2407                    there = TRUE;
2408                }
2409              else
2410                {
2411                  if(((id1 == *(temp2->pPolygon)) &&
2412                      (id2 == *(temp2->pPolygon+size-1))) ||
2413                     ((id2 == *(temp2->pPolygon)) &&
2414                      (id1 ==*(temp2->pPolygon+size-1))))
2415                    /*  edge is still there we are ok */
2416                    there = TRUE;
2417                }
2418            }
2419        }
2420     
2421      if (there )
2422        return 1;
2423      return 0;
2424    }
2425}
2426
2427///     Min_Adj:
2428int CustomStripifier::Min_Adj(int id)
2429{
2430  /*    Used for the lookahead to break ties. It will
2431        return the minimum adjacency found at this face.
2432  */
2433  int y,numverts,t,x=60;
2434  PF_FACES temp=NULL;
2435  ListHead *pListHead;
2436 
2437  /*    If polygon was used then we can't use this face */
2438  if (Done(id,&y) == NULL)
2439    return 60;
2440 
2441  /*    It was not used already */
2442  pListHead = PolFaces[id];
2443  temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
2444  if ( temp != NULL )
2445    {
2446      numverts = temp->nPolSize;
2447      for (y = 0; y< numverts; y++)
2448        {
2449          if (y != (numverts-1))
2450            t = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),id);
2451          else
2452            t = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+(numverts-1)),id);
2453          if (t < x)
2454            x = t;
2455        }
2456    }
2457  if (x == -1)
2458    {
2459      printf("Error in the look\n");
2460      exit(0);
2461    }
2462  return x;
2463}
2464
2465///     Edje_Least:
2466void CustomStripifier::Edge_Least(int *index,int *new1,int *new2,int face_id,int size)
2467{
2468  /*   We had a polygon without an input edge and now we re going to pick one
2469       of the edges with the least number of adjacencies to be the input
2470       edge
2471  */
2472  register int x,value,smallest=60;
2473 
2474  for (x = 0; x<size; x++)
2475    {
2476      if (x != (size -1) )
2477        value = Number_Adj(*(index+x),*(index+x+1),face_id);
2478      else
2479        value = Number_Adj(*(index),*(index+size-1),face_id);
2480      if (value < smallest)
2481        {
2482          smallest = value;
2483          if (x != (size -1))
2484            {
2485              *new1 = *(index+x);
2486              *new2 = *(index+x+1);
2487            }
2488          else
2489            {
2490              *new1 = *(index);
2491              *new2 = *(index+size-1);
2492            }
2493        }
2494    }
2495  if ((smallest == 60) || (smallest < 0))
2496    {
2497      printf("There is an error in getting the least edge\n");
2498      exit(0);
2499    }
2500}
2501
2502///     Check_In_Polygon:
2503void CustomStripifier::Check_In_Polygon(int face_id, int *min, int size)
2504{
2505  /*  Check to see the adjacencies by going into a polygon that has
2506      greater than 4 sides.
2507  */
2508 
2509  ListHead *pListHead;
2510  PF_FACES temp;
2511  int y,id1,id2,id3,x=0,z=0;
2512  int saved[2];
2513  int big_saved[60];
2514 
2515  pListHead = PolFaces[face_id];
2516  temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
2517 
2518  /*   Get the input edge that we came in on */
2519  Last_Edge(&id1,&id2,&id3,0);
2520 
2521  /*  Find the number of adjacencies to the edges that are adjacent
2522      to the input edge.
2523  */
2524  for (y=0; y< size; y++)
2525    {
2526      if (y != (size-1))
2527        {
2528          if (((*(temp->pPolygon+y) == id2) && (*(temp->pPolygon+y+1) != id3))
2529              || ((*(temp->pPolygon+y) == id3) && (*(temp->pPolygon+y+1) != id2)))
2530            {
2531              saved[x++] = Number_Adj(*(temp->pPolygon+y),
2532                                      *(temp->pPolygon+y+1),face_id);
2533              big_saved[z++] = saved[x-1];
2534            }
2535          else
2536            big_saved[z++] = Number_Adj(*(temp->pPolygon+y),
2537                                        *(temp->pPolygon+y+1),face_id);
2538        }
2539      else
2540        {
2541          if (((*(temp->pPolygon) == id2) &&
2542               (*(temp->pPolygon+size-1) != id3)) ||
2543              ((*(temp->pPolygon) == id3) &&
2544               (*(temp->pPolygon+size-1) != id2)))
2545            {
2546              saved[x++] = Number_Adj(*(temp->pPolygon),
2547                                      *(temp->pPolygon+size-1),face_id);
2548              big_saved[z++] = saved[x-1];
2549            }
2550          else
2551            big_saved[z++] = Number_Adj(*(temp->pPolygon),
2552                                        *(temp->pPolygon+size-1),face_id);
2553        }
2554    }
2555  /*  There was an input edge */
2556  if (x == 2)
2557    {
2558      if (saved[0] < saved[1])
2559        /*  Count the polygon that we will be cutting as another adjacency*/
2560        *min = saved[0] + 1;
2561      else
2562        *min = saved[1] + 1;
2563    }
2564  /*  There was not an input edge */
2565  else
2566    {
2567      if (z != size)
2568        {
2569          printf("There is an error with the z %d %d\n",size,z);
2570          exit(0);
2571        }
2572      *min = 60;
2573      for (x = 0; x < size; x++)
2574        {
2575          if (*min > big_saved[x])
2576            *min = big_saved[x];
2577        }
2578    }
2579}
2580
2581///     New_Face:
2582void CustomStripifier::New_Face (int face_id, int v1, int v2, int v3)
2583{
2584  /*    We want to change the face that was face_id, we will
2585        change it to a triangle, since the rest of the polygon
2586        was already outputtted
2587  */
2588  ListHead *pListHead;
2589  PF_FACES temp = NULL;
2590 
2591  pListHead = PolFaces[face_id];
2592  temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0);
2593  /*    Check each edge of the face and tally the number of adjacent
2594        polygons to this face.
2595  */                   
2596  if ( temp != NULL )
2597    {
2598      /*        Size of the polygon */
2599      if (temp->nPolSize != 4)
2600        {
2601          printf("There is a miscalculation in the partial\n");
2602          exit (0);
2603        }
2604      temp->nPolSize = 3;
2605      *(temp->pPolygon) = v1;
2606      *(temp->pPolygon+1) = v2;
2607      *(temp->pPolygon+2) = v3;
2608    }
2609}
2610
2611///     New_Size_Face:
2612void CustomStripifier::New_Size_Face(int face_id)
2613{
2614  /*    We want to change the face that was face_id, we will
2615        change it to a triangle, since the rest of the polygon
2616        was already outputtted
2617  */
2618  ListHead *pListHead;
2619  PF_FACES temp = NULL;
2620 
2621  pListHead = PolFaces[face_id];
2622  temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
2623  /*    Check each edge of the face and tally the number of adjacent
2624        polygons to this face.
2625  */                   
2626  if ( temp != NULL )
2627    (temp->nPolSize)--;
2628  else
2629    printf("There is an error in updating the size\n");
2630}
2631
2632///     Check_In_Quad:
2633void  CustomStripifier::Check_In_Quad(int face_id,int *min)
2634{
2635  /*   Check to see what the adjacencies are for the polygons that
2636       are inside the quad, ie the 2 triangles that we can form.
2637  */
2638  ListHead *pListHead;
2639  int y,id1,id2,id3,x=0;
2640  int saved[4];
2641  PF_FACES temp;
2642  register int size = 4;
2643 
2644  pListHead = PolFaces[face_id];
2645  temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
2646 
2647  /*   Get the input edge that we came in on */
2648  Last_Edge(&id1,&id2,&id3,0);
2649 
2650  /*    Now find the adjacencies for the inside triangles */
2651  for (y = 0; y< size; y++)
2652    {
2653      /*     Will not do this if the edge is the input edge */
2654      if (y != (size-1))
2655        {
2656          if ((((*(temp->pPolygon+y) == id2) &&
2657                (*(temp->pPolygon+y+1) == id3))) ||
2658              (((*(temp->pPolygon+y) == id3) &&
2659                (*(temp->pPolygon+y+1) == id2))))
2660            saved[x++] = -1;
2661          else
2662            {
2663              if (x == 4)
2664                {
2665                  printf("There is an error in the check in quad \n");
2666                  exit(0);
2667                }
2668              /*    Save the number of Adjacent Polygons to this edge */
2669              saved[x++] = Number_Adj(*(temp->pPolygon+y),
2670                                      *(temp->pPolygon+y+1),face_id);
2671            }
2672        }
2673      else if ((((*(temp->pPolygon) == id2) &&
2674                 (*(temp->pPolygon+size-1) == id3))) ||
2675               (((*(temp->pPolygon) == id3) &&
2676                 (*(temp->pPolygon+size-1) == id2))) )
2677        saved[x++] = -1;
2678      else
2679        {
2680          if (x == 4)
2681            {
2682              printf("There is an error in the check in quad \n");
2683              exit(0);
2684            }
2685          /*    Save the number of Adjacent Polygons to this edge */
2686          saved[x++] = Number_Adj(*(temp->pPolygon),
2687                                  *(temp->pPolygon+size-1),face_id);
2688         
2689        }
2690    }
2691  if (x != 4)
2692    {
2693      printf("Did not enter all the values %d \n",x);
2694      exit(0);
2695    }
2696 
2697  *min = 10;
2698  for (x=0; x<4; x++)
2699    {
2700      if (x!= 3)
2701        {
2702          if ((saved[x] != -1) && (saved[x+1] != -1) &&
2703              ((saved[x] + saved[x+1]) < *min))
2704            *min = saved[x] + saved[x+1];
2705        }
2706      else
2707        {
2708          if ((saved[0] != -1) && (saved[x] != -1) &&
2709              ((saved[x] + saved[0]) < *min))
2710            *min = saved[0] + saved[x];
2711        }
2712    }
2713}
2714
2715///     Get_Output_Edge:
2716int CustomStripifier::Get_Output_Edge(int face_id, int size, int *index,int id2,int id3)
2717{
2718  /*  Return the vertex adjacent to either input1 or input2 that
2719      is adjacent to the least number of polygons on the edge that
2720      is shared with either input1 or input2.
2721  */
2722  register int x=0,y;
2723  int saved[2];
2724  int edges[2][1];
2725 
2726  for (y = 0; y < size; y++)
2727    {
2728      if (y != (size-1))
2729        {
2730          if (((*(index+y) == id2) && (*(index+y+1) != id3))
2731              || ((*(index+y) == id3) && (*(index+y+1) != id2)))
2732            {
2733              saved[x++] = Number_Adj(*(index+y),*(index+y+1),face_id);
2734              edges[x-1][0] = *(index+y+1);
2735            }
2736          else if (y != 0)
2737            {
2738              if (( (*(index+y) == id2) && (*(index+y-1) != id3) ) ||
2739                  ( (*(index+y) == id3) && (*(index+y-1) != id2)) )
2740                {
2741                  saved[x++] = Number_Adj(*(index+y),*(index+y-1),face_id);
2742                  edges[x-1][0] = *(index+y-1);
2743                }
2744            }
2745          else if (y == 0)
2746            {
2747              if (( (*(index) == id2) && (*(index+size-1) != id3) ) ||
2748                  ( (*(index) == id3) && (*(index+size-1) != id2)) )
2749                {
2750                  saved[x++] = Number_Adj(*(index),*(index+size-1),face_id);
2751                  edges[x-1][0] = *(index+size-1);
2752                }
2753            }
2754         
2755        }
2756      else
2757        {
2758          if (((*(index+size-1) == id2) && (*(index) != id3))
2759              || ((*(index+size-1) == id3) && (*(index) != id2)))
2760            {
2761              saved[x++] = Number_Adj(*(index),*(index+size-1),face_id);
2762              edges[x-1][0] = *(index);
2763            }
2764         
2765          if (( (*(index+size-1) == id2) && (*(index+y-1) != id3) ) ||
2766              ( (*(index+size-1) == id3) && (*(index+y-1) != id2)) )
2767            {
2768              saved[x++] = Number_Adj(*(index+size-1),*(index+y-1),face_id);
2769              edges[x-1][0] = *(index+y-1);
2770            }
2771        }
2772    }
2773  if ((x != 2))
2774    {
2775      printf("There is an error in getting the input edge %d \n",x);
2776      exit(0);
2777    }
2778  if (saved[0] < saved[1])
2779    return edges[0][0];
2780  else
2781    return edges[1][0];
2782 
2783}
2784
2785///     Get_Input_Edge:
2786void CustomStripifier::Get_Input_Edge(int *index,int id1,int id2,int id3,
2787                    int *new1,int *new2,int size,int face_id)
2788{
2789  /*  We had a polygon without an input edge and now we are going to pick one
2790      as the input edge. The last triangle was id1,id2,id3, we will try to
2791      get an edge to have something in common with one of those vertices,
2792      otherwise we will pick the edge with the least number of adjacencies.
2793  */
2794 
2795  register int x;
2796  int saved[3];
2797 
2798  saved[0] = -1;
2799  saved[1] = -1;
2800  saved[2] = -1;
2801 
2802  /*  Go through the edges to see if there is one in common with one
2803      of the vertices of the last triangle that we had, preferably id2 or
2804      id3 since those are the last 2 things in the stack of size 2.
2805  */
2806  for (x=0; x< size; x++)
2807    {
2808      if (*(index+x) == id1)
2809        {
2810          if (x != (size-1))
2811            saved[0] = *(index+x+1);
2812          else
2813            saved[0] = *(index);
2814        }
2815     
2816      if (*(index+x) == id2)
2817        {
2818          if (x != (size-1))
2819            saved[1] = *(index+x+1);
2820          else
2821            saved[1] = *(index);
2822        }
2823     
2824      if (*(index+x) == id3)
2825        {
2826          if (x != (size -1))
2827            saved[2] = *(index+x+1);
2828          else
2829            saved[2] = *(index);
2830        }
2831    }
2832  /*  Now see what we saved */
2833  if (saved[2] != -1)
2834    {
2835      *new1 = id3;
2836      *new2 = saved[2];
2837      return;
2838    }
2839  else if (saved[1] != -1)
2840    {
2841      *new1 = id2;
2842      *new2 = saved[1];
2843      return;
2844    }
2845  else if (saved[0] != -1)
2846    {
2847      *new1 = id1;
2848      *new2 = saved[0];
2849      return;
2850    }
2851  /*  We did not find anything so get the edge with the
2852      least number of adjacencies
2853  */
2854  Edge_Least(index,new1,new2,face_id,size);
2855 
2856}
2857
2858///     Find_Face:
2859int CustomStripifier::Find_Face(int current_face, int id1, int id2, int *bucket)
2860{
2861  /*    Find the face that is adjacent to the edge and is not the
2862        current face.
2863  */
2864  register int size,y,count=0;   
2865  PF_EDGES temp = NULL;
2866  PF_FACES temp2 = NULL;
2867  ListHead *pListHead;
2868  int next_face;
2869  BOOL there = FALSE;
2870 
2871 
2872  /*    Always want smaller id first */
2873  switch_lower(&id1,&id2);
2874 
2875  pListHead = PolEdges[id1];
2876  temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
2877  /*  The input edge was a new edge */
2878  if (temp == NULL)
2879    return -1;
2880 
2881  while (temp->edge[0] != id2)
2882    {
2883      count++;
2884      temp = ( PF_EDGES )GetNextNode(temp);                                   
2885     
2886      /*  The input edge was a new edge */
2887      if (temp == NULL)
2888        return -1;
2889    }
2890  /*    Was not adjacent to anything else except itself */
2891  if (temp->edge[2] == -1)
2892    return -1;
2893  else
2894    {
2895      if (temp->edge[2] == current_face)
2896        next_face =  temp->edge[1];
2897      else
2898        next_face = temp->edge[2];
2899    }
2900  /* We have the other face adjacent to this edge, it is
2901     next_face.
2902  */
2903  pListHead = PolFaces[next_face];
2904  temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
2905 
2906  /* See if the face was already deleted, and where
2907     it is if it was not
2908  */
2909 
2910  if (Done(next_face,bucket) == NULL)
2911    return -1;
2912 
2913  /*  Make sure the edge is still in this polygon, and that it is not
2914      done
2915  */
2916  /* Size of the polygon */
2917  size = temp2->nPolSize;
2918  for (y = 0; y< size; y++)
2919    {
2920      /*  Make sure that the edge is still in the
2921          polygon and was not deleted, because if the edge was
2922          deleted, then we used it already.
2923      */
2924      if (y != (size-1))
2925        {
2926          if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1)))
2927              || ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1))))
2928            /*  edge is still there we are ok */
2929            there = TRUE;
2930        }
2931      else
2932        {               
2933          if(((id1 == *(temp2->pPolygon)) && (id2 ==*(temp2->pPolygon+size-1))) ||
2934             ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1))))
2935            /*  edge is still there we are ok */
2936            there = TRUE;
2937        }
2938    }
2939 
2940  if (!there)
2941    /*  Edge already used and deleted from the polygon*/
2942    return -1;
2943  else
2944    return next_face;
2945}
2946
2947///     Look_Up:
2948BOOL CustomStripifier::Look_Up(int id1,int id2,int face_id)
2949{
2950  /*    See if the endpoints of the edge specified by id1 and id2
2951        are adjacent to the face with face_id
2952  */
2953  register int count = 0;
2954  PF_EDGES temp  = NULL;
2955  ListHead *pListHead;
2956 
2957  /*    Always want smaller id first */
2958  switch_lower(&id1,&id2);
2959 
2960  pListHead = PolEdges[id1];
2961  temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
2962  if (temp == NULL)
2963    /*  Was a new edge that we created */
2964    return 0;
2965 
2966  while (temp->edge[0] != id2)
2967    {
2968      count++;
2969      temp = ( PF_EDGES )GetNextNode(temp);                                 
2970     
2971      if (temp == NULL)
2972        /*      Was a new edge that we created */
2973        return 0;
2974    }
2975  /*    Was not adjacent to anything else except itself */
2976  if ((temp->edge[2] == face_id) || (temp->edge[1] == face_id))
2977    {
2978      /*        Edge was adjacent to face, make sure that edge is
2979                still there
2980      */
2981      if (Exist(face_id,id1,id2))
2982        return 1;
2983      else
2984        return 0;
2985    }
2986  else
2987    return 0;
2988}
2989
2990///     Add_Id_Strips:
2991void CustomStripifier::Add_Id_Strips(int id, int where)
2992{
2993  /*    Just save the triangle for later  */
2994  P_STRIPS pfNode;
2995 
2996  pfNode = (P_STRIPS) malloc(sizeof(Strips) );
2997  if ( pfNode )
2998    {
2999      pfNode->face_id = id;
3000      if (where == 1)
3001        AddTail(strips[0],(PLISTINFO) pfNode);
3002      /* We are backtracking in the strip */
3003      else
3004        AddHead(strips[0],(PLISTINFO) pfNode);
3005    }
3006  else
3007    {
3008      printf("There is not enough memory to allocate for the strips\n");
3009      exit(0);
3010    }
3011}
3012
3013///     Num_Adj:
3014int CustomStripifier::Num_Adj(int id1, int id2)
3015{
3016  /*   Given edge whose endpoints are specified by id1 and id2,
3017       determine how many polygons share this edge and return that
3018       number minus one (since we do not want to include the polygon
3019       that the caller has already).
3020  */
3021 
3022  PF_EDGES temp = NULL;
3023  ListHead *pListHead;
3024  register count=-1;
3025 
3026  /*    Always want smaller id first */
3027  switch_lower(&id1,&id2);
3028 
3029  pListHead = PolEdges[id1];
3030  temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
3031  if (temp == NULL)
3032    {
3033      printf("There is an error in the creation of the table \n");
3034      exit(0);
3035    }
3036  while (temp->edge[0] != id2)
3037    {
3038      count++;
3039      temp = ( PF_EDGES )GetNextNode(temp);                                   
3040     
3041      if (temp == NULL)
3042        {
3043          printf("There is an error in the creation of the table\n");
3044          exit(0);
3045        }
3046    }
3047  /*      Was not adjacent to anything else except itself */
3048  if (temp->edge[2] == -1)
3049    return 0;
3050  return 1;
3051}
3052
3053///     Add_Sgi_Adj:
3054void CustomStripifier::Add_Sgi_Adj(int bucket,int face_id)
3055{
3056  /*   This routine will add the face to the proper bucket,
3057       depending on how many faces are adjacent to it (what the
3058       value bucket should be).
3059  */
3060  P_ADJACENCIES pfNode;
3061 
3062  pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
3063  if ( pfNode )
3064    {
3065      pfNode->face_id = face_id;
3066      AddHead(array[bucket],(PLISTINFO) pfNode);
3067      face_array[face_id].bucket = bucket;
3068      face_array[face_id].pfNode = pfNode;
3069      face_array[face_id].head = array[bucket];
3070    }
3071  else
3072    {
3073      printf("Out of memory for the SGI adj list!\n");
3074      exit(0);
3075    }
3076}
3077
3078///     Find_Adjacencies:
3079void CustomStripifier::Find_Adjacencies(int num_faces)
3080{
3081  register int  x,y;
3082  register int  numverts;
3083  PF_FACES                      temp    =NULL;
3084  ListHead*                     pListHead;
3085 
3086  /*   Fill in the adjacencies data structure for all the faces */
3087  for (x=0;x<num_faces;x++)
3088  {
3089    pListHead = PolFaces[x];
3090    temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
3091    if ( temp != NULL )
3092                {
3093                numverts = temp->nPolSize;
3094                if (numverts != 1)
3095            {
3096              for (y = 0; y< numverts; y++)
3097                                {
3098                                if (y != (numverts-1))
3099                                Add_AdjEdge(*(temp->pPolygon+y),
3100                                                                                                *(temp->pPolygon+y+1),x,y);
3101                 
3102                                else
3103                                Add_AdjEdge(*(temp->pPolygon),
3104                                                                                                *(temp->pPolygon+(numverts-1)),x,numverts-1);
3105                 
3106                                }
3107            }
3108                temp = NULL;
3109                }
3110        }
3111}
3112
3113///     Clear_Ties:
3114void CustomStripifier::Clear_Ties()
3115{
3116  /*    Clear the buffer, because we do not have the tie
3117        any more that we had before */
3118  last = 0;
3119}
3120
3121///     Add_Ties:
3122void CustomStripifier::Add_Ties(int id)
3123{
3124  /*    We have a tie to add to the buffer */
3125  ties_array[last++] = id;
3126}
3127
3128///     Alternate_Tie:
3129int CustomStripifier::Alternate_Tie()
3130{
3131  /*    Alternate in what we choose to break the tie
3132        We are just alternating between the first and
3133        second thing that we found
3134  */
3135  static int x = 0;
3136  register int t;
3137 
3138  t = ties_array[x];
3139  x++;
3140  if (x == 2)
3141    x = 0;
3142  return t;
3143}
3144
3145///     Random_Tie:
3146int CustomStripifier::Random_Tie()
3147{
3148  /*    Randomly choose the next face with which
3149        to break the tie
3150  */
3151  register int num;
3152 
3153  num = rand();
3154  while (num >= last)
3155    num = num/20;
3156  return (ties_array[num]);
3157}
3158
3159///     Look_Ahead:
3160int CustomStripifier::Look_Ahead(int id)
3161{
3162  /*    Look ahead at this face and save the minimum
3163        adjacency of all the faces that are adjacent to
3164        this face.
3165  */
3166  return Min_Adj(id);
3167}
3168
3169///     Random_Look:
3170int CustomStripifier::Random_Look(int id[],int count)
3171{
3172  /*    We had a tie within a tie in the lookahead,
3173        break it randomly
3174  */
3175  register int num;
3176 
3177  num = rand();
3178  while (num >= count)
3179    num = num/20;
3180  return (id[num]);
3181}
3182
3183///     Look_Ahead_Tie:
3184int CustomStripifier::Look_Ahead_Tie()
3185{
3186  /*    Look ahead and find the face to go to that
3187        will give the least number of adjacencies
3188  */
3189  int id[60],t,x,f=0,min = 60;
3190 
3191  for (x = 0; x < last; x++)
3192    {
3193      t = Look_Ahead(ties_array[x]);
3194      /*        We have a tie */
3195      if (t == min)
3196        id[f++] = ties_array[x];
3197      if (t < min)
3198        {
3199          f = 0;
3200          min = t;
3201          id[f++] = ties_array[x];
3202        }
3203    }
3204  /*    No tie within the tie */
3205  if ( f == 1)
3206    return id[0];
3207  /*    Or ties, but we are at the end of strips */
3208  if (min == 0)
3209    return id[0];
3210  return (Random_Look(id,f));
3211}
3212
3213///     Sequential_Tri:
3214int CustomStripifier::Sequential_Tri(int *index)
3215{
3216  /*  We have a triangle and need to break the ties at it.
3217      We will choose the edge that is sequential. There
3218      is definitely one since we know we have a triangle
3219      and that there is a tie and there are only 2 edges
3220      for the tie.
3221  */
3222  int reversed,e1,e2,e3,output1,output2,output3,output4;
3223 
3224  /*  e2 and e3 are the input edge to the triangle */
3225  Last_Edge(&e1,&e2,&e3,0);
3226 
3227  if ((e2 == 0) && (e3 == 0))
3228    /*  Starting the strip, don't need to do this */
3229    return ties_array[0];
3230 
3231  /*  For the 2 ties find the edge adjacent to face id */
3232  reversed = Get_EdgeEx(&output1,&output2,index,ties_array[0],3,0,0);
3233  reversed = Get_EdgeEx(&output3,&output4,index,ties_array[1],3,0,0);
3234 
3235  if ((output1 == e3) || (output2 == e3))
3236    return ties_array[0];
3237  if ((output3 == e3) || (output4 == e3))
3238    return ties_array[1];
3239  printf("There is an error trying to break sequential triangle \n");
3240  return -1;
3241}
3242
3243///     Sequential_Quad:
3244int CustomStripifier::Sequential_Quad(int *index,       int triangulate)
3245{
3246  /*  We have a quad that need to break its ties, we will try
3247      and choose a side that is sequential, otherwise use lookahead
3248  */
3249  int reversed,output1,output2,x,e1,e2,e3;
3250 
3251  /*  e2 and e3 are the input edge to the quad */
3252  Last_Edge(&e1,&e2,&e3,0);
3253 
3254  /*  No input edge */
3255  if ((e2 == 0) && (e3 == 0))
3256    return ties_array[0];
3257 
3258  /*  Go through the ties and see if there is a sequential one */
3259  for (x = 0; x < last; x++)
3260    {
3261      reversed = Get_EdgeEx(&output1,&output2,index,ties_array[x],4,0,0);
3262      /*  Partial and whole triangulation will have different requirements */
3263      if (((output1 == e3) || (output2 == e3)) && (triangulate == PARTIAL))
3264        return ties_array[x];
3265      if (((output1 != e3) && (output1 != e2) &&
3266           (output2 != e3) && (output2 != e2)))
3267        return ties_array[x];
3268    }
3269  /*  There was not a tie that was sequential */
3270  return Look_Ahead_Tie();
3271}
3272
3273///     Whole_Output:
3274void CustomStripifier::Whole_Output(int in1, int *index, int size, int *out1, int *out2)
3275{
3276  /*  Used to sequentially break ties in the whole triangulation for polygons
3277      greater than 4 sides. We will find the output edge that is good
3278      for sequential triangulation.
3279  */
3280 
3281  int half;
3282 
3283  /*  Put the input edge first in the list */
3284  Rearrange_IndexEx(index,size);
3285 
3286  if (!(EVEN(size)))
3287    {
3288      if (*(index) == in1)
3289        half = size/2 ;
3290      else
3291        half = size/2 +1;
3292    }
3293  else
3294    half = size/2;
3295 
3296  *out1 = *(index+half);
3297  *out2 = *(index+half+1);
3298}
3299
3300///     Sequential_Poly:
3301int CustomStripifier::Sequential_Poly(int size, int *index, int triangulate)
3302{
3303  /*  We have a polygon of greater than 4 sides and wish to break the
3304      tie in the most sequential manner.
3305  */
3306 
3307  int x,reversed,output1,output2,e1,e2,e3,saved1=-1,saved2=-1,output3,output4;
3308 
3309  /*  e2 and e3 are the input edge to the quad */
3310  Last_Edge(&e1,&e2,&e3,0);
3311 
3312  /*  If we are using whole, find the output edge that is sequential */
3313  if (triangulate == WHOLE)
3314    Whole_Output(e2,index,size,&output3,&output4);
3315 
3316  /*  No input edge */
3317  if ((e2 == 0) && (e3 == 0))
3318    return ties_array[0];
3319 
3320  for (x = 0; x < last ; x++)
3321    {
3322      reversed = Get_EdgeEx(&output1,&output2,index,ties_array[x],size,0,0);
3323      /*  Partial that can be removed in just one triangle */
3324      if (((output1 == e3) || (output2 == e3)) && (triangulate == PARTIAL))
3325        saved1 = ties_array[x];
3326      /*  Partial removed in more than one triangle */
3327      if ((output1 != e3) && (output1 != e2) &&
3328          (output2 != e3) && (output2 != e2) &&
3329          (triangulate == PARTIAL) && (saved2 != -1))
3330        saved2 = ties_array[x];
3331      /*  Whole is not so easy, since the whole polygon must be done. Given
3332          an input edge there is only one way to come out, approximately half
3333          way around the polygon.
3334      */
3335      if (((output1 == output3) && (output2 == output4)) ||
3336          ((output1 == output4) && (output2 == output3)) &&
3337          (triangulate == WHOLE))
3338        return ties_array[x];
3339    }
3340 
3341  if (saved1 != -1)
3342    return saved1;
3343  if (saved2 != -1)
3344    return saved2;
3345 
3346  /*  There was not a tie that was sequential */
3347  return Look_Ahead_Tie();
3348}
3349
3350///     Sequential_Tie:
3351int CustomStripifier::Sequential_Tie(int face_id,int triangulate)
3352{
3353  /*  Break the tie by choosing the face that will
3354      not give us a swap and is sequential. If there
3355      is not one, then do the lookahead to break the
3356      tie.
3357  */
3358  /*  Separate into 3 cases for simplicity, if the current
3359      polygon has 3 sides, 4 sides or if the sides were
3360      greater. We can do the smaller cases faster, so that
3361      is why I separated the cases.
3362  */
3363 
3364  ListHead *pListFace;
3365  PF_FACES face;
3366 
3367  /*    Get the polygon with id face_id */
3368  pListFace  = PolFaces[face_id];
3369  face = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
3370 
3371  if (face->nPolSize == 3)
3372    return(Sequential_Tri(face->pPolygon));
3373  if (face->nPolSize == 4)
3374    return(Sequential_Quad(face->pPolygon,triangulate));
3375  else
3376    return(Sequential_Poly(face->nPolSize,face->pPolygon,triangulate));
3377 
3378}
3379
3380///     Get_Next_Face:
3381int CustomStripifier::Get_Next_Face(int t, int face_id, int triangulate)
3382{
3383  /*    Get the next face depending on what
3384        the user specified
3385  */
3386 
3387  /*    Did not have a tie, don't do anything */
3388  if (last == 1)
3389    return(ties_array[0]);
3390  if (t == RANDOM)
3391    return Random_Tie();
3392  if (t == ALTERNA)
3393    return Alternate_Tie();
3394  if (t == LOOK)
3395    return Look_Ahead_Tie();
3396  if (t == SEQUENTIAL)
3397    return Sequential_Tie(face_id,triangulate);
3398 
3399  printf("Illegal option specified for ties, using first \n");
3400  return (ties_array[0]);
3401}
3402
3403///     new_vertex:
3404BOOL CustomStripifier::new_vertex(double difference, int id1,int id2,
3405                       struct vert_struct *n)
3406{
3407  /*   Is the difference between id1 and id2 (2 normal vertices that
3408       mapped to the same vertex) greater than the
3409       threshold that was specified?
3410  */
3411  struct vert_struct *pn1,*pn2;
3412  double dot_product;
3413  double distance1, distance2,distance;
3414  double rad;
3415  char arg1[100];
3416  char arg2[100];
3417 
3418  pn1 = n + id1;
3419  pn2 = n + id2;
3420 
3421  dot_product = ((pn1->x) * (pn2->x)) +
3422    ((pn1->y) * (pn2->y)) +
3423    ((pn1->z) * (pn2->z));
3424  /*   Get the absolute value */
3425  if (dot_product < 0)
3426    dot_product = dot_product * -1;
3427 
3428  distance1 = sqrt( (pn1->x * pn1->x) +
3429                    (pn1->y * pn1->y) +
3430                    (pn1->z * pn1->z) );
3431  distance2 = sqrt( (pn2->x * pn2->x) +
3432                    (pn2->y * pn2->y) +
3433                    (pn2->z * pn2->z) );
3434  distance = distance1 * distance2;
3435 
3436  rad = acos((double)dot_product/(double)distance);
3437  /*   convert to degrees */
3438  rad = (180 * rad)/GEO_PI;
3439 
3440  if ( rad <= difference)
3441    return FALSE;
3442 
3443  /*   double checking because of imprecision with floating
3444       point acos function
3445  */
3446  sprintf( arg1,"%.5f", rad );
3447  sprintf( arg2,"%.5f", difference );
3448  if ( strcmp( arg1, arg2 ) <=0 )
3449    return( FALSE );
3450  if ( rad <= difference)
3451    return FALSE;
3452  else
3453    return TRUE;
3454}
3455
3456///     Check_VN:
3457BOOL CustomStripifier::Check_VN(int vertex,int normal, struct vert_added *added)
3458{
3459  /*   Check to see if we already added this vertex and normal */
3460  register int x,n;
3461 
3462  n = (added+vertex)->num;
3463  for (x = 0; x < n; x++)
3464    {
3465      if (*((added+vertex)->normal+x) == normal)
3466        return TRUE;
3467    }
3468  return FALSE;
3469}
3470
3471///     norm_array:
3472BOOL CustomStripifier::norm_array(int id, int vertex, double normal_difference,
3473                struct vert_struct *n, int num_vert)
3474{
3475  static int last;
3476  static struct vert_added *added;
3477  register int x;
3478  static BOOL first = TRUE;
3479 
3480  if (first)
3481    {
3482      /*   This is the first time that we are in here, so we will allocate
3483           a structure that will save the vertices that we added, so that we
3484           do not add the same thing twice
3485      */
3486      first = FALSE;
3487      added = (struct vert_added *) malloc (sizeof (struct vert_added ) * num_vert);
3488      /*   The number of vertices added for each vertex must be initialized to
3489           zero
3490      */
3491      for (x = 0; x < num_vert; x++)
3492        (added+x)->num = 0;
3493    }
3494 
3495  if (vertex)
3496    /*   Set the pointer to the vertex, we will be calling again with the
3497         normal to fill it with
3498    */
3499    last = id;
3500  else
3501    {   
3502      /*   Fill the pointer with the id of the normal */
3503      if (*(vert_norms + last) == 0)
3504        *(vert_norms + last) = id;
3505      else if ((*(vert_norms + last) != id) && ((int)normal_difference != 360))
3506        {
3507          /*   difference is big enough, we need to create a new vertex */
3508          if (new_vertex(normal_difference,id,*(vert_norms + last),n))
3509            {
3510              /*  First check to see if we added this vertex and normal already */
3511              if (Check_VN(last,id,added))
3512                return FALSE;
3513              /*  OK, create the new vertex, and have its id = the number of
3514                  vertices and its normal what we have here
3515              */
3516              vert_norms = (int *)realloc(vert_norms, sizeof(int) * (num_vert + 1));
3517              if (!vert_norms)
3518                {
3519                  printf("Allocation error - aborting\n");
3520                  exit(1);
3521                }
3522              *(vert_norms + num_vert) = id;
3523              /*   We created a new vertex, now put it in our added structure so
3524                   we do not add the same thing twice
3525              */
3526              (added+last)->num = (added+last)->num + 1;
3527              if ((added+last)->num == 1)
3528                {
3529                  /*   First time */
3530                  (added+last)->normal =  (int *) malloc (sizeof (int ) * 1);
3531                  *((added+last)->normal) =  id;
3532                }
3533              else
3534                {
3535                  /*   Not the first time, reallocate space */
3536                  (added+last)->normal = (int *)realloc((added+last)->normal, sizeof(int) * (added+last)->num);
3537                  *((added+last)->normal+((added+last)->num-1)) = id;
3538                }
3539              return TRUE;
3540            }
3541        }
3542    }
3543  return FALSE;
3544}
3545
3546///     add_texture:
3547void CustomStripifier::add_texture(int id,BOOL vertex)
3548{
3549  /*   Save the texture with its vertex for future use when outputting */
3550  static int last;
3551 
3552  if (vertex)
3553    last = id;
3554  else
3555    *(vert_texture+last) = id;
3556}
3557
3558///     add_vert_id:
3559int     CustomStripifier::add_vert_id(int id, int       index_count)
3560{
3561  register int x;
3562 
3563  //   Test if degenerate, if so do not add degenerate vertex
3564  for (x = 1; x < index_count ; x++)
3565  {
3566        if (ids[x] == id)
3567                return 0;
3568  }
3569  ids[index_count] = id;
3570
3571  return 1;
3572}
3573
3574///     add_norm_id:
3575void CustomStripifier::add_norm_id(int id, int index_count)
3576{
3577  norms[index_count] = id;
3578}
3579
3580///     AddNewFace:
3581void CustomStripifier::AddNewFace(int ids[MAX1], int vert_count, int face_id, int norms[MAX1])
3582{
3583  PF_FACES                      pfNode;
3584  PF_VERTICES           pfVertNode;
3585  int                                           *pTempInt;
3586  int                                           *pnorms;
3587  F_EDGES                               **pTempVertptr;
3588  int                                           *pTempmarked;
3589        int                                             *pTempwalked;
3590  register      int     y;
3591        register        int     count = 0;
3592
3593  //  Add a new face into our face data structure
3594  pfNode = (PF_FACES) malloc(sizeof(F_FACES));
3595
3596  if (pfNode)
3597  {
3598                pfNode->pPolygon        =       (int*) malloc(sizeof(int) * (vert_count) );
3599                pfNode->pNorms          =       (int*) malloc(sizeof(int) * (vert_count) );
3600
3601                pfNode->VertandId       =       (F_EDGES**)malloc(sizeof(F_EDGES*)
3602                                                                                                *
3603                                                                                                (vert_count));
3604
3605                pfNode->marked          =       (int*)malloc(sizeof(int) * (vert_count));
3606                pfNode->walked          =       (int*)malloc(sizeof(int) * (vert_count));
3607  }
3608
3609  pTempInt                                      =       pfNode->pPolygon;
3610  pnorms                                                =       pfNode->pNorms;
3611  pTempmarked                           =       pfNode->marked;
3612  pTempwalked                           =       pfNode->walked;
3613  pTempVertptr                  =       pfNode->VertandId;
3614  pfNode->nPolSize      =       vert_count;
3615  pfNode->nOrgSize      =       vert_count;
3616  pfNode->seen                  =       -1;
3617  pfNode->seen2                 =       -1;
3618
3619  for (y = 1; y <= vert_count; y++)
3620  {
3621                *(pTempInt + count)                     =       ids[y];
3622                *(pnorms + count)                               =       norms[y];
3623                *(pTempmarked + count)  =       FALSE;
3624                *(pTempwalked + count)  =       -1;
3625                *(pTempVertptr+count)           =       NULL;
3626
3627                count++;
3628
3629                /* Add this FaceNode to the Vertices Structure */
3630                pfVertNode                              =       (PF_VERTICES) malloc(sizeof(F_VERTICES));
3631                pfVertNode->face        =       pfNode;
3632
3633                AddHead(Vertices[ids[y]],(PLISTINFO) pfVertNode);
3634  }
3635
3636  AddHead(PolFaces[face_id-1],(PLISTINFO) pfNode);
3637 
3638}
3639
3640///     CopyFace:
3641void CustomStripifier::CopyFace(int ids[MAX1], int vert_count, int face_id, int norms[MAX1])
3642{
3643  PF_FACES                      pfNode;
3644  int                                           *pTempInt;
3645  int                                           *pnorms;
3646  F_EDGES                               **pTempVertptr;
3647  int                                           *pTempmarked;
3648        int                                             *pTempwalked;
3649  register      int     y;
3650        register        int     count = 0;
3651 
3652  /*   Copy a face node into a new node, used after the global algorithm
3653       is run, so that we can save whatever is left into a new structure
3654  */
3655 
3656  pfNode        =       (PF_FACES) malloc(sizeof(F_FACES));
3657
3658  if ( pfNode )
3659  {
3660      pfNode->pPolygon  =       (int*) malloc(  sizeof(int)
3661                                                                                                                                                                        *
3662                                                                                                                                                                        (vert_count));
3663
3664      pfNode->pNorms            =       (int*) malloc(  sizeof(int)
3665                                                                                                                                                                        *
3666                                                                                                                                                                        (vert_count));
3667
3668      pfNode->VertandId =       (F_EDGES**) malloc(     sizeof(F_EDGES*)
3669                                                                                                                                                                                        *
3670                                                                                                                                                                                        (vert_count));
3671
3672      pfNode->marked    =       (int*)malloc(sizeof(int) * (vert_count));
3673      pfNode->walked    =       (int*)malloc(sizeof(int) * (vert_count));
3674  }
3675
3676  pTempInt                                      =       pfNode->pPolygon;
3677  pnorms                                                =       pfNode->pNorms;
3678  pTempmarked                           =       pfNode->marked;
3679  pTempwalked                           =       pfNode->walked;
3680  pTempVertptr                  =       pfNode->VertandId;
3681  pfNode->nPolSize      =       vert_count;
3682  pfNode->nOrgSize      =       vert_count;
3683  pfNode->seen                  =       -1;
3684  pfNode->seen2                 =       -1;
3685
3686  for (y = 0; y < vert_count; y++)
3687  {
3688                *(pTempInt + count)                     =       ids[y];
3689                *(pnorms + count)                               =       norms[y];
3690                *(pTempmarked + count)  =       FALSE;
3691                *(pTempwalked + count)  =       -1;
3692                *(pTempVertptr+count)           =       NULL;
3693
3694                count++;
3695  }
3696
3697  AddHead(PolFaces[face_id-1],(PLISTINFO) pfNode);
3698}
3699
3700///     Add_AdjEdge:
3701void CustomStripifier::Add_AdjEdge(int v1,int v2,int fnum,int index1 )
3702{
3703  PF_EDGES                      temp    =       NULL;
3704  PF_FACES                      temp2 = NULL;
3705  PF_EDGES                      pfNode;
3706  ListHead                      *pListHead;
3707  ListHead                      *pListFace;
3708  BOOL                                  flag    =       TRUE;
3709  register      int     count = 0;
3710  register      int     t;
3711        register        int     v3              =       -1;
3712 
3713  if (v1 > v2)
3714  {
3715                t               =       v1;
3716                v1      =       v2;
3717                v2      =       t;
3718  }
3719
3720  pListFace     =       PolFaces[fnum];
3721  temp2                 =       (PF_FACES) PeekList(pListFace,LISTHEAD,0);
3722  pListHead     =       PolEdges[v1];
3723  temp                  =       (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
3724
3725  if (temp == NULL)
3726        {
3727                flag    =       FALSE;
3728        }
3729
3730  count++;
3731
3732  while (flag)
3733  {
3734                if (v2 == temp->edge[0])
3735                {
3736                        /*      If greater than 2 polygons adjacent to an edge,
3737                                        then we will only save the first 2 that we found.
3738                                        We will have a small performance hit,
3739                                        but this does not happen often.
3740                        */
3741                        if (temp->edge[2] == -1)
3742                        {
3743                                temp->edge[2]   =       fnum;
3744                        }
3745                        else
3746                        {
3747                                v3      =       temp->edge[2];
3748
3749                                //      More than 3 edges are adjacent.
3750                                //      The mesh is not Manifold.
3751                                mError  =       1;
3752                        }
3753
3754                        flag    =       FALSE;
3755                }
3756                else
3757                {
3758                        temp    =       ( PF_EDGES ) GetNextNode(temp);
3759
3760                        count++;
3761
3762                        if (temp == NULL)
3763                        {
3764                                flag    =       FALSE;
3765                        }
3766                }
3767        }
3768 
3769  /*   Did not find it */
3770  if (temp == NULL)
3771  {
3772    pfNode      =       (PF_EDGES) malloc(sizeof(F_EDGES));
3773
3774    if (pfNode)
3775                {
3776                        pfNode->edge[0] =       v2;
3777                        pfNode->edge[1] =       fnum;
3778                        pfNode->edge[2] =       v3;
3779
3780                        AddTail(PolEdges[v1], (PLISTINFO) pfNode);
3781                }
3782                else
3783                {
3784                        printf("Out of memory!\n");
3785                        exit(1);
3786                }
3787
3788                *(temp2->VertandId+index1)      =       pfNode;
3789        }
3790  else
3791        {
3792                *(temp2->VertandId+index1)      =       temp;
3793        }
3794}
3795
3796///     power_10:
3797int CustomStripifier::power_10(int power)
3798{
3799  /*    Raise 10 to the power */
3800  register int i,p;
3801 
3802  p = 1;
3803  for (i = 1; i <= power; ++i)
3804    p = p * 10;
3805  return p;
3806}
3807
3808///     power_negative:
3809float CustomStripifier::power_negative(int power)
3810{
3811  /*   Raise 10 to the negative power */
3812 
3813  register int i;
3814  float p;
3815 
3816  p = (float)1;
3817  for (i = 1; i<=power; i++)
3818    p = p * (float).1;
3819  return p;
3820}
3821
3822///     convert_array:
3823float CustomStripifier::convert_array(int num[],int stack_size)
3824{
3825  /* Convert an array of characters to an integer */
3826 
3827  register int counter,c;
3828  float temp =(float)0.0;
3829 
3830  for (c=(stack_size-1), counter = 0; c>=0; c--, counter++)
3831    {
3832      if (num[c] == -1)
3833        /*   We are at the decimal point, convert to decimal
3834             less than 1
3835        */
3836        {
3837          counter = -1;
3838          temp = power_negative(stack_size - c - 1) * temp;
3839        }
3840      else
3841        temp += power_10(counter) * num[c];
3842    }
3843 
3844  return(temp);
3845}
3846
3847///     print_usage:
3848void CustomStripifier::print_usage(void)
3849{
3850  printf("Usage: stripe [abfglopqrw] file_name\n");
3851  printf("Options:\n");
3852  printf(" -b\tSpecifies that the input file is in binary\n");
3853  printf(" -g\tFind triangle strips only within the groups specified in the data file\n");
3854  printf(" -o\tTurn off orientation checking\n\n");
3855 
3856  printf("Tie Breaking:\n");
3857  printf(" -a\tAlternate left-right direction in choosing next polygon\n");
3858  printf(" -f\tChoose the first polygon that it found\n");
3859  printf(" -l\tLook ahead one level in choosing the next polygon\n");
3860  printf(" -q\tChoose the polygon which does not produce a swap\n");
3861  printf(" -r\tRandomly choose the next polygon\n\n");
3862 
3863  printf("Triangulation:\n");
3864  printf(" -p\tPartially triangulate faces\n");
3865  printf(" -w\tFully triangluate faces\n");
3866}
3867
3868///     get_options:
3869float CustomStripifier::get_options(int         argc,
3870                                                                                                                                                char    **argv,
3871                                                                                                                                                int             *f,
3872                                                                                                                                                int             *t,
3873                                                                                                                                                int             *tr,
3874                                                                                                                                                int             *group,
3875                                                                                                                                                int             *orientation)
3876{
3877  char c;
3878  int count = 0;
3879  int buffer[MAX1];
3880  int next = 0;
3881  /*    tie variable */
3882  enum tie_options tie = FIRST;
3883  /*   triangulation variable */
3884  enum triangulation_options triangulate = WHOLE;
3885  /*   normal difference variable (in degrees) */
3886  float norm_difference = (float)360.0;
3887  /*   file-type variable */
3888  enum file_options file_type = ASCII;
3889 
3890  *orientation = 1;
3891 
3892  /*      User has the wrong number of options */
3893  if ((argc > 6) || (argc < 2))
3894  {
3895    print_usage();
3896    exit(0);
3897  }
3898 
3899  /* Interpret the options specified */
3900  while (--argc > 0 && (*++argv)[0] == '-')
3901  {
3902    /*   At the next option that was specified */
3903    next = 1;
3904    while ((c = *++argv[0]))
3905                        switch (c)
3906                        {
3907                                case 'f':
3908                                        /*      Use the first polygon we see. */
3909                                        tie = FIRST;
3910                                        break;
3911                           
3912                                case 'r':
3913                                        /*      Randomly choose the next polygon */
3914                                        tie = RANDOM;
3915                                        break;
3916                           
3917                                case 'a':
3918                                        /*      Alternate direction in choosing the next polygon */
3919                                        tie = ALTERNA;
3920                                        break;
3921                           
3922                                case 'l':
3923                                        /*      Use lookahead to choose the next polygon */
3924                                        tie = LOOK;
3925                                        break;
3926                           
3927                                case 'q':
3928                                        /*  Try to reduce swaps */
3929                                        tie = SEQUENTIAL;
3930                                        break;
3931                           
3932                                case 'p':
3933                                        /*      Use partial triangulation of polygons */
3934                                        triangulate = PARTIAL;
3935                                        break;
3936                           
3937                                case 'w':
3938                                        /*      Use whole triangulation of polygons */
3939                                        triangulate = WHOLE;
3940                                        break;
3941                           
3942                                case 'b':
3943                                        /*      Input file is in binary */
3944                                        file_type = BINARY;
3945                                        break;
3946                           
3947                                case 'g':
3948                                        /*   Strips will be grouped according to the groups in
3949                                the data file. We will have to restrict strips to be
3950                                in the grouping of the data file.
3951                                        */
3952                                        *group = 1;
3953                                        break;
3954                           
3955                                                        case 'o':
3956                                        *orientation = 0;
3957                           
3958                                        /*      Get each the value of the integer */
3959                                        /*      We have an integer */
3960                                default:
3961                                        if ((c >= '0') && (c <= '9'))
3962                                                {
3963                                /* More than one normal difference specified, use the last one */
3964                                if (next == 1)
3965                                        {
3966                                                count = 0;
3967                                                next = 0;
3968                                        }
3969                                buffer[count++] = ATOI(c);
3970                                                }
3971                                        /*   At the decimal point */
3972                                        else if (c == '.')
3973                                                {
3974                                /* More than one normal difference specified, use the last one */
3975                                if (next == 1)
3976                                        {
3977                                                count = 0;
3978                                                next = 0;
3979                                        }
3980                                buffer[count++] = -1;
3981                                                }
3982                                        else
3983                                                break;
3984                        }
3985    }
3986  /*   Convert the buffer of characters to a floating pt integer */
3987  if (count != 0)
3988    norm_difference = convert_array(buffer,count);
3989  *f = file_type;
3990  *t = tie;
3991  *tr = triangulate;
3992  return norm_difference;
3993}
3994
3995///     AdjacentEx:
3996int CustomStripifier::AdjacentEx(int id2,int id1, int *list, int size)
3997{
3998  /*    Return the vertex that is adjacent to id1,
3999        but is not id2, in the list of integers.
4000  */
4001 
4002  register int x=0;
4003 
4004  while (x < size)
4005    {
4006      if (*(list+x) == id1)
4007        {
4008          if ((x != (size -1)) && (x != 0))
4009            {
4010              if ( *(list+x+1) != id2)
4011                return *(list+x+1);
4012              else
4013                return *(list+x-1);
4014            }
4015          else if (x == (size -1))
4016            {
4017              if (*(list) != id2)
4018                return *(list);
4019              else
4020                return *(list+x-1);
4021            }
4022          else
4023            {
4024              if (*(list+size-1) != id2)
4025                return *(list+size-1);
4026              else
4027                return *(list+x+1);
4028            }
4029        }
4030      x++;
4031    }
4032  printf("Error in the list\n");
4033  exit(0);
4034}
4035
4036///     Delete_From_ListEx:
4037void CustomStripifier::Delete_From_ListEx(int id,int *list, int size)
4038{
4039  /*    Delete the occurence of id in the list.
4040        (list has size size)
4041  */
4042 
4043  int *temp;
4044  register int x,y=0;
4045 
4046  temp = (int *) malloc(sizeof(int) * size);
4047  for (x=0; x<size; x++)
4048    {
4049      if (*(list+x) != id)
4050        {
4051          *(temp+y) = *(list+x);
4052          y++;
4053        }
4054    }
4055  if(y != (size-1))
4056    {
4057      printf("There is an error in the delete\n");
4058      exit(0);
4059    }
4060  *(temp+size-1) = -1;
4061  memcpy(list,temp,sizeof(int)*size);
4062 
4063}
4064
4065///     Triangulate_QuadEx:
4066void CustomStripifier::Triangulate_QuadEx(int out_edge1,int out_edge2,int in_edge1,
4067                               int in_edge2,int size,int *index,
4068                               int reversed,
4069                               int where)
4070{
4071  int vertex4,vertex5;
4072 
4073  /*    This routine will nonblindly triangulate a quad, meaning
4074        that there is a definite input and a definite output
4075        edge that we must adhere to. Reversed will tell the orientation
4076        of the input edge. (Reversed is -1 is we do not have an input
4077        edge, in other words we are at the beginning of a strip.)
4078        Out_edge* is the output edge, and in_edge* is the input edge.
4079        Index are the edges of the polygon
4080        and size is the size of the polygon. Begin is whether we are
4081        at the start of a new strip.
4082  */
4083 
4084  /*    If we do not have an input edge, then we can make our input
4085        edge whatever we like, therefore it will be easier to come
4086        out on the output edge.
4087  */
4088  if (reversed == -1)
4089    {
4090      vertex4 = AdjacentEx(out_edge1,out_edge2,index,size);
4091      vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index);
4092      Output_TriEx(vertex5,vertex4,out_edge1,NULL,-1,where);
4093      Output_TriEx(vertex4,out_edge1,out_edge2,NULL,-1,where);
4094      return;
4095    }
4096 
4097  /*    These are the 5 cases that we can have for the output edge */
4098 
4099  /*   Are they consecutive so that we form a triangle to
4100       peel off, but cannot use the whole quad?
4101  */
4102 
4103  if (in_edge2 == out_edge1)
4104    {
4105      /*        Output the triangle that comes out the correct
4106                edge last. First output the triangle that comes out
4107                the wrong edge.
4108      */
4109      vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index);
4110      Output_TriEx(in_edge1,in_edge2,vertex4,NULL,-1,where);
4111      Output_TriEx(vertex4,in_edge2,out_edge2,NULL,-1,where);
4112      return;
4113    }
4114  /*    The next case is where it is impossible to come out the
4115        edge that we want. So we will have to start a new strip to
4116        come out on that edge. We will output the one triangle
4117        that we can, and then start the new strip with the triangle
4118        that comes out on the edge that we want to come out on.
4119  */
4120  else if (in_edge1 == out_edge1)
4121    {
4122      /*        We want to output the first triangle (whose output
4123                edge is not the one that we want.
4124                We have to find the vertex that we need, which is
4125                the other vertex which we do not have.
4126      */
4127      vertex4 = Get_Other_Vertex(in_edge2,in_edge1,out_edge2,index);
4128      Output_TriEx(in_edge2,in_edge1,vertex4,NULL,-1,where);
4129      Output_TriEx(vertex4,in_edge1,out_edge2,NULL,-1,where);
4130      return;
4131    }
4132 
4133  /*    Consecutive cases again, but with the output edge reversed */
4134  else if (in_edge1 == out_edge2)
4135    {
4136      vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
4137      Output_TriEx(in_edge2,in_edge1,vertex4,NULL,-1,where);
4138      Output_TriEx(vertex4,in_edge1,out_edge1,NULL,-1,where);
4139      return;
4140    }
4141  else if (in_edge2 == out_edge2)
4142    {
4143      vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
4144      Output_TriEx(in_edge1,in_edge2,vertex4,NULL,-1,where);
4145      Output_TriEx(vertex4,in_edge2,out_edge1,NULL,-1,where);
4146      return;
4147    }
4148 
4149  /*    The final case is where we want to come out the opposite edge.*/
4150  else
4151    {
4152      if( ((!reversed) &&
4153           (out_edge1 == (AdjacentEx(in_edge1,in_edge2,index,size)))) ||
4154          ((reversed) &&
4155           (out_edge2 == (AdjacentEx(in_edge2,in_edge1,index,size)))))
4156        {
4157          /*    We need to know the orientation of the input
4158                edge, so we know which way to put the diagonal.
4159                And also the output edge, so that we triangulate correctly.
4160          */
4161          Output_TriEx(in_edge1,in_edge2,out_edge2,NULL,-1,where);
4162          Output_TriEx(in_edge2,out_edge2,out_edge1,NULL,-1,where);
4163        }
4164      else
4165        {
4166          /*   Input and output orientation was reversed, so diagonal will
4167               be reversed from above.
4168          */
4169          Output_TriEx(in_edge1,in_edge2,out_edge1,NULL,-1,where);
4170          Output_TriEx(in_edge2,out_edge1,out_edge2,NULL,-1,where);
4171        }
4172      return;
4173    }
4174}
4175
4176///     Triangulate_PolygonEx:
4177void CustomStripifier::Triangulate_PolygonEx(   int out_edge1,int out_edge2,
4178                                                                                                                                                                                        int in_edge1, int in_edge2,
4179                                                                                                                                                                                        int size,                       int *index,
4180                                                                                                                                                                                FILE *fp,                       int reversed,
4181                                                                                                                                                                                        int face_id,  int where)
4182{
4183  /*    We have a polygon that we need to nonblindly triangulate.
4184        We will recursively try to triangulate it, until we are left
4185        with a polygon of size 4, which can use the quad routine
4186        from above. We will be taking off a triangle at a time
4187        and outputting it. We will have 3 cases similar to the
4188        cases for the quad above. The inputs to this routine
4189        are the same as for the quad routine.
4190  */
4191 
4192  int vertex4;
4193  int *temp;
4194 
4195 
4196  /*    Since we are calling this recursively, we have to check whether
4197        we are down to the case of the quad.
4198  */
4199 
4200  if (size == 4)
4201    {
4202      Triangulate_QuadEx(out_edge1,out_edge2,in_edge1,in_edge2,size,
4203                         index,reversed,where);
4204      return;
4205    }
4206 
4207 
4208 
4209  /*    We do not have a specified input edge, and therefore we
4210        can make it anything we like, as long as we still come out
4211        the output edge that we want.
4212  */
4213  if (reversed  == -1)
4214    {
4215      /*        Get the vertex for the last triangle, which is
4216                the one coming out the output edge, before we do
4217                any deletions to the list. We will be doing this
4218                bottom up.
4219      */
4220      vertex4 = AdjacentEx(out_edge1,out_edge2,index,size);
4221      temp = (int *) malloc(sizeof(int) * size);
4222      memcpy(temp,index,sizeof(int)*size);
4223      Delete_From_ListEx(out_edge2,index,size);
4224      Triangulate_PolygonEx(out_edge1,vertex4,in_edge2,
4225                            vertex4,size-1,index,
4226                            fp,reversed,face_id,where);
4227      memcpy(index,temp,sizeof(int)*size);
4228      /*        Lastly do the triangle that comes out the output
4229                edge.
4230      */
4231      Output_TriEx(vertex4,out_edge1,out_edge2,NULL,-1,where);
4232      return;
4233    }
4234 
4235  /*    These are the 5 cases that we can have for the output edge */
4236 
4237  /*  Are they consecutive so that we form a triangle to
4238      peel off that comes out the correct output edge,
4239      but we cannot use the whole polygon?
4240  */
4241  if (in_edge2 == out_edge1)
4242    {
4243      /*        Output the triangle that comes out the correct
4244                edge last. First recursively do the rest of the
4245                polygon.
4246      */
4247      /*        Do the rest of the polygon without the triangle.
4248                We will be doing a fan triangulation.
4249      */
4250      /*        Get the vertex adjacent to in_edge1, but is not
4251                in_edge2.
4252      */
4253      vertex4 = AdjacentEx(in_edge2,in_edge1,index,size);
4254      Output_TriEx(in_edge1,in_edge2,vertex4,NULL,-1,where);
4255      /*        Create a new edgelist without the triangle that
4256                was just outputted.
4257      */
4258      temp = (int *) malloc(sizeof(int) * size);
4259      memcpy(temp,index,sizeof(int)*size);
4260      Delete_From_ListEx(in_edge1,index,size);
4261      Triangulate_PolygonEx(out_edge1,out_edge2,in_edge2,
4262                            vertex4,size-1,index,fp,
4263                            !reversed,face_id,where);
4264      memcpy(index,temp,sizeof(int)*size);
4265      return;
4266    }
4267 
4268  /*    Next case is where it is again consecutive, but the triangle
4269        formed by the consecutive edges do not come out of the
4270        correct output edge. For this case, we can not do much to
4271        keep it sequential. Try and do the fan.
4272  */
4273  else if (in_edge1 == out_edge1)
4274    {
4275      /*        Get vertex adjacent to in_edge2, but is not in_edge1 */
4276      vertex4 = AdjacentEx(in_edge1,in_edge2,index,size);
4277      Output_TriEx(in_edge1,in_edge2,vertex4,fp,-1,where);
4278      /*        Since that triangle goes out of the polygon (the
4279                output edge of it), we can make our new input edge
4280                anything we like, so we will try to make it good for
4281                the strip. (This will be like starting a new strip,
4282                all so that we can go out the correct output edge.)
4283      */
4284      temp = (int *) malloc(sizeof(int) * size);
4285      memcpy(temp,index,sizeof(int)*size);
4286      Delete_From_ListEx(in_edge2,index,size);
4287      Triangulate_PolygonEx(out_edge1,out_edge2,in_edge1,
4288                            vertex4,size-1,index,fp,
4289                            reversed,face_id,where);
4290      memcpy(index,temp,sizeof(int)*size);
4291      return;
4292    }
4293  /*    Consecutive cases again, but with the output edge reversed */
4294  else if (in_edge1 == out_edge2)
4295    {
4296      /*        Get vertex adjacent to in_edge2, but is not in_edge1 */
4297      vertex4 = AdjacentEx(in_edge1,in_edge2,index,size);
4298      Output_TriEx(in_edge2,in_edge1,vertex4,fp,-1,where);
4299      temp = (int *) malloc(sizeof(int) * size);
4300      memcpy(temp,index,sizeof(int)*size);
4301      Delete_From_ListEx(in_edge2,index,size);
4302      Triangulate_PolygonEx(out_edge1,out_edge2,in_edge1,
4303                            vertex4,size-1,index,fp,
4304                            reversed,face_id,where);
4305      memcpy(index,temp,sizeof(int)*size);
4306      return;
4307    }
4308  else if (in_edge2 == out_edge2)
4309    {
4310      /*        Get vertex adjacent to in_edge2, but is not in_edge1 */
4311      vertex4 = AdjacentEx(in_edge2,in_edge1,index,size);
4312      Output_TriEx(in_edge1,in_edge2,vertex4,fp,-1,where);
4313      temp = (int *) malloc(sizeof(int) * size);
4314      memcpy(temp,index,sizeof(int)*size);
4315      Delete_From_ListEx(in_edge1,index,size);
4316      Triangulate_PolygonEx(out_edge1,out_edge2,vertex4,
4317                            in_edge2,size-1,index,fp,
4318                            reversed,face_id,where);
4319      memcpy(index,temp,sizeof(int)*size);
4320      return;
4321    }
4322 
4323  /*    Else the edge is not consecutive, and it is sufficiently
4324        far away, for us not to make a conclusion at this time.
4325        So we can take off a triangle and recursively call this
4326        function.
4327  */
4328  else
4329    {
4330      vertex4 = AdjacentEx(in_edge2,in_edge1,index,size);
4331      Output_TriEx(in_edge1,in_edge2,vertex4,fp,-1,where);
4332      temp = (int *) malloc(sizeof(int) * size);
4333      memcpy(temp,index,sizeof(int)*size);
4334      Delete_From_ListEx(in_edge1,index,size);
4335      Triangulate_PolygonEx(out_edge1,out_edge2,in_edge2,
4336                            vertex4,size-1,index,fp,
4337                            !reversed,face_id,where);
4338      memcpy(index,temp,sizeof(int)*size);
4339      return;
4340    }
4341}
4342
4343///     TriangulateEx:
4344void CustomStripifier::TriangulateEx(int out_edge1,int out_edge2,int in_edge1,
4345                          int in_edge2,int size,int *index,
4346                          FILE *output,int reversed,int face_id, int where)
4347{
4348  /*    We have the info we need to triangulate a polygon */
4349 
4350  if (size == 4)
4351    Triangulate_QuadEx(out_edge1,out_edge2,in_edge1,in_edge2,size,
4352                       index,reversed,where);
4353  else
4354    Triangulate_PolygonEx(out_edge1,out_edge2,in_edge1,in_edge2,size,
4355                          index,output,reversed,face_id,where);
4356}
4357
4358///     Non_Blind_TriangulateEx:
4359void CustomStripifier::Non_Blind_TriangulateEx(int size,int *index,
4360                             FILE *output,int next_face_id,int face_id,int where)
4361{
4362  int id1,id2,id3;
4363  int nedge1,nedge2;
4364  int reversed;
4365  /*    We have a polygon that has to be triangulated and we cannot
4366        do it blindly, ie we will try to come out on the edge that
4367        has the least number of adjacencies
4368  */
4369 
4370  Last_Edge(&id1,&id2,&id3,0);
4371  /*    Find the edge that is adjacent to the new face ,
4372        also return whether the orientation is reversed in the
4373        face of the input edge, which is id2 and id3.
4374  */
4375  if (next_face_id == -1)
4376    {
4377      printf("The face is -1 and the size is %d\n",size);
4378      exit(0);
4379    }
4380 
4381  reversed = Get_EdgeEx(&nedge1,&nedge2,index,next_face_id,size,id2,id3);
4382  /*    Do the triangulation */
4383 
4384  /*    If reversed is -1, the input edge is not in the polygon,
4385        therefore we can have the input edge to be anything we like,
4386        since we are at the beginning of a strip
4387  */
4388  TriangulateEx(nedge1,nedge2,id2,id3,size,index,output,reversed,
4389                face_id, where);
4390}
4391
4392///     Rearrange_IndexEx:
4393void CustomStripifier::Rearrange_IndexEx(int *index, int size)
4394{
4395  /*    If we are in the middle of a strip we must find the
4396        edge to start on, which is the last edge that we had
4397        transmitted.
4398  */
4399  int x,f,y,e1,e2,e3;
4400  int increment = 1;
4401  int *temp;
4402 
4403  /*    Find where the input edge is in the input list */
4404  Last_Edge(&e1,&e2,&e3,0);
4405  for (y = 0; y < size; y++)
4406    {
4407      if (*(index+y) == e2)
4408        {
4409          if ((y != (size - 1)) && (*(index+y+1) == e3))
4410            break;
4411          else if ((y == (size - 1)) && (*(index) == e3))
4412            break;
4413          else if ((y != 0) && (*(index+y-1) == e3))
4414            {
4415              increment = -1;
4416              break;
4417            }
4418          else if ((y==0) && (*(index+size-1) == e3))
4419            {
4420              increment = -1;
4421              break;
4422            }
4423        }
4424      if (*(index+y) == e3)
4425        {
4426          if ((y != (size - 1)) && (*(index+y+1) == e2))
4427            break;
4428          else if ((y == (size - 1)) && (*(index) == e2))
4429            break;
4430          else if ((y != 0) && (*(index+y-1) == e2))
4431            {
4432              increment = -1;
4433              break;
4434            }
4435          else if ((y==0) && (*(index+size-1) == e2))
4436            {
4437              increment = -1;
4438              break;
4439            }
4440        }
4441      /*        Edge is not here, we are at the beginning */
4442      if ((y == (size-1)) && (increment != -1))
4443        return;
4444    }
4445 
4446  /*    Now put the list into a new list, starting with the
4447        input edge. Increment tells us whether we have to go
4448        forward or backward.
4449  */
4450  /*    Was in good position already */
4451  if ((y == 0) && (increment == 1))
4452    return;
4453 
4454 
4455  temp = (int *) malloc(sizeof(int) * size);
4456  memcpy(temp,index,sizeof(int)*size);
4457 
4458  if (increment == 1)
4459    {
4460      x=0;
4461      for (f = y ; f< size; f++)
4462        {
4463          *(index+x) = *(temp+f);
4464          x++;
4465        }
4466      /*        Finish the rest of the list */ 
4467      for(f = 0; f < y ; f++)
4468        {
4469          *(index+x) = *(temp+f);
4470          x++;
4471        }
4472    }
4473  else
4474    {
4475      x=0;
4476      for (f = y ; f >= 0; f--)
4477        {
4478          *(index+x) = *(temp+f);
4479          x++;
4480        }
4481      /*        Finish the rest of the list */ 
4482      for(f = (size - 1); f > y ; f--)
4483        {
4484          *(index+x) = *(temp+f);
4485          x++;
4486        }
4487    }
4488}
4489
4490///     Blind_TriangulateEx:
4491void CustomStripifier::Blind_TriangulateEx(int size, int *index,
4492                         BOOL begin, int where )
4493{
4494  /*    save sides in temp array, we need it so we know
4495        about swaps.
4496  */
4497  int mode, decreasing,increasing,e1,e2,e3;
4498 
4499  /*    Rearrange the index list so that the input edge is first
4500   */
4501  if (!begin)
4502    Rearrange_IndexEx(index,size);
4503 
4504  /*    We are given a polygon of more than 3 sides
4505        and want to triangulate it. We will output the
4506        triangles to the output file.
4507  */
4508 
4509  /*    Find where the input edge is in the input list */
4510  Last_Edge(&e1,&e2,&e3,0);
4511  if (( (!begin) && (*(index) == e2) ) || (begin))
4512    {
4513      Output_TriEx(*(index+0),*(index+1),*(index+size-1),NULL,-1,where);
4514      /*        If we have a quad, (chances are yes), then we know that
4515                we can just add one diagonal and be done. (divide the
4516                quad into 2 triangles.
4517      */
4518      if (size == 4)
4519        {
4520          Output_TriEx(*(index+1),*(index+size-1),*(index+2),NULL,-1,where);
4521          return;
4522        }
4523      increasing = 1;
4524      mode = 1;
4525     
4526    }
4527  else if (!begin)
4528    {
4529      Output_TriEx(*(index+1),*(index+0),*(index+size-1),NULL,-1,where);
4530      if (size == 4)
4531        {
4532          Output_TriEx(*(index+0),*(index+size-1),*(index+2),NULL,-1,where);
4533          return;
4534        }
4535      Output_TriEx(*(index+0),*(index+size-1),*(index+2),NULL,-1,where);
4536      increasing = 2;
4537      mode = 0;
4538    }
4539  if (size != 4)
4540    {
4541      /*        We do not have a quad, we have something bigger. */
4542      decreasing = size - 1;
4543     
4544      do
4545        {
4546          /*    Will be alternating diagonals, so we will be increasing
4547                and decreasing around the polygon.
4548          */
4549          if (mode)
4550            {
4551              Output_TriEx(*(index+increasing),*(index+decreasing),
4552                           *(index+increasing+1),NULL,-1,where);
4553              increasing++;
4554            }
4555          else
4556            {
4557              Output_TriEx(*(index+decreasing),*(index+increasing),
4558                           *(index+decreasing-1),NULL,-1,where);
4559              decreasing--;
4560            }
4561          mode = !mode;
4562        } while ((decreasing - increasing) >= 2);
4563     
4564    }
4565}
4566
4567///     Get_EdgeEx:
4568int CustomStripifier::Get_EdgeEx(int *edge1,int *edge2,int *index,int face_id,
4569               int size, int id1, int id2)
4570{
4571  /*    Put the edge that is adjacent to face_id into edge1
4572        and edge2. For each edge see if it is adjacent to
4573        face_id. Id1 and id2 is the input edge, so see if
4574        the orientation is reversed, and save it in reversed.
4575  */
4576  int x;
4577  int reversed = -1;
4578  BOOL set = FALSE;
4579 
4580  for (x=0; x< size; x++)
4581    {
4582      if (x == (size-1))
4583        {
4584          if ((*(index) == id1) && (*(index+size-1)==id2))
4585            {
4586              if (set)
4587                return 1;
4588              reversed = 1;
4589            }
4590          else if ((*(index) == id2) && (*(index+size-1)==id1))
4591            {
4592              if (set)
4593                return 0;
4594              reversed = 0;
4595            }
4596         
4597          if (Look_Up(*(index),*(index+size-1),face_id))
4598            {
4599              if ( (out1Ex != -1) &&
4600                   ( (out1Ex == *(index)) || (out1Ex == *(index+size-1)) ) &&
4601                   ( (out2Ex == *(index)) || (out2Ex == *(index+size-1)) ))
4602                {
4603                  set = TRUE;
4604                  *edge1 = *(index);
4605                  *edge2 = *(index+size-1);
4606                }
4607              else if (out1Ex == -1)
4608                {
4609                  set = TRUE;
4610                  *edge1 = *(index);
4611                  *edge2 = *(index+size-1);
4612                }
4613              if ((reversed != -1) && (set)) 
4614                return reversed;
4615            }
4616        }               
4617      else
4618        {
4619          if ((*(index+x) == id1) && (*(index+x+1)==id2))
4620            {
4621              if (set)
4622                return 0;
4623              reversed = 0;
4624            }
4625          else if ((*(index+x) == id2) && (*(index+x+1)==id1))
4626            {
4627              if (set)
4628                return 1;
4629              reversed = 1;
4630            }
4631         
4632          if (Look_Up(*(index+x),*(index+x+1),face_id))
4633            {
4634              if ( (out1Ex != -1) &&
4635                   ( (out1Ex == *(index+x)) || (out1Ex == *(index+x+1)) ) &&
4636                   ((out2Ex == *(index+x)) || (out2Ex == *(index+x+1))))
4637                {
4638                  set = TRUE;
4639                  *edge1 = *(index+x);
4640                  *edge2 = *(index+x+1);
4641                }
4642              else if (out1Ex == -1)
4643                {
4644                  set = TRUE;
4645                  *edge1 = *(index+x);
4646                  *edge2 = *(index+x + 1);
4647                }
4648              if ((reversed != -1) && (set))
4649                return reversed;
4650            }
4651        }
4652    }                   
4653  if ((x == size) && (reversed != -1))
4654    {
4655      /*        Could not find the output edge */
4656      printf("Error in the Lookup %d %d %d %d %d %d %d %d\n",
4657             face_id,id1,id2,reversed,*edge1,*edge2,out1Ex,out2Ex);
4658      exit(0);
4659    }
4660  return reversed;
4661}
4662
4663///     Update_FaceEx:
4664void CustomStripifier::Update_FaceEx(   int *next_bucket,int *min_face,
4665                                                                                                                                                        int face_id, int *e1,
4666                                                                                                                                                int *e2,int temp1,
4667                                                                                                                                                        int temp2,int *ties)
4668{
4669  /*    We have a face id that needs to be decremented.
4670        We have to determine where it is in the structure,
4671        so that we can decrement it.
4672  */
4673  /*    The number of adjacencies may have changed, so to locate
4674        it may be a little tricky. However we know that the number
4675        of adjacencies is less than or equal to the original number
4676        of adjacencies,
4677  */
4678  int y,size;
4679  ListHead *pListHead;
4680  PF_FACES temp = NULL;
4681  PLISTINFO lpListInfo;
4682  static int each_poly = 0;
4683  BOOL there = FALSE;
4684 
4685  pListHead = PolFaces[face_id];
4686  temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
4687  /*    Check each edge of the face and tally the number of adjacent
4688        polygons to this face.
4689  */                   
4690  if ( temp != NULL )
4691    {
4692      /*        Size of the polygon */
4693      size = temp->nPolSize;
4694      for (y = 0; y< size; y++)
4695        {
4696          /*    If we are doing partial triangulation, we must check
4697                to see whether the edge is still there in the polygon,
4698                since we might have done a portion of the polygon
4699                and saved the rest for later.
4700          */
4701          if (y != (size-1))
4702            {
4703              if( ((temp1 == *(temp->pPolygon+y)) &&
4704                   (temp2 ==*(temp->pPolygon+y+1))) ||
4705                  ((temp2 == *(temp->pPolygon+y)) &&
4706                   (temp1 ==*(temp->pPolygon+y+1))))
4707                /*      edge is still there we are ok */
4708                there = TRUE;
4709            }
4710          else
4711            {
4712              if( ((temp1 == *(temp->pPolygon)) &&
4713                   (temp2 == *(temp->pPolygon+size-1))) ||
4714                  ((temp2 == *(temp->pPolygon)) &&
4715                   (temp1 ==*(temp->pPolygon+size-1))))
4716                /*      edge is still there we are ok */
4717                there = TRUE;
4718            }
4719        }
4720     
4721      if (!there)
4722        /*      Original edge was already used, we cannot use this polygon */
4723        return;
4724     
4725      /*        We have a starting point to start our search to locate
4726                this polygon.
4727      */
4728     
4729      /*        Check to see if this polygon was done */
4730      lpListInfo = Done(face_id,&y);
4731     
4732      if (lpListInfo == NULL)
4733        return;
4734     
4735      /*  Was not done, but there is an error in the adjacency calculations */
4736      /*     If more than one edge is adj to it then maybe it was not updated */
4737      if (y == 0)
4738        return;
4739     
4740      /*        Now put the face in the proper bucket depending on tally. */
4741      /*        First add it to the new bucket, then remove it from the old */
4742      Add_Sgi_Adj(y-1,face_id);
4743      RemoveList(array[y],lpListInfo);
4744     
4745      /*        Save it if it was the smallest seen so far since then
4746                it will be the next face
4747                Here we will have different options depending on
4748                what we want for resolving ties:
4749                1) First one we see we will use
4750                2) Random resolving
4751                3) Look ahead
4752                4) Alternating direction
4753      */
4754      /*        At a new strip */
4755      if (*next_bucket == 60)
4756        *ties = *ties + each_poly;
4757      /*        Have a tie */
4758      if (*next_bucket == (y-1))
4759        {
4760          Add_Ties(face_id);
4761          each_poly++;
4762        }
4763      /*        At a new minimum */
4764      if (*next_bucket > (y-1))
4765        {
4766          *next_bucket = y-1;
4767          *min_face = face_id;
4768          *e1 = temp1;
4769          *e2 = temp2;
4770          each_poly = 0;
4771          Clear_Ties();
4772          Add_Ties(face_id);
4773        }
4774    }
4775}
4776
4777///     Delete_AdjEx:
4778void CustomStripifier::Delete_AdjEx(int id1,                                    int id2,
4779                                                                                                                                                int *next_bucket,       int *min_face,
4780                                                                                                                                        int current_face,       int *e1,
4781                                                                                                                                                int *e2,                                        int *ties)
4782{
4783  /*    Find the face that is adjacent to the edge and is not the
4784        current face. Delete one adjacency from it. Save the min
4785        adjacency seen so far.
4786  */
4787  register int count=0;
4788  PF_EDGES temp = NULL;
4789  ListHead *pListHead;
4790  int next_face;
4791 
4792  /*    Always want smaller id first */
4793  switch_lower(&id1,&id2);
4794 
4795  pListHead = PolEdges[id1];
4796  temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
4797  if (temp == NULL)
4798    /*  It could be a new edge that we created. So we can
4799        exit, since there is not a face adjacent to it.
4800    */
4801    return;
4802  while (temp->edge[0] != id2)
4803    {
4804      count++;
4805      temp = ( PF_EDGES )GetNextNode(temp);                                     
4806     
4807      if (temp == NULL)
4808        /*      Was a new edge that was created and therefore
4809                does not have anything adjacent to it
4810        */
4811        return;
4812    }
4813  /*    Was not adjacent to anything else except itself */
4814  if (temp->edge[2] == -1)
4815    return;
4816 
4817  /*    Was adjacent to something */
4818  else
4819    {
4820      if (temp->edge[2] == current_face)
4821        next_face =  temp->edge[1];
4822      else
4823        next_face = temp->edge[2];
4824    }
4825  /*    We have the other face adjacent to this edge, it is
4826        next_face. Now we need to decrement this faces' adjacencies.
4827  */
4828  Update_FaceEx(next_bucket, min_face, next_face,e1,e2,id1,id2,ties);
4829}
4830
4831///     Change_FaceEx:
4832int CustomStripifier::Change_FaceEx(int face_id,int in1,int in2,
4833                  ListHead *pListHead, BOOL no_check)
4834{
4835  /*    We are doing a partial triangulation and we need to
4836        put the new face of triangle into the correct bucket
4837  */
4838  int input_adj,y;
4839  P_ADJACENCIES lpListInfo; 
4840 
4841  /*    Find the old number of adjacencies to this face,
4842        so we know where to delete it from
4843  */
4844  y = Old_Adj(face_id);
4845  pListHead = array[y];
4846  lpListInfo = face_array[face_id].pfNode;
4847 
4848  if (lpListInfo == NULL)
4849    {
4850      printf("There is an error finding the next polygon3 %d\n",face_id);
4851      exit(0);
4852    }
4853 
4854  /*    Do we need to change the adjacency? Maybe the edge on the triangle
4855        that was outputted was not adjacent to anything. We know if we
4856        have to check by "check". We came out on the output edge
4857        that we needed, then we know that the adjacencies will decrease
4858        by exactly one.
4859  */
4860  if (!no_check)
4861    {
4862      input_adj = Number_Adj(in1,in2,face_id);
4863      /*        If there weren't any then don't do anything */
4864      if (input_adj == 0)
4865        return y;
4866    }
4867 
4868  if (face_array[lpListInfo->face_id].head == pListHead)
4869    face_array[lpListInfo->face_id].pfNode = NULL;
4870  RemoveList(pListHead,(PLISTINFO)/*(temp*/lpListInfo);
4871  /*    Before we had a quad with y adjacencies. The in edge
4872        did not have an adjacency, since it was just deleted,
4873        since we came in on it. The outedge must have an adjacency
4874        otherwise we would have a bucket 0, and would not be in this
4875        routine. Therefore the new adjacency must be y-1
4876  */
4877 
4878  Add_Sgi_Adj(y-1,face_id);
4879  return (y-1);
4880}
4881
4882///     Update_AdjacenciesEx:
4883int CustomStripifier::Update_AdjacenciesEx(int face_id, int *next_bucket, int *e1, int *e2,
4884                         int *ties)
4885{
4886  /*    Give the face with id face_id, we want to decrement
4887        all the faces that are adjacent to it, since we will
4888        be deleting face_id from the data structure.
4889        We will return the face that has the least number
4890        of adjacencies.
4891  */
4892  PF_FACES temp = NULL;
4893  ListHead *pListHead;
4894  int size,y,min_face = -1;
4895 
4896  *next_bucket = 60;
4897  pListHead = PolFaces[face_id];
4898  temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
4899 
4900  if ( temp == NULL )
4901    {
4902      printf("The face was already deleted, there is an error\n");
4903      exit(0);
4904    }
4905 
4906  /*    Size of the polygon */
4907  size = temp->nPolSize;
4908  for (y = 0; y< size; y++)
4909    {
4910      if (y != (size-1))
4911        Delete_AdjEx(*(temp->pPolygon+y),*(temp->pPolygon+y+1),
4912                     next_bucket,&min_face,face_id,e1,e2,ties);
4913      else
4914        Delete_AdjEx(*(temp->pPolygon),*(temp->pPolygon+(size-1)),
4915                     next_bucket,&min_face,face_id,e1,e2,ties);
4916    }
4917  return (min_face);
4918}
4919
4920///     Find_Adj_TallyEx:
4921void CustomStripifier::Find_Adj_TallyEx(int id1,                                        int id2,
4922                                                                                                                                                                int *next_bucket,       int *min_face,
4923                                                                                                                                                int current_face,       int *ties)
4924{
4925  /*    Find the face that is adjacent to the edge and is not the
4926        current face. Save the min adjacency seen so far.
4927  */
4928  int size,each_poly=0,y,count=0;           
4929  PF_EDGES temp = NULL;
4930  PF_FACES temp2 = NULL;
4931  ListHead *pListHead;
4932  int next_face;
4933  BOOL there = FALSE;
4934 
4935 
4936  /*    Always want smaller id first */
4937  switch_lower(&id1,&id2);
4938 
4939  pListHead = PolEdges[id1];
4940  temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
4941  if (temp == NULL)
4942    /*  This was a new edge that was created, so it is
4943        adjacent to nothing.
4944    */
4945    return;
4946  while (temp->edge[0] != id2)
4947    {
4948      count++;
4949      temp =( PF_EDGES ) GetNextNode(temp);                                       
4950     
4951      if (temp == NULL)
4952        /*      This was a new edge that we created */
4953        return;
4954    }
4955  /*    Was not adjacent to anything else except itself */
4956  if (temp->edge[2] == -1)
4957    return;
4958  else
4959    {
4960      if (temp->edge[2] == current_face)
4961        next_face =  temp->edge[1];
4962      else
4963        next_face = temp->edge[2];
4964    }
4965  /*    We have the other face adjacent to this edge, it is
4966        next_face. Find how many faces it is adjacent to.
4967  */
4968  pListHead = PolFaces[next_face];
4969  temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
4970  /*    Check each edge of the face and tally the number of adjacent
4971        polygons to this face. This will be the original number of
4972        polygons adjacent to this polygon, we must then see if this
4973        number has been decremented
4974  */                   
4975  if ( temp2 != NULL )
4976    {
4977      /*        Size of the polygon */
4978      size = temp2->nPolSize;
4979      for (y = 0; y< size; y++)
4980        {
4981          /*    Make sure that the edge is still in the
4982                polygon and was not deleted, because if the edge was
4983                deleted, then we used it already.
4984          */
4985          if (y != (size-1))
4986            {
4987              if( ((id1 == *(temp2->pPolygon+y)) &&
4988                   (id2 ==*(temp2->pPolygon+y+1))) ||
4989                  ((id2 == *(temp2->pPolygon+y)) &&
4990                   (id1 ==*(temp2->pPolygon+y+1))))
4991                /*      edge is still there we are ok */
4992                there = TRUE;
4993            }
4994          else
4995            {           
4996              if( ((id1 == *(temp2->pPolygon)) &&
4997                   (id2 ==*(temp2->pPolygon+size-1))) ||
4998                  ((id2 == *(temp2->pPolygon)) &&
4999                   (id1 ==*(temp2->pPolygon+size-1))))
5000                /*      edge is still there we are ok */
5001                there = TRUE;
5002            }
5003        }
5004     
5005      if (!there)
5006        /*      Edge already used and deleted from the polygon*/
5007        return;
5008     
5009      /*        See if the face was already deleted, and where
5010                it is if it was not
5011      */
5012      if (Done(next_face,&y) == NULL)
5013        return;
5014     
5015      /*        Save it if it was the smallest seen so far since then
5016                it will be the next face
5017                Here we will have different options depending on
5018                what we want for resolving ties:
5019                1) First one we see we will use
5020                2) Random resolving
5021                3) Look ahead
5022                4) Alternating direction
5023      */
5024     
5025      /*        At a new strip */
5026      if (*next_bucket == 60)
5027        *ties = *ties + each_poly;
5028      /*        Have a tie */
5029      if (*next_bucket == (y-1))
5030        {
5031          Add_Ties(next_face);
5032          each_poly++;
5033        }
5034      /*        At a new minimum */
5035      if (*next_bucket > (y-1))
5036        {
5037          *next_bucket = y-1;
5038          *min_face = next_face;
5039          each_poly = 0;
5040          Clear_Ties();
5041          Add_Ties(next_face);
5042        }
5043    }
5044}
5045
5046///     Min_Face_AdjEx:
5047int CustomStripifier::Min_Face_AdjEx(int face_id, int *next_bucket, int *ties)
5048{
5049  /*    Used for the Partial triangulation to find the next
5050        face. It will return the minimum adjacency face id
5051        found at this face.
5052  */
5053  PF_FACES temp = NULL;
5054  ListHead *pListHead;
5055  int size,y,min_face,test_face;
5056 
5057  *next_bucket = 60;
5058  pListHead = PolFaces[face_id];
5059  temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
5060 
5061  if ( temp == NULL )
5062    {
5063      printf("The face was already deleted, there is an error\n");
5064      exit(0);
5065    }
5066 
5067  /*    Size of the polygon */
5068  size = temp->nPolSize;
5069  for (y = 0; y< size; y++)
5070    {
5071      if (y != (size-1))
5072        Find_Adj_TallyEx(*(temp->pPolygon+y),*(temp->pPolygon+y+1),
5073                         next_bucket,&min_face,face_id,ties);
5074      else
5075        Find_Adj_TallyEx(*(temp->pPolygon),*(temp->pPolygon+(size-1)),
5076                         next_bucket,&min_face,face_id,ties);
5077    }
5078  /*    Maybe we can do better by triangulating the face, because
5079        by triangulating the face we will go to a polygon of lesser
5080        adjacencies
5081  */
5082  if (size == 4)
5083    {
5084      /*    Checking for a quad whether to do the whole polygon will
5085            result in better performance because the triangles in the polygon
5086            have less adjacencies
5087      */
5088      Check_In_Quad(face_id,&test_face);
5089      if (*next_bucket > test_face)
5090        /*    We can do better by going through the polygon */
5091        min_face = face_id;
5092    }
5093 
5094  /*  We have a polygon with greater than 4 sides, check to see if going
5095      inside is better than going outside the polygon for the output edge.
5096  */
5097  else
5098    {
5099      Check_In_Polygon(face_id,&test_face,size);
5100      if (*next_bucket > test_face)
5101        /*  We can do better by going through the polygon */
5102        min_face = face_id;
5103    }
5104 
5105  return (min_face);
5106}
5107
5108///     Find_StripsEx:
5109void CustomStripifier::Find_StripsEx(FILE *output,int *ties,
5110                          int  tie, int triangulate,
5111                          int  swaps,int *next_id)
5112{
5113  /*    This routine will peel off the strips from the model */
5114 
5115  ListHead                      *pListHead;
5116  P_ADJACENCIES temp                            =       NULL;
5117  register int  max,bucket      =       0;
5118  BOOL                                  whole_flag      =       TRUE;
5119  int                                           dummy                           = 0;
5120  int                                           cont                            =       0;
5121 
5122  /*  Set the last known input edge to be null */
5123  Last_Edge(&dummy,&dummy,&dummy,1);
5124 
5125  /*    Search for lowest adjacency polygon and output strips */
5126  while (whole_flag)
5127        {
5128                bucket = -1;
5129    /*  Search for polygons in increasing number of adjacencies */
5130    while (bucket < 59)
5131                {
5132                        bucket++;
5133                        pListHead = array[bucket];
5134                        max = NumOnList(pListHead);
5135                        if (max > 0)
5136            {
5137                                temp = (P_ADJACENCIES) PeekList(pListHead,LISTHEAD,0);
5138              if (temp == NULL)
5139                                {
5140                                        printf("Error in the buckets%d %d %d\n",bucket,max,0);
5141                                        exit(0);
5142                                }
5143
5144              Polygon_OutputEx(temp,temp->face_id,bucket,pListHead, output,ties,tie,triangulate,swaps,next_id,1);
5145              /*  Try to extend backwards, if the starting polygon in the
5146                                                strip had 2 or more adjacencies to begin with
5147              */
5148              if (bucket >= 2)
5149                                        Extend_BackwardsEx(temp->face_id,output,ties,tie, triangulate,swaps,next_id);
5150
5151                                break; 
5152                        }
5153                }
5154                /*      Went through the whole structure, it is empty and we are done.
5155                */
5156                if ((bucket == 59) && (max == 0))
5157                        whole_flag = FALSE;
5158     
5159    /*  We just finished a strip, send dummy data to signal the end
5160                                of the strip so that we can output it.
5161    */
5162    else
5163                {
5164                        Output_TriEx(-1,-2,-3,output,-10,1);
5165                        Last_Edge(&dummy,&dummy,&dummy,1);
5166                        cont++;
5167                }
5168  }
5169        printf("We got %d strips\n",cont);
5170}
5171
5172///     SGI_Strip:
5173void CustomStripifier::SGI_Strip(int    num_faces,
5174                                                                                                                                 FILE *output,
5175                                                                                                                                 int    ties,
5176                                                                                                                                 int    triangulate)
5177{
5178  int next_id = -1,t=0;
5179 
5180  /* We are going to output and find triangle strips
5181     according the the method that SGI uses, ie always
5182     choosing as the next triangle in our strip the triangle
5183     that has the least number of adjacencies. We do not have
5184     all triangles and will be triangulating on the fly those
5185     polygons that have more than 3 sides.
5186  */
5187 
5188  /* Build a table that has all the polygons sorted by the number
5189     of polygons adjacent to it.
5190  */
5191  /* Initialize it */
5192  Init_Table_SGI(num_faces);
5193  /* Build it */
5194  Build_SGI_Table(num_faces);
5195 
5196  /* We will have a structure to hold all the strips, until
5197     outputted.
5198  */
5199  InitStripTable();
5200  /*  Now we have the structure built to find the polygons according
5201      to the number of adjacencies. Now use the SGI Method to find
5202      strips according to the adjacencies
5203  */
5204
5205  Find_StripsEx(output,&t,ties,triangulate,ON,&next_id);
5206 
5207}
5208
5209///     P_Triangulate_Quad:
5210void CustomStripifier::P_Triangulate_Quad(int out_edge1,int out_edge2,
5211                                                                                                                                                                        int in_edge1, int in_edge2,
5212                                                                                                                                                                        int size,                       int *index,
5213                                                                                                                                                int reversed, int face_id,
5214                                                                                                                                                                        ListHead *pListHead,
5215                                                                                                                                                P_ADJACENCIES temp,
5216                                                                                                                                                int where)
5217{
5218  int vertex4,vertex5,dummy=60;
5219 
5220  /*    This routine will nonblindly triangulate a quad, meaning
5221        that there is a definite input and a definite output
5222        edge that we must adhere to. Reversed will tell the orientation
5223        of the input edge. (Reversed is -1 is we do not have an input
5224        edge, in other words we are at the beginning of a strip.)
5225        Out_edge* is the output edge, and in_edge* is the input edge.
5226        Index are the edges of the polygon
5227        and size is the size of the polygon. Begin is whether we are
5228        at the start of a new strip.
5229        Note that we will not necessarily triangulate the whole quad;
5230        maybe we will do half and leave the other half (a triangle)
5231        for later.
5232  */
5233 
5234 
5235  /*    If we do not have an input edge, then we can make our input
5236        edge whatever we like, therefore it will be easier to come
5237        out on the output edge. In this case the whole quad is done.
5238  */
5239  if (reversed == -1)
5240    {
5241      vertex4 = AdjacentEx(out_edge1,out_edge2,index,size);
5242      vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index);
5243      Output_TriEx(vertex5,vertex4,out_edge1,NULL,-1,where);
5244      Output_TriEx(vertex4,out_edge1,out_edge2,NULL,-1,where);
5245      dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy);
5246     
5247      if (face_array[temp->face_id].head == pListHead)
5248        face_array[temp->face_id].pfNode = NULL;
5249      RemoveList(pListHead,(PLISTINFO) temp);
5250      return;
5251    }
5252 
5253  /*    These are the 5 cases that we can have for the output edge */
5254 
5255  /*  Are they consecutive so that we form a triangle to
5256      peel off, but cannot use the whole quad?
5257  */
5258 
5259  if (in_edge2 == out_edge1)
5260    {
5261      /*        Output the triangle that comes out the correct
5262                edge. Save the other half for later.
5263      */
5264      vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index);
5265      Output_TriEx(in_edge1,in_edge2,out_edge2,NULL,-1,where);
5266      /*        Now we have a triangle used, and a triangle that is
5267                left for later.
5268      */
5269     
5270      /*        Now delete the adjacencies by one for all the faces
5271                that are adjacent to the triangle that we just outputted.
5272      */
5273      Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,
5274                   face_id,&dummy,&dummy,&dummy);
5275      Delete_AdjEx(out_edge2,in_edge2,&dummy,&dummy,
5276                   face_id,&dummy,&dummy,&dummy);
5277      /*        Put the new face in the proper bucket of adjacencies
5278                There are 2 edges that need to be checked for the triangle
5279                that was just outputted. For the output edge we definitely
5280                will be decreasing the adjacency, but we must check for the
5281                input edge.
5282      */
5283     
5284      dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,FALSE);
5285      dummy = Change_FaceEx(face_id,in_edge2,out_edge2,pListHead,TRUE);
5286     
5287      /*        Update the face data structure, by deleting the old
5288                face and putting in the triangle as the new face
5289      */
5290      New_Face(face_id,in_edge1,out_edge2,vertex4);
5291      return;                                                                     
5292    }
5293  else if (in_edge1 == out_edge1)
5294    {
5295      /*        We want to output the first triangle (whose output
5296                edge is not the one that we want.
5297                We have to find the vertex that we need, which is
5298                the other vertex which we do not have.
5299      */                                               
5300      vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index);
5301      Output_TriEx(in_edge2,in_edge1,out_edge2,NULL,-1,where);
5302      /*        Now we have a triangle used, and a triangle that is
5303                left for later.
5304      */
5305     
5306      /*        Now delete the adjacencies by one for all the faces
5307                that are adjacent to the triangle that we just outputted.
5308      */
5309      Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
5310                   &dummy,&dummy,&dummy);
5311      Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy,
5312                   face_id,&dummy,&dummy,&dummy);
5313     
5314      /*        Put the new face in the proper bucket of adjacencies */
5315      dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,FALSE);
5316      dummy = Change_FaceEx(face_id,in_edge1,out_edge2,pListHead,TRUE);
5317     
5318      /*        Update the face data structure, by deleting the old
5319                face and putting in the triangle as the new face
5320      */
5321      New_Face(face_id,in_edge2,out_edge2,vertex4);
5322      return;
5323    }
5324 
5325  /*    Consecutive cases again, but with the output edge reversed */
5326  else if (in_edge1 == out_edge2)
5327    {
5328      vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
5329      Output_TriEx(in_edge2,in_edge1,out_edge1,NULL,-1,where);
5330      /*        Now we have a triangle used, and a triangle that is
5331                left for later.
5332      */
5333     
5334      /*        Now delete the adjacencies by one for all the faces
5335                that are adjacent to the triangle that we just outputted.
5336      */
5337      Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
5338                   &dummy,&dummy,&dummy);
5339      Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy,
5340                   face_id,&dummy,&dummy,&dummy);
5341     
5342      /*        Put the new face in the proper bucket of adjacencies */
5343      dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,FALSE);
5344      dummy = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,TRUE);
5345     
5346      /*        Update the face data structure, by deleting the old
5347                face and putting in the triangle as the new face
5348      */
5349      New_Face(face_id,in_edge2,out_edge1,vertex4);
5350      return;
5351    }
5352  else if (in_edge2 == out_edge2)
5353    {
5354      vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
5355      Output_TriEx(in_edge1,in_edge2,out_edge1,NULL,-1,where);
5356      /*        Now we have a triangle used, and a triangle that is
5357                left for later.
5358      */
5359      /*        Now delete the adjacencies by one for all the faces
5360                that are adjacent to the triangle that we just outputted.
5361      */
5362      Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
5363                   &dummy,&dummy,&dummy);
5364      Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy,
5365                   face_id,&dummy,&dummy,&dummy);
5366     
5367      /*        Put the new face in the proper bucket of adjacencies */
5368      dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,FALSE);
5369      dummy = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,TRUE);
5370     
5371      /*        Update the face data structure, by deleting the old
5372                face and putting in the triangle as the new face
5373      */
5374      New_Face(face_id,in_edge1,out_edge1,vertex4);
5375      return;
5376    }
5377 
5378  /*    The final case is where we want to come out the opposite
5379        edge.
5380  */
5381  else
5382    {
5383      if( ((!reversed) &&
5384           (out_edge1 == (AdjacentEx(in_edge1,in_edge2,index,size)))) ||
5385          ((reversed) &&
5386           (out_edge2 == (AdjacentEx(in_edge2,in_edge1,index,size)))))
5387        {
5388          /*    We need to know the orientation of the input
5389                edge, so we know which way to put the diagonal.
5390                And also the output edge, so that we triangulate
5391                correctly. Does not need partial.
5392          */
5393          Output_TriEx(in_edge1,in_edge2,out_edge2,NULL,-1,where);
5394          Output_TriEx(in_edge2,out_edge2,out_edge1,NULL,-1,where);
5395          dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy);
5396         
5397          if (face_array[temp->face_id].head == pListHead)
5398            face_array[temp->face_id].pfNode = NULL;
5399          RemoveList(pListHead,(PLISTINFO) temp);
5400        }
5401      else
5402        {
5403          /*      Input and output orientation was reversed, so diagonal will
5404                  be reversed from above.
5405          */
5406          Output_TriEx(in_edge1,in_edge2,out_edge1,NULL,-1,where);
5407          Output_TriEx(in_edge2,out_edge1,out_edge2,NULL,-1,where);
5408          dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy);
5409         
5410          if (face_array[temp->face_id].head == pListHead)
5411            face_array[temp->face_id].pfNode = NULL;
5412          RemoveList(pListHead,(PLISTINFO) temp);
5413        }
5414      return;
5415    }
5416}
5417
5418///     P_Triangulate_Polygon:
5419void CustomStripifier::P_Triangulate_Polygon(   int out_edge1,int out_edge2,
5420                                                                                                                                                                                        int in_edge1, int in_edge2,
5421                                                                                                                                                                                        int size,               int *index,
5422                                                                                                                                                                                        FILE *fp,                 int reversed,
5423                                                                                                                                                                                        int face_id,    int *next_id,
5424                                                                                                                                                                                ListHead *pListHead,
5425                                                                                                                                                                                        P_ADJACENCIES temp2,
5426                                                                                                                                                                                int where)
5427{
5428  /*    We have a polygon greater than 4 sides, which we wish
5429        to partially triangulate
5430  */
5431  int next_bucket,vertex4,dummy = 60;
5432  int *temp;
5433 
5434 
5435  /*    Since we are calling this recursively, we have to check whether         
5436        we are down to the case of the quad.
5437  */
5438  if (size == 4)
5439    {
5440      P_Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size,
5441                         index,reversed,face_id,
5442                         pListHead,temp2,where);
5443      return;
5444    }
5445 
5446  /*    We do not have a specified input edge, and therefore we
5447        can make it anything we like, as long as we still come out
5448        the output edge that we want.
5449  */
5450  if (reversed  == -1)
5451    {
5452      /*        Get the vertex for the last triangle, which is
5453                the one coming out the output edge, before we do
5454                any deletions to the list. We will be doing this
5455                bottom up.
5456      */
5457      vertex4 = AdjacentEx(out_edge1,out_edge2,index,size);
5458      temp = (int *) malloc(sizeof(int) * size);
5459      memcpy(temp,index,sizeof(int)*size);
5460      Delete_From_ListEx(out_edge2,index,size);
5461      /*        We do not have to partially triangulate, since
5462                we will do the whole thing, so use the whole routine
5463      */
5464      Triangulate_PolygonEx(vertex4,out_edge1,in_edge2,
5465                            vertex4,size-1,index,fp,
5466                            reversed,face_id,
5467                            where);
5468      memcpy(index,temp,sizeof(int)*size);
5469      /*        Lastly do the triangle that comes out the output
5470                edge.
5471      */
5472      Output_TriEx(vertex4,out_edge1,out_edge2,NULL,-1,where);
5473      /*        We were able to do the whole polygon, now we
5474                can delete the whole thing from our data structure.
5475      */
5476      dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy);
5477     
5478      if (face_array[temp2->face_id].head == pListHead)
5479        face_array[temp2->face_id].pfNode = NULL;
5480      RemoveList(pListHead,(PLISTINFO) temp2);
5481      return;
5482    }     
5483 
5484  /*    These are the 5 cases that we can have for the output edge */
5485 
5486  /*  Are they consecutive so that we form a triangle to
5487      peel off that comes out the correct output edge,
5488      but we cannot use the whole polygon?
5489  */
5490  if (in_edge2 == out_edge1)
5491    {
5492      Output_TriEx(in_edge1,out_edge1,out_edge2,NULL,-1,where);
5493     
5494      /*        Now delete the adjacencies by one for all the faces
5495                that are adjacent to the triangle that we just outputted.
5496      */
5497      Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
5498                   &dummy,&dummy,&dummy);
5499      Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy,
5500                   face_id,&dummy,&dummy,&dummy);
5501     
5502      /*        Put the new face in the proper bucket of adjacencies */
5503      next_bucket=Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,FALSE);
5504      next_bucket=Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,TRUE);
5505     
5506      /*        Create a new edgelist without the triangle that
5507                was just outputted.
5508      */
5509      Delete_From_ListEx(in_edge2,index,size);
5510      /*        Update the face data structure, by deleting the old
5511                face and putting in the polygon minus the triangle
5512                as the new face, here we will be decrementing the size
5513                by one.
5514      */
5515      New_Size_Face(face_id);
5516      return;
5517    }
5518 
5519  /*    Next case is where it is again consecutive, but the triangle
5520        formed by the consecutive edges do not come out of the
5521        correct output edge. (the input edge will be reversed in
5522        the next triangle)
5523  */
5524  else if (in_edge1 == out_edge1)
5525    {
5526      /*        Get vertex adjacent to in_edge2, but is not in_edge1 */
5527      Output_TriEx(in_edge2,in_edge1,out_edge2,NULL,-1,where);
5528     
5529      /*        Now delete the adjacencies by one for all the faces
5530                that are adjacent to the triangle that we just outputted.
5531      */
5532      Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
5533                   &dummy,&dummy,&dummy);
5534      Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy,
5535                   face_id,&dummy,&dummy,&dummy);
5536     
5537      /*        Put the new face in the proper bucket of adjacencies */
5538      next_bucket=Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,FALSE);
5539      next_bucket=Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,TRUE);
5540     
5541      /*        Create a new edgelist without the triangle that
5542                was just outputted.
5543      */
5544      Delete_From_ListEx(in_edge1,index,size);
5545      /*        Update the face data structure, by deleting the old
5546                face and putting in the polygon minus the triangle
5547                as the new face, here we will be decrementing the size
5548                by one.
5549      */
5550      New_Size_Face(face_id);
5551      return;
5552    }
5553 
5554  /*    Consecutive cases again, but with the output edge reversed */
5555  else if (in_edge1 == out_edge2)
5556    {
5557      Output_TriEx(in_edge2,in_edge1,out_edge1,NULL,-1,where);
5558     
5559      /*        Now delete the adjacencies by one for all the faces
5560                that are adjacent to the triangle that we just outputted.
5561      */
5562      Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
5563                   &dummy,&dummy,&dummy);
5564      Delete_AdjEx(out_edge1,out_edge2,&dummy,&dummy,
5565                   face_id,&dummy,&dummy,&dummy);
5566     
5567      /*        Put the new face in the proper bucket of adjacencies */
5568      next_bucket=Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,FALSE);
5569      next_bucket=Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,TRUE);
5570     
5571      /*        Create a new edgelist without the triangle that
5572                was just outputted.
5573      */
5574      Delete_From_ListEx(in_edge1,index,size);
5575      /*        Update the face data structure, by deleting the old
5576                face and putting in the polygon minus the triangle
5577                as the new face, here we will be decrementing the size
5578                by one.
5579      */
5580      New_Size_Face(face_id);
5581      return;
5582    }
5583  else if (in_edge2 == out_edge2)
5584    {
5585      Output_TriEx(in_edge1,in_edge2,out_edge1,NULL,-1,where);
5586     
5587      /*        Now delete the adjacencies by one for all the faces
5588                that are adjacent to the triangle that we just outputted.
5589      */
5590      Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
5591                   &dummy,&dummy,&dummy);
5592      Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy,
5593                   face_id,&dummy,&dummy,&dummy);
5594     
5595      /*        Put the new face in the proper bucket of adjacencies */
5596      next_bucket=Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,FALSE);
5597      next_bucket=Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,TRUE);
5598     
5599      /*        Create a new edgelist without the triangle that
5600                was just outputted.
5601      */
5602      Delete_From_ListEx(in_edge2,index,size);
5603      /*        Update the face data structure, by deleting the old
5604                face and putting in the polygon minus the triangle
5605                as the new face, here we will be decrementing the size
5606                by one.
5607      */
5608      New_Size_Face(face_id);
5609      return;
5610    }
5611 
5612  /*    Else the edge is not consecutive, and it is sufficiently
5613        far away, for us not to make a conclusion at this time.
5614        So we can take off a triangle and recursively call this
5615        function.
5616  */
5617  else
5618    {
5619      if (!reversed)
5620        {
5621          vertex4 = AdjacentEx(in_edge2,in_edge1,index,size);
5622          Output_TriEx(in_edge1,in_edge2,vertex4,NULL,-1,where);
5623         
5624          /*    Now delete the adjacencies by one for all the faces
5625                that are adjacent to the triangle that we just outputted.
5626          */
5627          Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
5628                       &dummy,&dummy,&dummy);
5629          Delete_AdjEx(in_edge1,vertex4,&dummy,&dummy,
5630                       face_id,&dummy,&dummy,&dummy);
5631         
5632          /*    Put the new face in the proper bucket of adjacencies */
5633          next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,
5634                                      pListHead,FALSE);
5635          next_bucket = Change_FaceEx(face_id,in_edge1,vertex4,
5636                                      pListHead,FALSE);
5637         
5638          /*    Create a new edgelist without the triangle that
5639                was just outputted.
5640          */
5641          Delete_From_ListEx(in_edge1,index,size);
5642          /*    Update the face data structure, by deleting the old
5643                face and putting in the polygon minus the triangle
5644                as the new face, here we will be decrementing the size
5645                by one.
5646          */
5647          New_Size_Face(face_id);
5648         
5649          /*    Save the info for the new bucket, we will need it on
5650                the next pass for the variables, pListHead and temp
5651          */
5652          pListHead = array[next_bucket];
5653          temp2 = face_array[face_id].pfNode;
5654          if (temp2 == NULL)
5655            {
5656              printf("There is an error finding the next polygon10\n",
5657                     next_bucket,face_id);
5658              exit(0);
5659            }
5660         
5661          P_Triangulate_Polygon(out_edge1,out_edge2,in_edge2,
5662                                vertex4,size-1,index,fp,!reversed,
5663                                face_id,next_id,pListHead,temp2,where);
5664        }
5665      else
5666        {
5667          vertex4 = AdjacentEx(in_edge1,in_edge2,index,size);
5668          Output_TriEx(in_edge2,in_edge1,vertex4,NULL,-1,where);
5669         
5670          /*    Now delete the adjacencies by one for all the faces
5671                that are adjacent to the triangle that we just outputted.
5672          */
5673          Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
5674                       &dummy,&dummy,&dummy);
5675          Delete_AdjEx(in_edge2,vertex4,&dummy,&dummy,
5676                       face_id,&dummy,&dummy,&dummy);
5677         
5678          /*    Put the new face in the proper bucket of adjacencies */
5679          next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,
5680                                      pListHead,FALSE);
5681          next_bucket = Change_FaceEx(face_id,in_edge2,vertex4,
5682                                      pListHead,FALSE);
5683         
5684          /*    Create a new edgelist without the triangle that
5685                was just outputted.
5686          */
5687          Delete_From_ListEx(in_edge2,index,size);
5688         
5689          /*    Update the face data structure, by deleting the old
5690                face and putting in the polygon minus the triangle
5691                as the new face, here we will be decrementing the size
5692                by one.
5693          */
5694          New_Size_Face(face_id);
5695         
5696          /*    Save the info for the new bucket, we will need it on
5697                the next pass for the variables, pListHead and temp
5698          */
5699          pListHead = array[next_bucket];
5700          temp2 = face_array[face_id].pfNode;
5701          if (temp2 == NULL)
5702            {
5703              printf("There is an error finding the next polygon11 %d %d\n",
5704                     face_id,next_bucket);
5705              exit(0);
5706            }
5707         
5708          P_Triangulate_Polygon(out_edge1,out_edge2,vertex4,
5709                                in_edge1,size-1,index,fp,!reversed,
5710                                face_id,next_id,pListHead,temp2,where);
5711        }
5712      return;
5713    }
5714}
5715
5716///     P_Triangulate:
5717void CustomStripifier::P_Triangulate(   int out_edge1,int out_edge2,int in_edge1,
5718                                                                                                                                                int in_edge2,   int size,                       int *index,
5719                                                                                                                                                FILE *output,   int reversed,   int face_id,
5720                                                                                                                                                int *next_id,   ListHead *pListHead,
5721                                                                                                                                                P_ADJACENCIES temp,int where)
5722{
5723 
5724  if (size == 4)
5725    P_Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size,
5726                       index,reversed,face_id,
5727                       pListHead,temp,where);
5728  else
5729    P_Triangulate_Polygon(out_edge1,out_edge2,in_edge1,in_edge2,size,
5730                          index,output,reversed,face_id,next_id,
5731                          pListHead,temp,where);
5732}
5733
5734void CustomStripifier::Partial_Triangulate(int size,int *index,
5735                         FILE *output,int next_face_id,int face_id,
5736                         int *next_id,ListHead *pListHead,
5737                         P_ADJACENCIES temp, int where)
5738{
5739  int id1,id2,id3;
5740  int nedge1,nedge2;
5741  int reversed;
5742 
5743  /*    We have a polygon that has to be triangulated and we cannot
5744        do it blindly, ie we will try to come out on the edge that
5745        has the least number of adjacencies, But also we do not
5746        want to triangulate the whole polygon now, so that means
5747        we will output the least number of triangles that we can
5748        and then update the data structures, with the polygon
5749        that is left after we are done.
5750  */
5751  Last_Edge(&id1,&id2,&id3,0);
5752 
5753  /*    Find the edge that is adjacent to the new face ,
5754        also return whether the orientation is reversed in the
5755        face of the input edge, which is id2 and id3.
5756  */
5757  reversed = Get_EdgeEx(&nedge1,&nedge2,index,next_face_id,size,id2,id3);
5758 
5759  /*   Input edge and output edge can be the same if there are more than
5760       one polygon on an edge
5761  */
5762  if ( ((nedge1 == id2) && (nedge2 == id3)) ||
5763       ((nedge1 == id3) && (nedge2 == id2)) )
5764    /*   Set output edge arbitrarily but when come out of here the
5765         next face will be on the old output edge (identical one)
5766    */
5767    nedge2 = Return_Other(index,id2,id3);
5768 
5769  /*    Do the triangulation */
5770  P_Triangulate(nedge1,nedge2,id2,id3,size,index,output,reversed,
5771                face_id,next_id,pListHead,temp,where);
5772}
5773
5774///     Input_Edge:
5775void CustomStripifier::Input_Edge(int face_id,  int *index,
5776                                                                                                                                        int size,               int in_edge1,
5777                                                                                                                                        int in_edge2, ListHead *pListHead,
5778                                                                                                                int where)
5779{
5780  /* The polygon had an input edge, specified by input1 and input2 */
5781 
5782  int output1,next_bucket;
5783  int vertex4, vertex5,dummy=60;
5784 
5785  output1 = Get_Output_Edge(face_id,size,index,in_edge1,in_edge2);
5786  vertex5 = AdjacentEx(in_edge2,in_edge1,index,size);
5787  vertex4 = AdjacentEx(in_edge1,in_edge2,index,size);
5788 
5789  if (vertex4 == output1)
5790    {
5791      Output_TriEx(in_edge2,in_edge1,output1,NULL,-1,where);
5792      /*        Now delete the adjacencies by one for all the faces
5793                that are adjacent to the triangle that we just outputted.
5794      */
5795      Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
5796                   &dummy,&dummy,&dummy);
5797      Delete_AdjEx(in_edge2,output1,&dummy,&dummy,
5798                   face_id,&dummy,&dummy,&dummy);
5799      /*        Put the new face in the proper bucket of adjacencies */
5800      next_bucket=Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,FALSE);
5801      next_bucket=Change_FaceEx(face_id,in_edge2,output1,pListHead,FALSE);
5802     
5803      /*        Create a new edgelist without the triangle that
5804                was just outputted.
5805      */
5806      Delete_From_ListEx(in_edge2,index,size);
5807     
5808    }   
5809  else if (vertex5 == output1)
5810    {
5811      Output_TriEx(in_edge1,in_edge2,vertex5,NULL,-1,where);
5812      /*        Now delete the adjacencies by one for all the faces
5813                that are adjacent to the triangle that we just outputted.
5814      */
5815      Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
5816                   &dummy,&dummy,&dummy);
5817      Delete_AdjEx(in_edge1,vertex5,&dummy,&dummy,
5818                   face_id,&dummy,&dummy,&dummy);
5819      /*        Put the new face in the proper bucket of adjacencies */
5820      next_bucket=Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,FALSE);
5821      next_bucket=Change_FaceEx(face_id,in_edge1,vertex5,pListHead,FALSE);
5822     
5823      /*        Create a new edgelist without the triangle that
5824                was just outputted.
5825      */
5826      Delete_From_ListEx(in_edge1,index,size);
5827    }
5828 
5829  /*    Update the face data structure, by deleting the old
5830        face and putting in the polygon minus the triangle
5831        as the new face, here we will be decrementing the size
5832        by one.
5833  */
5834  New_Size_Face(face_id);
5835  return;
5836}
5837
5838///     Inside_Polygon:
5839void CustomStripifier::Inside_Polygon(int size,int *index,
5840                    int face_id,ListHead *pListHead, int where)
5841{
5842  /* We know that we have a polygon that is greater than 4 sides, and
5843     that it is better for us to go inside the polygon for the next
5844     one, since inside will have less adjacencies than going outside.
5845     So, we are not doing partial for a part of the polygon.
5846  */
5847  int id1,id2,id3;
5848  int new1,new2;
5849 
5850  Last_Edge(&id1,&id2,&id3,0);
5851 
5852  /*  See if the input edge existed in the polygon, that will help us */
5853  if (Exist(face_id,id2,id3))
5854    Input_Edge(face_id,index,size,id2,id3,pListHead,where);
5855  else
5856    {
5857      /*  Make one of the input edges
5858          We will choose it by trying to get an edge that has something
5859          in common with the last triangle, or by getting the edge that
5860          is adjacent to the least number of thigs, with preference given
5861          to the first option
5862      */
5863     
5864      Get_Input_Edge(index,id1,id2,id3,&new1,&new2,size,face_id);
5865      Input_Edge(face_id,index,size,new1,new2,pListHead,where);
5866    }
5867}
5868
5869///     Finished:
5870int CustomStripifier::Finished(int *swap, FILE *output, int startnewstrip)
5871{
5872  /*   We have finished all the triangles, now is time to output to
5873       the data file. In the strips data structure, every three ids
5874       is  a triangle. Now we see whether we can swap, or make a new strip
5875       or continue the strip, and output the data accordingly to the
5876       data file.
5877  */
5878  int num,x,vertex1,vertex2;
5879  ListHead *pListHead;
5880  int id[2],other1,other2,index = 0,a,b,c;
5881  P_STRIPS temp1,temp2,temp3,temp4,temp5,temp6;
5882  BOOL cptexture;
5883  *swap =0;
5884 
5885  cptexture = text;
5886  pListHead = strips[0];
5887  if (pListHead == NULL)
5888        return 0;
5889 
5890  num = NumOnList(pListHead);
5891  //printf ("There are %d triangles in the extend\n",num/3);
5892 
5893  // Go through the list triangle by triangle
5894  temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 0);
5895  temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 1);
5896  temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 2);
5897 
5898  // Next triangle for lookahead
5899  temp4 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 3);
5900
5901  // There is only one polygon in the strip
5902  if (temp4 == NULL)
5903  {
5904        // Data might be mixed and we do not have textures for some of the vertices
5905    if ((text) &&  (vt[temp3->face_id] == 0))
5906                cptexture = FALSE;
5907    if ((norm) && (!cptexture)) {
5908                if (startnewstrip && orient) // If we want to keep orientation
5909                        preserve_strip_orientation_with_normal(output, temp3->face_id+1,vn[temp3->face_id]+1,
5910                                                temp2->face_id+1,vn[temp2->face_id]+1, temp1->face_id+1,vn[temp1->face_id]+1);
5911               
5912                fprintf(output," %d//%d %d//%d %d//%d", temp3->face_id+1,vn[temp3->face_id]+1,
5913                                        temp2->face_id+1,vn[temp2->face_id]+1, temp1->face_id+1,vn[temp1->face_id]+1);
5914        }
5915        else if ((cptexture) && (!norm)) {
5916                if (startnewstrip && orient) /* If we want to keep orientation */
5917                        preserve_strip_orientation_with_texture(output, temp3->face_id+1,vt[temp3->face_id]+1,
5918                                temp2->face_id+1,vt[temp2->face_id]+1,  temp1->face_id+1,vt[temp1->face_id]+1);
5919               
5920                fprintf(output," %d/%d %d/%d %d/%d", temp3->face_id+1,vt[temp3->face_id]+1,
5921                                        temp2->face_id+1,vt[temp2->face_id]+1, temp1->face_id+1,vt[temp1->face_id]+1);
5922        }
5923    else if ((cptexture)&& (norm)) {
5924        if (startnewstrip && orient) /* If we want to keep orientation */
5925          preserve_strip_orientation_with_texture_and_normal(output, temp3->face_id+1,vt[temp3->face_id]+1,vn[temp3->face_id]+1,
5926                                temp2->face_id+1,vt[temp2->face_id]+1,vn[temp2->face_id]+1, temp1->face_id+1,vt[temp1->face_id]+1,vn[temp1->face_id]+1);
5927       
5928        fprintf(output," %d/%d/%d %d/%d/%d %d/%d/%d", temp3->face_id+1,vt[temp3->face_id]+1,vn[temp3->face_id]+1,
5929                temp2->face_id+1,vt[temp2->face_id]+1,vn[temp2->face_id]+1, temp1->face_id+1,vt[temp1->face_id]+1,vn[temp1->face_id]+1);
5930    }
5931    else
5932    {
5933                if (startnewstrip && orient) /* If we want to keep orientation */
5934                        preserve_strip_orientation(output, temp3->face_id+1,temp2->face_id+1,temp1->face_id+1);
5935         
5936                fprintf(output," %d %d %d", temp3->face_id+1,temp2->face_id+1,temp1->face_id+1);
5937                mi_vector[num_tiras].push_back(temp3->face_id);
5938                mi_vector[num_tiras].push_back(temp2->face_id);
5939                mi_vector[num_tiras].push_back(temp1->face_id);
5940    }
5941    Free_Strips();
5942
5943    return 1;
5944  }
5945 
5946  // We have a real strip
5947  temp5 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 4);
5948  temp6 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 5);
5949 
5950  if ((temp1 == NULL) || (temp2 == NULL) || (temp3 == NULL) || (temp5 == NULL) || (temp6 == NULL))
5951  {
5952        printf("There is an error in the output of the triangles\n");
5953    exit(0);
5954  }
5955 
5956  // Find the vertex in the first triangle that is not in the second
5957  vertex1 = Different(temp1->face_id,temp2->face_id,temp3->face_id, temp4->face_id,temp5->face_id,temp6->face_id, &other1,&other2);
5958  // Find the vertex in the second triangle that is not in the first
5959  vertex2 = Different(temp4->face_id,temp5->face_id,temp6->face_id, temp1->face_id,temp2->face_id,temp3->face_id, &other1,&other2);
5960 
5961  // Lookahead for the correct order of the 2nd and 3rd vertex of the first triangle
5962  temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 6);
5963  temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 7);
5964  temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 8);
5965 
5966  if (temp1 != NULL)
5967    other1 = Different(temp3->face_id,temp4->face_id,temp5->face_id, temp1->face_id,temp2->face_id,temp3->face_id,&other1,&a);
5968 
5969  id[index] = vertex1; index = !index;
5970  id[index] = other1; index = !index;
5971  id[index] = other2; index = !index;
5972 
5973  a = temp4->face_id;
5974  b = temp5->face_id;
5975  c = temp6->face_id;
5976 
5977        /*
5978  // If we need to rearrange the first sequence because otherwise there would have been a swap.
5979  if ((temp3 != NULL) && (text) && ( vt[temp3->face_id]==0))
5980    cptexture = FALSE;
5981  if ((norm) && (!cptexture)) {
5982    if (orient && startnewstrip) // If we want to keep orientation
5983      preserve_strip_orientation_with_normal(output, vertex1+1,vn[vertex1]+1, other1+1,vn[other1]+1, other2+1,vn[other2]+1);
5984   
5985    fprintf(output," %d//%d %d//%d %d//%d", vertex1+1,vn[vertex1]+1, other1+1,vn[other1]+1, other2+1,vn[other2]+1);
5986  }
5987  else if ((cptexture) && (!norm)) {
5988    if (orient && startnewstrip) // If we want to keep orientation
5989      preserve_strip_orientation_with_texture(output, vertex1+1,vt[vertex1]+1, other1+1,vt[other1]+1, other2+1,vt[other2]+1);
5990   
5991    fprintf(output," %d/%d %d/%d %d/%d", vertex1+1,vt[vertex1]+1, other1+1,vt[other1]+1, other2+1,vt[other2]+1);
5992  }
5993  else if ((cptexture) && (norm)) {
5994    if (orient && startnewstrip) // If we want to keep orientation
5995      preserve_strip_orientation_with_texture_and_normal(output, vertex1+1,vt[vertex1]+1,vn[vertex1]+1,
5996                                                         other1+1,vt[other1]+1,vn[other1]+1, other2+1,vt[other2]+1,vn[other2]+1);
5997   
5998    fprintf(output," %d/%d/%d %d/%d/%d %d/%d/%d", vertex1+1,vt[vertex1]+1,vn[vertex1]+1,
5999            other1+1,vt[other1]+1,vn[other1]+1, other2+1,vt[other2]+1,vn[other2]+1);
6000  }
6001  else
6002  {
6003        */
6004        if (orient && startnewstrip) // If we want to keep orientation
6005                preserve_strip_orientation(output,vertex1+1,other1+1,other2+1);
6006   
6007    fprintf(output," %d %d %d",vertex1+1,other1+1,other2+1);
6008        mi_vector[num_tiras].push_back(vertex1);
6009        mi_vector[num_tiras].push_back(other1);
6010        mi_vector[num_tiras].push_back(other2);
6011
6012        /*
6013  }
6014  */
6015  for (x = 6; x < num ; x = x+3)
6016  {
6017        //    Get the next triangle
6018    temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, x);       
6019    temp2 = ( P_STRIPS ) GetNextNode(temp1);                                     
6020    temp3 = ( P_STRIPS ) GetNextNode(temp2);                                     
6021     
6022    //    Error checking
6023    if (!(member(id[0],a,b,c)) || !(member(id[1],a,b,c)) || !(member(vertex2,a,b,c)))
6024    {
6025                // If we used partial we might have a break in the middle of a strip
6026                fprintf(output,"\nt");
6027        startnewstrip = 1;
6028                mi_vector_tipo nada;
6029                mi_vector.push_back(nada);
6030                num_tiras++;
6031        // Find the vertex in the first triangle that is not in the second
6032        vertex1 = Different(a,b,c,temp1->face_id,temp2->face_id,temp3->face_id,&other1,&other2);
6033        // Find the vertex in the second triangle that is not in the first
6034        vertex2 = Different(temp1->face_id,temp2->face_id,temp3->face_id, a,b,c,&other1,&other2);
6035         
6036        id[index] = vertex1; index = !index;
6037        id[index] = other1; index = !index;
6038        id[index] = other2; index = !index;
6039        }
6040     
6041    if ((temp1 == NULL ) || (temp2 == NULL) || (temp3 == NULL))
6042    {
6043                printf("There is an error in the triangle list \n");
6044        exit(0);
6045    }
6046     
6047    if ((id[0] == id[1]) || (id[0] == vertex2))
6048        continue;
6049     
6050    if ((member(id[index],temp1->face_id,temp2->face_id,temp3->face_id)))
6051    {
6052                if ((text) && ( vt[id[index]]==0))
6053                        cptexture = FALSE;
6054        if ((!norm) && (!cptexture))
6055                {
6056            fprintf(output," %d",id[index]+1);
6057                        mi_vector[num_tiras].push_back(id[index]);
6058                }
6059        else if ((norm) && (!cptexture))
6060            fprintf(output," %d//%d",id[index]+1,vn[id[index]]+1);
6061        else if ((!norm) && (cptexture))
6062            fprintf(output," %d/%d",id[index]+1,vt[id[index]]+1);
6063        else
6064            fprintf(output," %d/%d/%d", id[index]+1,vt[id[index]]+1,vn[id[index]]+1);
6065
6066        index = !index;
6067        *swap = *swap + 1;
6068        }
6069     
6070    if ((text) && ( vt[vertex2]==0))
6071                cptexture = FALSE;
6072    if ((!norm) && (!cptexture))
6073        {
6074        fprintf(output,"\nq %d",vertex2+1);
6075                mi_vector[num_tiras].push_back(vertex2);
6076        }
6077    else if ((norm) && (!cptexture))
6078        fprintf(output,"\nq %d//%d",vertex2+1,vn[vertex2]+1);
6079    else if ((!norm) && (cptexture))
6080        fprintf(output,"\nq %d/%d",vertex2+1,vt[vertex2]+1);
6081    else
6082        fprintf(output,"\nq %d/%d/%d",vertex2+1,vt[vertex2]+1,vn[vertex2]+1);
6083     
6084    id[index] = vertex2; index = !index;
6085     
6086    //    Get the next vertex not in common
6087                vertex2 =       Different(temp1->face_id,temp2->face_id,temp3->face_id, a,b,c,&other1,&other2);
6088                a                               =       temp1->face_id;
6089                b                               =       temp2->face_id;
6090                c                               =       temp3->face_id;
6091  }
6092  //   Do the last vertex
6093  if ((text) && (vt[vertex2]==0))
6094  {
6095        if (cptexture)
6096                fprintf(output,"\nq");
6097    cptexture = FALSE;
6098  }
6099
6100  if ((!norm) && (!cptexture))
6101  {
6102    fprintf(output," %d",vertex2+1);
6103        mi_vector[num_tiras].push_back(vertex2);
6104  }
6105  else if ((norm) && (!cptexture))
6106    fprintf(output," %d//%d",vertex2+1,vn[vertex2]+1);
6107  else if ((!norm) && (cptexture))
6108    fprintf(output," %d/%d",vertex2+1,vt[vertex2]+1);
6109  else
6110    fprintf(output," %d/%d/%d",vertex2+1,vt[vertex2]+1,vn[vertex2]+1);
6111 
6112  Free_Strips();
6113  return (num/3);       
6114}
6115
6116///     Output_Tri:
6117void CustomStripifier::Output_Tri(int id1, int id2, int id3,BOOL end)
6118{
6119  /*   We will save everything into a list, rather than output at once,
6120       as was done in the old routine. This way for future modifications
6121       we can change the strips later on if we want to.
6122  */
6123 
6124  int temp1,temp2,temp3;
6125 
6126  /*  Make sure we do not have an error */
6127  /*    There are degeneracies in some of the files */
6128  if ( (id1 == id2) || (id1 == id3) || (id2 == id3))
6129    {
6130      printf("Degenerate triangle %d %d %d\n",id1,id2,id3);
6131      exit(0);
6132    }
6133  else
6134    {
6135      Last_Edge(&temp1,&temp2,&temp3,0);
6136      Add_Id_Strips(id1,end);
6137      Add_Id_Strips(id2,end);
6138      Add_Id_Strips(id3,end);
6139      Last_Edge(&id1,&id2,&id3,1);
6140    }
6141}
6142
6143///     Polygon_Output:
6144int CustomStripifier::Polygon_Output(   P_ADJACENCIES temp,     int face_id,
6145                                                                                                                                                        int bucket,                             ListHead *pListHead,
6146                                                                                                                                                        BOOL first,                             int *swaps,
6147                                                                                                                                                FILE *bands,                            int color1,
6148                                                                                                                                                        int color2,                                     int color3,
6149                                                                                                                                                        BOOL global,                    BOOL end)
6150{
6151  ListHead *pListFace;
6152  PF_FACES face;
6153  int next_face_id,next_bucket,e1,e2,e3,other1,other2,other3;
6154  P_ADJACENCIES lpListInfo;
6155  int ties=0;
6156 
6157  /* We have a polygon to output, the id is face id, and the number
6158     of adjacent polygons to it is bucket. This routine extends the patches from
6159     either end to make longer triangle strips.
6160  */
6161 
6162 
6163  /*  Now get the edge */
6164  Last_Edge(&e1,&e2,&e3,0);
6165 
6166  /*  Get the polygon with id face_id */
6167  pListFace  = PolFaces[face_id];
6168  face = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
6169 
6170  /*  We can't go any more */
6171  if ((face->nPolSize == 1) || ((face->nPolSize == 4) && (global)))
6172    /* if global, then we are still doing patches */
6173    {
6174      /*     Remove it from the list so we do not have to waste
6175             time visiting it in the future, or winding up in an infinite loop
6176             if it is the first on that we are looking at for a possible strip
6177      */
6178      if (face->nPolSize == 1) {
6179        if (face_array[temp->face_id].head == pListHead)
6180          face_array[temp->face_id].pfNode = NULL;
6181        RemoveList(pListHead,(PLISTINFO) temp);
6182      }
6183      if (first)
6184        return 0;
6185      else
6186        return (Finished(swaps,bands,0));
6187    }
6188 
6189  if (face->nPolSize == 3)
6190    {
6191      /*      It is already a triangle */
6192      if (bucket == 0)
6193        {
6194          /*      It is not adjacent to anything so we do not have to
6195                  worry about the order of the sides or updating adjacencies
6196          */
6197         
6198          next_face_id = Different(*(face->pPolygon),*(face->pPolygon+1),
6199                                   *(face->pPolygon+2),
6200                                   e1,e2,e3,&other1,&other2); 
6201          face->nPolSize = 1;
6202         
6203          /* If this is the first triangle in the strip */
6204          if ((e2 == 0) && (e3 ==0))
6205            {
6206              e2 = other1;
6207              e3 = other2;
6208            }
6209         
6210          Output_Tri(e2,e3,next_face_id,end);
6211          if (face_array[temp->face_id].head == pListHead)
6212            face_array[temp->face_id].pfNode = NULL;
6213          RemoveList(pListHead,(PLISTINFO) temp);
6214          return (Finished(swaps,bands,0));
6215        }
6216     
6217     
6218      /*  It is a triangle with adjacencies. This means that we
6219          have to:
6220          1. Update the adjacencies in the list, because we are
6221          using this polygon and it will be deleted.
6222          2. Get the next polygon.
6223      */
6224      else
6225        {
6226          /*   Return the face_id of the next polygon we will be using,
6227               while updating the adjacency list by decrementing the
6228               adjacencies of everything adjacent to the current triangle.
6229          */
6230         
6231          next_face_id = Update_Adjacencies(face_id, &next_bucket, &e1,&e2,&ties);
6232          /*  Maybe we deleted something in a patch and could not
6233              find an adj polygon */
6234          if (next_face_id == -1)
6235            {
6236              Output_Tri(*(face->pPolygon),*(face->pPolygon+1),
6237                         *(face->pPolygon+2),end);
6238              face->nPolSize = 1;
6239              if (face_array[temp->face_id].head == pListHead)
6240                face_array[temp->face_id].pfNode = NULL;
6241              RemoveList(pListHead,(PLISTINFO) temp);
6242              return (Finished(swaps,bands,0));
6243            }
6244         
6245         
6246          /*      Find the other vertex to transmit in the triangle */
6247          e3 = Return_Other(face->pPolygon,e1,e2);
6248          Last_Edge(&other1,&other2,&other3,0);
6249         
6250          if ((other2 != 0) && (other3 != 0))
6251            {
6252              /*   See which vertex in the output edge is not in the input edge */
6253              if ((e1 != other2) && (e1 != other3))
6254                e3 = e1;
6255              else if ((e2 != other2) && (e2 != other3))
6256                e3 = e2;
6257              else
6258                {
6259                  printf("There is an error in the tri with adj\n");
6260                  exit(0);
6261                }
6262             
6263              /*   See which vertex of the input edge is not in the output edge */
6264              if ((other2 != e1) && (other2 != e2))
6265                {
6266                  other1 = other2;
6267                  other2 = other3;
6268                }
6269              else if ((other3 != e1) && (other3 != e2))
6270                other1 = other3;
6271              else
6272                {
6273                  printf("There is an error in getting the tri with adj\n");
6274                  exit(0);
6275                }
6276             
6277            }
6278          else
6279            {
6280              /*     We are the first triangle in the strip and the starting edge
6281                     has not been set yet
6282              */
6283              /*  Maybe we deleted something in a patch and could not
6284                  find an adj polygon */
6285              if (next_face_id == -1)
6286                {
6287                  Output_Tri(*(face->pPolygon),*(face->pPolygon+1),
6288                             *(face->pPolygon+2),end);
6289                  face->nPolSize = 1;
6290                  face_array[temp->face_id].pfNode = NULL;
6291                  RemoveList(pListHead,(PLISTINFO) temp);
6292                  return (Finished(swaps,bands,0));
6293                }
6294             
6295              other1 = e3;
6296              e3 = e2;
6297              other2 = e1;
6298            }
6299         
6300          /*   At this point the adjacencies have been updated  and we
6301               have the next polygon id
6302          */
6303         
6304          Output_Tri(other1,other2,e3,end);
6305          face->nPolSize = 1;
6306          if (face_array[temp->face_id].head == pListHead)
6307            face_array[temp->face_id].pfNode = NULL;
6308          RemoveList(pListHead,(PLISTINFO) temp);
6309         
6310          /*  Maybe we deleted something in a patch and could not
6311              find an adj polygon */
6312          if (next_face_id == -1)
6313            return (Finished(swaps,bands,0));
6314         
6315          if (Done(next_face_id,&next_bucket) == NULL)
6316            {
6317              printf("We deleted the next face 4%d\n",next_face_id);
6318              exit(0);
6319            }
6320         
6321          pListHead = array[next_bucket];
6322          lpListInfo = face_array[next_face_id].pfNode;
6323          if (lpListInfo == NULL)
6324            {
6325              printf("There is an error finding the next polygon3 %d\n",
6326                     next_face_id);
6327              exit(0);
6328            }
6329          return (Polygon_Output(lpListInfo,next_face_id,next_bucket,
6330                                 pListHead, FALSE, swaps,bands,
6331                                 color1,color2,color3,global,end));
6332         
6333        }
6334    }
6335 
6336  else
6337    {
6338      /*   It is not a triangle, we have to triangulate it .
6339           Since it is not adjacent to anything we can triangulate it
6340           blindly
6341      */
6342      if (bucket == 0)
6343        {
6344          /*   It is the first polygon in the strip, therefore there is no
6345               input edge to start with.
6346          */
6347          if ((e2 == 0) && (e3 ==0))
6348            Blind_Triangulate(face->nPolSize,face->pPolygon,TRUE,1);
6349         
6350          else
6351            Blind_Triangulate(face->nPolSize,face->pPolygon,FALSE,1);
6352         
6353          if (face_array[temp->face_id].head == pListHead)
6354            face_array[temp->face_id].pfNode = NULL;
6355          RemoveList(pListHead,(PLISTINFO) temp);
6356         
6357          /*      We will be at the beginning of the next strip. */
6358          face->nPolSize = 1;
6359          return (Finished(swaps,bands,0));
6360        }
6361     
6362     
6363      else
6364        {
6365         
6366         
6367          /*  WHOLE triangulation */
6368          /*  It is not a triangle and has adjacencies.
6369              This means that we have to:
6370              1. Triangulate this polygon, not blindly because
6371              we have an edge that we want to come out on, that
6372              is the edge that is adjacent to a polygon with the
6373              least number of adjacencies. Also we must come in
6374              on the last seen edge.
6375              2. Update the adjacencies in the list, because we are
6376              using this polygon .
6377              3. Get the next polygon.
6378          */
6379          /*      Return the face_id of the next polygon we will be using,
6380                  while updating the adjacency list by decrementing the
6381                  adjacencies of everything adjacent to the current polygon.
6382          */
6383         
6384          next_face_id = Update_Adjacencies(face_id, &next_bucket, &e1,&e2,&ties);
6385         
6386          /*  Maybe we deleted something in a patch and could not
6387              find an adj polygon */
6388          if (next_face_id == -1)
6389            {
6390             
6391              /*   If we are at the first polygon in the strip and
6392                   there is no input
6393                   edge, then begin is TRUE
6394              */
6395              if ((e2 == 0) && (e3 == 0))
6396                Blind_Triangulate(face->nPolSize,face->pPolygon,TRUE,1);
6397             
6398              else
6399                Blind_Triangulate(face->nPolSize,face->pPolygon,FALSE,1);
6400             
6401              if (face_array[temp->face_id].head == pListHead)
6402                face_array[temp->face_id].pfNode = NULL;
6403              RemoveList(pListHead,(PLISTINFO) temp);
6404             
6405              /*      We will be at the beginning of the next strip. */
6406              face->nPolSize = 1;
6407              return (Finished(swaps,bands,0));
6408            }
6409         
6410          if (Done(next_face_id,&next_bucket) == NULL)
6411            {
6412              printf("We deleted the next face 6 %d %d\n",next_face_id,face_id);
6413              exit(0);
6414            }
6415         
6416          Non_Blind_Triangulate(face->nPolSize,face->pPolygon,
6417                                bands,next_face_id,face_id,1,
6418                                color1,color2,color3);
6419         
6420          if (face_array[temp->face_id].head == pListHead)       
6421            face_array[temp->face_id].pfNode = NULL;
6422          RemoveList(pListHead,(PLISTINFO) temp);
6423          face->nPolSize = 1;
6424          pListHead = array[next_bucket];
6425          lpListInfo = face_array[next_face_id].pfNode;
6426         
6427          if (lpListInfo == NULL)
6428            {
6429              printf("There is an error finding the next polygon2 %d %d\n",
6430                     next_face_id,next_bucket);
6431              exit(0);
6432            }
6433          return (Polygon_Output(lpListInfo,next_face_id,next_bucket,
6434                                 pListHead, FALSE, swaps,bands,
6435                                 color1,color2,color3,global,end));
6436        }
6437     
6438    }
6439}       
6440
6441///     Extend_Face:
6442int CustomStripifier::Extend_Face(int           face_id,
6443                                                                                                                                        int             e1,
6444                                                                                                                                        int             e2,
6445                                                                                                                                        int             *swaps,
6446                                                                                                                                        FILE    *bands,
6447                                                                                                                                        int             color1,
6448                                                                                                                                        int             color2,
6449                                                                                                                                        int             color3,
6450                                                                                                                                        int             *vert_norm,
6451                                                                                                                                        int             normals,
6452                                                                                                                                        int             *vert_texture,
6453                                                                                                                                        int             texture)
6454{
6455  int                                           dummy   =       0;
6456        int                                             next_bucket;
6457  P_ADJACENCIES lpListInfo;   
6458  ListHead                      *pListHead;
6459 
6460  /*    Try to extend backwards off of the local strip that we just found */
6461 
6462  vn = vert_norm;
6463  vt = vert_texture;
6464  norm = normals;
6465  text = texture;
6466 
6467  *swaps = 0;
6468  /*    Find the face that is adjacent to the edge and is not the
6469        current face.
6470  */
6471  face_id = Find_Face(face_id, e1, e2,&next_bucket);
6472  if (face_id == -1)
6473    return 0;
6474 
6475  pListHead = array[next_bucket];
6476  lpListInfo = face_array[face_id].pfNode;
6477 
6478  if (lpListInfo == NULL)
6479    {
6480      printf("There is an error finding the next polygon3 %d\n",face_id);
6481      exit(0);
6482    }
6483  Last_Edge(&dummy,&e1,&e2,1);
6484 
6485  /*  Find a strip extending from the patch and return the cost */
6486  return (Polygon_Output(lpListInfo,face_id,next_bucket,pListHead,TRUE,swaps,
6487                         bands,color1,color2,color3,TRUE,TRUE));
6488}
6489
6490///     ParseAndFreeList:
6491void CustomStripifier::ParseAndFreeList( ListHead *pListHead )
6492{
6493  PLISTINFO                     value;
6494  register      int     c;
6495        register        int     num;
6496 
6497  /*    Freeing a linked list */
6498  num   =       NumOnList(pListHead);
6499
6500  for (c = 0; c< num; c++)
6501        {
6502    value =   RemHead(pListHead);
6503        }
6504}
6505
6506///     Free_Strips:
6507void CustomStripifier::Free_Strips()
6508{
6509  /*    Free strips data structure */
6510  if (strips[0] == NULL)
6511    return;
6512  else
6513    ParseAndFreeList(strips[0]);
6514}
6515
6516///     FreeFaceTable:
6517void CustomStripifier::FreeFaceTable(int nSize)
6518{
6519  register int nIndex;
6520 
6521  for ( nIndex=0; nIndex < nSize; nIndex++ )
6522    {
6523      if ( PolFaces[nIndex] != NULL )
6524        ParseAndFreeList( PolFaces[nIndex] );
6525    }
6526  free( PolFaces );
6527}
6528
6529///     FreeEdgeTable:
6530void CustomStripifier::FreeEdgeTable(int nSize)
6531{
6532  register int nIndex;
6533 
6534  for ( nIndex=0; nIndex < nSize; nIndex++ )
6535    {
6536      if ( PolEdges[nIndex] != NULL )
6537        ParseAndFreeList( PolEdges[nIndex] );
6538    }
6539  free( PolEdges );
6540}
6541
6542///     End_Face_Struct:
6543void CustomStripifier::End_Face_Struct(int numfaces)
6544{
6545  FreeFaceTable(numfaces);
6546}
6547
6548///     End_Edge_Struct:
6549void CustomStripifier::End_Edge_Struct(int numverts)
6550{
6551  FreeEdgeTable(numverts);
6552}
6553
6554///     Calculate_Walks:
6555int CustomStripifier::Calculate_Walks(int lastvert,int y, PF_FACES temp2)
6556{
6557  /* Find the length of the walk */
6558 
6559  int previous_edge1, previous_edge2;
6560  register int nextvert,numverts,counter,walk=0;
6561  BOOL flag;
6562  F_EDGES *node;
6563  ListHead *pListHead;
6564  static int seen = 0;
6565 
6566  /* Find the edge that we are currently on */
6567  if (y != 3)
6568    {
6569      previous_edge1 = *(temp2->pPolygon +y);
6570      previous_edge2 = *(temp2->pPolygon + y + 1);
6571    }
6572  else
6573    {
6574      previous_edge1 = *(temp2->pPolygon +y);
6575      previous_edge2 = *(temp2->pPolygon);
6576    }
6577 
6578  temp2->seen = seen;
6579  counter = y;
6580 
6581  /*Find the adjacent face to this edge */
6582  node = *(temp2->VertandId+y);                 
6583  if (node->edge[2] != lastvert)
6584    nextvert = node->edge[2];
6585  else
6586    nextvert = node->edge[1];
6587 
6588  /* Keep walking in this direction until we cannot do so */
6589  while ((nextvert != lastvert) && (nextvert != -1))
6590    {
6591      walk++;
6592      pListHead = PolFaces[nextvert];
6593      temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
6594      numverts = temp2->nPolSize;
6595      if ((numverts != 4) || (temp2->seen == seen))
6596        {
6597          walk--;
6598          nextvert = -1;
6599        }
6600      else
6601        {
6602          temp2->seen = seen;
6603          /* Find edge that is not adjacent to the previous one */
6604          counter = 0;
6605          flag = TRUE;
6606          while ((counter < 3) && (flag))
6607            {
6608              if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
6609                    (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
6610                   ((*(temp2->pPolygon+counter) == previous_edge2) ||
6611                    (*(temp2->pPolygon+counter+1) == previous_edge1)) )
6612                counter++;             
6613              else
6614                flag = FALSE;   
6615            }
6616          /* Get the IDs of the next edge */
6617          if (counter < 3)
6618            {
6619              previous_edge1 = *(temp2->pPolygon + counter);
6620              previous_edge2 = *(temp2->pPolygon + counter + 1);
6621            }
6622          else
6623            {
6624              previous_edge1 = *(temp2->pPolygon + counter);
6625              previous_edge2 = *(temp2->pPolygon);
6626            }
6627         
6628          node = *(temp2->VertandId + counter);
6629          if (node->edge[1] == nextvert)
6630            nextvert = node->edge[2];
6631          else
6632            nextvert = node->edge[1];
6633        }
6634    }
6635  seen++;
6636  return walk;
6637}
6638
6639///     Check_Right:
6640BOOL CustomStripifier::Check_Right(     int last_seen,PF_FACES temp2,
6641                                                                                                                                                int y,int face_id)
6642{
6643  /* Check when we last saw the face to the right of the current
6644     one. We want to have seen it just before we started this strip
6645  */
6646 
6647  F_EDGES *node;
6648  ListHead *pListHead;
6649  register int nextvert,oldy;
6650  PF_FACES t;
6651 
6652  oldy = y;
6653  if (y != 3)
6654    y = y+1;
6655  else
6656    y = 0;
6657  node = *(temp2->VertandId + y);
6658  if (face_id == node->edge[1])
6659    nextvert = node->edge[2];
6660  else
6661    nextvert = node->edge[1];
6662 
6663  if (nextvert == -1)
6664    return FALSE;
6665 
6666  pListHead = PolFaces[nextvert];
6667  t = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
6668  if (t->seen != (last_seen - 1))
6669    {
6670      /* maybe because of the numbering, we are not
6671         on the right orientation, so we have to check the
6672         opposite one to be sure
6673      */
6674      if (oldy != 0)
6675        y = oldy-1;
6676      else
6677        y = 3;
6678      node = *(temp2->VertandId + y);
6679      if (face_id == node->edge[1])
6680        nextvert = node->edge[2];
6681      else
6682        nextvert = node->edge[1];
6683      if (nextvert == -1)
6684        return FALSE;
6685      pListHead = PolFaces[nextvert];
6686      t = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
6687      if (t->seen != (last_seen - 1))
6688        return FALSE;
6689    }
6690  return TRUE;
6691}
6692
6693///     Update_and_Test:
6694int CustomStripifier::Update_and_Test(PF_FACES temp2,int y,
6695                                                                                                                                                        BOOL first,int distance,
6696                                                                                                                                                int lastvert, int val)
6697{
6698 
6699  static int last_seen = 17;
6700  int previous_edge1, previous_edge2;
6701  register int original_distance,nextvert,numverts,counter;
6702  BOOL flag;
6703  F_EDGES *node;
6704  ListHead *pListHead;
6705 
6706  original_distance = distance;
6707  /* Find the edge that we are currently on */
6708  if (y != 3)
6709    {
6710      previous_edge1 = *(temp2->pPolygon +y);
6711      previous_edge2 = *(temp2->pPolygon + y + 1);
6712    }
6713  else
6714    {
6715      previous_edge1 = *(temp2->pPolygon +y);
6716      previous_edge2 = *(temp2->pPolygon);
6717    }
6718 
6719  temp2->seen = val;
6720  temp2->seen2 = val;
6721 
6722  node = *(temp2->VertandId+y);                   
6723  if (lastvert != node->edge[2])
6724    nextvert = node->edge[2];
6725  else
6726    nextvert = node->edge[1];
6727 
6728  /* Keep walking in this direction until we cannot do so  or
6729     we go to distance */
6730  while ((distance > 0)  && (nextvert != lastvert) && (nextvert != -1))
6731    {
6732      distance--;
6733     
6734      pListHead = PolFaces[nextvert];
6735      temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
6736      temp2->seen = val;
6737     
6738      if (temp2->seen2 == val)
6739        {
6740          last_seen++;
6741          return (original_distance - distance);
6742        }
6743     
6744      temp2->seen2 = val;
6745     
6746      numverts = temp2->nPolSize;
6747     
6748      if (numverts != 4)
6749        nextvert = -1;
6750     
6751      else if ((!first) && (!(Check_Right(last_seen,temp2,y,nextvert))))
6752        {
6753          last_seen++;
6754          return (original_distance - distance);
6755        }
6756      else
6757        {
6758          /* Find edge that is not adjacent to the previous one */
6759          counter = 0;
6760          flag = TRUE;
6761          while ((counter < 3) && (flag))
6762            {
6763              if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
6764                    (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
6765                   ((*(temp2->pPolygon+counter) == previous_edge2) ||
6766                    (*(temp2->pPolygon+counter+1) == previous_edge1)) )
6767                counter++;
6768              else
6769                flag = FALSE;
6770            }
6771          /* Get the IDs of the next edge */
6772          if (counter < 3)
6773            {
6774              previous_edge1 = *(temp2->pPolygon + counter);
6775              previous_edge2 = *(temp2->pPolygon + counter + 1);
6776            }
6777          else
6778            {
6779              previous_edge1 = *(temp2->pPolygon + counter);
6780              previous_edge2 = *(temp2->pPolygon);
6781            }
6782          if      ( ((*(temp2->walked+counter) == -1) &&
6783                     (*(temp2->walked+counter+2) == -1)))
6784            {
6785              printf("There is an error in the walks!\n");
6786              printf("1Code %d %d \n",*(temp2->walked+counter),
6787                     *(temp2->walked+counter+2));
6788              exit(0);
6789            }
6790          else
6791            {
6792              if      ((*(temp2->walked+counter) == -1) &&
6793                       (*(temp2->walked+counter-2) ==  -1))
6794                {
6795                  printf("There is an error in the walks!\n");
6796                  printf("2Code %d %d \n",*(temp2->walked+counter),
6797                         *(temp2->walked+counter-2));
6798                  exit(0);
6799                }
6800            }
6801          node = *(temp2->VertandId + counter);
6802          y = counter;
6803          if (node->edge[1] == nextvert)
6804            nextvert = node->edge[2];
6805          else
6806            nextvert = node->edge[1];
6807        }
6808    }
6809 
6810  last_seen++;
6811 
6812  if  (distance != 0) 
6813    {
6814      if (((nextvert == -1) || (nextvert == lastvert)) && (distance != 1))
6815        return (original_distance - distance);
6816    }
6817  return original_distance;
6818}
6819
6820///     Test_Adj:
6821int CustomStripifier::Test_Adj(PF_FACES temp2,int x,int north,int distance,int lastvert, int value)
6822{
6823  /* if first time, then just update the last seen field */
6824  if (x==1)
6825    return(Update_and_Test(temp2,north,TRUE,distance,lastvert,value));
6826  /* else we have to check if we are adjacent to the last strip */
6827  else
6828    return(Update_and_Test(temp2,north,FALSE,distance,lastvert,value));
6829}
6830
6831///     Find_Max:
6832int CustomStripifier::Find_Max( PF_FACES temp2, int lastvert,
6833                                                                                                                                int north,                      int left,
6834                                                                                                                int *lastminup, int *lastminleft)
6835{
6836  int temp,walk,counter,minup,x,band_value;
6837  int previous_edge1, previous_edge2;
6838  F_EDGES       *node;
6839  ListHead *pListHead;
6840  BOOL flag;   
6841  static int last_seen = 0;
6842  register int smallest_so_far,nextvert,max=-1;         
6843 
6844  *lastminup = MAX_BAND;
6845  *lastminleft = 1;
6846 
6847  if (left == 3)
6848    {
6849      previous_edge1 = *(temp2->pPolygon + left);
6850      previous_edge2 = *(temp2->pPolygon);
6851    }
6852 
6853  else
6854    {
6855      previous_edge1 = *(temp2->pPolygon + left + 1);
6856      previous_edge2 = *(temp2->pPolygon + left);
6857    }
6858 
6859  temp2->seen = last_seen;
6860  walk = *(temp2->walked + left);
6861 
6862  for (x=1;x<=(walk+1); x++)
6863    {
6864      /*   test to see if we have a true band
6865           that is, are they adjacent to each other
6866      */
6867     
6868      minup = *(temp2->walked + north) + 1;
6869     
6870      /*        if we are at the very first face, then we do not
6871                have to check the adjacent faces going up
6872                and our north distance is the distance of this face's
6873                north direction.
6874      */
6875      if (x == 1)
6876        {
6877          *lastminup = minup;
6878          minup = Test_Adj(temp2,x,north,*lastminup,lastvert,last_seen);
6879          *lastminup = minup;
6880          smallest_so_far = minup;     
6881        }
6882     
6883     
6884      /* find the largest band that we can have */
6885      if (minup < (*lastminup))
6886        {
6887          /*    see if we really can go up all the way
6888                temp should by less than our equal to minup
6889                if it is less, then one of the faces was not
6890                adjacent to those next to it and the band height
6891                will be smaller
6892          */
6893          temp = Test_Adj(temp2,x,north,minup,lastvert,last_seen);
6894          if (temp > minup)
6895            {
6896              printf("There is an error in the test adj\n");
6897              exit(0);
6898            }
6899          minup = temp;
6900          band_value = x * minup;
6901          if (minup < smallest_so_far)
6902            {
6903              if (band_value > max)
6904                {
6905                  smallest_so_far = minup;
6906                  *lastminup = minup;
6907                  *lastminleft = x;
6908                  max = band_value;
6909                }
6910              else
6911                smallest_so_far = minup;
6912            }
6913          else
6914            {
6915              band_value = x * smallest_so_far;
6916              if (band_value > max)
6917                {
6918                  *lastminup = smallest_so_far;
6919                  *lastminleft = x;
6920                  max = band_value;
6921                }
6922            }
6923        }
6924      else
6925        {
6926          if (x != 1)
6927            {
6928              temp = Test_Adj(temp2,x,north,smallest_so_far,lastvert,last_seen);
6929              if (temp > smallest_so_far)
6930                {
6931                  printf("There is an error in the test adj\n");
6932                  exit(0);
6933                }
6934              smallest_so_far = temp;
6935            }
6936          band_value = x * smallest_so_far;
6937          if (band_value > max)
6938            {
6939              *lastminup = smallest_so_far;
6940              *lastminleft = x;
6941              max = band_value;
6942            }
6943        }
6944      if ( x != (walk + 1))
6945        {
6946          node = *(temp2->VertandId+left);
6947          if (lastvert == node->edge[1])
6948            nextvert = node->edge[2];
6949          else
6950            nextvert = node->edge[1];
6951         
6952          lastvert = nextvert;
6953         
6954          if (nextvert == -1)
6955            return max;
6956         
6957          pListHead = PolFaces[nextvert];
6958          temp2 = (PF_FACES) PeekList(pListHead, LISTHEAD, 0);
6959         
6960          /* if we have visited this face before, then there is an error */
6961          if (((*(temp2->walked) == -1) && (*(temp2->walked+1) == -1) &&
6962               (*(temp2->walked+2) == -1) && (*(temp2->walked+3) == -1))
6963              || (temp2->nPolSize !=4) || (temp2->seen == last_seen))
6964            {
6965             
6966              if (lastvert == node->edge[1])
6967                nextvert = node->edge[2];
6968              else
6969                nextvert = node->edge[1];
6970              if (nextvert == -1)
6971                return max;
6972              lastvert = nextvert;
6973              /*   Last attempt to get the face ... */
6974              pListHead = PolFaces[nextvert];
6975              temp2 = (PF_FACES) PeekList(pListHead, LISTHEAD, 0);
6976              if (((*(temp2->walked) == -1) && (*(temp2->walked+1) == -1) &&
6977                   (*(temp2->walked+2) == -1) && (*(temp2->walked+3) == -1))
6978                  || (temp2->nPolSize !=4) || (temp2->seen == last_seen))
6979                return max;    /*   The polygon was not saved with the edge, not
6980                                    enough room. We will get the walk when we come
6981                                    to that polygon later.
6982                               */
6983            }
6984          else
6985            {
6986              counter = 0;
6987              flag = TRUE;
6988              temp2->seen = last_seen;
6989             
6990              while ((counter < 3) && (flag))
6991                {
6992                 
6993                  if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
6994                        (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
6995                       ((*(temp2->pPolygon+counter) == previous_edge2) ||
6996                        (*(temp2->pPolygon+counter+1) == previous_edge1)) )
6997                    counter++;
6998                  else
6999                    flag = FALSE;
7000                }
7001            }
7002         
7003          /* Get the IDs of the next edge */
7004          left = counter;
7005          north = left+1;
7006          if (left ==3)
7007            north = 0; 
7008          if (counter < 3)
7009            {
7010              previous_edge1 = *(temp2->pPolygon + counter + 1);
7011              previous_edge2 = *(temp2->pPolygon + counter);
7012            }
7013          else
7014            {
7015              previous_edge1 = *(temp2->pPolygon + counter);
7016              previous_edge2 = *(temp2->pPolygon);
7017            }
7018         
7019        }
7020     
7021    }
7022  last_seen++;
7023  return max;
7024}
7025
7026///     Mark_Face:
7027void CustomStripifier::Mark_Face(       PF_FACES temp2,                 int color1,
7028                                                                                                                                        int color2,                     int color3,
7029                                                                                                                                        FILE *output_file,      BOOL end,
7030                                                                                                                                        int *edge1,                                     int *edge2,
7031                                                                                                                int *face_id,                           int norms,
7032                                                                                                                                        int texture)
7033{
7034  static int last_quad[4];
7035  register int x,y,z=0;
7036  int saved[2];
7037  static int output1, output2,last_id;
7038  BOOL cptexture;
7039 
7040  /*   Are we done with the patch? If so return the last edge that
7041       we will come out on, and that will be the edge that we will
7042       start to extend upon.
7043  */
7044 
7045  cptexture = texture;
7046  if (end)
7047    {
7048      *edge1 = output1;
7049      *edge2 = output2;
7050      *face_id = last_id;
7051      return;
7052    }
7053 
7054  last_id = *face_id;
7055  *(temp2->walked) = -1;
7056  *(temp2->walked+1) = -1;
7057  *(temp2->walked+2) = -1;
7058  *(temp2->walked+3) = -1;
7059  added_quad++;
7060  temp2->nPolSize = 1;
7061 
7062  if (patch == 0)
7063    {
7064      /*   At the first quad in the strip -- save it */
7065      last_quad[0] = *(temp2->pPolygon);
7066      last_quad[1] = *(temp2->pPolygon+1);
7067      last_quad[2] = *(temp2->pPolygon+2);
7068      last_quad[3] = *(temp2->pPolygon+3);
7069      patch++;
7070    }
7071  else
7072    {
7073      /*   Now we have a triangle to output, find the edge in common */
7074      for (x=0; x < 4 ;x++)
7075        {
7076          for (y=0; y< 4; y++)
7077            {
7078              if (last_quad[x] == *(temp2->pPolygon+y))
7079                {
7080                  saved[z++] = last_quad[x];               
7081                  if (z > 2)
7082                    {
7083                      /*    This means that there was a non convex or
7084                            an overlapping polygon
7085                      */
7086                      z--;
7087                      break;
7088                    }
7089                }                             
7090            }
7091        }
7092     
7093      if (z != 2)
7094        {
7095          printf("Z is not 2 %d \n",patch);
7096          printf("4 %d %d %d %d %d %d %d\n",*(temp2->pPolygon),
7097                 *(temp2->pPolygon+1),*(temp2->pPolygon+2),*(temp2->pPolygon+3),
7098                 color1,color2,color3);
7099          printf("%d %d %d %d\n",last_quad[0],last_quad[1],
7100                 last_quad[2],last_quad[3]);
7101          exit(1);
7102        }
7103     
7104      if (patch == 1)
7105        {
7106          /*   First one to output, there was no output edge */
7107          patch++;
7108          x = Adjacent(saved[0],saved[1],last_quad,4);
7109          y = Adjacent(saved[1],saved[0],last_quad,4);
7110         
7111          /*   Data might be mixed and we do not have textures
7112               for some of the vertices
7113          */
7114          if ((texture) &&
7115              (((vt[x]) == 0) ||
7116               ((vt[y])==0) ||
7117               ((vt[saved[1]])==0)))
7118            cptexture = FALSE;
7119         
7120          if ((!norms) && (!cptexture))
7121            {
7122              fprintf(output_file,"\nt");
7123              if (orient) /* If we want to preserve normal orientation */
7124                preserve_strip_orientation(output_file,x+1,y+1,saved[1]+1);
7125             
7126              fprintf(output_file," %d %d %d",x+1,y+1,saved[1]+1);
7127              fprintf(output_file," %d",saved[0]+1);
7128            }
7129          else if ((norms) && (!cptexture))
7130            {
7131              fprintf(output_file,"\nt");
7132              if (orient) /* If we want to preserve normal orientation */
7133                preserve_strip_orientation_with_normal(output_file,
7134                                                       x+1,vn[x] +1,
7135                                                       y+1,vn[y] +1,
7136                                                       saved[1]+1,vn[saved[1]]+1);
7137             
7138              fprintf(output_file," %d//%d %d//%d %d//%d",
7139                      x+1,vn[x] +1,
7140                      y+1,vn[y] +1,
7141                      saved[1]+1,vn[saved[1]]+1);
7142              fprintf(output_file," %d//%d",saved[0]+1,vn[saved[0]]+1);
7143            }
7144          else if ((cptexture) && (!norms))
7145            {
7146              fprintf(output_file,"\nt");
7147              if (orient) /* If we want to preserve normal orientation */
7148                preserve_strip_orientation_with_texture(output_file,
7149                                                        x+1,vt[x] +1,
7150                                                        y+1,vt[y] +1,
7151                                                        saved[1]+1,vt[saved[1]]+1);
7152             
7153              fprintf(output_file," %d/%d %d/%d %d/%d",
7154                      x+1,vt[x] +1,
7155                      y+1,vt[y] +1,
7156                      saved[1]+1,vt[saved[1]]+1);
7157             
7158              fprintf(output_file," %d//%d",saved[0]+1,vt[saved[0]]+1);
7159            }
7160          else
7161            {
7162              fprintf(output_file,"\nt");
7163              if (orient) /* If we want to preserve normal orientation */
7164                preserve_strip_orientation_with_texture_and_normal(output_file,
7165                                                                   x+1,vt[x]+1,vn[x] +1,
7166                                                                   y+1,vt[y]+1,vn[y] +1,
7167                                                                   saved[1]+1,vt[saved[1]]+1,vn[saved[1]]+1);
7168             
7169              fprintf(output_file," %d/%d/%d %d/%d/%d %d/%d/%d",
7170                      x+1,vt[x]+1,vn[x] +1,
7171                      y+1,vt[y]+1,vn[y] +1,
7172                      saved[1]+1,vt[saved[1]]+1,vn[saved[1]]+1);
7173             
7174              fprintf(output_file," %d/%d/%d",
7175                      saved[0]+1,vt[saved[0]]+1,vn[saved[0]]+1);
7176            }
7177         
7178          x = Adjacent(saved[0],saved[1],temp2->pPolygon,4);
7179          y = Adjacent(saved[1],saved[0],temp2->pPolygon,4);
7180         
7181          /*   Data might be mixed and we do not have textures
7182               for some of the vertices
7183          */
7184          if ((texture) && ( (vt[x] == 0) || (vt[y]==0)))
7185            {
7186              if (cptexture)
7187                fprintf(output_file,"\nq");
7188              cptexture = FALSE;
7189            }
7190          if ((!norms) && (!cptexture))
7191            {
7192              fprintf(output_file," %d",x+1);
7193              fprintf(output_file," %d",y+1);
7194            }
7195          else if ((norms) && (!cptexture))
7196            {
7197              fprintf(output_file," %d//%d",x+1,vn[x]+1);
7198              fprintf(output_file," %d//%d",y+1,vn[y]+1);
7199            }
7200          else if ((cptexture) && (!norms))
7201            {
7202              fprintf(output_file," %d/%d",x+1,vt[x]+1);
7203              fprintf(output_file," %d/%d",y+1,vt[y]+1);
7204            }
7205          else
7206            {
7207              fprintf(output_file," %d/%d/%d",x+1,vt[x]+1,vn[x]+1);
7208              fprintf(output_file," %d/%d/%d",y+1,vt[y]+1,vn[y]+1);
7209            }
7210         
7211          output1 = x;
7212          output2 = y;
7213        }
7214     
7215      else
7216        {
7217          x = Adjacent(output2,output1,temp2->pPolygon,4);
7218          y = Adjacent(output1,output2,temp2->pPolygon,4);
7219          /*   Data might be mixed and we do not have textures
7220               for some of the vertices */
7221          if ((texture) && ( ((vt[x]) == 0) || ((vt[y])==0) ))
7222            texture = FALSE;
7223         
7224          if ((!norms) && (!texture))
7225            {
7226              fprintf(output_file,"\nq %d",x+1);
7227              fprintf(output_file," %d",y+1);
7228            }
7229          else if ((norms) && (!texture))
7230            {
7231              fprintf(output_file,"\nq %d//%d",x+1,vn[x]+1);
7232              fprintf(output_file," %d//%d" ,y+1,vn[y]+1);
7233            }
7234          else if ((texture) && (!norms))
7235            {
7236              fprintf(output_file,"\nq %d/%d",x+1,vt[x]+1);
7237              fprintf(output_file," %d/%d",y+1,vt[y]+1);
7238            }
7239          else
7240            {
7241              fprintf(output_file,"\nq %d/%d/%d",x+1,vt[x]+1,vn[x]+1);
7242              fprintf(output_file," %d/%d/%d",y+1,vt[y]+1,vn[y]+1);
7243            }
7244         
7245          output1 = x;
7246          output2 = y;
7247        }
7248     
7249      last_quad[0] = *(temp2->pPolygon);
7250      last_quad[1] = *(temp2->pPolygon+1);
7251      last_quad[2] = *(temp2->pPolygon+2);
7252      last_quad[3] = *(temp2->pPolygon+3);
7253    }
7254}
7255
7256///     Assign_Walk:
7257void CustomStripifier::Assign_Walk(     int lastvert,           PF_FACES temp2,
7258                                                                                                                                                int front_walk, int y,
7259                                                                                                                                                int back_walk)
7260{
7261  /*      Go back and do the walk again, but this time save the lengths inside
7262          the data structure.
7263          y was the starting edge number for the front_walk length
7264          back_walk is the length of the walk along the opposite edge
7265  */
7266  int previous_edge1, previous_edge2;
7267  register int walk = 0,nextvert,numverts,counter;
7268  BOOL flag;
7269  F_EDGES *node;
7270  ListHead *pListHead;
7271  static int seen = 0;
7272  static BOOL first = TRUE;         
7273  BOOL wrap = FALSE, set = FALSE;             
7274 
7275 
7276  /*     In the "Fast_Reset" resetting will be true */
7277  if ((resetting) && (first))
7278    {
7279      seen = 0;
7280      first = FALSE;
7281    }
7282 
7283  seen++;
7284 
7285  /*     Had a band who could be a cycle  */
7286  if (front_walk == back_walk)
7287    wrap = TRUE;
7288 
7289  /* Find the edge that we are currently on */
7290  if (y != 3)
7291    {
7292      previous_edge1 = *(temp2->pPolygon +y);
7293      previous_edge2 = *(temp2->pPolygon + y + 1);
7294    }
7295  else
7296    {
7297      previous_edge1 = *(temp2->pPolygon +y);
7298      previous_edge2 = *(temp2->pPolygon);
7299    }
7300 
7301  /* Assign the lengths */
7302  if (y < 2)
7303    {
7304      *(temp2->walked+y) = front_walk--;
7305      *(temp2->walked+y+2) = back_walk++;
7306    }
7307  else
7308    {                           
7309      *(temp2->walked+y) = front_walk--;
7310      *(temp2->walked+y-2) = back_walk++;
7311    }
7312 
7313  /*Find the adjacent face to this edge */
7314  node = *(temp2->VertandId+y);                   
7315 
7316  if (node->edge[2] != lastvert)
7317    nextvert = node->edge[2];
7318  else
7319    nextvert = node->edge[1];
7320 
7321  temp2->seen3 = seen;
7322 
7323  /* Keep walking in this direction until we cannot do so */
7324  while ((nextvert != lastvert) && (nextvert != -1) && (front_walk >= 0))
7325    {
7326      walk++;
7327      pListHead = PolFaces[nextvert];
7328     
7329      temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
7330      numverts = temp2->nPolSize;
7331      if ((numverts != 4))
7332        {
7333          nextvert = -1;
7334          /* Don't include this face in the walk */
7335          walk--;
7336        }
7337      else
7338        {
7339          /* Find edge that is not adjacent to the previous one */
7340          counter = 0;
7341          flag = TRUE;
7342          while ((counter < 3) && (flag))
7343            {
7344              if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
7345                    (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
7346                   ((*(temp2->pPolygon+counter) == previous_edge2) ||
7347                    (*(temp2->pPolygon+counter+1) == previous_edge1)) )
7348                counter++;
7349              else
7350                flag = FALSE;
7351            }
7352          /* Get the IDs of the next edge */
7353          if (counter < 3)
7354            {
7355              previous_edge1 = *(temp2->pPolygon + counter);
7356              previous_edge2 = *(temp2->pPolygon + counter + 1);
7357            }
7358          else
7359            {
7360              previous_edge1 = *(temp2->pPolygon + counter);
7361              previous_edge2 = *(temp2->pPolygon);
7362            }
7363         
7364         
7365          /*      Put in the walk lengths */
7366          if (counter < 2)
7367            {
7368              if (((*(temp2->walked + counter) >= 0)
7369                   || (*(temp2->walked +counter + 2) >= 0)))
7370                {
7371                  if ((resetting == FALSE) && ((temp2->seen3) != (seen-1)))
7372                    {
7373                      /*   If there are more than 2 polygons adjacent
7374                           to an edge then we can be trying to assign more than
7375                           once. We will save the smaller one
7376                      */
7377                      temp2->seen3 = seen;
7378                      if ( (*(temp2->walked+counter) <= front_walk) &&
7379                           (*(temp2->walked+counter+2) <= back_walk) )
7380                        return;
7381                      if (*(temp2->walked+counter) > front_walk)
7382                        *(temp2->walked+counter) = front_walk--;
7383                      else
7384                        front_walk--;
7385                      if (*(temp2->walked+counter+2) > back_walk)
7386                        *(temp2->walked+counter+2) = back_walk++;
7387                      else
7388                        back_walk++;
7389                    }
7390                  else if (resetting == FALSE)
7391                    {
7392                      /* if there was a cycle then all lengths are the same */
7393                      walk--;
7394                      back_walk--;
7395                      front_walk++;
7396                      temp2->seen3 = seen;
7397                      *(temp2->walked+counter) = front_walk--;
7398                      *(temp2->walked+counter+2) = back_walk++;
7399                    }
7400                  else if (((temp2->seen3 == (seen-1))
7401                            && (wrap) && (walk == 1)) || (set))
7402                    {
7403                      /* if there was a cycle then all lengths are the same */
7404                      set = TRUE;
7405                      walk--;
7406                      back_walk--;
7407                      front_walk++;
7408                      temp2->seen3 = seen;
7409                      *(temp2->walked+counter) = front_walk--;
7410                      *(temp2->walked+counter+2) = back_walk++;
7411                    }
7412                  else
7413                    {
7414                      temp2->seen3 = seen;
7415                      *(temp2->walked+counter) = front_walk--;
7416                      *(temp2->walked+counter+2) = back_walk++;
7417                    }
7418                } /* if was > 0 */     
7419              else
7420                {
7421                  temp2->seen3 = seen;
7422                  *(temp2->walked+counter) = front_walk--;
7423                  *(temp2->walked+counter+2) = back_walk++;
7424                }
7425            }
7426         
7427          else
7428            {
7429              if (((*(temp2->walked + counter) >= 0 )
7430                   || (*(temp2->walked +counter - 2) >= 0)) )
7431                {
7432                  if ((temp2->seen3 != (seen-1))  && (resetting == FALSE))
7433                    {
7434                      /*   If there are more than 2 polygons adjacent
7435                           to an edge then we can be trying to assign more than
7436                           once. We will save the smaller one
7437                      */
7438                      temp2->seen3 = seen;
7439                      if ( (*(temp2->walked+counter) <= front_walk) &&
7440                           (*(temp2->walked+counter-2) <= back_walk) )
7441                        return;
7442                      if (*(temp2->walked+counter) > front_walk)
7443                        *(temp2->walked+counter) = front_walk--;
7444                      else
7445                        front_walk--;
7446                      if (*(temp2->walked+counter-2) > back_walk)
7447                        *(temp2->walked+counter-2) = back_walk++;
7448                      else
7449                        back_walk++;
7450                    }
7451                  else if (resetting == FALSE)
7452                    {
7453                      walk--;
7454                      back_walk--;
7455                      front_walk++;
7456                      temp2->seen3 = seen;
7457                      *(temp2->walked+counter) = front_walk--;
7458                      *(temp2->walked+counter-2) = back_walk++;
7459                    }
7460                  else if (((temp2->seen3 == (seen-1)) && (walk == 1) && (wrap))
7461                           || (set))
7462                    {
7463                      /* if there was a cycle then all lengths are the same */
7464                      set = TRUE;
7465                      walk--;
7466                      back_walk--;
7467                      front_walk++;
7468                      temp2->seen3 = seen;
7469                      *(temp2->walked+counter) = front_walk--;
7470                      *(temp2->walked+counter-2) = back_walk++;
7471                    }
7472                  else
7473                    {
7474                      temp2->seen3 = seen;
7475                      *(temp2->walked+counter) = front_walk--;
7476                      *(temp2->walked+counter-2) = back_walk++;
7477                    }
7478                }
7479              else
7480                {
7481                  temp2->seen3 = seen;
7482                  *(temp2->walked+counter) = front_walk--;
7483                  *(temp2->walked+counter-2) = back_walk++;
7484                }
7485             
7486            }
7487          if (nextvert != -1)
7488            {
7489              node = *(temp2->VertandId + counter);
7490              if (node->edge[1] == nextvert)
7491                nextvert = node->edge[2];
7492              else
7493                nextvert = node->edge[1];
7494            }
7495         
7496        }
7497    }
7498  if ((EVEN(seen)) )
7499    seen+=2;
7500}
7501
7502///     Fast_Reset:
7503void CustomStripifier::Fast_Reset(int x)
7504{
7505  register int y,numverts;
7506  register int front_walk, back_walk;
7507  ListHead *pListHead;
7508  PF_FACES temp = NULL;
7509 
7510  pListHead = PolFaces[x];
7511  temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
7512  numverts = temp->nPolSize;
7513 
7514  front_walk = 0;
7515  back_walk = 0;         
7516  resetting = TRUE;
7517 
7518  /* we are doing this only for quads */
7519  if (numverts == 4)
7520    {
7521      /*        for each face not seen yet, do North and South together
7522                and East and West together
7523      */
7524      for (y=0;y<2;y++)
7525        {
7526          /* Check if the opposite sides were seen already */
7527          /* Find walk for the first edge */
7528          front_walk = Calculate_Walks(x,y,temp);
7529          /* Find walk in the opposite direction */
7530          back_walk = Calculate_Walks(x,y+2,temp);
7531          /*    Now put into the data structure the numbers that
7532                we have found
7533          */
7534          Assign_Walk(x,temp,front_walk,y,back_walk);
7535          Assign_Walk(x,temp,back_walk,y+2,front_walk);
7536        }
7537    }
7538  resetting = FALSE;
7539}
7540
7541///     Reset_Max:
7542void CustomStripifier::Reset_Max(       PF_FACES temp2,int face_id,
7543                                                                                                                                        int north,int last_north,
7544                                                                                                                int orientation,int last_left,
7545                                                                                                                                        FILE *output_file,int color1,
7546                                                                                                                                        int color2,int color3,
7547                                                                                                                BOOL start)
7548{
7549  int previous_edge1,previous_edge2;
7550  F_EDGES *node;
7551  ListHead *pListHead;
7552  int f,t,nextvert,counter;
7553  BOOL flag;
7554 
7555 
7556  /*   Reset walks on faces, since we just found a patch */
7557  if (orientation !=3)
7558    {
7559      previous_edge1 = *(temp2->pPolygon + orientation+1);
7560      previous_edge2 = *(temp2->pPolygon + orientation );
7561    }
7562  else
7563    {
7564      previous_edge1 = *(temp2->pPolygon + orientation );
7565      previous_edge2 = *(temp2->pPolygon);
7566    }
7567 
7568  /* only if we are going left, otherwise there will be -1 there */
7569  /*Find the adjacent face to this edge */
7570 
7571  for (t = 0; t <=3 ; t++)
7572    {
7573      node = *(temp2->VertandId+t);
7574     
7575      if (face_id == node->edge[1])
7576        f = node->edge[2];
7577      else
7578        f = node->edge[1];
7579     
7580      if (f != -1)
7581        Fast_Reset(f);
7582    }
7583 
7584  node = *(temp2->VertandId+orientation);
7585  if (face_id == node->edge[1])
7586    nextvert = node->edge[2];
7587  else
7588    nextvert = node->edge[1];
7589 
7590  while ((last_left--) > 1)
7591    {
7592     
7593      if (start)
7594        Reset_Max(temp2,face_id,orientation,last_left,north,last_north,
7595                  output_file,color1,color2,color3,FALSE);             
7596     
7597      face_id = nextvert;
7598      pListHead = PolFaces[nextvert];               
7599      temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
7600      if ((temp2->nPolSize != 4) && (temp2->nPolSize != 1))
7601        {
7602          /*   There is more than 2 polygons on the edge, and we could have
7603               gotten the wrong one
7604          */
7605          if (nextvert != node->edge[1])
7606            nextvert = node->edge[1];
7607          else
7608            nextvert = node->edge[2];
7609          pListHead = PolFaces[nextvert];         
7610          temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
7611          node = *(temp2->VertandId+orientation);
7612        }
7613     
7614     
7615      if (!start)
7616        {
7617          for (t = 0; t <=3 ; t++)
7618            {
7619              node = *(temp2->VertandId+t);
7620             
7621              if (face_id == node->edge[1])
7622                f = node->edge[2];
7623              else
7624                f = node->edge[1];
7625             
7626              if (f != -1)
7627                Fast_Reset(f);
7628            }
7629        }
7630     
7631     
7632      counter = 0;
7633      flag = TRUE;
7634      while ((counter < 3) && (flag))
7635        {
7636          if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
7637                (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
7638               ((*(temp2->pPolygon+counter) == previous_edge2) ||
7639                (*(temp2->pPolygon+counter+1) == previous_edge1)) )
7640            counter++;
7641          else
7642            flag = FALSE;
7643        }
7644     
7645      /* Get the IDs of the next edge */
7646      if (counter < 3)
7647        {
7648          previous_edge1 = *(temp2->pPolygon + counter+1);
7649          previous_edge2 = *(temp2->pPolygon + counter);
7650        }
7651      else
7652        {
7653          previous_edge1 = *(temp2->pPolygon + counter);
7654          previous_edge2 = *(temp2->pPolygon);
7655        }
7656      orientation = counter;
7657     
7658      node = *(temp2->VertandId + counter);
7659      if (node->edge[1] == nextvert)
7660        nextvert = node->edge[2];
7661      else
7662        nextvert = node->edge[1];
7663     
7664      if (!reversed)
7665        {
7666          if (counter != 3)
7667            north = counter +1;
7668          else
7669            north = 0;
7670        }
7671      else
7672        {
7673          if (counter != 0)
7674            north = counter -1;
7675          else
7676            north = 3;
7677         
7678        }
7679    }
7680  if (start)
7681    Reset_Max(temp2,face_id,orientation,last_left,north,last_north,output_file,
7682              color1,color2,color3,FALSE);
7683  else if (nextvert != -1)       
7684    Fast_Reset(nextvert);
7685 
7686}
7687
7688///     Peel_Max
7689int CustomStripifier::Peel_Max( PF_FACES temp2,int face_id,
7690                                                                                                                                int north,int last_north,
7691                                                                                                                                int orientation,int last_left,
7692                                                                                                                                FILE *output_file,int color1,
7693                                                                                                                                int color2,int color3,
7694                                                                                                                BOOL start, int *swaps_added,
7695                                                                                                                                int norms, int texture)
7696{
7697  int end1,end2,last_id,s=0,walk = 0;
7698  int previous_edge1,previous_edge2;
7699  int static last_seen = 1000;
7700  F_EDGES *node;
7701  ListHead *pListHead;
7702  int nextvert,numverts,counter,dummy,tris=0;
7703  BOOL flag;
7704 
7705  /* Peel the patch from the model.
7706     We will try and extend off the end of each strip in the patch. We will return
7707     the number of triangles completed by this extension only, and the number of
7708     swaps in the extension only.
7709  */   
7710  patch = 0;
7711 
7712  if (orientation !=3)
7713    {
7714      previous_edge1 = *(temp2->pPolygon + orientation+1);
7715      previous_edge2 = *(temp2->pPolygon + orientation );
7716    }
7717  else
7718    {
7719      previous_edge1 = *(temp2->pPolygon + orientation );
7720      previous_edge2 = *(temp2->pPolygon);
7721    }
7722 
7723 
7724  walk = *(temp2->walked + orientation);
7725 
7726  /* only if we are going left, otherwise there will be -1 there */
7727  if ((start) && ((walk+1) < last_left))
7728    {
7729      printf("There is an error in the left %d %d\n",walk,last_left);
7730      exit(0);
7731    }
7732 
7733  /* Find the adjacent face to this edge */
7734  node = *(temp2->VertandId+orientation);
7735  if (face_id == node->edge[1])
7736    nextvert = node->edge[2];
7737  else
7738    nextvert = node->edge[1];
7739  temp2->seen = last_seen;
7740 
7741 
7742  while ((last_left--) > 1)
7743    {
7744      if (start)
7745        tris += Peel_Max(temp2,face_id,orientation,last_left,north,last_north,
7746                         output_file,color1,color2,color3,FALSE,swaps_added,
7747                         norms,texture);                   
7748      else
7749        Mark_Face(temp2,color1,color2,color3,output_file,FALSE,
7750                  &dummy,&dummy,&face_id,norms,texture);
7751     
7752     
7753      pListHead = PolFaces[nextvert];     
7754      temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
7755      numverts = temp2->nPolSize;
7756     
7757      if ((numverts != 4) || (temp2->seen == last_seen)
7758          ||  (nextvert == -1))
7759        {
7760         
7761          /*   There is more than 2 polygons on the edge, and we could have
7762               gotten the wrong one
7763          */
7764          if (nextvert != node->edge[1])
7765            nextvert = node->edge[1];
7766          else
7767            nextvert = node->edge[2];
7768          pListHead = PolFaces[nextvert];
7769          temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
7770          numverts = temp2->nPolSize;
7771          if ((numverts != 4) || (temp2->seen == last_seen) )
7772            {
7773              printf("Peel 2 %d\n",numverts);
7774              exit(1);
7775            }
7776        }
7777     
7778      face_id = nextvert;
7779      temp2->seen = last_seen;
7780     
7781      counter = 0;
7782      flag = TRUE;
7783      while ((counter < 3) && (flag))
7784        {
7785          if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
7786                (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
7787               ((*(temp2->pPolygon+counter) == previous_edge2) ||
7788                (*(temp2->pPolygon+counter+1) == previous_edge1)) )
7789            counter++;
7790          else
7791            flag = FALSE;
7792        }
7793      /* Get the IDs of the next edge */
7794      if (counter < 3)
7795        {
7796          previous_edge1 = *(temp2->pPolygon + counter+1);
7797          previous_edge2 = *(temp2->pPolygon + counter);
7798        }
7799      else
7800        {
7801          previous_edge1 = *(temp2->pPolygon + counter);
7802          previous_edge2 = *(temp2->pPolygon);
7803        }
7804      orientation = counter;
7805     
7806      node = *(temp2->VertandId + counter);
7807      if (node->edge[1] == nextvert)
7808        nextvert = node->edge[2];
7809      else
7810        nextvert = node->edge[1];
7811     
7812      if (!reversed)
7813        {
7814          if (counter != 3)
7815            north = counter +1;
7816          else
7817            north = 0;
7818        }
7819      else
7820        {
7821          if (counter != 0)
7822            north = counter -1;
7823          else
7824            north = 3;
7825        }
7826    }
7827 
7828  if (start)
7829    tris += Peel_Max(temp2,face_id,orientation,last_left,north,last_north,
7830                     output_file,color1,color2,color3,FALSE,swaps_added,
7831                     norms,texture);   
7832  else
7833    Mark_Face(temp2,color1,color2,color3,output_file,FALSE,
7834              &dummy,&dummy,&face_id,norms,texture);/* do the last face */
7835 
7836  last_seen++;
7837 
7838  /*    Get the edge that we came out on the last strip of the patch */
7839  Mark_Face(NULL,0,0,0,output_file,TRUE,&end1,&end2,&last_id,norms,texture);
7840  tris += Extend_Face(last_id,end1,end2,&s,output_file,color1,color2,color3,
7841                      vn,norms,vt,texture);
7842  *swaps_added = *swaps_added + s;
7843  return tris;
7844}
7845
7846///     Find_Bands:
7847void CustomStripifier::Find_Bands(int numfaces, FILE *output_file,
7848                                                                                                                                        int *swaps,             int *bands,
7849                                                                                        int *cost,              int *tri,
7850                                                                                                                                        int norms,              int *vert_norms,
7851                                                                                                                                        int texture,    int *vert_texture)
7852{
7853 
7854  register int x,y,max1,max2,numverts,face_id,flag,maximum = 25;
7855  ListHead *pListHead;
7856  PF_FACES temp = NULL;
7857  int color1 = 0, color2 = 100, color3 = 255;
7858  int smaller;                       
7859  int north_length1,last_north,left_length1,last_left,north_length2,left_length2;
7860  int total_tri = 0, total_swaps = 0,last_id;
7861  int end1, end2,s=0;
7862  register int cutoff = 20;
7863 
7864  /*   Code that will find the patches. "Cutoff" will be
7865       the cutoff of the area of the patches that we will be allowing. After
7866       we reach this cutoff length, then we will run the local algorithm on the
7867       remaining faces.
7868  */
7869 
7870  /*    For each faces that is left find the largest possible band that we can
7871        have with the remaining faces. Note that we will only be finding patches
7872        consisting of quads.
7873  */
7874 
7875  vn = vert_norms;
7876  vt = vert_texture;
7877  y=1;
7878  *bands = 0;
7879 
7880  while ((maximum >= cutoff))
7881    {
7882      y++;
7883      maximum = -1;
7884      for (x=0; x<numfaces; x++)
7885        {
7886         
7887          /*   Used to produce the triangle strips */
7888         
7889          /* for each face, get the face */
7890          pListHead = PolFaces[x];
7891          temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
7892          numverts = temp->nPolSize;
7893         
7894          /* we are doing this only for quads */
7895          if (numverts == 4)
7896            {
7897              /*   We want a face that is has not been used yet,
7898                   since we know that that face must be part of
7899                   a band. Then we will find the largest band that
7900                   the face may be contained in
7901              */
7902             
7903              /*  Doing the north and the left */
7904              if ((*(temp->walked) != -1) && (*(temp->walked+3) != -1))
7905                max1 = Find_Max(temp,x,0,3,&north_length1,&left_length1);
7906              if ((*(temp->walked+1) != -1) && (*(temp->walked+2) != -1))
7907                max2 = Find_Max(temp,x,2,1,&north_length2,&left_length2);
7908              if ((max1 != (north_length1 * left_length1)) ||
7909                  (max2 != (north_length2 * left_length2)))
7910                {
7911                  printf("Max1 %d, %d %d        Max2 %d, %d %d\n",
7912                         max1,north_length1,left_length1,max2,
7913                         north_length2,left_length2);
7914                  exit(0);
7915                }
7916             
7917             
7918              if ((max1 > max2) && (max1 > maximum))
7919                {
7920                  maximum = max1;
7921                  face_id = x;
7922                  flag = 1;
7923                  last_north = north_length1;
7924                  last_left = left_length1;
7925                  /* so we know we saved max1 */
7926                }
7927              else if ((max2 > maximum) )
7928                {
7929                  maximum = max2;
7930                  face_id = x;
7931                  flag = 2;
7932                  last_north = north_length2;
7933                  last_left = left_length2;
7934                  /* so we know we saved max2 */
7935                }
7936            }
7937        }
7938      if ((maximum < cutoff) && (*bands == 0))
7939        return;
7940      pListHead = PolFaces[face_id];
7941      temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
7942      /*   There are no patches that we found in this pass */
7943      if (maximum == -1)
7944        break;
7945      /*printf("The maximum is  face %d area %d: lengths %d %d\n",face_id,maximum,last_north,last_left);*/
7946     
7947      if (last_north > last_left)
7948        {
7949          smaller = last_left;
7950        }
7951      else
7952        {
7953          smaller = last_north;
7954        }
7955     
7956     
7957      if (flag == 1)
7958        {
7959          if (last_north > last_left) /*     go north sequentially */
7960            {
7961              total_tri += Peel_Max(temp,face_id,0,last_north,3,last_left,
7962                                    output_file,color1,color2,color3,TRUE,
7963                                    &s,norms,texture);
7964              Reset_Max(temp,face_id,0,last_north,3,last_left,
7965                        output_file,color1,color2,color3,TRUE);
7966              total_swaps += s;
7967            }
7968          else
7969            {
7970              reversed = TRUE;
7971              total_tri += Peel_Max(temp,face_id,3,last_left,0,last_north,
7972                                    output_file,color1,color2,color3,TRUE,
7973                                    &s,norms,texture);
7974              Reset_Max(temp,face_id,3,last_left,0,last_north,output_file,
7975                        color1,color2,color3,TRUE);
7976              reversed = FALSE;
7977              total_swaps += s;
7978            }
7979         
7980         
7981          /*    Get the edge that we came out on the last strip of the patch */
7982          Mark_Face(NULL,0,0,0,NULL,TRUE,&end1,&end2,&last_id,norms,texture);
7983          total_tri += Extend_Face(last_id,end1,end2,&s,output_file,
7984                                   color1,color2,color3,vn,norms,vt,texture);
7985          total_swaps += s;
7986         
7987        }
7988      else
7989        {
7990          if (last_north > last_left)
7991            {
7992              total_tri += Peel_Max(temp,face_id,2,last_north,1,last_left,
7993                                    output_file,color1,color2,color3,TRUE,
7994                                    &s,norms,texture);
7995              Reset_Max(temp,face_id,2,last_north,1,last_left,output_file,
7996                        color1,color2,color3,TRUE);
7997              total_swaps += s;
7998            }
7999          else
8000            {
8001              reversed = TRUE;
8002              total_tri += Peel_Max(temp,face_id,1,last_left,2,last_north,
8003                                    output_file,color1,color2,color3,TRUE,
8004                                    &s,norms,texture);
8005              Reset_Max(temp,face_id,1,last_left,2,last_north,output_file,
8006                        color1,color2,color3,TRUE);
8007              reversed = FALSE;
8008              total_swaps += s;
8009            }
8010         
8011          /*    Get the edge that we came out on on the patch */
8012          Mark_Face(NULL,0,0,0,NULL,TRUE,&end1,&end2,&last_id,norms,texture);
8013          total_tri += Extend_Face(last_id,end1,end2,&s,output_file,
8014                                   color1,color2,color3,vn,norms,vt,texture);
8015          total_swaps += s;
8016        }
8017     
8018      /*  Now compute the cost of transmitting this band, is equal to
8019          going across the larger portion sequentially,
8020          and swapping 3 times per other dimension
8021      */
8022     
8023      total_tri += (maximum * 2);
8024      *bands = *bands + smaller;
8025     
8026    }
8027 
8028  /*printf("We transmitted %d triangles,using %d swaps and %d strips\n",total_tri,
8029    total_swaps, *bands);
8030    printf("COST %d\n",total_tri + total_swaps + *bands + *bands);*/
8031  *cost = total_tri + total_swaps + *bands + *bands;
8032  *tri = total_tri;
8033  added_quad = added_quad * 4;
8034  *swaps = total_swaps;
8035}
8036
8037///     Save_Rest:
8038void CustomStripifier::Save_Rest(int *numfaces)
8039{
8040  /*  Put the polygons that are left into a data structure so that we can run the
8041      stripping code on it.
8042  */
8043  register int x,y=0,numverts;
8044  ListHead *pListHead;
8045  PF_FACES temp=NULL;
8046 
8047  for (x=0; x<*numfaces; x++)
8048    {
8049      /* for each face, get the face */
8050      pListHead = PolFaces[x];
8051      temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
8052      numverts = temp->nPolSize;
8053      /*  If we did not do the face before add it to data structure with new
8054          face id number
8055      */
8056      if (numverts != 1)
8057        {
8058          CopyFace(temp->pPolygon,numverts,y+1,temp->pNorms);
8059          y++;
8060        }
8061      /*   Used it, so remove it */
8062      else
8063        RemoveList(pListHead,(PLISTINFO) temp);
8064     
8065    }
8066  *numfaces = y;
8067}
8068
8069///     Save_Walks:
8070void CustomStripifier::Save_Walks(int numfaces)
8071{
8072  int x,y,numverts;
8073  int front_walk, back_walk;
8074  ListHead *pListHead;
8075  PF_FACES temp = NULL;
8076 
8077  for (x=0; x<numfaces; x++)
8078    {
8079      /* for each face, get the face */
8080      pListHead = PolFaces[x];
8081      temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
8082      numverts = temp->nPolSize;
8083      front_walk = 0;
8084      back_walk = 0;
8085     
8086      /* we are finding patches only for quads */
8087      if (numverts == 4)
8088        {
8089          /*    for each face not seen yet, do North and South together
8090                and East and West together
8091          */
8092          for (y=0;y<2;y++)
8093            {
8094              /*   Check if the opposite sides were seen already from another
8095                   starting face, if they were then there is no need to do
8096                   the walk again
8097              */
8098             
8099              if        ( ((*(temp->walked+y) == -1) &&
8100                           (*(temp->walked+y+2) == -1) ))
8101                {
8102                  /* Find walk for the first edge */
8103                  front_walk = Calculate_Walks(x,y,temp);
8104                  /* Find walk in the opposite direction */
8105                  back_walk = Calculate_Walks(x,y+2,temp);
8106                  /*    Now put into the data structure the numbers that
8107                        we have found
8108                  */
8109                  Assign_Walk(x,temp,front_walk,y,back_walk);
8110                  Assign_Walk(x,temp,back_walk,y+2,front_walk);
8111                }
8112            }
8113        }
8114    }
8115}
8116
8117///     OpenOutputFile:
8118FILE *  CustomStripifier::OpenOutputFile(char *fname)
8119{
8120  FILE  *bands;
8121  int           flength =       0;
8122  char  *newfname;
8123 
8124  // get the length of the fname.
8125  flength       =       int(strlen(fname));
8126
8127  // make a new string in memory one larger than fname.
8128  newfname      =       (char *) malloc(sizeof(char) * (flength+2));
8129
8130  // Copy the fname to the newfname.
8131  strcpy(newfname,fname);
8132
8133  // Add an 'f' to the end of it.
8134  newfname[flength]             =       'f';
8135  newfname[flength+1]   =       '\0';
8136 
8137  printf("   Output file : %s\n",newfname);
8138 
8139  // File that will contain the triangle strip data
8140  bands =       fopen(newfname,"w");
8141  fprintf(bands,"#%s: a triangle strip representation created by STRIPE.\n#This is a .objf file\n#by Francine Evans\n",fname);
8142 
8143  return        bands;
8144}
8145
8146///     AllocateStruct: Reserves memory for structures.
8147void CustomStripifier::AllocateStruct(int num_faces,
8148                                                                                int num_vert,
8149                                                                                int num_nvert,
8150                                                                                int num_texture)
8151{
8152  /* Allocate structures for the information */
8153  Start_Face_Struct(num_faces);
8154  Start_Vertex_Struct(num_vert);
8155 
8156  vertices      =       (struct vert_struct *)
8157                                                        malloc (sizeof (struct vert_struct) * num_vert);
8158 
8159  if (num_nvert > 0)
8160  {
8161                nvertices               =       (struct vert_struct *)
8162                                                                        malloc (sizeof (struct vert_struct) * num_nvert);
8163
8164                vert_norms      =       (int *)
8165                                                                        malloc (sizeof (int) * num_vert);
8166
8167                /*      Initialize entries to zero, in case there are 2 hits
8168                                to the same vertex we will know it - used for determining
8169                                the normal difference
8170                */
8171                init_vert_norms(num_vert);
8172  }
8173  else
8174    nvertices = NULL;
8175 
8176  if (num_texture > 0)
8177        {
8178                vert_texture    =       (int *) malloc (sizeof(int) * num_vert);
8179
8180                init_vert_texture(num_vert);
8181        }
8182 
8183  /*   Set up the temporary 'p' pointers  */
8184  pvertices             =       vertices;
8185  pnvertices    =       nvertices;
8186 
8187}
8188
8189///     miReadFile: Loads the object in memory.
8190void CustomStripifier::miReadFile(char *fname, char *file_open, FILE *bands, Geometry::SubMesh *geoSubMesh)
8191{
8192  int           face_id =       0;
8193  int           vert_count;
8194        int             num_vert=0;
8195  int           vertex;
8196  int           temp[MAX1];
8197        int             i       =       0;
8198        int             num_buffers     =       0;
8199  Geometry::VertexBuffer        *geoVertexBuffer        =       geoSubMesh->mVertexBuffer;
8200       
8201        /**
8202         * Faces
8203         */
8204        for(unsigned int j = 0; j < geoSubMesh->mIndexCount; j = j + 3)
8205        {
8206               
8207                // loop on the number of vertices in this line of face data.
8208                vert_count = 0;
8209               
8210                //      3 vertices of a triangle.
8211                for(int k = 0;k < 3;k++)
8212                {
8213                        // no nvertices.
8214                        vertex                                          =       geoSubMesh->mIndex[j+k];
8215                        temp[vert_count]        =       vertex;
8216
8217                        vert_count++;
8218
8219                        add_vert_id(vertex,vert_count);
8220                }
8221
8222                //      Increment the number of faces.
8223                face_id++;
8224
8225                //      Add a new face to the list.
8226                AddNewFace(ids,vert_count,face_id,norms);
8227
8228        }
8229
8230  // Done reading in all the information into data structures.
8231  num_faces     =       face_id;
8232
8233  printf(" Done.\n\n");
8234
8235  free(vertices);
8236  free(nvertices);
8237
8238}
8239
8240///     stripify:       Make triangle strips for a given mesh.
8241int CustomStripifier::stripify (char                                                            *fname,
8242                                                                                                                                Geometry::Mesh                  *geoMesh)
8243{
8244  BOOL                                                          quads = FALSE;
8245        BOOL                                                            oddStrip;
8246        FILE                                                            *bands;
8247        char                                                            *file_open;
8248        int                                                                     i;
8249        unsigned int                                            j;
8250        int                                                                     f;
8251        int                                                                     t;
8252        int                                                                     tr;
8253        int                                                                     num_buffers     =       0;
8254        int                                                                     cost                            =       0;
8255  int                                                                   num_vert                =       0;
8256        int                                                                     num_faces               =       0;
8257        int                                                                     num_nvert   = 0;
8258        int                                                                     num_texture     = 0;
8259        int                                                                     num_tris    = 0;
8260        int                                                                     totalStripIndices;
8261
8262        Geometry::SubMesh*      geoSubMesh;
8263  mi_vector_tipo                        v_indices;
8264   
8265  /*  Scan the file once to find out the number of vertices,
8266                        vertice normals, and faces so we can set up some memory structures.*/
8267  f                                     =       ASCII;
8268  file_open =   "w+";
8269  tr                            =       1;
8270  t                                     =       3;
8271  orient                =       1;
8272
8273        //      Proces OK.
8274        mError                  =       0;
8275
8276
8277        //      Progress bar.
8278        float   percent;
8279        percent =       float(100.0 / (geoMesh->mSubMeshCount * 10.0));
8280        //--------------------------
8281
8282        //      For all submeshes.
8283        for(unsigned int k = 0; k < geoMesh->mSubMeshCount; k++)
8284        {
8285                //      Leaves submesh doesn't stripify.
8286                if (mSubMeshLeaves != k)
8287                {
8288                        v_indices.clear();
8289                        mi_vector.clear();
8290                        mi_vector.push_back(v_indices);
8291                        num_tiras       =       0;
8292
8293                        //      Actual submesh.
8294                        geoSubMesh      =       &geoMesh->mSubMesh[k];
8295
8296                        //      Mesh type.
8297                        geoSubMesh->mType       =       GEO_TRIANGLE_STRIPS;
8298
8299                        num_vert        =       int(geoSubMesh->mVertexBuffer->mVertexCount);
8300                        num_faces       =       int(geoSubMesh->mIndexCount / 3);
8301                        num_tris        =       num_faces;
8302
8303                        //      Debug.
8304                        //vt    =       new     int[num_vert];
8305                        //vn    =       new int[num_vert];
8306                        text    =       0;
8307                        norm    =       0;
8308
8309                        //      2006-02-14.
8310                        //      Updtate progress bar.
8311                        if (mUPB)
8312                        {
8313                                mUPB(percent);
8314                        }
8315                        //-----------------------
8316
8317                        // Open the output file.
8318                        bands   =       OpenOutputFile(fname);
8319
8320                        //      2006-02-14.
8321                        //      Updtate progress bar.
8322                        if (mUPB)
8323                        {
8324                                mUPB(percent);
8325                        }
8326                        //-----------------------
8327
8328                        //      Reserve memory for the mesh structure.
8329                        AllocateStruct(num_faces,num_vert,num_nvert,num_texture);
8330
8331                        //      2006-02-14.
8332                        //      Updtate progress bar.
8333                        if (mUPB)
8334                        {
8335                                mUPB(percent);
8336                        }
8337                        //-----------------------
8338
8339                        //      Load the object into memory.
8340                        miReadFile(fname,file_open,bands,geoSubMesh);
8341
8342                        //      2006-02-14.
8343                        //      Updtate progress bar.
8344                        if (mUPB)
8345                        {
8346                                mUPB(percent);
8347                        }
8348                        //-----------------------
8349
8350                        Start_Edge_Struct(num_vert);
8351                        Find_Adjacencies(num_faces);
8352
8353                        //      2006-02-14.
8354                        //      Updtate progress bar.
8355                        if (mUPB)
8356                        {
8357                                mUPB(percent);
8358                        }
8359                        //-----------------------
8360
8361                        //      If the mesh is not manifold.
8362                        if (mError)
8363                        {
8364                                return  0;
8365                        }
8366
8367                        // Initialize it.
8368                        face_array = NULL;
8369                        Init_Table_SGI(num_faces);
8370
8371                        //      2006-02-14.
8372                        //      Updtate progress bar.
8373                        if (mUPB)
8374                        {
8375                                mUPB(percent);
8376                        }
8377                        //-----------------------
8378
8379                        //      Build it.
8380                        Build_SGI_Table(num_faces);
8381                        InitStripTable();
8382
8383                        //      2006-02-14.
8384                        //      Updtate progress bar.
8385                        if (mUPB)
8386                        {
8387                                mUPB(percent);
8388                        }
8389                        //-----------------------
8390
8391                        SGI_Strip(num_faces,bands,t,tr);
8392
8393                        //      2006-02-14.
8394                        //      Updtate progress bar.
8395                        if (mUPB)
8396                        {
8397                                mUPB(percent);
8398                        }
8399                        //-----------------------
8400
8401                        //      Get the total cost.
8402                        Output_TriEx(-1,-2,-3,NULL,-20,cost);
8403
8404                        End_Face_Struct(num_faces);
8405                        End_Edge_Struct(num_vert);
8406                        fclose(bands);
8407
8408                        //      2006-02-14.
8409                        //      Updtate progress bar.
8410                        if (mUPB)
8411                        {
8412                                mUPB(percent);
8413                        }
8414                        //-----------------------
8415
8416                        num_vert        =       num_tiras;
8417
8418                        totalStripIndices       =       0;
8419
8420
8421                        //      Asigna el numero de tiras.
8422                        geoSubMesh->mStripCount =       num_tiras;
8423
8424                        //      Reserva memoria para el array de punteros al inicio
8425                        //      de las tiras.
8426                        //for(i = 0; i < geoSubMesh->mStripCount; i++)
8427                        //{
8428                        geoSubMesh->mStrip      =       (Index**) malloc(       sizeof(Index*)
8429                                        *
8430                                        geoSubMesh->mStripCount);
8431                        //}
8432
8433                        //      2006-02-28.
8434                        //      La primera sera diferente.
8435                        v_indices       =       mi_vector[1];
8436
8437                        //      Number of vertices of a strip odd or even.
8438                        if(v_indices.size() % 2)
8439                        {
8440                                oddStrip        = TRUE;
8441                        }
8442                        else
8443                        {
8444                                oddStrip        =       FALSE;
8445                        }
8446
8447                        //      Obtiene el total de indices de la primera strip.
8448                        geoSubMesh->mIndexCount =       v_indices.size();
8449
8450                        //      Calculate the Index Count.
8451                        for (i = 2; i <= num_tiras; i++)
8452                        {
8453                                v_indices                                                               =               mi_vector[i];
8454                                geoSubMesh->mIndexCount +=      v_indices.size() + 2;
8455
8456                                //      Insert a new vertex if the strip es odd.
8457                                if(oddStrip)
8458                                {
8459                                        geoSubMesh->mIndexCount++;
8460                                }
8461
8462                                //      Number of vertices of a strip odd or even.
8463                                if(v_indices.size() % 2)
8464                                {
8465                                        oddStrip        = TRUE;
8466                                }
8467                                else
8468                                {
8469                                        oddStrip        =       FALSE;
8470                                }
8471                        }
8472
8473                        //      Delete the actual indices.
8474                        delete[]        geoSubMesh->mIndex;
8475                        geoSubMesh->mIndex      =       new     Index[geoSubMesh->mIndexCount];
8476                        //--------------------------------------------
8477
8478                        //      La primera sera diferente.
8479                        v_indices       =       mi_vector[1];
8480
8481                        //      Obtiene el total de indices de la primera strip.
8482                        //geoSubMesh->mIndexCount       =       v_indices.size();
8483
8484                        //      Copia la primera tira en el array de indices.
8485                        for(j   =       0;j < v_indices.size();j++)
8486                        {
8487                                geoSubMesh->mIndex[totalStripIndices++] =       v_indices[j];
8488                        }
8489
8490                        //      Asigna el inicio de la primera tira de triangulos.
8491                        geoSubMesh->mStrip[0]   =       &geoSubMesh->mIndex[0];
8492
8493                        //      2006-02-14.
8494                        //      Updtate progress bar.
8495                        if (mUPB)
8496                        {
8497                                mUPB(percent);
8498                        }
8499                        //-----------------------
8500
8501                        //      Number of vertices of a strip odd or even.
8502                        if(v_indices.size() % 2)
8503                        {
8504                                oddStrip        = TRUE;
8505                        }
8506                        else
8507                        {
8508                                oddStrip        =       FALSE;
8509                        }
8510
8511                        //      Para todas las tiras menos la primera.
8512                        for(i   =       2;      i <= num_tiras; i++)
8513                        {
8514                                /*      copia en el inicio de la tira el final de la anterior.
8515                                                triangulos degenerados. */
8516                                geoSubMesh->mIndex[totalStripIndices++] =       geoSubMesh->
8517                                        mIndex[totalStripIndices-1];
8518
8519                                v_indices                                                               =       mi_vector[i];
8520
8521                                /*      copia el inicio de la tira 2 veces.
8522                                                triangulos degenerados.
8523                                                */
8524                                geoSubMesh->mIndex[totalStripIndices++] =       v_indices[0];
8525
8526                                //      Asigna el inicio de la tira de triangulos.
8527                                geoSubMesh->mStrip[i-1] =       &geoSubMesh->mIndex[totalStripIndices - 1];
8528
8529                                //      Triangulo Degenerado.
8530                                geoSubMesh->mIndex[totalStripIndices++] =       v_indices[0];
8531
8532                                //      Insert a new vertex if the strip es odd.
8533                                if(oddStrip)
8534                                {
8535                                        geoSubMesh->mIndex[totalStripIndices++] =       v_indices[0];
8536                                }
8537
8538                                //      Number of vertices of a strip odd or even.
8539                                if(v_indices.size() % 2)
8540                                {
8541                                        oddStrip        = TRUE;
8542                                }
8543                                else
8544                                {
8545                                        oddStrip        =       FALSE;
8546                                }
8547                               
8548                                //      Copia la tira en curso en el array de indices.
8549                                for(j   =       1;      j < v_indices.size();   j++)
8550                                {
8551                                        geoSubMesh->mIndex[totalStripIndices++] =       v_indices[j];
8552                                }
8553                        }
8554                }
8555        }//     End For. SubMeshes.
8556
8557        //      2006-02-14.
8558        //      Updtate progress bar.
8559        if (mUPB)
8560        {
8561                mUPB(100.0);
8562        }
8563        //-----------------------
8564
8565        return  1;
8566}
8567
8568//-----------------------------------------------------------------------------
8569//      Constructors.
8570//-----------------------------------------------------------------------------
8571
8572MeshStripifier::MeshStripifier()
8573{
8574}
8575
8576MeshStripifier::MeshStripifier( const   Geometry::Mesh  *geoMesh)
8577{
8578}
8579
8580CustomStripifier::CustomStripifier()
8581{
8582}
8583CustomStripifier::CustomStripifier(     const   Geometry::Mesh  *geoMesh)
8584{
8585        MeshGlobal      =       new Geometry::Mesh();
8586        *MeshGlobal     =       *geoMesh;
8587
8588        //      Initialize the leaves submesh index.
8589        mSubMeshLeaves  =       -1;
8590
8591        //      Sets the actual progress bar function.
8592        mUPB    =       NULL;
8593}
8594
8595//-----------------------------------------------------------------------------
8596//      Destroyers.
8597//-----------------------------------------------------------------------------
8598CustomStripifier::~CustomStripifier()
8599{       
8600        delete  MeshGlobal;
8601}
8602
8603MeshStripifier::~MeshStripifier()
8604{
8605}
8606
8607//-----------------------------------------------------------------------------
8608//      Public.
8609//-----------------------------------------------------------------------------
8610
8611//-----------------------------------------------------------------------------
8612//      Stripify.
8613//-----------------------------------------------------------------------------
8614int CustomStripifier::Stripify()
8615{
8616        //      Init variables.
8617        resetting               =       FALSE;
8618        added_quad      =       0;
8619        reversed                =       FALSE;
8620        patch                           =       0;
8621        out1                            =       -1;
8622        out2                            =       -1;
8623        out1Ex                  =       -1;
8624        out2Ex                  =       -1;
8625        last                            =       0;
8626
8627        //      Make Triangle Strips.
8628        return  stripify("out.obj",MeshGlobal);
8629}
8630
8631//-----------------------------------------------------------------------------
8632//      GetMesh: Return de current Mesh.
8633//-----------------------------------------------------------------------------
8634Mesh*   CustomStripifier::GetMesh()
8635{
8636        Mesh            *mesh_stripified;
8637
8638        mesh_stripified                 =       new Mesh();
8639        *mesh_stripified                =       *MeshGlobal;
8640
8641        return  mesh_stripified;
8642}
8643
8644//-----------------------------------------------------------------------------
8645//      Set the progress bar function.
8646//-----------------------------------------------------------------------------
8647void    CustomStripifier::SetProgressFunc(TIPOFUNC upb)
8648{
8649        //      Sets the actual progress bar function.
8650        mUPB    =       upb;
8651}
8652
8653//-----------------------------------------------------------------------------
8654// Sets what is the submesh that stores the leaves.
8655//-----------------------------------------------------------------------------
8656void CustomStripifier::SetSubMeshLeaves(size_t  submesh)
8657{
8658        mSubMeshLeaves  =       submesh;
8659}
8660
Note: See TracBrowser for help on using the repository browser.