]> git.mxchange.org Git - flightgear.git/commitdiff
Initial revision.
authorcurt <curt>
Fri, 31 Jul 1998 18:27:36 +0000 (18:27 +0000)
committercurt <curt>
Fri, 31 Jul 1998 18:27:36 +0000 (18:27 +0000)
39 files changed:
Stripe_w/Makefile.am [new file with mode: 0644]
Stripe_w/add.c [new file with mode: 0644]
Stripe_w/add.h [new file with mode: 0644]
Stripe_w/bands.c [new file with mode: 0644]
Stripe_w/common.c [new file with mode: 0644]
Stripe_w/common.h [new file with mode: 0644]
Stripe_w/extend.h [new file with mode: 0644]
Stripe_w/free.c [new file with mode: 0644]
Stripe_w/free.h [new file with mode: 0644]
Stripe_w/global.h [new file with mode: 0644]
Stripe_w/init.c [new file with mode: 0644]
Stripe_w/init.h [new file with mode: 0644]
Stripe_w/local.c [new file with mode: 0644]
Stripe_w/local.h [new file with mode: 0644]
Stripe_w/newpolve.c [new file with mode: 0644]
Stripe_w/options.c [new file with mode: 0644]
Stripe_w/options.h [new file with mode: 0644]
Stripe_w/output.c [new file with mode: 0644]
Stripe_w/output.h [new file with mode: 0644]
Stripe_w/outputex.c [new file with mode: 0644]
Stripe_w/outputex.h [new file with mode: 0644]
Stripe_w/partial.c [new file with mode: 0644]
Stripe_w/partial.h [new file with mode: 0644]
Stripe_w/polverts.h [new file with mode: 0644]
Stripe_w/polyvertsex.h [new file with mode: 0644]
Stripe_w/queue.c [new file with mode: 0644]
Stripe_w/queue.h [new file with mode: 0644]
Stripe_w/sgi_triang.c [new file with mode: 0644]
Stripe_w/sgi_triangex.c [new file with mode: 0644]
Stripe_w/struct.c [new file with mode: 0644]
Stripe_w/structex.c [new file with mode: 0644]
Stripe_w/sturcts.h [new file with mode: 0644]
Stripe_w/sturctsex.h [new file with mode: 0644]
Stripe_w/ties.c [new file with mode: 0644]
Stripe_w/ties.h [new file with mode: 0644]
Stripe_w/triangulate.h [new file with mode: 0644]
Stripe_w/triangulatex.h [new file with mode: 0644]
Stripe_w/util.c [new file with mode: 0644]
Stripe_w/util.h [new file with mode: 0644]

diff --git a/Stripe_w/Makefile.am b/Stripe_w/Makefile.am
new file mode 100644 (file)
index 0000000..d3dbaab
--- /dev/null
@@ -0,0 +1,26 @@
+bin_PROGRAMS = strips
+
+strips_SOURCES = \
+       add.c add.h \
+       bands.c \
+       common.c common.h \
+       extend.h \
+       free.c free.h \
+       global.h \
+       init.c init.h \
+       local.c local.h \
+       newpolve.c \
+       options.c options.h \
+       output.c output.h \
+       outputex.c outputex.h \
+       partial.c partial.h \
+       polverts.h polyvertsex.h \
+       queue.c queue.h \
+       sgi_triang.c sgi_triangex.c \
+       struct.c \
+       structex.c \
+       sturcts.h sturctsex.h \
+       ties.c ties.h \
+       triangulate.h triangulatex.h \
+       util.c util.h
+
diff --git a/Stripe_w/add.c b/Stripe_w/add.c
new file mode 100644 (file)
index 0000000..ef6e673
--- /dev/null
@@ -0,0 +1,384 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: add.c
+     This file contains the procedure code that will add information
+     to our data structures.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include "global.h"
+#include "queue.h"
+#include "polverts.h"
+#include "triangulate.h"
+#include "ties.h"
+#include "outputex.h"
+#include "options.h"
+#include "local.h"
+
+BOOL new_vertex(double difference, int id1,int id2,
+                struct vert_struct *n)
+{
+  /*   Is the difference between id1 and id2 (2 normal vertices that
+       mapped to the same vertex) greater than the
+       threshold that was specified?
+  */
+  struct vert_struct *pn1,*pn2;
+  double dot_product;
+  double distance1, distance2,distance;
+  double rad;
+  char arg1[100];
+  char arg2[100];
+
+  pn1 = n + id1;
+  pn2 = n + id2;
+  dot_product = ((pn1->x) * (pn2->x)) +
+                ((pn1->y) * (pn2->y)) +
+                ((pn1->z) * (pn2->z));
+  /*   Get the absolute value */
+  if (dot_product < 0)
+    dot_product = dot_product * -1;
+
+  distance1 = sqrt( (pn1->x * pn1->x) +
+                    (pn1->y * pn1->y) +
+                    (pn1->z * pn1->z) );
+  distance2 = sqrt( (pn2->x * pn2->x) +
+                    (pn2->y * pn2->y) +
+                    (pn2->z * pn2->z) );
+  distance = distance1 * distance2;
+
+  rad = acos((double)dot_product/(double)distance);
+  /* convert to degrees */
+  rad = (180 * rad)/PI;
+    
+  if ( rad <= difference)
+    return FALSE;
+     
+  /*   double checking because of imprecision with floating
+       point acos function
+  */
+  sprintf( arg1,"%.5f", rad );
+  sprintf( arg2,"%.5f", difference );
+  if ( strcmp( arg1, arg2 ) <=0 )
+    return( FALSE );
+  if ( rad <= difference)
+    return FALSE;
+  else 
+    return TRUE;
+}
+
+BOOL Check_VN(int vertex,int normal, struct vert_added *added)
+{
+  /*   Check to see if we already added this vertex and normal */
+  register int x,n;
+
+  n = (added+vertex)->num;
+  for (x = 0; x < n; x++)
+  {
+    if (*((added+vertex)->normal+x) == normal)
+      return TRUE;
+  }
+  return FALSE;
+}
+
+BOOL norm_array(int id, int vertex, double normal_difference,
+                struct vert_struct *n, int num_vert)
+{
+  static int last;
+  static struct vert_added *added;
+  register int x;
+  static BOOL first = TRUE;
+
+  if (first)
+  {
+    /*   This is the first time that we are in here, so we will allocate
+         a structure that will save the vertices that we added, so that we
+         do not add the same thing twice
+    */
+    first = FALSE;
+    added = (struct vert_added *) malloc (sizeof (struct vert_added ) * num_vert);
+    /*   The number of vertices added for each vertex must be initialized to
+         zero
+    */
+    for (x = 0; x < num_vert; x++)
+      (added+x)->num = 0;
+  }
+
+  if (vertex)
+    /*   Set the pointer to the vertex, we will be calling again with the
+         normal to fill it with
+    */
+    last = id;
+  else
+  {    
+    /*   Fill the pointer with the id of the normal */
+    if (*(vert_norms + last) == 0)
+      *(vert_norms + last) = id;
+    else if ((*(vert_norms + last) != id) && ((int)normal_difference != 360))
+    {
+      /*   difference is big enough, we need to create a new vertex */
+      if (new_vertex(normal_difference,id,*(vert_norms + last),n))
+      {
+        /*   First check to see if we added this vertex and normal already */
+        if (Check_VN(last,id,added))
+          return FALSE;
+        /*   OK, create the new vertex, and have its id = the number of vertices
+             and its normal what we have here
+        */
+        vert_norms = realloc(vert_norms, sizeof(int) * (num_vert + 1));
+        if (!vert_norms)
+        {
+          printf("Allocation error - aborting\n");
+          exit(1);
+        }
+        *(vert_norms + num_vert) = id;
+        /*   We created a new vertex, now put it in our added structure so
+             we do not add the same thing twice
+        */
+        (added+last)->num = (added+last)->num + 1;
+        if ((added+last)->num == 1)
+        {
+          /*   First time */
+          (added+last)->normal =  (int *) malloc (sizeof (int ) * 1);
+          *((added+last)->normal) =  id;
+        }
+        else
+        {
+          /*   Not the first time, reallocate space */
+          (added+last)->normal = realloc((added+last)->normal,sizeof(int) * (added+last)->num);
+          *((added+last)->normal+((added+last)->num-1)) = id;
+        }
+        return TRUE;
+      }
+    }
+  }
+  return FALSE;
+}
+
+void add_texture(int id,BOOL vertex)
+{
+  /*   Save the texture with its vertex for future use when outputting */
+  static int last;
+
+  if (vertex)
+    last = id;
+  else
+    *(vert_texture+last) = id;
+}
+
+int    add_vert_id(int id, int index_count)
+{
+  register int x;
+
+  /*   Test if degenerate, if so do not add degenerate vertex */
+  for (x = 1; x < index_count ; x++)
+  {
+    if (ids[x] == id)
+      return 0;
+  }
+  ids[index_count] = id;
+  return 1;
+}
+
+void   add_norm_id(int id, int index_count)
+{
+       norms[index_count] = id;
+}
+
+void AddNewFace(int ids[STRIP_MAX], int vert_count, int face_id, 
+               int norms[STRIP_MAX])
+{
+  PF_FACES pfNode;
+  int  *pTempInt;
+  int *pnorms;
+  F_EDGES **pTempVertptr;
+  int  *pTempmarked, *pTempwalked;
+  register int y,count = 0;
+       
+       /*   Add a new face into our face data structure */
+
+  pfNode = (PF_FACES) malloc(sizeof(F_FACES) );
+  if ( pfNode )
+  {
+    pfNode->pPolygon = (int*) malloc(sizeof(int) * (vert_count) );
+    pfNode->pNorms = (int*) malloc(sizeof(int) * (vert_count) );
+    pfNode->VertandId = (F_EDGES**)malloc(sizeof(F_EDGES*) * (vert_count)); 
+               pfNode->marked  = (int*)malloc(sizeof(int) * (vert_count));
+               pfNode->walked = (int*)malloc(sizeof(int) * (vert_count));
+       }
+       pTempInt =pfNode->pPolygon;
+       pnorms = pfNode->pNorms;
+  pTempmarked = pfNode->marked;
+       pTempwalked = pfNode->walked;
+       pTempVertptr = pfNode->VertandId;
+       pfNode->nPolSize = vert_count;
+       pfNode->seen = -1;
+  pfNode->seen2 = -1;
+       for (y=1;y<=vert_count;y++)
+       {
+               *(pTempInt + count) = ids[y];
+               *(pnorms + count) = norms[y];
+    *(pTempmarked + count) = FALSE;
+         *(pTempwalked + count) =  -1;
+               *(pTempVertptr+count) = NULL;
+               count++;
+       }
+       AddHead(PolFaces[face_id-1],(PLISTINFO) pfNode);
+}      
+
+       
+void CopyFace(int ids[STRIP_MAX], int vert_count, int face_id, 
+             int norms[STRIP_MAX])
+{
+  PF_FACES pfNode;
+  int  *pTempInt;
+  int *pnorms;
+  F_EDGES **pTempVertptr;
+  int  *pTempmarked, *pTempwalked;
+  register int y,count = 0;
+       
+       /*   Copy a face node into a new node, used after the global algorithm
+       is run, so that we can save whatever is left into a new structure
+  */
+     
+  pfNode = (PF_FACES) malloc(sizeof(F_FACES) );
+  if ( pfNode )
+  {
+    pfNode->pPolygon = (int*) malloc(sizeof(int) * (vert_count) );
+    pfNode->pNorms = (int*) malloc(sizeof(int) * (vert_count) );
+    pfNode->VertandId = (F_EDGES**)malloc(sizeof(F_EDGES*) * (vert_count)); 
+               pfNode->marked  = (int*)malloc(sizeof(int) * (vert_count));
+               pfNode->walked = (int*)malloc(sizeof(int) * (vert_count));
+       }
+       pTempInt =pfNode->pPolygon;
+       pnorms = pfNode->pNorms;
+  pTempmarked = pfNode->marked;
+       pTempwalked = pfNode->walked;
+       pTempVertptr = pfNode->VertandId;
+       pfNode->nPolSize = vert_count;
+       pfNode->seen = -1;
+  pfNode->seen2 = -1;
+       for (y=0;y<vert_count;y++)
+       {
+               *(pTempInt + count) = ids[y];
+               *(pnorms + count) = norms[y];
+    *(pTempmarked + count) = FALSE;
+               *(pTempwalked + count) =  -1;
+               *(pTempVertptr+count) = NULL;
+               count++;
+       }
+       AddHead(PolFaces[face_id-1],(PLISTINFO) pfNode);
+}      
+       
+void Add_Edge(int v1,int v2)
+{
+  PF_EDGES temp  = NULL;
+  ListHead *pListHead;
+  BOOL flag = TRUE;
+  register int t,count = 0;
+       
+       /*   Add a new edge into the edge data structure */
+  if (v1 > v2)
+       {
+               t  = v1;
+               v1 = v2;
+               v2 = t;
+       }
+       
+  pListHead = PolEdges[v1];
+       temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+       if (temp == NULL)
+  {
+    printf("Have the wrong edge \n:");
+    exit(1);
+  }
+       
+       while (flag)
+       {
+               if (v2 == temp->edge[0])
+      return;
+    else
+       temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,++count);
+       }                       
+}
+
+void Add_AdjEdge(int v1,int v2,int fnum,int index1 )
+{
+  PF_EDGES temp  = NULL;
+  PF_FACES temp2 = NULL;
+  PF_EDGES pfNode;
+  ListHead *pListHead;
+  ListHead *pListFace;
+  BOOL         flag = TRUE;
+  register int count = 0;
+  register int t,v3 = -1;
+       
+       if (v1 > v2)
+       {
+               t  = v1;
+               v1 = v2;
+               v2 = t;
+       }
+       pListFace  = PolFaces[fnum];
+       temp2 = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
+       pListHead = PolEdges[v1];
+       temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+       if (temp == NULL)
+               flag = FALSE;
+       count++;
+       while (flag)
+       {
+               if (v2 == temp->edge[0])
+               {
+      /*   If greater than 2 polygons adjacent to an edge, then we will
+           only save the first 2 that we found. We will have a small performance
+           hit, but this does not happen often.
+      */
+      if (temp->edge[2] == -1)
+        temp->edge[2] = fnum;
+      else
+        v3 = temp->edge[2];
+      flag = FALSE;
+               }
+               else
+               {
+                       temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+                       count++;
+                       if (temp == NULL)
+                               flag = FALSE;
+               }
+       }
+                
+       /*   Did not find it */
+  if (temp == NULL)
+       {
+               pfNode = (PF_EDGES) malloc(sizeof(F_EDGES) );
+    if ( pfNode )
+    {
+      pfNode->edge[0] = v2;
+                       pfNode->edge[1] = fnum;
+           pfNode->edge[2] =  v3;
+                       AddTail( PolEdges[v1], (PLISTINFO) pfNode );
+    }
+               else
+    {
+      printf("Out of memory!\n");
+      exit(1);
+    }
+               
+    *(temp2->VertandId+index1) = pfNode;
+       }
+       else
+         *(temp2->VertandId+index1) =  temp;
+}
diff --git a/Stripe_w/add.h b/Stripe_w/add.h
new file mode 100644 (file)
index 0000000..fb37f72
--- /dev/null
@@ -0,0 +1,31 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: add.h
+-----------------------------------------------------------------------*/
+
+#include "global.h"
+
+BOOL new_vertex(double difference, int id1,int id2,
+                struct vert_struct *n);
+BOOL Check_VN(int vertex,int normal, struct vert_added *added);
+BOOL norm_array(int id, int vertex, double normal_difference,
+                struct vert_struct *n, int num_vert);
+void add_texture(int id,BOOL vertex);
+int    add_vert_id(int id, int index_count);
+void   add_norm_id(int id, int index_count);
+void AddNewFace(int ids[STRIP_MAX], int vert_count, int face_id, 
+               int norms[STRIP_MAX]);
+void CopyFace(int ids[STRIP_MAX], int vert_count, int face_id, 
+             int norms[STRIP_MAX]);
+void Add_Edge(int v1,int v2);
+void Add_AdjEdge(int v1,int v2,int fnum,int index1 );
+
+
+
diff --git a/Stripe_w/bands.c b/Stripe_w/bands.c
new file mode 100644 (file)
index 0000000..981c132
--- /dev/null
@@ -0,0 +1,560 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: bands.c
+     This file contains the main procedure code that will read in the
+     object and then call the routines that produce the triangle strips.
+*/
+/*---------------------------------------------------------------------*/
+
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+  
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include "global.h"
+#include "polverts.h"
+#include "triangulate.h"
+#include "ties.h"
+#include "outputex.h"
+#include "options.h"
+#include "local.h"
+#include "init.h"
+#include "free.h"
+#include "add.h"
+
+/*   TIMING for Windows */
+#ifdef WIN32
+#include <sys/timeb.h>
+#include <time.h>
+/*   TIMING for UNIX */
+#else
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/times.h>
+extern long times( );
+long elapsed()
+{
+  static long total = 0;
+  long cpu_time, dummy;
+  struct tms buffer;
+  times(&buffer);
+  dummy    = buffer.tms_utime  + buffer.tms_stime +
+             buffer.tms_cutime + buffer.tms_cstime;
+  cpu_time = ((dummy - total) * 1000) / HZ;
+  total    = dummy;
+  return(cpu_time);
+}
+#endif
+
+
+int     norms[STRIP_MAX];
+int     *vert_norms;
+int     *vert_texture;
+
+
+void get_time()
+{
+  /*   For timing */
+#ifdef WIN32
+  struct timeb timebuffer;
+  char *timeline;
+#else
+  long timer;
+#endif
+
+
+#ifdef WIN32
+  ftime( &timebuffer );
+  timeline = ctime( & ( timebuffer.time ) );
+  printf( "The time is %.19s.%hu %s", timeline, timebuffer.millitm, &timeline[20] );
+#else
+  timer = elapsed();
+  printf("The time is %ld\n",timer);
+#endif
+}
+
+/*
+** 
+     Here the main program begins. It will start by loading in a .obj file
+     then it will convert the polygonal model into triangle strips.
+**  
+*/
+
+int main (int argc,char *argv[])
+{
+  char *fname,*all,buff[255], *ptr, *ptr2;
+       FILE    *file, *bands;
+       int face_id=0;
+  int vert_count=0;
+  int loop=0;
+  int num=0;
+  int num2=0;
+
+       float center[3];
+  int temp[STRIP_MAX],vertex,strips, swaps,tempi,cost,triangles;
+  int f,t,tr,g;
+  char *file_open;
+       int     num_vert        = 0,
+               num_faces       = 0,
+               num_nvert       = 0,
+               num_edges       = 0,
+    num_texture = 0,
+    num_tris = 0;
+  double fra = 0.0;
+  BOOL texture, normal, normal_and_texture,quads = FALSE;
+
+  /*   Options variables */
+  double norm_difference;
+
+       /*   Structures for the object */
+  struct vert_struct   *vertices       = NULL,
+    *nvertices = NULL,
+               *pvertices      = NULL,
+               *pnvertices     = NULL;
+
+  get_time();
+
+  /*   File that will contain the triangle strip data */
+  bands = fopen("stripe.objf","w");
+
+  /*
+       Scan the file once to find out the number of vertices,
+       vertice normals, and faces so we can set up some memory
+       structures 
+       */
+       /* Interpret the options specified */
+       norm_difference = get_options(argc,argv,&f,&t,&tr,&g);
+  if (f == BINARY)
+    file_open = "rb";
+  else
+    file_open = "r";
+
+       fname = argv[argc-1];
+
+  printf ("File: %s\n",fname);
+       printf ("Scanning...%s ",file_open);
+
+           
+  /*   File can be in binary for faster reading */
+  if (file = fopen (fname,file_open))
+       {
+         while (!feof (file))
+               {
+                       /*   Read a line */
+      if (f == BINARY)
+        fread (buff,sizeof(char) * 255,1, file);
+                       else
+        fgets (buff, sizeof(char) * 255, file);
+      num++;
+      
+      printf("%d\r",num);
+
+      
+      /*   At a vertex */
+      if (*buff == 'v')
+                       {
+                               /*   At a normal */
+        if (*(buff+1)=='n')
+                                       num_nvert++;
+                               else if (*(buff+1)=='t')
+          num_texture++;
+        /*   At a regular vertex */
+        else
+                                 num_vert++;
+                       }
+                       /*   At a face */
+      else if (*buff == 'f')
+                       {  
+        num_faces++;
+                         strtok(buff, " ");
+                         tempi = 0;
+                         while (strtok(NULL, " ") != NULL) tempi++;
+                         num_tris += tempi - 2;
+      }
+               }
+               fclose (file);
+  }
+       else
+  {
+    printf("Error in the file name\n");
+    exit(1);
+  }
+       
+  printf("%s pass 1\n",fname);
+       
+       /* Allocate structures for the information */
+       Start_Face_Struct(num_faces);
+       vertices = (struct vert_struct *)
+                       malloc (sizeof (struct vert_struct) * num_vert);
+
+       if (num_nvert > 0) {
+    nvertices = (struct vert_struct *)
+               malloc (sizeof (struct vert_struct) * num_nvert);
+    vert_norms = (int *) malloc (sizeof (int) * num_vert);
+    /*   
+    Initialize entries to zero, in case there are 2 hits
+    to the same vertex we will know it - used for determining
+    the normal difference
+    */
+    init_vert_norms(num_vert);
+  } else {
+               nvertices = NULL;
+  }
+
+  if (num_texture > 0) {
+    vert_texture = (int *) malloc (sizeof(int) * num_vert);
+    init_vert_texture(num_vert);
+  }
+     
+       /*
+  Set up the temporary 'p' pointers 
+  */
+       pvertices = vertices;
+       pnvertices = nvertices;
+
+       /* Load the object into memory */
+       /*printf (" Loading...");*/
+   fprintf(bands,"#%s: a triangle strip representation created by STRIPE.\n#This is a .objf file\n#by Francine Evans\n",fname);
+  /*  File will be put in a list for faster execution if file is in binary */   
+  if (file = fopen(fname,file_open)) {
+    if (f == BINARY) {
+      all = (char *) malloc (sizeof(char) * 255 * num);
+      fread(all,sizeof(char) * 255 * num, 1, file);
+      ptr = all;
+    } else {
+      ptr = (char *) malloc (sizeof(char) * 255 * num);
+    }
+  }
+
+   
+  while (num > 0) {
+    num--;
+
+    printf("%d\r",num);
+
+               if (f == ASCII) {
+      fgets (ptr, sizeof(char) * 255, file);
+    } else {
+      ptr = ptr + 255;
+    }
+
+    /* Load in vertices/normals */
+               if (*ptr == 'v') {
+                       if (*(ptr+1)=='n') {
+                               sscanf (ptr+3,"%lf%lf%lf",
+                                       &(pnvertices->x),
+                                       &(pnvertices->y),
+                                       &(pnvertices->z));
+                               fprintf(bands,"vn %f %f %f\n",
+                                       pnvertices->x,pnvertices->y,pnvertices->z); 
+                       ++pnvertices;
+                       } else if (*(ptr+1)=='t') {
+                               sscanf (ptr+3,"%f%f%f",&center[0],&center[1],&center[2]);
+                       fprintf(bands,"vt %f %f %f\n",center[0],center[1],center[2]); 
+      } else {
+                               sscanf (ptr+2,"%lf%lf%lf",
+                                       &(pvertices->x), 
+                                       &(pvertices->y), 
+                                       &(pvertices->z));
+                       fprintf(bands,"v %f %f %f\n",
+                                       pvertices->x,pvertices->y,pvertices->z); 
+                               ++pvertices;
+      }
+               } else if (*ptr == 'f') {
+                       /* Read in faces */
+                       num2 = 0;
+                       face_id++;
+      ptr2 = ptr+1;
+      normal = FALSE; texture = FALSE, normal_and_texture = FALSE;
+      while (*ptr2) {
+                         if (*ptr2 >='0' && *ptr2 <='9') {
+                                 num2++;
+                                 ++ptr2;
+                                 while (*ptr2 && (*ptr2!=' ' && *ptr2!='/')) {
+                                         ptr2++;
+          }
+          /*   There are normals in this line */
+          if (*ptr2 == '/') {
+            if (*(ptr2+1) == '/') {
+              normal = TRUE;
+            } else {
+              texture = TRUE;
+            }
+                           } else if (*ptr2 == ' ') {
+            if ((num2 == 3) && (texture)) {
+              normal_and_texture = TRUE;
+            }
+          }
+        } else {
+                                 ++ptr2;
+        }
+                       }
+
+      ptr2 = ptr+1;
+                       
+      /* 
+      loop on the number of numbers in this line of face data 
+      */
+                       vert_count = 0;
+                                                               
+                       for (loop=0;loop<num2;loop++) {
+                               /* skip the whitespace */
+                               while (*ptr2<'0' || *ptr2>'9') {
+          if (*ptr2 == '-') {
+            break;
+          }
+          ptr2++;
+        }
+                               vertex = atoi(ptr2)-1;
+        if (vertex < 0) {
+          vertex = num_vert + vertex;
+          *ptr2 = ' ';
+          ptr2++;
+        }
+        /*
+        If there are either normals or textures with the vertices
+        in this file, the data alternates so we must read it this way 
+        */
+                               if ( (normal) && (!normal_and_texture)) {
+                                       if (loop%2) {
+            add_norm_id(vertex,vert_count);
+            /*
+            Test here to see if we added a new vertex, since the
+            vertex has more than one normal and the 2 normals are greater
+            than the threshold specified
+            */
+            if (norm_array(vertex,0,norm_difference,nvertices,num_vert)) {
+              /*
+              Add a new vertex and change the
+              id of the vertex that we just read to the id of the new
+              vertex that we just added
+              */
+              /*
+              Put it in the output file, note the added vertices will
+              be after the normals and separated from the rest of the 
+              vertices. Will not affect our viewer
+              */
+              fprintf(bands,"v %f %f %f\n",
+                (vertices + temp[vert_count - 1])->x,
+                (vertices + temp[vert_count - 1])->y,
+                (vertices + temp[vert_count - 1])->z); 
+              num_vert++;
+              temp[vert_count - 1] = num_vert - 1;
+              if (!(add_vert_id(num_vert - 1,vert_count))) {
+                vert_count--;
+              }
+            }
+          } else {
+                                         /* the vertex */
+                                               temp[vert_count] = vertex ;
+                                               vert_count++;
+            if (!(add_vert_id(vertex,vert_count))) {
+                vert_count--;
+            }
+            norm_array(vertex,1,norm_difference,nvertices,num_vert);
+                                       }
+        } else if (normal_and_texture) {                      
+          /* Else there are vertices and textures with the data */
+          if( !((loop+1)%3)) {
+            add_norm_id(vertex,vert_count);
+            /*
+            Test here to see if we added a new vertex, since the
+            vertex has more than one normal and the 2 normals are greater
+            than the threshold specified
+            */
+            if (norm_array(vertex,0,norm_difference,nvertices,num_vert)) {
+              /*
+              Add a new vertex and change the
+              id of the vertex that we just read to the id of the new
+              vertex that we just added
+              */
+              /*
+              Put it in the output file, note the added vertices will
+              be after the normals and separated from the rest of the 
+              vertices. Will not affect our viewer
+              */
+              fprintf(bands,"v %f %f %f\n",
+                (vertices + temp[vert_count - 1])->x,
+                (vertices + temp[vert_count - 1])->y,
+                (vertices + temp[vert_count - 1])->z); 
+              num_vert++;
+              temp[vert_count - 1] = num_vert - 1;
+              if (!(add_vert_id(num_vert - 1,vert_count))) {
+                vert_count--;
+              }
+            }
+          } else if ((loop == 0) || (*(ptr2-1) == ' ')) {
+            /*   the vertex */
+            temp[vert_count] = vertex ;
+            vert_count++;
+            if (vert_count == 4) {
+              quads = TRUE;
+            }
+            if (!(add_vert_id(vertex,vert_count))) {
+              vert_count--;
+            }
+            add_texture(vertex,TRUE);
+            norm_array(vertex,1,norm_difference,nvertices,num_vert);
+                                       } else {
+            /*   The texture */
+            add_texture(vertex,FALSE);
+          }
+        } else if ( texture ) {
+                                       /*   the vertex */
+          if (!(loop%2)) {
+                                               temp[vert_count] = vertex ;
+                                               vert_count++;
+            if (vert_count == 4)
+              quads = TRUE;
+            add_texture(vertex,TRUE);
+            if (!(add_vert_id(vertex,vert_count)))
+              vert_count--;
+            norm_array(vertex,1,norm_difference,nvertices,num_vert);
+                                       } else {
+            /*   texture */
+            add_texture(vertex,FALSE);
+          }
+        } else {
+                                 /*** no nvertices ***/
+                                       temp[vert_count] = vertex ;
+                                       vert_count++;
+          if (vert_count == 4)
+            quads = TRUE;
+          if (!(add_vert_id(vertex,vert_count)))
+            vert_count--;
+                               }
+                               while (*ptr2>='0' && *ptr2<='9')
+                                       ptr2++;
+      }
+                       /* Done with the polygon */
+                       num_edges += vert_count;
+                       /* add it to face structure */
+                       if (vert_count >= 3)
+        AddNewFace(ids,vert_count,face_id,norms);
+      else
+        face_id--;
+      if (vert_count == 4)
+        quads = TRUE;
+    }
+    else if ((g == TRUE) && (face_id > 0)
+         && ((*ptr == 'g') || (*ptr  == 's') || (*ptr == 'm') || (*ptr == 'o')))
+    {
+      /*
+      The user specified that the strips will be contained in each group
+      from the data file, so we just finished a group and will find the
+      triangle strips in it.
+      */
+      Start_Edge_Struct(num_vert);
+           Find_Adjacencies(face_id);
+           if (quads)
+      {
+        Init_Table_SGI();
+             Build_SGI_Table(num_vert,face_id);
+        /* Code for lengths of walks in each direction */
+             /* Save_Walks(face_id,TRUE); */
+             Save_Walks(face_id);
+
+        /* Code for finding the bands */
+             Find_Bands(face_id,bands,&swaps,&strips,&cost,&triangles,num_nvert,vert_norms,num_texture,vert_texture);
+
+        /*
+        Remove the faces that we did  so that we can
+        run the strip code on the rest of the faces that are left
+        */
+        if (cost != 0)
+        {
+          printf("Total %d triangles with %d cost\n",triangles,cost);
+          Save_Rest(&face_id);
+          printf("We saved %d .... now doing the local algorithm\n",face_id);
+          fprintf(bands,"\n#local\n");
+               End_Edge_Struct(num_vert);
+          Start_Edge_Struct(num_vert);
+               Find_Adjacencies(face_id);
+        }
+      }
+              
+      SGI_Strip(num_vert,face_id,bands,t,tr);
+
+      /* Get the total cost */
+      Output_TriEx(-1,-2,-3,NULL,-1,-20,cost);
+
+      End_Face_Struct(num_faces);
+      End_Edge_Struct(num_vert);
+      cost = 0;
+      face_id = 0;
+      quads = FALSE;
+      Start_Face_Struct(num_faces-face_id);
+      num_faces = num_faces - face_id;
+      Free_Strips();
+    }
+  }
+               
+  /*   Done reading in all the information into data structures */
+  num_faces = face_id;
+  fclose (file);
+  
+  printf("Input Done.\n\n");
+
+  free(vertices);
+  free(nvertices);
+
+  printf ("Vertices:   %d\nNormals:    %d\nFaces:              %d\n",num_vert,num_nvert,num_faces);
+
+  Start_Edge_Struct(num_vert);
+  Find_Adjacencies(num_faces);
+
+  /* Initialize it */
+  Init_Table_SGI();
+  /* Build it */
+  Build_SGI_Table(num_vert,num_faces);
+
+  InitStripTable();
+
+  if (quads) {
+    /* Code for lengths of walks in each direction */
+          /* Save_Walks(num_faces,TRUE); */
+         Save_Walks(num_faces);
+         
+    /* Code for finding the bands */
+         Find_Bands(num_faces,bands,&swaps,&strips,&cost,&triangles,num_nvert,vert_norms,num_texture,vert_texture);
+    /*printf("Total %d triangles with %d cost\n",triangles,cost);*/
+
+    /*  
+    Remove the faces that we did  so that we can
+    run the strip code on the rest of the faces that are left
+    */
+    Save_Rest(&num_faces);
+    /*printf("We saved %d .... now doing the local algorithm\n",num_faces);*/
+    fprintf(bands,"\n#local\n");
+         End_Edge_Struct(num_vert);
+    Start_Edge_Struct(num_vert);
+         Find_Adjacencies(num_faces);
+  }
+              
+  SGI_Strip(num_vert,num_faces,bands,t,tr);
+
+  /*   Get the total cost */
+  Output_TriEx(-1,-2,-3,NULL,-1,-20,cost);
+
+  End_Face_Struct(num_faces);
+  End_Edge_Struct(num_vert);
+  fclose(bands);
+
+  get_time();
+
+  return(0);
+}
+
diff --git a/Stripe_w/common.c b/Stripe_w/common.c
new file mode 100644 (file)
index 0000000..ca836e1
--- /dev/null
@@ -0,0 +1,810 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: common.c
+     This file contains common code used in both the local and global algorithm
+*/
+/*---------------------------------------------------------------------*/
+
+
+#include <stdlib.h>
+#include "polverts.h"
+#include "extend.h"
+#include "output.h"
+#include "triangulate.h"
+#include "util.h"
+#include "add.h"
+
+int  Old_Adj(int face_id)
+{
+       /*      Find the bucket that the face_id is currently in,
+               because maybe we will be deleting it. 
+       */
+       PF_FACES temp = NULL;
+       ListHead *pListHead;
+       int size,y;
+       
+       pListHead = PolFaces[face_id];
+       temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+       if ( temp == NULL )
+       {
+               printf("The face was already deleted, there is an error\n");
+               exit(0);
+       }
+       
+       size = temp->nPolSize;
+       if (Done(face_id,size,&y) == NULL)
+       {
+               printf("There is an error in finding the face\n");
+               exit(0);
+       }
+       return y;
+}
+
+int Number_Adj(int id1, int id2, int curr_id)
+{
+       /*      Given edge whose endpoints are specified by id1 and id2,
+               determine how many polygons share this edge and return that
+               number minus one (since we do not want to include the polygon
+               that the caller has already).
+       */
+
+       int size,y,count=0;
+       PF_EDGES temp = NULL;
+       PF_FACES temp2 = NULL;
+       ListHead *pListHead;
+       BOOL there= FALSE;
+
+       /*      Always want smaller id first */
+       switch_lower(&id1,&id2);
+       
+       pListHead = PolEdges[id1];
+       temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     if (temp == NULL)
+     /*        new edge that was created might not be here */
+               return 0;
+       while (temp->edge[0] != id2)
+     {
+               count++;
+               temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+          if (temp == NULL)
+                       /*      This edge was not there in the original, which
+                               mean that we created it in the partial triangulation.
+                               So it is adjacent to nothing.
+                       */
+                       return 0;
+       }
+       /*      Was not adjacent to anything else except itself */
+       if (temp->edge[2] == -1)
+               return 0;
+       else
+       {
+               /*      It was adjacent to another polygon, but maybe we did this
+                       polygon already, and it was done partially so that this edge
+                       could have been done
+               */
+               if (curr_id != temp->edge[1])
+               {
+                       /*      Did we use this polygon already?and it was deleted
+                               completely from the structure
+                       */
+                       pListHead = PolFaces[temp->edge[1]];
+                       temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+                       if (Done(temp->edge[1],temp2->nPolSize,&size) == NULL)
+                               return 0;
+               }
+               else
+               {
+                       pListHead = PolFaces[temp->edge[2]];
+                       temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+                       if (Done(temp->edge[2],temp2->nPolSize,&size)== NULL)
+                               return 0;
+               }
+
+               /*      Now we have to check whether it was partially done, before
+                       we can say definitely if it is adjacent.
+                       Check each edge of the face and tally the number of adjacent
+                       polygons to this face. 
+               */                      
+               if ( temp2 != NULL )
+               {
+                       /*      Size of the polygon */
+                       size = temp2->nPolSize;
+                       for (y = 0; y< size; y++)
+                       {
+                               /*      If we are doing partial triangulation, we must check
+                                       to see whether the edge is still there in the polygon,
+                                       since we might have done a portion of the polygon
+                                       and saved the rest for later.
+                               */
+                               if (y != (size-1))
+                               {
+                                       if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1)))
+                                               || ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1))))
+                                               /*      edge is still there we are ok */
+                                               there = TRUE;
+                               }
+                               else
+                               {
+                                       if( ((id1 == *(temp2->pPolygon)) && (id2 == *(temp2->pPolygon+size-1)))
+                                       || ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1))))
+                                       /*      edge is still there we are ok */
+                                               there = TRUE;
+                               }
+                       }
+               }
+               
+               if (there )
+                       return 1;
+               return 0;
+       }
+}
+
+int Min_Adj(int id)
+{
+       /*      Used for the lookahead to break ties. It will
+               return the minimum adjacency found at this face.
+       */
+       int y,numverts,t,x=60;
+       PF_FACES temp=NULL;
+       ListHead *pListHead;
+
+       /*      If polygon was used then we can't use this face */
+       if (Done(id,59,&y) == NULL)
+               return 60;
+               
+       /*      It was not used already */
+       pListHead = PolFaces[id];
+       temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+     if ( temp != NULL )
+       {
+               numverts = temp->nPolSize;
+               for (y = 0; y< numverts; y++)
+               {
+                       if (y != (numverts-1))
+                               t = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),id);
+                       else
+                               t = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+(numverts-1)),id);
+                       if (t < x)
+                               x = t;
+               }
+       }
+       if (x == -1)
+       {
+               printf("Error in the look\n");
+               exit(0);
+       }
+       return x;
+}
+
+
+
+void Edge_Least(int *index,int *new1,int *new2,int face_id,int size)
+{
+    /*   We had a polygon without an input edge and now we re going to pick one
+         of the edges with the least number of adjacencies to be the input
+         edge
+    */
+    register int x,value,smallest=60;
+
+    for (x = 0; x<size; x++)
+    {
+        if (x != (size -1) )
+            value = Number_Adj(*(index+x),*(index+x+1),face_id);
+        else 
+            value = Number_Adj(*(index),*(index+size-1),face_id);
+        if (value < smallest)
+        {
+            smallest = value;
+            if (x != (size -1))
+            {
+                *new1 = *(index+x);
+                *new2 = *(index+x+1);
+            }
+            else
+            {
+                *new1 = *(index);
+                *new2 = *(index+size-1);
+            }
+        }
+    }
+    if ((smallest == 60) || (smallest < 0))
+    {
+        printf("There is an error in getting the least edge\n");
+        exit(0);
+    }
+}
+
+
+void Check_In_Polygon(int face_id, int *min, int size)
+{
+    /*  Check to see the adjacencies by going into a polygon that has
+        greater than 4 sides.
+    */
+    
+    ListHead *pListHead;
+    PF_FACES temp;
+    int y,id1,id2,id3,x=0,z=0;
+    int saved[2];
+    int big_saved[60];
+
+    pListHead = PolFaces[face_id];
+    temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+
+    /*   Get the input edge that we came in on */
+    Last_Edge(&id1,&id2,&id3,0);
+
+    /*  Find the number of adjacencies to the edges that are adjacent
+        to the input edge.
+    */
+    for (y=0; y< size; y++)
+    {
+        if (y != (size-1))
+        {
+            if (((*(temp->pPolygon+y) == id2) && (*(temp->pPolygon+y+1) != id3))
+                || ((*(temp->pPolygon+y) == id3) && (*(temp->pPolygon+y+1) != id2)))
+            {
+                saved[x++] = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),face_id);
+                big_saved[z++] = saved[x-1];
+            }
+            else
+                big_saved[z++] = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),face_id);
+        }
+        else
+        {
+            if (((*(temp->pPolygon) == id2) && (*(temp->pPolygon+size-1) != id3))
+                || ((*(temp->pPolygon) == id3) && (*(temp->pPolygon+size-1) != id2)))
+            {
+                saved[x++] = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+size-1),face_id);
+                big_saved[z++] = saved[x-1];
+            }
+            else
+                big_saved[z++] = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+size-1),face_id);
+        }
+    }
+    /*  There was an input edge */
+    if (x == 2)
+    {
+        if (saved[0] < saved[1])
+            /*  Count the polygon that we will be cutting as another adjacency*/
+            *min = saved[0] + 1;
+        else
+            *min = saved[1] + 1;
+    }
+    /*  There was not an input edge */
+    else
+    {
+        if (z != size)
+        {
+            printf("There is an error with the z %d %d\n",size,z);
+            exit(0);
+        }
+        *min = 60;
+        for (x = 0; x < size; x++)
+        {
+            if (*min > big_saved[x])
+                *min = big_saved[x];
+        }
+    }
+}
+
+
+void New_Face (int face_id, int v1, int v2, int v3)
+{
+       /*      We want to change the face that was face_id, we will
+               change it to a triangle, since the rest of the polygon
+               was already outputtted
+       */
+       ListHead *pListHead;
+       PF_FACES temp = NULL;
+
+       pListHead = PolFaces[face_id];
+     temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0);
+       /*      Check each edge of the face and tally the number of adjacent
+               polygons to this face. 
+       */                      
+       if ( temp != NULL )
+       {
+               /*      Size of the polygon */
+               if (temp->nPolSize != 4)
+               {
+                       printf("There is a miscalculation in the partial\n");
+                       exit (0);
+               }
+               temp->nPolSize = 3;
+               *(temp->pPolygon) = v1;
+               *(temp->pPolygon+1) = v2;
+               *(temp->pPolygon+2) = v3;
+       }
+}
+
+void New_Size_Face (int face_id)
+{
+       /*      We want to change the face that was face_id, we will
+               change it to a triangle, since the rest of the polygon
+               was already outputtted
+       */
+       ListHead *pListHead;
+       PF_FACES temp = NULL;
+
+       pListHead = PolFaces[face_id];
+       temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+       /*      Check each edge of the face and tally the number of adjacent
+               polygons to this face. 
+       */                      
+       if ( temp != NULL )
+               (temp->nPolSize)--;
+       else
+               printf("There is an error in updating the size\n");
+}
+
+
+
+void  Check_In_Quad(int face_id,int *min)
+{
+     /*   Check to see what the adjacencies are for the polygons that
+          are inside the quad, ie the 2 triangles that we can form.
+     */
+    ListHead *pListHead;
+    int y,id1,id2,id3,x=0;
+    int saved[4];
+    PF_FACES temp;
+    register int size = 4;
+
+    pListHead = PolFaces[face_id];
+    temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+       
+     /*   Get the input edge that we came in on */
+    Last_Edge(&id1,&id2,&id3,0);
+       
+    /*    Now find the adjacencies for the inside triangles */
+    for (y = 0; y< size; y++)
+       {
+         /*     Will not do this if the edge is the input edge */
+         if (y != (size-1))
+         {
+              if ((((*(temp->pPolygon+y) == id2) && (*(temp->pPolygon+y+1) == id3))) ||
+             (((*(temp->pPolygon+y) == id3) && (*(temp->pPolygon+y+1) == id2))))
+                    saved[x++] = -1;
+              else
+              {
+                   if (x == 4)
+                   {
+                        printf("There is an error in the check in quad \n");
+                        exit(0);
+                   }
+                   /*    Save the number of Adjacent Polygons to this edge */
+                   saved[x++] = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),face_id);
+              }
+         }
+               else if ((((*(temp->pPolygon) == id2) && (*(temp->pPolygon+size-1) == id3))) ||
+             (((*(temp->pPolygon) == id3) && (*(temp->pPolygon+size-1) == id2))) )
+             saved[x++] = -1;
+        else
+        {
+               if (x == 4)
+               {
+                    printf("There is an error in the check in quad \n");
+                    exit(0);
+               }
+               /*    Save the number of Adjacent Polygons to this edge */
+               saved[x++] = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+size-1),face_id);
+
+        }
+    }
+    if (x != 4)
+    {
+         printf("Did not enter all the values %d \n",x);
+         exit(0);
+    }
+    
+    *min = 10;
+    for (x=0; x<4; x++)
+    {
+         if (x!= 3)
+         {
+              if ((saved[x] != -1) && (saved[x+1] != -1) && 
+                   ((saved[x] + saved[x+1]) < *min))
+                   *min = saved[x] + saved[x+1];
+         }
+         else
+         {
+              if ((saved[0] != -1) && (saved[x] != -1) &&
+                   ((saved[x] + saved[0]) < *min))
+                   *min = saved[0] + saved[x];
+         }
+    }
+}
+
+
+
+int Get_Output_Edge(int face_id, int size, int *index,int id2,int id3)
+{
+    /*  Return the vertex adjacent to either input1 or input2 that
+        is adjacent to the least number of polygons on the edge that
+        is shared with either input1 or input2.
+    */
+    register int x=0,y;
+    int saved[2];
+    int edges[2][1];
+
+    for (y = 0; y < size; y++)
+    {
+        if (y != (size-1))
+        {
+            if (((*(index+y) == id2) && (*(index+y+1) != id3))
+                || ((*(index+y) == id3) && (*(index+y+1) != id2)))
+            {
+                saved[x++] = Number_Adj(*(index+y),*(index+y+1),face_id);
+                edges[x-1][0] = *(index+y+1);
+            }
+            else if (y != 0)
+            {
+                if (( (*(index+y) == id2) && (*(index+y-1) != id3) ) ||
+                    ( (*(index+y) == id3) && (*(index+y-1) != id2)) )
+                {
+                    saved[x++] = Number_Adj(*(index+y),*(index+y-1),face_id);
+                    edges[x-1][0] = *(index+y-1);
+                }
+            }
+            else if (y == 0)
+            {
+                if (( (*(index) == id2) && (*(index+size-1) != id3) ) ||
+                    ( (*(index) == id3) && (*(index+size-1) != id2)) )
+                {
+                    saved[x++] = Number_Adj(*(index),*(index+size-1),face_id);
+                    edges[x-1][0] = *(index+size-1);
+                }
+            }
+
+        }
+        else
+        {
+            if (((*(index+size-1) == id2) && (*(index) != id3))
+                || ((*(index+size-1) == id3) && (*(index) != id2)))
+            {
+                saved[x++] = Number_Adj(*(index),*(index+size-1),face_id);
+                edges[x-1][0] = *(index);
+            }
+
+            if (( (*(index+size-1) == id2) && (*(index+y-1) != id3) ) ||
+                    ( (*(index+size-1) == id3) && (*(index+y-1) != id2)) )
+                {
+                    saved[x++] = Number_Adj(*(index+size-1),*(index+y-1),face_id);
+                    edges[x-1][0] = *(index+y-1);
+                }
+        }
+    }
+    if ((x != 2))
+    {
+        printf("There is an error in getting the input edge %d \n",x);
+        exit(0);
+    }
+    if (saved[0] < saved[1])
+        return edges[0][0];
+    else
+        return edges[1][0];
+
+}
+
+void Get_Input_Edge(int *index,int id1,int id2,int id3,int *new1,int *new2,int size,
+                    int face_id)
+{
+    /*  We had a polygon without an input edge and now we are going to pick one
+        as the input edge. The last triangle was id1,id2,id3, we will try to
+        get an edge to have something in common with one of those vertices, otherwise
+        we will pick the edge with the least number of adjacencies.
+    */
+
+    register int x;
+    int saved[3];
+
+    saved[0] = -1;
+    saved[1] = -1;
+    saved[2] = -1;
+    
+    /*  Go through the edges to see if there is one in common with one
+        of the vertices of the last triangle that we had, preferably id2 or
+        id3 since those are the last 2 things in the stack of size 2.
+    */
+    for (x=0; x< size; x++)
+    {
+        if (*(index+x) == id1)
+        {
+            if (x != (size-1))
+                saved[0] = *(index+x+1);
+            else
+                saved[0] = *(index);
+        }
+
+        if (*(index+x) == id2)
+        {
+            if (x != (size-1))
+                saved[1] = *(index+x+1);
+            else
+                saved[1] = *(index);
+        }
+        
+        if (*(index+x) == id3)
+        {
+            if (x != (size -1))
+                saved[2] = *(index+x+1);
+            else
+                saved[2] = *(index);
+        }
+    }
+    /*  Now see what we saved */
+    if (saved[2] != -1)
+    {
+        *new1 = id3;
+        *new2 = saved[2];
+        return;
+    }
+    else if (saved[1] != -1)
+    {
+        *new1 = id2;
+        *new2 = saved[1];
+        return;
+    }
+    else if (saved[0] != -1)
+    {
+        *new1 = id1;
+        *new2 = saved[0];
+        return;
+    }
+    /*  We did not find anything so get the edge with the least number of adjacencies */
+    Edge_Least(index,new1,new2,face_id,size);
+
+}
+
+int Find_Face(int current_face, int id1, int id2, int *bucket)
+{
+       /*      Find the face that is adjacent to the edge and is not the
+               current face.
+       */
+       register int size,y,count=0;
+       PF_EDGES temp = NULL;
+       PF_FACES temp2 = NULL;
+       ListHead *pListHead;
+       int next_face;
+       BOOL there = FALSE;
+
+    
+    /* Always want smaller id first */
+       switch_lower(&id1,&id2);
+       
+       pListHead = PolEdges[id1];
+       temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     /*  The input edge was a new edge */
+     if (temp == NULL)
+        return -1;
+        
+     while (temp->edge[0] != id2)
+     {
+               count++;
+               temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+          /*  The input edge was a new edge */
+          if (temp == NULL)
+            return -1;
+     }
+       /*      Was not adjacent to anything else except itself */
+       if (temp->edge[2] == -1)
+               return -1;
+       else
+       {
+               if (temp->edge[2] == current_face)
+                       next_face =  temp->edge[1];
+               else 
+                       next_face = temp->edge[2];
+       }
+       /*      We have the other face adjacent to this edge, it is 
+               next_face. 
+       */
+       pListHead = PolFaces[next_face];
+       temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+               
+     /*        See if the face was already deleted, and where
+              it is if it was not
+     */
+               
+     if (Done(next_face,59,bucket) == NULL)
+        return -1;
+
+     /*  Make sure the edge is still in this polygon, and that it is not
+         done
+     */
+               /*      Size of the polygon */
+               size = temp2->nPolSize;
+               for (y = 0; y< size; y++)
+               {
+                       /*      Make sure that the edge is still in the
+                               polygon and was not deleted, because if the edge was
+                               deleted, then we used it already.
+                       */
+                       if (y != (size-1))
+                       {
+                               if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1)))
+                                       || ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1))))
+                                       /*      edge is still there we are ok */
+                                       there = TRUE;
+                       }
+                       else
+                       {               
+                               if( ((id1 == *(temp2->pPolygon)) && (id2 ==*(temp2->pPolygon+size-1)))
+                                       || ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1))))
+                                       /*      edge is still there we are ok */
+                                       there = TRUE;
+                       }
+               }
+               
+               if (!there)
+                       /*      Edge already used and deleted from the polygon*/
+                       return -1;
+         else
+            return next_face;
+}
+
+BOOL Look_Up(int id1,int id2,int face_id)
+{
+       /*      See if the endpoints of the edge specified by id1 and id2
+               are adjacent to the face with face_id 
+       */
+       register int count = 0;
+       PF_EDGES temp  = NULL;
+       ListHead *pListHead;
+               
+       /*      Always want smaller id first */
+       switch_lower(&id1,&id2);
+
+       pListHead = PolEdges[id1];
+       temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     if (temp == NULL)
+     /*        Was a new edge that we created */
+               return 0;
+       
+       while (temp->edge[0] != id2)
+     {
+               count++;
+               temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+          if (temp == NULL)
+                       /*      Was a new edge that we created */
+                       return 0;
+     }
+       /*      Was not adjacent to anything else except itself */
+       if ((temp->edge[2] == face_id) || (temp->edge[1] == face_id))
+       {
+               /*      Edge was adjacent to face, make sure that edge is 
+                       still there
+               */
+               if (Exist(face_id,id1,id2))
+                       return 1;
+               else
+                       return 0;
+       }
+       else
+               return 0;
+}
+
+
+void Add_Id_Strips(int id, int where)
+{
+     /*    Just save the triangle for later  */
+     P_STRIPS pfNode;
+
+       pfNode = (P_STRIPS) malloc(sizeof(Strips) );
+       if ( pfNode )
+       {
+            pfNode->face_id = id;
+            if (where == 1)
+                AddTail(strips[0],(PLISTINFO) pfNode);
+            /* We are backtracking in the strip */
+            else
+                AddHead(strips[0],(PLISTINFO) pfNode);
+       }
+       else
+       {
+            printf("There is not enough memory to allocate for the strips\n");
+            exit(0);
+       }
+}
+
+
+int Num_Adj(int id1, int id2)
+{
+       /*   Given edge whose endpoints are specified by id1 and id2,
+               determine how many polygons share this edge and return that
+               number minus one (since we do not want to include the polygon
+               that the caller has already).
+       */
+
+       PF_EDGES temp = NULL;
+       ListHead *pListHead;
+       register count=-1;
+
+       /*      Always want smaller id first */
+       switch_lower(&id1,&id2);
+       
+       pListHead = PolEdges[id1];
+       temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     if (temp == NULL)
+       {
+               printf("There is an error in the creation of the table \n");
+               exit(0);
+       }
+       while (temp->edge[0] != id2)
+     {
+               count++;
+               temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+            if (temp == NULL)
+               {
+                       printf("There is an error in the creation of the table\n");
+                       exit(0);
+               }
+       }
+       /*      Was not adjacent to anything else except itself */
+       if (temp->edge[2] == -1)
+               return 0;
+       return 1;
+}
+
+
+void Add_Sgi_Adj(int bucket,int face_id)
+{
+       /*   This routine will add the face to the proper bucket,
+               depending on how many faces are adjacent to it (what the
+               value bucket should be).
+       */
+       P_ADJACENCIES pfNode;
+
+       pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+     if ( pfNode )
+     {
+               pfNode->face_id = face_id;
+            AddHead(array[bucket],(PLISTINFO) pfNode);
+       }
+       else
+       {
+               printf("Out of memory for the SGI adj list!\n");
+               exit(0);
+       }
+}
+
+void Find_Adjacencies(int num_faces)
+{
+     register int      x,y;
+     register int      numverts;
+     PF_FACES temp=NULL;
+     ListHead *pListHead;
+
+       /*   Fill in the adjacencies data structure for all the faces */
+     for (x=0;x<num_faces;x++)
+       {
+               pListHead = PolFaces[x];
+               temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+       if ( temp != NULL )
+               {
+                       numverts = temp->nPolSize;
+                       if (numverts != 1)
+               {
+                    for (y = 0; y< numverts; y++)
+                            {
+                                    if (y != (numverts-1))
+                                            Add_AdjEdge(*(temp->pPolygon+y),*(temp->pPolygon+y+1),x,y);
+                       
+                                    else 
+                                            Add_AdjEdge(*(temp->pPolygon),*(temp->pPolygon+(numverts-1)),x,numverts-1);
+                       
+                    }
+               }
+                       temp = NULL;
+               }
+       }
+}
+
+
diff --git a/Stripe_w/common.h b/Stripe_w/common.h
new file mode 100644 (file)
index 0000000..aca1982
--- /dev/null
@@ -0,0 +1,42 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: common.h
+-----------------------------------------------------------------------*/
+
+void Add_AdjEdge(int v1,int v2,int fnum,int index1 );
+void Find_Adjacencies(int num_faces);
+void Add_Sgi_Adj(int bucket,int face_id);
+int Num_Adj(int id1, int id2);
+void Add_Id_Strips(int id, int where);
+BOOL Look_Up(int id1,int id2,int face_id);
+int Number_Adj(int id1, int id2, int curr_id);
+int  Old_Adj(int face_id);
+int Min_Adj(int id);
+int Find_Face(int current_face, int id1, int id2, int *bucket);
+void Edge_Least(int *index,int *new1,int *new2,int face_id,int size);
+void Get_Input_Edge(int *index,int id1,int id2,int id3,int *new1,int *new2,
+                   int size, int face_id);
+int Get_Output_Edge(int face_id, int size, int *index,int id2,int id3);
+void Check_In_Polygon(int face_id, int *min, int size);
+void  Check_In_Quad(int face_id,int *min);
+void New_Size_Face (int face_id);
+void New_Face (int face_id, int v1, int v2, int v3);
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Stripe_w/extend.h b/Stripe_w/extend.h
new file mode 100644 (file)
index 0000000..78c135e
--- /dev/null
@@ -0,0 +1,17 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: extend.h
+-----------------------------------------------------------------------*/
+
+int Bottom_Left();
+int Top_Left();
+void Start_Edge();
+
+
diff --git a/Stripe_w/free.c b/Stripe_w/free.c
new file mode 100644 (file)
index 0000000..ad655fc
--- /dev/null
@@ -0,0 +1,112 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: free.c
+     This file contains the code used to free the data structures.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "polverts.h"
+
+ListHead *array[60];
+int     id_array[60];
+ListHead *strips[1];
+ListHead *all_strips[100000]; /*  Assume max 100000 strips */
+
+void ParseAndFreeList( ListHead *pListHead )
+{
+    register int c,num;
+         
+    /*    Freeing a linked list */
+    num = NumOnList(pListHead);
+    for (c = 0; c< num; c++)
+            RemHead(pListHead);
+} 
+
+void FreePolygonNode( PF_VERTS pfVerts)
+{
+       /*   Free a vertex node */
+     if ( pfVerts->pPolygon )
+               free( pfVerts->pPolygon );
+       free( pfVerts );
+
+}
+void Free_Strips()
+{
+    /*    Free strips data structure */
+    if (strips[0] == NULL)
+         return;
+    else
+         ParseAndFreeList(strips[0]);
+}
+
+void FreeFaceNode( PF_FACES pfFaces)
+{
+       /*   Free face node */
+     if ( pfFaces->pPolygon )
+                free( pfFaces->pPolygon );
+        free( pfFaces );
+}
+
+
+void FreeFaceTable(int nSize)
+{
+     register int nIndex;
+
+     for ( nIndex=0; nIndex < nSize; nIndex++ )
+     { 
+               if ( PolFaces[nIndex] != NULL ) 
+             ParseAndFreeList( PolFaces[nIndex] );
+     }
+     free( PolFaces );
+}
+
+void FreeEdgeTable(int nSize)
+{
+        register int nIndex;
+
+        for ( nIndex=0; nIndex < nSize; nIndex++ )
+        {
+                if ( PolEdges[nIndex] != NULL )
+                        ParseAndFreeList( PolEdges[nIndex] );
+        }
+        free( PolEdges );
+}
+
+
+void Free_All_Strips()
+{
+
+       ListHead *pListHead;
+       register int y;
+
+       for (y =0; ; y++)
+       {
+               pListHead = all_strips[y];
+               if (pListHead == NULL)
+                       return;
+               else
+                       ParseAndFreeList(all_strips[y]);
+       }
+}
+
+void End_Face_Struct(int numfaces)
+{
+     FreeFaceTable(numfaces);
+}
+
+void End_Edge_Struct(int numverts)
+{
+     FreeEdgeTable(numverts);
+}      
+
+
diff --git a/Stripe_w/free.h b/Stripe_w/free.h
new file mode 100644 (file)
index 0000000..4c1d055
--- /dev/null
@@ -0,0 +1,22 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: free.h
+-----------------------------------------------------------------------*/
+
+void Free_All_Strips();
+void ParseAndFreeList( ListHead *pListHead );
+void FreePolygonNode( PF_VERTS pfVerts);
+void Free_Strips();
+void FreeFaceTable(int nSize);
+void FreeEdgeTable(int nSize);
+void End_Face_Struct(int numfaces);
+void End_Edge_Struct(int numverts);
+
+
diff --git a/Stripe_w/global.h b/Stripe_w/global.h
new file mode 100644 (file)
index 0000000..3538f82
--- /dev/null
@@ -0,0 +1,44 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: global.h
+-----------------------------------------------------------------------*/
+
+#ifndef _GLOBAL_H
+#define _GLOBAL_H
+
+
+#define   VRDATA               double
+#define   STRIP_MAX            60
+       
+#define        TRUE            1
+#define        FALSE           0
+
+#ifndef PI
+#define   PI           3.1415926573
+#endif
+
+#define   ATOI(C)        (C -'0')
+#define   X              0
+#define   Y              1
+#define   Z              2
+#define   EVEN(x)       (((x) & 1) == 0)
+#define   MAX_BAND      10000
+
+struct vert_struct {
+       VRDATA  x, y, z;        /* point coordinates */
+};
+
+extern int     ids[STRIP_MAX];
+extern int     norms[STRIP_MAX];
+extern int     *vert_norms;
+extern int     *vert_texture;
+
+
+#endif _GLOBAL_H
diff --git a/Stripe_w/init.c b/Stripe_w/init.c
new file mode 100644 (file)
index 0000000..2e0f258
--- /dev/null
@@ -0,0 +1,217 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: init.c
+     This file contains the initialization of data structures.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "global.h"
+#include "polverts.h"
+
+void init_vert_norms(int num_vert)
+{
+     /*   Initialize vertex/normal array to have all zeros to
+          start with.
+     */
+     register int x;
+
+     for (x = 0; x < num_vert; x++)
+          *(vert_norms + x) = 0;
+}
+
+void init_vert_texture(int num_vert)
+{
+     /*   Initialize vertex/normal array to have all zeros to
+          start with.
+     */
+     register int x;
+
+     for (x = 0; x < num_vert; x++)
+          *(vert_texture + x) = 0;
+}
+
+BOOL InitVertTable( int nSize )
+{
+     register int nIndex;
+
+       /*   Initialize the vertex table */
+     PolVerts = (ListHead**) malloc(sizeof(ListHead*) * nSize ); 
+       if ( PolVerts )
+       {
+               for ( nIndex=0; nIndex < nSize; nIndex++ )
+               {
+                       PolVerts[nIndex] = NULL;
+               }
+               return( TRUE ); 
+       }
+       return( FALSE );
+}  
+
+BOOL InitFaceTable( int nSize )
+{
+        register int nIndex;
+
+        /*     Initialize the face table */
+        PolFaces = (ListHead**) malloc(sizeof(ListHead*) * nSize ); 
+        if ( PolFaces )
+        {
+                for ( nIndex=0; nIndex < nSize; nIndex++ )
+                {
+                        PolFaces[nIndex] = NULL;
+                }
+                return( TRUE );
+        }
+        return( FALSE );
+} 
+
+BOOL InitEdgeTable( int nSize )
+{
+        register int nIndex;
+
+        /*     Initialize the edge table */
+        PolEdges = (ListHead**) malloc(sizeof(ListHead*) * nSize );
+        if ( PolEdges )
+        {
+                for ( nIndex=0; nIndex < nSize; nIndex++ )
+                {
+                        PolEdges[nIndex] = NULL;
+                }
+                return( TRUE );
+        }
+        return( FALSE );
+}
+
+
+void InitStripTable(  )
+{
+
+     PLISTHEAD pListHead;
+
+     /*   Initialize the strip table */
+     pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
+       if ( pListHead )
+     {
+               InitList( pListHead );
+               strips[0] = pListHead;
+       }
+     else
+       {
+            printf("Out of memory !\n");
+               exit(0);
+       }
+
+}
+
+void Init_Table_SGI()
+{
+       PLISTHEAD pListHead;
+       int max_adj = 60;
+       register int x;
+       
+       /*   This routine will initialize the table that will
+               have the faces sorted by the number of adjacent polygons
+               to it.
+       */
+
+       for (x=0; x< max_adj; x++)
+       {
+               /* We are allowing the max number of sides of a polygon
+       to be max_adj.
+               */                      
+               pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
+               if ( pListHead )
+         {
+                 InitList( pListHead );
+                       array[x] = pListHead;
+               }
+    else
+               {
+                 printf("Out of memory !\n");
+                       exit(0);
+               }
+       }
+}
+
+void BuildVertTable( int nSize )
+{
+  register int nIndex;
+  PLISTHEAD pListHead;
+       
+       for ( nIndex=0; nIndex < nSize; nIndex++ )
+       {
+               pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
+               if ( pListHead )
+    {
+                       InitList( pListHead );
+                       PolVerts[nIndex] = pListHead;
+               }
+    else
+      return;  
+               
+       }
+}
+   
+
+void BuildFaceTable( int nSize )
+{
+        register int nIndex;
+        PLISTHEAD pListHead;
+        
+        for ( nIndex=0; nIndex < nSize; nIndex++ )
+        {
+                pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
+                if ( pListHead )
+                {
+                        InitList( pListHead );
+                        PolFaces[nIndex] = pListHead;
+                }
+                else
+                        return; 
+                
+        }
+}
+   
+void BuildEdgeTable( int nSize )
+{
+        register int nIndex;
+        PLISTHEAD pListHead;
+
+        for ( nIndex=0; nIndex < nSize; nIndex++ )
+        {
+                pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
+                if ( pListHead )
+                {
+                        InitList( pListHead );
+                        PolEdges[nIndex] = pListHead;
+                }
+                else
+                        return;
+        }
+}
+
+void Start_Face_Struct(int numfaces)
+{
+       if (InitFaceTable(numfaces))
+       {
+               BuildFaceTable(numfaces);
+       }
+}
+
+void Start_Edge_Struct(int numverts)
+{
+        if (InitEdgeTable(numverts))
+        {
+                BuildEdgeTable(numverts);
+        }
+}
+
+
diff --git a/Stripe_w/init.h b/Stripe_w/init.h
new file mode 100644 (file)
index 0000000..fe9a05f
--- /dev/null
@@ -0,0 +1,30 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: init.h
+-----------------------------------------------------------------------*/
+
+void init_vert_norms(int num_vert);
+void init_vert_texture(int num_vert);
+BOOL InitVertTable( int nSize );
+BOOL InitFaceTable( int nSize );
+BOOL InitEdgeTable( int nSize );
+void InitStripTable(  );
+void Init_Table_SGI();
+void BuildVertTable( int nSize );
+void BuildFaceTable( int nSize );
+void BuildEdgeTable( int nSize );
+void Start_Face_Struct(int numfaces);
+void Start_Edge_Struct(int numverts);
+
+
+
+
+
+
diff --git a/Stripe_w/local.c b/Stripe_w/local.c
new file mode 100644 (file)
index 0000000..3f3e69d
--- /dev/null
@@ -0,0 +1,119 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: local.c
+     This file contains the code that initializes the data structures for
+     the local algorithm, and starts the local algorithm going.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "polverts.h"
+#include "local.h"
+#include "triangulatex.h"
+#include "sturctsex.h"
+#include "common.h"
+#include "outputex.h"
+#include "util.h"
+#include "init.h"
+
+void Find_StripsEx(FILE *output, FILE *strip,int *ties, int tie, 
+                  int triangulate, int swaps, int *next_id)
+{
+       /*      This routine will peel off the strips from the model */
+
+       ListHead *pListHead;
+       P_ADJACENCIES temp = NULL;
+       register int max,bucket=0;
+       BOOL whole_flag = TRUE;
+     int dummy = 0;
+       
+       /* Set the last known input edge to be null */
+  Last_Edge(&dummy,&dummy,&dummy,1);
+    
+  /* Search for lowest adjacency polygon and output strips */
+       while (whole_flag)
+       {
+               bucket = -1;
+               /* Search for polygons in increasing number of adjacencies */
+               while (bucket < 59)
+               {
+                       bucket++;
+                       pListHead = array[bucket];
+                       max = NumOnList(pListHead);
+                       if (max > 0)
+                       {
+                               temp = (P_ADJACENCIES) PeekList(pListHead,LISTHEAD,0);
+                               if (temp == NULL)
+                               {
+                                       printf("Error in the buckets%d %d %d\n",bucket,max,0);
+                                       exit(0);
+                               }
+                               Polygon_OutputEx(temp,temp->face_id,bucket,pListHead,
+                                              output,strip,ties,tie,triangulate,swaps,next_id,1);
+                               /* Try to extend backwards, if the starting polygon in the
+           strip had 2 or more adjacencies to begin with
+        */
+        if (bucket >= 2)
+          Extend_BackwardsEx(temp->face_id,output,strip,ties,tie,triangulate,swaps,next_id);
+        break;  
+                       }
+               }
+               /*      Went through the whole structure, it is empty and we are done.
+               */
+               if ((bucket == 59) && (max == 0))
+                       whole_flag = FALSE;
+        
+    /*  We just finished a strip, send dummy data to signal the end
+        of the strip so that we can output it.
+    */
+    else
+    {
+      Output_TriEx(-1,-2,-3,output,-1,-10,1);
+      Last_Edge(&dummy,&dummy,&dummy,1);
+    }
+  }
+}
+
+
+void SGI_Strip(int num_verts,int num_faces,FILE *output,
+                          int ties,int triangulate)
+               
+{
+       FILE *strip;
+  int next_id = -1,t=0;
+
+  strip = fopen("output.d","w");
+  /* We are going to output and find triangle strips
+        according the the method that SGI uses, ie always
+                choosing as the next triangle in our strip the triangle
+                that has the least number of adjacencies. We do not have
+                all triangles and will be triangulating on the fly those
+                polygons that have more than 3 sides.
+       */
+
+       /*      Build a table that has all the polygons sorted by the number
+               of polygons adjacent to it.
+       */
+       /*      Initialize it */
+       Init_Table_SGI();
+       /*      Build it */
+       Build_SGI_Table(num_verts,num_faces);
+
+       /*    We will have a structure to hold all the strips, until
+        outputted.
+  */
+  InitStripTable();
+  /* Now we have the structure built to find the polygons according
+                to the number of adjacencies. Now use the SGI Method to find
+                strips according to the adjacencies
+       */
+  Find_StripsEx(output,strip,&t,ties,triangulate,ON,&next_id);
+}
diff --git a/Stripe_w/local.h b/Stripe_w/local.h
new file mode 100644 (file)
index 0000000..df5256f
--- /dev/null
@@ -0,0 +1,20 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE:local.h
+-----------------------------------------------------------------------*/
+
+void Local_Polygon_Output();
+void Local_Output_Tri();
+int Different();
+void Local_Non_Blind_Triangulate();
+void Local_Blind_Triangulate();
+void Local_Triangulate_Polygon();
+void SGI_Strip(int num_verts,int num_faces,FILE *output,
+              int ties,int triangulate);
diff --git a/Stripe_w/newpolve.c b/Stripe_w/newpolve.c
new file mode 100644 (file)
index 0000000..6267bbc
--- /dev/null
@@ -0,0 +1,1659 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: newpolve.c
+     This routine contains the bulk of the code that will find the
+     patches of quads in the data model
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include "polverts.h"
+#include "extend.h"
+#include "output.h"
+#include "triangulate.h"
+#include "common.h"
+#include "util.h"
+#include "global.h"        
+#include "init.h"
+#include "add.h"
+
+ListHead **PolVerts;
+ListHead **PolFaces;
+ListHead **PolEdges;
+int length;
+BOOL resetting = FALSE;
+int     ids[STRIP_MAX];
+int    added_quad = 0;
+BOOL reversed = FALSE;
+int patch = 0;
+extern int *vn;
+extern int *vt;
+
+int Calculate_Walks(int lastvert,int y, PF_FACES temp2)
+{
+       /* Find the length of the walk */
+       
+       int previous_edge1, previous_edge2;
+       register int nextvert,numverts,counter,walk=0;
+       BOOL flag;
+       F_EDGES *node;
+     ListHead *pListHead;
+     static int seen = 0;
+     
+       /* Find the edge that we are currently on */
+       if (y != 3)
+       {
+               previous_edge1 = *(temp2->pPolygon +y);
+               previous_edge2 = *(temp2->pPolygon + y + 1);
+       }
+       else
+       {
+               previous_edge1 = *(temp2->pPolygon +y);
+               previous_edge2 = *(temp2->pPolygon);
+       }
+
+       temp2->seen = seen;
+     counter = y;
+
+     /*Find the adjacent face to this edge */
+       node = *(temp2->VertandId+y);                   
+       if (node->edge[2] != lastvert)
+        nextvert = node->edge[2];
+     else
+        nextvert = node->edge[1];
+                                       
+       /* Keep walking in this direction until we cannot do so */
+       while ((nextvert != lastvert) && (nextvert != -1))
+       {
+               walk++;
+               pListHead = PolFaces[nextvert];
+               temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+               numverts = temp2->nPolSize;
+               if ((numverts != 4) || (temp2->seen == seen))
+               {
+                       walk--;
+                       nextvert = -1;
+               }
+               else
+               {
+                       temp2->seen = seen;
+               /* Find edge that is not adjacent to the previous one */
+                       counter = 0;
+                       flag = TRUE;
+                       while ((counter < 3) && (flag))
+                       {
+                               if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
+                                       (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
+                                       ((*(temp2->pPolygon+counter) == previous_edge2) || 
+                                       (*(temp2->pPolygon+counter+1) == previous_edge1)) )
+                                       counter++;              
+                               else
+                                       flag = FALSE;   
+                       }
+               /* Get the IDs of the next edge */
+                    if (counter < 3)
+                    {
+                            previous_edge1 = *(temp2->pPolygon + counter);
+                            previous_edge2 = *(temp2->pPolygon + counter + 1);
+                    }
+                    else
+                    {
+                    previous_edge1 = *(temp2->pPolygon + counter);
+                    previous_edge2 = *(temp2->pPolygon);
+                    }
+       
+                    node = *(temp2->VertandId + counter);
+                    if (node->edge[1] == nextvert)
+                            nextvert = node->edge[2];
+                    else
+                            nextvert = node->edge[1];
+               }
+       }
+     seen++;
+       return walk;
+}
+
+
+BOOL Check_Right(int last_seen,PF_FACES temp2,int y,int face_id)
+{
+       /* Check when we last saw the face to the right of the current
+          one. We want to have seen it just before we started this strip
+       */
+
+       F_EDGES *node;
+       ListHead *pListHead;
+       register int nextvert,oldy;
+       PF_FACES t;
+       
+     oldy = y;
+       if (y != 3)
+               y = y+1;
+       else
+               y = 0;
+       node = *(temp2->VertandId + y);
+       if (face_id == node->edge[1])
+               nextvert = node->edge[2];
+       else
+               nextvert = node->edge[1];
+       
+     if (nextvert == -1)
+          return FALSE;
+     
+     pListHead = PolFaces[nextvert];
+       t = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+       if (t->seen != (last_seen - 1))
+       {
+                /* maybe because of the numbering, we are not
+                   on the right orientation, so we have to check the
+                   opposite one to be sure 
+           */
+               if (oldy != 0)
+                       y = oldy-1;
+               else
+                       y = 3;
+               node = *(temp2->VertandId + y);
+               if (face_id == node->edge[1])
+                       nextvert = node->edge[2];
+               else
+                       nextvert = node->edge[1];
+               if (nextvert == -1)
+               return FALSE;
+          pListHead = PolFaces[nextvert];
+               t = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+               if (t->seen != (last_seen - 1))
+                       return FALSE;
+       }
+       return TRUE;
+}
+
+
+int Update_and_Test(PF_FACES temp2,int y,BOOL first,int distance,int lastvert, int val)
+{
+            
+        static int last_seen = 17;
+        int previous_edge1, previous_edge2;
+        register int original_distance,nextvert,numverts,counter;
+        BOOL flag;
+        F_EDGES *node;
+        ListHead *pListHead;
+                                                        
+        original_distance = distance;
+        /* Find the edge that we are currently on */
+        if (y != 3)
+        {
+                previous_edge1 = *(temp2->pPolygon +y);
+                previous_edge2 = *(temp2->pPolygon + y + 1);
+        }
+        else
+        {
+                previous_edge1 = *(temp2->pPolygon +y);
+                previous_edge2 = *(temp2->pPolygon);
+        }
+
+        temp2->seen = val;
+        temp2->seen2 = val;
+               
+        node = *(temp2->VertandId+y);                   
+        if (lastvert != node->edge[2])
+                       nextvert = node->edge[2];
+          else
+                       nextvert = node->edge[1];
+                                        
+        /* Keep walking in this direction until we cannot do so  or
+               we go to distance */
+        while ((distance > 0)  && (nextvert != lastvert) && (nextvert != -1))
+        {
+                distance--;
+                                  
+                pListHead = PolFaces[nextvert];
+                temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+                temp2->seen = val;
+                               
+                if (temp2->seen2 == val)
+                {
+                     last_seen++;
+                     return (original_distance - distance);
+                }
+                
+                temp2->seen2 = val;
+                
+                numverts = temp2->nPolSize;
+                                
+                if (numverts != 4)
+                    nextvert = -1;
+               
+                else if ((!first) && (!(Check_Right(last_seen,temp2,y,nextvert))))
+                {
+                    last_seen++;
+                    return (original_distance - distance);
+                }
+                     else
+                {
+                        /* Find edge that is not adjacent to the previous one */
+                        counter = 0;
+                        flag = TRUE;
+                        while ((counter < 3) && (flag))
+                        {
+                                if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
+                                        (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
+                                        ((*(temp2->pPolygon+counter) == previous_edge2) ||
+                                        (*(temp2->pPolygon+counter+1) == previous_edge1)) )
+                                        counter++;
+                                else
+                                        flag = FALSE;
+                        }
+                        /* Get the IDs of the next edge */
+                        if (counter < 3)
+                        {
+                              previous_edge1 = *(temp2->pPolygon + counter);
+                              previous_edge2 = *(temp2->pPolygon + counter + 1);
+                        }
+                        else
+                        {
+                              previous_edge1 = *(temp2->pPolygon + counter);
+                              previous_edge2 = *(temp2->pPolygon);
+                        }
+                        if      ( ((*(temp2->walked+counter) == -1) && 
+                                (*(temp2->walked+counter+2) == -1)))
+                        {
+                                printf("There is an error in the walks!\n");
+                                printf("1Code %d %d \n",*(temp2->walked+counter),*(temp2->walked+counter+2));
+                                exit(0);
+                        }
+                        else
+                        {
+                                if      ((*(temp2->walked+counter) == -1) && 
+                                        (*(temp2->walked+counter-2) ==  -1))
+                                {
+                                        printf("There is an error in the walks!\n");
+                                        printf("2Code %d %d \n",*(temp2->walked+counter),*(temp2->walked+counter-2));
+                                        exit(0);
+                                }
+                        }
+                        node = *(temp2->VertandId + counter);
+                        y = counter;
+                             if (node->edge[1] == nextvert)
+                              nextvert = node->edge[2];
+                        else
+                              nextvert = node->edge[1];
+             }
+    }
+       
+    last_seen++;
+
+    if  (distance != 0)  
+    {
+               if (((nextvert == -1) || (nextvert == lastvert)) && (distance != 1))
+                       return (original_distance - distance);
+    }
+    return original_distance;
+}
+
+
+int Test_Adj(PF_FACES temp2,int x,int north,int distance,int lastvert, int value)
+{
+       /* if first time, then just update the last seen field */
+       if (x==1)
+               return(Update_and_Test(temp2,north,TRUE,distance,lastvert,value));
+       /* else we have to check if we are adjacent to the last strip */
+       else
+               return(Update_and_Test(temp2,north,FALSE,distance,lastvert,value));
+}
+  
+void Get_Band_Walk(PF_FACES temp2,int face_id,int *dir1,int *dir2, 
+                                       int orientation,int cutoff_length)
+{
+       int previous_edge1, previous_edge2;
+       F_EDGES *node;
+       ListHead *pListHead;
+       register int walk = 0, nextvert,numverts,counter;
+       BOOL flag;
+       
+       /*      Get the largest band that will include this face, starting
+               from orientation. Save the values of the largest band
+               (either north and south together, or east and west together)
+               in the direction variables.
+       */
+       /* Find the edge that we are currently on */
+     if (orientation != 3)
+     {
+                previous_edge1 = *(temp2->pPolygon + orientation);
+                previous_edge2 = *(temp2->pPolygon + orientation + 1);
+     }
+     else
+     {
+                previous_edge1 = *(temp2->pPolygon + orientation );
+                previous_edge2 = *(temp2->pPolygon);
+     }
+               
+     if (orientation == 0)
+     {
+                        if (*dir1 > *(temp2->walked + 1))
+                               *dir1 = *(temp2->walked + 1);
+                        if (*dir2 > *(temp2->walked + 3))
+                               *dir2 = *(temp2->walked + 3);
+       }
+       else if (orientation == 3)
+       {
+                       if (*dir1 > *(temp2->walked + orientation - 3))
+                            *dir1 = *(temp2->walked + orientation - 3) ;
+                       if (*dir2 > *(temp2->walked + orientation -1 ))
+                               *dir2 = *(temp2->walked + orientation - 1);
+       }
+       else
+       {
+                       if (*dir1 > *(temp2->walked + orientation - 1))
+                               *dir1 = *(temp2->walked + orientation -1) ;
+                       if (*dir2 > *(temp2->walked+ orientation + 1))
+                               *dir2 = *(temp2->walked + orientation + 1);
+       }
+        
+     /*        if we know already that we can't extend the
+               band from this face, we do not need to do the walk
+     */
+     if ((*dir1 != 0) && (*dir2 != 0))
+     {
+               /* Find the adjacent face to this edge */
+               node = *(temp2->VertandId+orientation);                   
+               if (face_id == node->edge[1])
+                       nextvert = node->edge[2];
+               else 
+                       nextvert = node->edge[1];
+       }
+     else
+               nextvert = -1; /* leave w/o walking */                                
+       
+       /* Keep walking in this direction until we cannot do so */
+     while ((nextvert != face_id) && (nextvert != -1))
+     {
+            walk++;
+            pListHead = PolFaces[nextvert];
+            temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+            numverts = temp2->nPolSize;
+            if ((numverts != 4)        || (walk > cutoff_length))
+                   nextvert = -1;
+            else
+            {
+                         /* Find edge that is not adjacent to the previous one */
+                 counter = 0;
+                 flag = TRUE;
+                 while ((counter < 3) && (flag))
+                 {
+                           if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
+                                (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
+                                ((*(temp2->pPolygon+counter) == previous_edge2) ||
+                                (*(temp2->pPolygon+counter+1) == previous_edge1)) )
+                                     counter++;
+                           else
+                                flag = FALSE;
+                 }
+                 /* Get the IDs of the next edge */
+                 if (counter < 3)
+                 {
+                        previous_edge1 = *(temp2->pPolygon + counter);
+                        previous_edge2 = *(temp2->pPolygon + counter + 1);
+                 }
+                 else
+                 {
+                        previous_edge1 = *(temp2->pPolygon + counter);
+                        previous_edge2 = *(temp2->pPolygon);
+                 }
+                
+                         /*    find out how far we can extend in the 2 directions
+                                       along this new face in the walk
+                         */
+                         if (counter == 0)
+                         {
+                                       if (*dir1 > *(temp2->walked + 1))
+                                               *dir1 = *(temp2->walked + 1);
+                                       if (*dir2 > *(temp2->walked + 3))
+                                               *dir2 = *(temp2->walked + 3);
+                         }
+                         else if (counter == 3)
+                         {
+                                       if (*dir1 > *(temp2->walked + counter - 3))
+                                               *dir1 = *(temp2->walked + counter - 3) ;
+                                       if (*dir2 > *(temp2->walked + counter -1 ))
+                                               *dir2 = *(temp2->walked + counter -1);
+                         }
+                         else
+                         {
+                                       if (*dir1 > *(temp2->walked + counter - 1))
+                                               *dir1 = *(temp2->walked + counter -1) ;
+                                       if (*dir2 > *(temp2->walked + counter + 1))
+                                               *dir2 = *(temp2->walked + counter + 1);
+                         }
+        
+                     /*        if we know already that we can't extend the
+                       band from this face, we do not need to do the walk
+                     */
+                        if ((*dir1 == 0) || (*dir2 == 0))
+                       nextvert = -1;
+                if (nextvert != -1)
+                {
+                       node = *(temp2->VertandId + counter);
+                       if (node->edge[1] == nextvert)
+                        nextvert = node->edge[2];
+                       else
+                        nextvert = node->edge[1];
+                }
+
+           }
+        }
+}
+
+
+
+
+int Find_Max(PF_FACES temp2,int lastvert,int north,int left,
+                       int *lastminup,int *lastminleft)
+{
+       int temp,walk,counter,minup,x,band_value;
+       int previous_edge1, previous_edge2;
+       F_EDGES *node;
+       ListHead *pListHead;
+       BOOL flag;      
+       static int last_seen = 0;
+       register int smallest_so_far,nextvert,max=-1;
+               
+     *lastminup = MAX_BAND;
+       *lastminleft = 1;
+
+     if (left == 3)
+       {
+          previous_edge1 = *(temp2->pPolygon + left);
+          previous_edge2 = *(temp2->pPolygon);
+       }
+                
+       else
+       {
+          previous_edge1 = *(temp2->pPolygon + left + 1);
+          previous_edge2 = *(temp2->pPolygon + left);
+       }
+
+       temp2->seen = last_seen;
+     walk = *(temp2->walked + left);
+
+     for (x=1;x<=(walk+1); x++)
+       {
+               /*   test to see if we have a true band
+                    that is, are they adjacent to each other
+               */
+        
+         minup = *(temp2->walked + north) + 1;
+
+           /*  if we are at the very first face, then we do not
+                    have to check the adjacent faces going up
+                    and our north distance is the distance of this face's
+                       north direction. 
+           */
+         if (x == 1) 
+           {
+                       *lastminup = minup;
+                       minup = Test_Adj(temp2,x,north,*lastminup,lastvert,last_seen);
+                       *lastminup = minup;
+               smallest_so_far = minup;        
+         }
+               
+       
+           /* find the largest band that we can have */
+           if (minup < (*lastminup))
+           {
+                       /*      see if we really can go up all the way 
+                               temp should by less than our equal to minup
+                               if it is less, then one of the faces was not
+                               adjacent to those next to it and the band height
+                               will be smaller
+                       */
+                       temp = Test_Adj(temp2,x,north,minup,lastvert,last_seen);
+                       if (temp > minup)
+                       {
+                               printf("There is an error in the test adj\n");
+                               exit(0);
+                       }
+                       minup = temp;
+                       band_value = x * minup;
+                       if (minup < smallest_so_far)
+                       {
+                               if (band_value > max)
+                       {
+                                       smallest_so_far = minup;
+                                       *lastminup = minup;
+                                       *lastminleft = x;
+                         max = band_value;
+                    }
+                               else
+                                       smallest_so_far = minup;
+                       }
+                       else
+                       {
+                               band_value = x * smallest_so_far;
+                 if (band_value > max)
+                    {
+                            *lastminup = smallest_so_far;
+                         *lastminleft = x;
+                         max = band_value;
+                    }
+                       }
+               }
+               else
+               {
+                       if (x != 1)
+               {
+                    temp = Test_Adj(temp2,x,north,smallest_so_far,lastvert,last_seen);
+                            if (temp > smallest_so_far)
+                            {
+                                   printf("There is an error in the test adj\n");
+                                   exit(0);
+                            }
+                           smallest_so_far = temp;
+               }
+               band_value = x * smallest_so_far; 
+                       if (band_value > max)
+                       {
+                               *lastminup = smallest_so_far;
+                               *lastminleft = x;
+                               max = band_value;
+                       }
+               }
+               if ( x != (walk + 1))
+               {
+                       node = *(temp2->VertandId+left);
+                       if (lastvert == node->edge[1])
+                               nextvert = node->edge[2];
+                       else
+                               nextvert = node->edge[1];
+
+               lastvert = nextvert;
+               
+               if (nextvert == -1)
+                    return max;
+               
+               pListHead = PolFaces[nextvert];
+                       temp2 = (PF_FACES) PeekList(pListHead, LISTHEAD, 0);
+                       
+               /* if we have visited this face before, then there is an error */
+               if (((*(temp2->walked) == -1) && (*(temp2->walked+1) == -1) &&
+                               (*(temp2->walked+2) == -1) && (*(temp2->walked+3) == -1))
+                               || (temp2->nPolSize !=4) || (temp2->seen == last_seen))
+                       {
+
+                    if (lastvert == node->edge[1])
+                         nextvert = node->edge[2];
+                    else
+                         nextvert = node->edge[1];
+                    if (nextvert == -1)
+                         return max;
+                    lastvert = nextvert;
+                    /*   Last attempt to get the face ... */
+                    pListHead = PolFaces[nextvert];
+                       temp2 = (PF_FACES) PeekList(pListHead, LISTHEAD, 0);
+                    if (((*(temp2->walked) == -1) && (*(temp2->walked+1) == -1) &&
+                                    (*(temp2->walked+2) == -1) && (*(temp2->walked+3) == -1))
+                                    || (temp2->nPolSize !=4) || (temp2->seen == last_seen))
+                         return max;    /*   The polygon was not saved with the edge, not
+                                             enough room. We will get the walk when we come
+                                             to that polygon later.
+                                        */
+                       }
+                       /*else
+                       {*/
+                               counter = 0;
+                               flag = TRUE;
+                               temp2->seen = last_seen;
+
+                    while ((counter < 3) && (flag))
+                            {
+
+                         if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
+                                        (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
+                                        ((*(temp2->pPolygon+counter) == previous_edge2) ||
+                                        (*(temp2->pPolygon+counter+1) == previous_edge1)) )
+                                        counter++;
+                                    else
+                                        flag = FALSE;
+                    }
+               /*}*/
+               
+               /* Get the IDs of the next edge */
+               left = counter;
+                    north = left+1;
+               if (left ==3)
+                            north = 0; 
+                    if (counter < 3)
+               {
+                        previous_edge1 = *(temp2->pPolygon + counter + 1);
+                        previous_edge2 = *(temp2->pPolygon + counter);
+               }
+               else
+               {
+                        previous_edge1 = *(temp2->pPolygon + counter);
+                        previous_edge2 = *(temp2->pPolygon);
+               }
+
+          } 
+
+}
+last_seen++;
+return max;
+}
+
+void Mark_Face(PF_FACES temp2, int color1, int color2,
+                               int color3, FILE *output_file, BOOL end, int *edge1, int *edge2, 
+                    int *face_id, int norms, int texture)
+{
+     static int last_quad[4];
+     int x,y,z=0;
+     int saved[2];
+     static int output1, output2,last_id;
+     BOOL cptexture = FALSE;
+
+     /*   Are we done with the patch? If so return the last edge that
+          we will come out on, and that will be the edge that we will
+          start to extend upon.
+     */
+
+     if (end)
+     {
+          *edge1 = output1;
+          *edge2 = output2;
+          *face_id = last_id;
+          return;
+     }
+
+     cptexture = texture;
+     last_id = *face_id;
+       *(temp2->walked) = -1;
+       *(temp2->walked+1) = -1;
+       *(temp2->walked+2) = -1;
+       *(temp2->walked+3) = -1;
+       added_quad++;
+       temp2->nPolSize = 1;
+
+     if (patch == 0)
+     {
+          /*   At the first quad in the strip -- save it */
+          last_quad[0] = *(temp2->pPolygon);
+          last_quad[1] = *(temp2->pPolygon+1);
+          last_quad[2] = *(temp2->pPolygon+2);
+          last_quad[3] = *(temp2->pPolygon+3);
+          patch++;
+     }
+     else
+     {
+          /*   Now we have a triangle to output, find the edge in common */
+          for (x=0; x < 4 ;x++)
+          {
+              for (y=0; y< 4; y++)
+              {
+                   if (last_quad[x] == *(temp2->pPolygon+y))
+                   {
+                        saved[z++] = last_quad[x];               
+                        if (z > 2)
+                        {
+                             /*    This means that there was a non convex or
+                                   an overlapping polygon
+                             */
+                             z--;
+                             break;
+                        }
+                   }                             
+              }
+          }
+          
+          if (z != 2)
+          {
+               printf("Z is not 2 %d \n",patch);
+               printf("4 %d %d %d %d %d %d %d\n",*(temp2->pPolygon),
+                               *(temp2->pPolygon+1),*(temp2->pPolygon+2),*(temp2->pPolygon+3),
+                               color1,color2,color3);
+               printf("%d %d %d %d\n",last_quad[0],last_quad[1],last_quad[2],last_quad[3]);
+               exit(1);
+          }
+          
+          if (patch == 1)
+          {
+               /*   First one to output, there was no output edge */
+               patch++;
+               x = Adjacent(saved[0],saved[1],last_quad,4);
+               y = Adjacent(saved[1],saved[0],last_quad,4);
+               
+               /*   Data might be mixed and we do not have textures for some of the vertices */
+               if ((texture) && ( ((vt[x]) == 0) || ((vt[y])==0) || ((vt[saved[1]])==0)))
+                    cptexture = FALSE;
+
+               if ((!norms) && (!cptexture))
+               {
+                    fprintf(output_file,"\nt %d %d %d ",x+1,y+1,saved[1]+1);
+                    fprintf(output_file,"%d ",saved[0]+1);
+               }
+               else if ((norms) && (!cptexture))
+               {
+                    fprintf(output_file,"\nt %d//%d %d//%d %d//%d ",x+1,vn[x] +1,
+                                                                    y+1,vn[y] +1,
+                                                                    saved[1]+1,vn[saved[1]]+1);
+                    fprintf(output_file,"%d//%d ",saved[0]+1,vn[saved[0]]+1);
+               }
+               else if ((cptexture) && (!norms))
+               {
+                    fprintf(output_file,"\nt %d/%d %d/%d %d/%d ",x+1,vt[x] +1,
+                                                                    y+1,vt[y] +1,
+                                                                    saved[1]+1,vt[saved[1]]+1);
+                    fprintf(output_file,"%d//%d ",saved[0]+1,vt[saved[0]]+1);
+               }
+               else
+               {
+                    fprintf(output_file,"\nt %d/%d/%d %d/%d/%d %d/%d/%d ",x+1,vt[x]+1,vn[x] +1,
+                                                                    y+1,vt[y]+1,vn[y] +1,
+                                                                    saved[1]+1,vt[saved[1]]+1,vn[saved[1]]+1);
+                    fprintf(output_file,"%d/%d/%d ",saved[0]+1,vt[saved[0]]+1,vn[saved[0]]+1);
+               }
+
+               x = Adjacent(saved[0],saved[1],temp2->pPolygon,4);
+               y = Adjacent(saved[1],saved[0],temp2->pPolygon,4);
+
+               /*   Data might be mixed and we do not have textures for some of the vertices */
+               if ((texture) && ( (vt[x] == 0) || (vt[y]==0)))
+               {
+                    if (cptexture)
+                         fprintf(output_file,"\nq ");
+                    cptexture = FALSE;
+               }
+               if ((!norms) && (!cptexture))
+               {
+                    fprintf(output_file,"%d ",x+1);
+                    fprintf(output_file,"%d ",y+1);
+               }
+               else if ((norms) && (!cptexture))
+               {
+                    fprintf(output_file,"%d//%d ",x+1,vn[x]+1);
+                    fprintf(output_file,"%d//%d ",y+1,vn[y]+1);
+               }
+               else if ((cptexture) && (!norms))
+               {
+                    fprintf(output_file,"%d/%d ",x+1,vt[x]+1);
+                    fprintf(output_file,"%d/%d ",y+1,vt[y]+1);
+               }
+               else
+               {
+                    fprintf(output_file,"%d/%d/%d ",x+1,vt[x]+1,vn[x]+1);
+                    fprintf(output_file,"%d/%d/%d ",y+1,vt[y]+1,vn[y]+1);
+               }
+
+               output1 = x;
+               output2 = y;
+          }
+          
+          else 
+          {
+               x = Adjacent(output2,output1,temp2->pPolygon,4);
+               y = Adjacent(output1,output2,temp2->pPolygon,4);
+               /*   Data might be mixed and we do not have textures for some of the vertices */
+               if ((texture) && ( ((vt[x]) == 0) || ((vt[y])==0) ))
+                    texture = FALSE;
+
+               if ((!norms) && (!texture))
+               {
+                    fprintf(output_file,"\nq %d ",x+1);
+                    fprintf(output_file,"%d ",y+1);
+               }
+               else if ((norms) && (!texture))
+               {
+                    fprintf(output_file,"\nq %d//%d ",x+1,vn[x]+1);
+                    fprintf(output_file,"%d//%d ",y+1,vn[y]+1);
+               }
+               else if ((texture) && (!norms))
+               {
+                    fprintf(output_file,"\nq %d/%d ",x+1,vt[x]+1);
+                    fprintf(output_file,"%d/%d ",y+1,vt[y]+1);
+               }
+               else
+               {
+                    fprintf(output_file,"\nq %d/%d/%d ",x+1,vt[x]+1,vn[x]+1);
+                    fprintf(output_file,"%d/%d/%d ",y+1,vt[y]+1,vn[y]+1);
+               }
+               
+               output1 = x;
+               output2 = y;
+          }
+          
+          last_quad[0] = *(temp2->pPolygon);
+          last_quad[1] = *(temp2->pPolygon+1);
+          last_quad[2] = *(temp2->pPolygon+2);
+          last_quad[3] = *(temp2->pPolygon+3);
+     }
+}
+
+void Fast_Reset(int x)
+{
+       register int y,numverts;
+       register int front_walk, back_walk;
+       ListHead *pListHead;
+       PF_FACES temp = NULL;
+
+     pListHead = PolFaces[x];
+       temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+       numverts = temp->nPolSize;
+     
+     front_walk = 0; 
+     back_walk = 0;          
+     resetting = TRUE;
+          
+     /* we are doing this only for quads */
+       if (numverts == 4)
+       {
+                       /*      for each face not seen yet, do North and South together
+                               and East and West together
+                       */
+                       for (y=0;y<2;y++)
+                       {
+                               /* Check if the opposite sides were seen already */
+                       /* Find walk for the first edge */
+                               front_walk = Calculate_Walks(x,y,temp);
+                               /* Find walk in the opposite direction */
+                               back_walk = Calculate_Walks(x,y+2,temp);
+                               /*      Now put into the data structure the numbers that
+                               we have found
+                               */
+                    Assign_Walk(x,temp,front_walk,y,back_walk);
+                               Assign_Walk(x,temp,back_walk,y+2,front_walk);
+                       }
+       }
+     resetting = FALSE;
+}
+
+
+void Reset_Max(PF_FACES temp2,int face_id,int north,int last_north, int orientation,
+               int last_left,FILE *output_file,int color1,int color2,int color3,
+               BOOL start)
+{
+       int previous_edge1,previous_edge2;
+       F_EDGES *node;
+       ListHead *pListHead;
+       int f,t,nextvert,counter;
+     BOOL flag;
+
+     /*   Reset walks on faces, since we just found a patch */
+     if (orientation !=3)
+     {
+                previous_edge1 = *(temp2->pPolygon + orientation+1);
+                previous_edge2 = *(temp2->pPolygon + orientation );
+     }
+     else
+     {
+                previous_edge1 = *(temp2->pPolygon + orientation );
+                previous_edge2 = *(temp2->pPolygon);
+     }
+
+       /* only if we are going left, otherwise there will be -1 there */
+       /*Find the adjacent face to this edge */
+        
+     for (t = 0; t <=3 ; t++)
+     {
+             node = *(temp2->VertandId+t);
+              
+             if (face_id == node->edge[1])
+                f = node->edge[2];
+             else
+               f = node->edge[1];
+       
+             if (f != -1)
+                  Fast_Reset(f);
+        }
+
+        node = *(temp2->VertandId+orientation);
+        if (face_id == node->edge[1])
+             nextvert = node->edge[2];
+        else
+             nextvert = node->edge[1];
+
+       while ((last_left--) > 1)
+       {
+               
+          if (start)
+               Reset_Max(temp2,face_id,orientation,last_left,north,last_north,output_file,color1,color2,color3,FALSE);         
+        
+          face_id = nextvert;
+          pListHead = PolFaces[nextvert];                
+          temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+          if ((temp2->nPolSize != 4) && (temp2->nPolSize != 1))
+          {
+             /*   There is more than 2 polygons on the edge, and we could have
+                  gotten the wrong one
+             */
+             if (nextvert != node->edge[1])
+                  nextvert = node->edge[1];
+             else
+                  nextvert = node->edge[2];
+             pListHead = PolFaces[nextvert];          
+             temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+             node = *(temp2->VertandId+orientation);
+          }
+
+                
+         if (!start)
+         {
+             for (t = 0; t <=3 ; t++)
+             {
+                    node = *(temp2->VertandId+t);
+              
+                    if (face_id == node->edge[1])
+                         f = node->edge[2];
+                    else
+                         f = node->edge[1];
+          
+                    if (f != -1)
+                         Fast_Reset(f);
+             }
+        }
+
+
+        counter = 0;
+          flag = TRUE;
+          while ((counter < 3) && (flag))
+        {
+             if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
+                   (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
+                  ((*(temp2->pPolygon+counter) == previous_edge2) ||
+                   (*(temp2->pPolygon+counter+1) == previous_edge1)) )
+                   counter++;
+             else
+                  flag = FALSE;
+        }
+
+        /* Get the IDs of the next edge */
+        if (counter < 3)
+        {
+             previous_edge1 = *(temp2->pPolygon + counter+1);
+             previous_edge2 = *(temp2->pPolygon + counter);
+        }
+        else
+        {
+             previous_edge1 = *(temp2->pPolygon + counter);
+             previous_edge2 = *(temp2->pPolygon);
+        }
+        orientation = counter;
+
+        node = *(temp2->VertandId + counter);
+          if (node->edge[1] == nextvert)
+                       nextvert = node->edge[2];
+          else
+                       nextvert = node->edge[1];
+
+        if (!reversed)
+        {
+               if (counter != 3)
+                            north = counter +1;
+                    else
+                            north = 0;
+        }
+        else
+        {
+               if (counter != 0)
+                    north = counter -1;
+               else
+                    north = 3;
+    
+        }
+     }
+if (start)
+       Reset_Max(temp2,face_id,orientation,last_left,north,last_north,output_file,color1,color2,color3,FALSE);
+else if (nextvert != -1)       
+     Fast_Reset(nextvert);
+
+}
+
+
+int Peel_Max(PF_FACES temp2,int face_id,int north,int last_north, int orientation,
+               int last_left,FILE *output_file,int color1,int color2,int color3,
+               BOOL start, int *swaps_added, int norms, int texture)
+{
+       int end1,end2,last_id,s=0,walk = 0;
+       int previous_edge1,previous_edge2;
+       static int last_seen = 1000;
+       F_EDGES *node;
+       ListHead *pListHead;
+       int nextvert,numverts,counter,dummy,tris=0;
+     BOOL flag;
+
+     /*   Peel the patch from the model.
+          We will try and extend off the end of each strip in the patch. We will return the
+          number of triangles completed by this extension only, and the number of swaps
+          in the extension only.
+     */        
+     patch = 0;
+     
+     if (orientation !=3)
+     {
+                previous_edge1 = *(temp2->pPolygon + orientation+1);
+                previous_edge2 = *(temp2->pPolygon + orientation );
+     }
+     else
+     {
+                previous_edge1 = *(temp2->pPolygon + orientation );
+                previous_edge2 = *(temp2->pPolygon);
+     }
+
+
+     walk = *(temp2->walked + orientation);
+       
+     /* only if we are going left, otherwise there will be -1 there */
+       if ((start) && ((walk+1) < last_left))
+       {
+               printf("There is an error in the left %d %d\n",walk,last_left);
+               exit(0);
+       }
+       
+     /* Find the adjacent face to this edge */
+     node = *(temp2->VertandId+orientation);
+     if (face_id == node->edge[1])
+          nextvert = node->edge[2];
+     else
+          nextvert = node->edge[1];
+       temp2->seen = last_seen;
+
+
+       while ((last_left--) > 1)
+       {
+               if (start)
+             tris += Peel_Max(temp2,face_id,orientation,last_left,north,last_north,output_file,
+                              color1,color2,color3,FALSE,swaps_added,norms,texture);               
+          else
+             Mark_Face(temp2,color1,color2,color3,output_file,FALSE,&dummy,&dummy,&face_id,norms,texture);
+               
+
+          pListHead = PolFaces[nextvert];      
+          temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+          numverts = temp2->nPolSize;
+       
+          if ((numverts != 4) || (temp2->seen == last_seen) 
+                       ||  (nextvert == -1))
+          {
+       
+             /*   There is more than 2 polygons on the edge, and we could have
+                  gotten the wrong one
+             */
+             if (nextvert != node->edge[1])
+                  nextvert = node->edge[1];
+             else
+                  nextvert = node->edge[2];
+             pListHead = PolFaces[nextvert];
+             temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+             numverts = temp2->nPolSize;
+             if ((numverts != 4) || (temp2->seen == last_seen) )
+             {
+                  printf("Peel 2 %d\n",numverts);
+                  exit(1);
+             }
+        }
+
+        face_id = nextvert;
+        temp2->seen = last_seen;
+                
+        counter = 0;
+        flag = TRUE;
+          while ((counter < 3) && (flag))
+        {
+             if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
+                   (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
+                  ((*(temp2->pPolygon+counter) == previous_edge2) ||
+                   (*(temp2->pPolygon+counter+1) == previous_edge1)) )
+                   counter++;
+             else
+                  flag = FALSE;
+        }
+        /* Get the IDs of the next edge */
+        if (counter < 3)
+        {
+             previous_edge1 = *(temp2->pPolygon + counter+1);
+             previous_edge2 = *(temp2->pPolygon + counter);
+        }
+        else
+        {
+             previous_edge1 = *(temp2->pPolygon + counter);
+             previous_edge2 = *(temp2->pPolygon);
+        }
+        orientation = counter;
+                             
+          node = *(temp2->VertandId + counter);
+          if (node->edge[1] == nextvert)
+                       nextvert = node->edge[2];
+          else
+                       nextvert = node->edge[1];
+
+          if (!reversed)
+        {
+               if (counter != 3)
+                            north = counter +1;
+                    else
+                            north = 0;
+        }
+        else
+        {
+               if (counter != 0)
+                    north = counter -1;
+               else
+                    north = 3;
+        }
+}
+
+if (start)
+       tris += Peel_Max(temp2,face_id,orientation,last_left,north,last_north,output_file,
+                        color1,color2,color3,FALSE,swaps_added,norms,texture); 
+else
+     Mark_Face(temp2,color1,color2,color3,output_file,FALSE,&dummy,&dummy,&face_id,norms,texture);/* do the last face */
+
+last_seen++;
+
+/*    Get the edge that we came out on the last strip of the patch */
+Mark_Face(NULL,0,0,0,output_file,TRUE,&end1,&end2,&last_id,norms,texture);
+tris += Extend_Face(last_id,end1,end2,&s,output_file,color1,color2,color3,vn,norms,vt,texture);
+*swaps_added = *swaps_added + s;
+return tris;
+}
+
+
+
+void Find_Bands(int numfaces, FILE *output_file, int *swaps, int *bands, 
+                int *cost, int *tri, int norms, int *vert_norms, int texture, int *vert_texture)
+{
+
+       register int x,y,max1,max2,numverts,face_id,flag,maximum = 25;
+       ListHead *pListHead;
+       PF_FACES temp = NULL;
+       int color1 = 0, color2 = 100, color3 = 255;
+       int larger,smaller;
+       int north_length1,last_north,left_length1,last_left,north_length2,left_length2;
+  int total_tri = 0, total_swaps = 0,last_id;
+  int end1, end2,s=0;
+  register int cutoff = 20;
+    
+  /* Code that will find the patches. "Cutoff" will be
+     the cutoff of the area of the patches that we will be allowing. After
+     we reach this cutoff length, then we will run the local algorithm on the
+     remaining faces.
+  */
+
+       /* For each faces that is left find the largest possible band that we can
+                have with the remaining faces. Note that we will only be finding patches
+     consisting of quads.
+       */
+
+  vn = vert_norms;
+  vt = vert_texture;
+  y=1;
+  *bands = 0;
+
+  while ((maximum >= cutoff))
+  {
+         y++;
+    maximum = -1;
+         for (x=0; x<numfaces; x++)
+         { 
+      /*   Used to produce the triangle strips */
+      /* for each face, get the face */
+                 pListHead = PolFaces[x];
+                 temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+                 numverts = temp->nPolSize;
+                 
+      /* we are doing this only for quads */
+                 if (numverts == 4)
+                 {
+                         /* We want a face that is has not been used yet,
+           since we know that that face must be part of
+                                  a band. Then we will find the largest band that
+                                  the face may be contained in
+                         */
+                         
+        /*  Doing the north and the left */
+                         if ((*(temp->walked) != -1) && (*(temp->walked+3) != -1))
+                                 max1 = Find_Max(temp,x,0,3,&north_length1,&left_length1);
+                         if ((*(temp->walked+1) != -1) && (*(temp->walked+2) != -1))
+                                 max2 = Find_Max(temp,x,2,1,&north_length2,&left_length2);
+                         if ((max1 != (north_length1 * left_length1)) ||
+                             (max2 != (north_length2 * left_length2)))
+                         {
+                                 printf("Max1 %d, %d %d        Max2 %d, %d %d\n",max1,north_length1,left_length1,max2,north_length2,left_length2);
+                                 exit(0);
+                         }
+                
+                    
+        if ((max1 > max2) && (max1 > maximum))
+                         {
+          maximum = max1;
+          face_id = x;
+          flag = 1; 
+          last_north = north_length1;
+          last_left = left_length1;
+          /* so we know we saved max1 */
+                         }
+                         else if ((max2 > maximum) )
+                         {
+          maximum = max2;
+          face_id = x;
+          flag = 2; 
+          last_north = north_length2;
+          last_left = left_length2;
+          /* so we know we saved max2 */
+        }
+      }
+    }
+    if ((maximum < cutoff) && (*bands == 0))
+      return;
+    pListHead = PolFaces[face_id];
+    temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0);  
+    /*   There are no patches that we found in this pass */
+    if (maximum == -1)
+      break;
+    printf("The maximum is  face %d area %d: lengths %d %d\n",face_id,maximum,last_north,last_left);
+    if (maximum == 16)
+      printf("Fran");
+
+    if (last_north > last_left)
+    {
+      larger = last_north;
+      smaller = last_left;
+    }
+    else
+    {
+      larger = last_left;
+      smaller = last_north;
+    }
+
+    length = larger;
+
+    if (flag == 1)
+    {
+           if (last_north > last_left) /*     go north sequentially */
+      {
+        total_tri += Peel_Max(temp,face_id,0,last_north,3,last_left,output_file,color1,color2,color3,TRUE,&s,norms,texture);
+        Reset_Max(temp,face_id,0,last_north,3,last_left,output_file,color1,color2,color3,TRUE);
+        total_swaps += s;
+      }
+      else
+      {
+        reversed = TRUE;
+        total_tri += Peel_Max(temp,face_id,3,last_left,0,last_north,output_file,color1,color2,color3,TRUE,&s,norms,texture);
+        Reset_Max(temp,face_id,3,last_left,0,last_north,output_file,color1,color2,color3,TRUE);
+        reversed = FALSE;
+        total_swaps += s;
+      }
+
+
+      /*    Get the edge that we came out on the last strip of the patch */
+      Mark_Face(NULL,0,0,0,NULL,TRUE,&end1,&end2,&last_id,norms,texture);
+      total_tri += Extend_Face(last_id,end1,end2,&s,output_file,color1,color2,color3,vn,norms,vt,texture);
+      total_swaps += s;
+
+    }
+    else
+    {
+       if (last_north > last_left)
+       {
+            total_tri += Peel_Max(temp,face_id,2,last_north,1,last_left,output_file,color1,color2,color3,TRUE,&s,norms,texture); 
+            Reset_Max(temp,face_id,2,last_north,1,last_left,output_file,color1,color2,color3,TRUE); 
+            total_swaps += s;
+       }
+       else
+       {
+            reversed = TRUE;
+            total_tri += Peel_Max(temp,face_id,1,last_left,2,last_north,output_file,color1,color2,color3,TRUE,&s,norms,texture);
+            Reset_Max(temp,face_id,1,last_left,2,last_north,output_file,color1,color2,color3,TRUE);
+            reversed = FALSE;
+            total_swaps += s;
+       }
+
+       /*    Get the edge that we came out on on the patch */
+      Mark_Face(NULL,0,0,0,NULL,TRUE,&end1,&end2,&last_id,norms,texture);
+      total_tri += Extend_Face(last_id,end1,end2,&s,output_file,color1,color2,color3,vn,norms,vt,texture);
+      total_swaps += s;
+    }
+
+    /* Now compute the cost of transmitting this band, is equal to 
+       going across the larger portion sequentially,
+       and swapping 3 times per other dimension
+    */
+
+    total_tri += (maximum * 2);
+    *bands = *bands + smaller;
+  }
+
+  printf("We transmitted %d triangles,using %d swaps and %d strips\n",total_tri,total_swaps, *bands);
+  printf("COST %d\n",total_tri + total_swaps + *bands + *bands);
+
+  *cost = total_tri + total_swaps + *bands + *bands;
+  *tri = total_tri;
+  added_quad = added_quad * 4;
+  *swaps = total_swaps;
+}
+
+void Save_Rest(int *numfaces)
+{
+    /*  Put the polygons that are left into a data structure so that we can run the
+        stripping code on it.
+    */
+    register int x,y=0,numverts;
+    ListHead *pListHead;
+    PF_FACES temp=NULL;
+
+    for (x=0; x<*numfaces; x++)
+    { 
+                       /* for each face, get the face */
+                       pListHead = PolFaces[x];
+                       temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+                       numverts = temp->nPolSize;
+               /*  If we did not do the face before add it to data structure with new 
+                   face id number
+               */
+               if (numverts != 1)
+               {
+                   CopyFace(temp->pPolygon,numverts,y+1,temp->pNorms);
+                   y++;
+               }
+               /*   Used it, so remove it */
+               else
+                    RemoveList(pListHead,(PLISTINFO) temp);
+
+    }
+    *numfaces = y;
+}
+
+void Assign_Walk(int lastvert,PF_FACES temp2, int front_walk,int y,
+                               int back_walk)
+{
+/*      Go back and do the walk again, but this time save the lengths inside
+        the data structure.
+        y was the starting edge number for the front_walk length
+        back_walk is the length of the walk along the opposite edge
+ */
+        int previous_edge1, previous_edge2;
+        register int walk = 0,nextvert,numverts,counter;
+        BOOL flag;
+        F_EDGES *node;
+        ListHead *pListHead;
+        static int seen = 0;
+        static BOOL first = TRUE;         
+        BOOL wrap = FALSE, set = FALSE;
+             
+        /*     In the "Fast_Reset" resetting will be true */
+        if ((resetting) && (first))
+        {
+             seen = 0;
+             first = FALSE;
+        }
+
+        seen++;
+        /*     Had a band who could be a cycle  */
+        if (front_walk == back_walk)
+             wrap = TRUE;
+             
+        /* Find the edge that we are currently on */
+        if (y != 3)
+        {
+                previous_edge1 = *(temp2->pPolygon +y);
+                previous_edge2 = *(temp2->pPolygon + y + 1);
+        }
+        else
+        {
+                previous_edge1 = *(temp2->pPolygon +y);
+                previous_edge2 = *(temp2->pPolygon);
+        }
+
+        /* Assign the lengths */
+          if (y < 2) 
+          {
+                *(temp2->walked+y) = front_walk--;
+                        *(temp2->walked+y+2) = back_walk++;
+          }
+          else
+          {                            
+               *(temp2->walked+y) = front_walk--;
+               *(temp2->walked+y-2) = back_walk++;
+          }
+
+          /*Find the adjacent face to this edge */
+        node = *(temp2->VertandId+y);                   
+
+        if (node->edge[2] != lastvert)
+          nextvert = node->edge[2];
+        else
+          nextvert = node->edge[1];
+                                       
+        temp2->seen3 = seen;
+        
+        /* Keep walking in this direction until we cannot do so */
+        while ((nextvert != lastvert) && (nextvert != -1) && (front_walk >= 0))
+        {
+                    walk++;
+               pListHead = PolFaces[nextvert];
+               
+               temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+               numverts = temp2->nPolSize;
+               if ((numverts != 4))
+               {
+                    nextvert = -1;
+                    /* Don't include this face in the walk */
+                    walk--;
+               }
+               else
+               {
+                    /* Find edge that is not adjacent to the previous one */
+                    counter = 0;
+                    flag = TRUE;
+                    while ((counter < 3) && (flag))
+                    {
+                         if ( ((*(temp2->pPolygon+counter) == previous_edge1) ||
+                               (*(temp2->pPolygon+counter+1) == previous_edge2)) ||
+                              ((*(temp2->pPolygon+counter) == previous_edge2) ||
+                               (*(temp2->pPolygon+counter+1) == previous_edge1)) )
+                              counter++;
+                         else
+                              flag = FALSE;
+                    }
+                    /* Get the IDs of the next edge */
+                    if (counter < 3)
+                    {
+                         previous_edge1 = *(temp2->pPolygon + counter);
+                         previous_edge2 = *(temp2->pPolygon + counter + 1);
+                    }
+                    else
+                    {
+                         previous_edge1 = *(temp2->pPolygon + counter);
+                         previous_edge2 = *(temp2->pPolygon);
+                    }
+               
+
+                         /*      Put in the walk lengths */
+                         if (counter < 2)
+                         {
+                        if (((*(temp2->walked + counter) >= 0)
+                                 || (*(temp2->walked +counter + 2) >= 0)))
+                                 {
+                                         if ((resetting == FALSE) && ((temp2->seen3) != (seen-1)))
+                                         {
+                                                 /*   If there are more than 2 polygons adjacent
+                                        to an edge then we can be trying to assign more than
+                                        once. We will save the smaller one
+                                   */
+                                   temp2->seen3 = seen;
+                                   if ( (*(temp2->walked+counter) <= front_walk) &&
+                                        (*(temp2->walked+counter+2) <= back_walk) )
+                                        return;
+                                   if (*(temp2->walked+counter) > front_walk)
+                                       *(temp2->walked+counter) = front_walk--;
+                                   else
+                                        front_walk--;
+                                   if (*(temp2->walked+counter+2) > back_walk)
+                                       *(temp2->walked+counter+2) = back_walk++;
+                                   else
+                                        back_walk++;
+                                         }
+                                         else if (resetting == FALSE)
+                                         {
+                                                 /* if there was a cycle then all lengths are the same */
+                                                 walk--;
+                                                 back_walk--;
+                                                 front_walk++;
+                                   temp2->seen3 = seen;
+                                   *(temp2->walked+counter) = front_walk--;
+                                   *(temp2->walked+counter+2) = back_walk++;
+                              }
+                              else if (((temp2->seen3 == (seen-1))
+                                   && (wrap) && (walk == 1)) || (set))
+                              {
+                                                 /* if there was a cycle then all lengths are the same */
+                                                 set = TRUE;
+                                   walk--;
+                                                 back_walk--;
+                                                 front_walk++;
+                                   temp2->seen3 = seen;
+                                   *(temp2->walked+counter) = front_walk--;
+                                   *(temp2->walked+counter+2) = back_walk++;
+                              }
+                              else
+                              {
+                                   temp2->seen3 = seen;
+                                   *(temp2->walked+counter) = front_walk--;
+                                   *(temp2->walked+counter+2) = back_walk++;
+                              }
+                        } /* if was > 0 */     
+                        else
+                        {
+                             temp2->seen3 = seen;
+                             *(temp2->walked+counter) = front_walk--;
+                             *(temp2->walked+counter+2) = back_walk++;
+                        }
+                    }
+               
+               else
+               {
+                    if (((*(temp2->walked + counter) >= 0 )
+                        || (*(temp2->walked +counter - 2) >= 0)) )
+                    {
+                         if ((temp2->seen3 != (seen-1))  && (resetting == FALSE))
+                         {
+                              /*   If there are more than 2 polygons adjacent
+                                   to an edge then we can be trying to assign more than
+                                   once. We will save the smaller one
+                              */
+                              temp2->seen3 = seen;
+                              if ( (*(temp2->walked+counter) <= front_walk) &&
+                                   (*(temp2->walked+counter-2) <= back_walk) )
+                                   return;
+                              if (*(temp2->walked+counter) > front_walk)
+                                   *(temp2->walked+counter) = front_walk--;
+                              else
+                                   front_walk--;
+                              if (*(temp2->walked+counter-2) > back_walk)
+                                   *(temp2->walked+counter-2) = back_walk++;
+                              else
+                                   back_walk++;
+                               }
+                                    else if (resetting == FALSE)
+                               {
+                                       walk--;
+                                       back_walk--;
+                                       front_walk++;
+                                temp2->seen3 = seen;
+                              *(temp2->walked+counter) = front_walk--;
+                              *(temp2->walked+counter-2) = back_walk++;
+                         }
+                         else if (((temp2->seen3 == (seen-1)) && (walk == 1) && (wrap))
+                              || (set))
+                         {
+                                            /* if there was a cycle then all lengths are the same */
+                                            set = TRUE;
+                              walk--;
+                                            back_walk--;
+                                            front_walk++;
+                              temp2->seen3 = seen;
+                              *(temp2->walked+counter) = front_walk--;
+                              *(temp2->walked+counter-2) = back_walk++;
+                         }
+                         else
+                         {
+                              temp2->seen3 = seen;
+                              *(temp2->walked+counter) = front_walk--;
+                              *(temp2->walked+counter-2) = back_walk++;
+                         }
+                       }
+                    else
+                    {
+                         temp2->seen3 = seen;
+                         *(temp2->walked+counter) = front_walk--;
+                         *(temp2->walked+counter-2) = back_walk++;
+                    }
+                               
+                    } 
+                    if (nextvert != -1)
+                    {
+                            node = *(temp2->VertandId + counter);
+                       if (node->edge[1] == nextvert)
+                               nextvert = node->edge[2];
+                       else
+                               nextvert = node->edge[1];
+               }
+               
+     }
+}
+if ((EVEN(seen)) )
+     seen+=2;
+}
+
+void Save_Walks(int numfaces)
+{
+       int x,y,numverts;
+       int front_walk, back_walk;
+       ListHead *pListHead;
+       PF_FACES temp = NULL;
+
+       for (x=0; x<numfaces; x++)
+       { 
+               /* for each face, get the face */
+               pListHead = PolFaces[x];
+               temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0);
+               numverts = temp->nPolSize;
+               front_walk = 0; 
+          back_walk = 0;
+
+          /* we are finding patches only for quads */
+               if (numverts == 4)
+               {
+                       /*      for each face not seen yet, do North and South together
+                               and East and West together
+                       */
+                       for (y=0;y<2;y++)
+                       {
+                               /*   Check if the opposite sides were seen already from another
+                         starting face, if they were then there is no need to do the walk again
+                    */
+
+                               if      ( ((*(temp->walked+y) == -1) &&
+                                       (*(temp->walked+y+2) == -1) ))
+                               {
+                                       /* Find walk for the first edge */
+                                       front_walk = Calculate_Walks(x,y,temp);
+                                       /* Find walk in the opposite direction */
+                                       back_walk = Calculate_Walks(x,y+2,temp);
+                                       /*      Now put into the data structure the numbers that
+                                               we have found
+                                       */
+                         Assign_Walk(x,temp,front_walk,y,back_walk);
+                                       Assign_Walk(x,temp,back_walk,y+2,front_walk);
+                       }
+                       }
+               }
+       }
+}
+
+
diff --git a/Stripe_w/options.c b/Stripe_w/options.c
new file mode 100644 (file)
index 0000000..cbc9d4e
--- /dev/null
@@ -0,0 +1,181 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: options.c
+     This file contains routines that are used to determine the options
+     that were specified by the user
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "options.h"
+#include "global.h"
+
+int power_10(int power)
+{
+       /*      Raise 10 to the power */
+       register int i,p;
+
+       p = 1;
+       for (i = 1; i <= power; ++i)
+               p = p * 10;
+       return p;
+}
+
+float power_negative(int power)
+{
+     /*   Raise 10 to the negative power */
+
+     register int i;
+     float p;
+     
+     p = (float)1;
+     for (i = 1; i<=power; i++)
+          p = p * (float).1;
+     return p;
+}
+
+float convert_array(int num[],int stack_size)
+{
+       /* Convert an array of characters to an integer */
+       
+       register int counter,c;
+       float temp =(float)0.0;
+
+       for (c=(stack_size-1), counter = 0; c>=0; c--, counter++)
+     {
+          if (num[c] == -1)
+          /*   We are at the decimal point, convert to decimal
+               less than 1
+          */
+          {
+               counter = -1;
+               temp = power_negative(stack_size - c - 1) * temp;
+          }
+          else 
+               temp += power_10(counter) * num[c];
+     }
+                       
+       return(temp);
+}
+
+double get_options(int argc, char **argv, int *f, int *t, int *tr, int *group)
+{
+     char c;
+     int count = 0;
+     int buffer[STRIP_MAX];
+     int next = 0;
+     /*    tie variable */
+     enum tie_options tie = SEQUENTIAL;
+     /*   triangulation variable */
+     enum triangulation_options triangulate = PARTIAL;
+     /*   normal difference variable (in degrees) */
+     float norm_difference = (float)360.0;
+     /*   file-type variable */
+     enum file_options file_type = ASCII;
+
+     /*      User has the wrong number of options */
+       if ((argc > 5) || (argc < 2))
+       {
+               printf("Usage: bands -[file_option][ties_option][triangulation_option][normal_difference] file_name\n");
+               exit(0);
+       }
+       
+     /* Interpret the options specified */
+       while (--argc > 0 && (*++argv)[0] == '-')
+     {
+          /*   At the next option that was specified */
+          next = 1;
+          while (c = *++argv[0])
+                       switch (c)
+               {
+                               case 'f': 
+                                       /*      Use the first polygon we see. */
+                         tie = FIRST;
+                                       break;
+                               
+                               case 'r':
+                                       /*      Randomly choose the next polygon */
+                         tie = RANDOM;
+                                       break;
+
+                               case 'a':
+                                       /*      Alternate direction in choosing the next polygon */
+                         tie = ALTERNATE;
+                                       break;
+
+                               case 'l':
+                                       /*      Use lookahead to choose the next polygon */
+                         tie = LOOK;
+                                       break;
+
+                               case 'q':
+                                       /*  Try to reduce swaps */
+                         tie = SEQUENTIAL;
+                                       break;
+
+                               case 'p':
+                                       /*      Use partial triangulation of polygons */
+                         triangulate = PARTIAL;
+                                       break;
+
+                               case 'w':
+                                       /*      Use whole triangulation of polygons */
+                         triangulate = WHOLE;
+                                       break;
+
+                    case 'b':
+                         /*      Input file is in binary */
+                         file_type = BINARY;
+                         break;
+
+                    case 'g':
+                         /*   Strips will be grouped according to the groups in 
+                              the data file. We will have to restrict strips to be
+                              in the grouping of the data file.
+                         */
+                         *group = 1;
+                   
+                         /*    Get each the value of the integer */
+                         /*    We have an integer */
+                    default:
+                         if ((c >= '0') && (c <= '9'))
+                         {
+                              /*   More than one normal difference specified, use the last one */
+                              if (next == 1)
+                              {
+                                   count = 0;
+                                   next = 0;
+                              }
+                              buffer[count++] = ATOI(c);
+                         }
+                              /*   At the decimal point */
+                         else if (c == '.')
+                         {
+                              /*   More than one normal difference specified, use the last one */
+                              if (next == 1)
+                              {
+                                   count = 0;
+                                   next = 0;
+                              }
+                              buffer[count++] = -1;
+                         }
+                         else 
+                              break;
+               }
+     }
+     /*   Convert the buffer of characters to a floating pt integer */
+     if (count != 0) 
+          norm_difference = convert_array(buffer,count);
+     *f = file_type;
+     *t = tie;
+     *tr = triangulate;
+     return norm_difference;
+}
diff --git a/Stripe_w/options.h b/Stripe_w/options.h
new file mode 100644 (file)
index 0000000..34c10bc
--- /dev/null
@@ -0,0 +1,17 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: options.h
+-----------------------------------------------------------------------*/
+
+double get_options(int argc, char **argv, int *f, int *t, int *tr, int *group);
+enum file_options {ASCII,BINARY};
+enum tie_options {FIRST, RANDOM, ALTERNATE, LOOK, SEQUENTIAL};
+enum triangulation_options {PARTIAL,WHOLE};
+     
diff --git a/Stripe_w/output.c b/Stripe_w/output.c
new file mode 100644 (file)
index 0000000..16eb6ab
--- /dev/null
@@ -0,0 +1,579 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: output.c
+     This file contains routines that are finding and outputting the
+     strips from the local algorithm
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "global.h"
+#include "polverts.h"
+#include "triangulate.h"
+#include "partial.h"
+#include "sturcts.h"
+#include "ties.h"
+#include "options.h"
+#include "common.h"
+#include "util.h"
+#include "free.h"
+
+int *vn;
+int *vt;
+int norm;
+int text;
+
+int Finished(int *swap, FILE *output, BOOL global)
+{
+  /* We have finished all the triangles, now is time to output to
+     the data file. In the strips data structure, every three ids
+     is a triangle. Now we see whether we can swap, or make a new strip
+     or continue the strip, and output the data accordingly to the
+     data file. 
+  */
+  int num,x,vertex1,vertex2;
+  ListHead *pListHead;
+  int id[2],other1,other2,index = 0,a,b,c;
+  P_STRIPS temp1,temp2,temp3,temp4,temp5,temp6;
+  BOOL cptexture;
+  *swap =0;
+   
+  cptexture = text;
+  pListHead = strips[0];
+  if (pListHead == NULL)
+    return 0;
+
+  num = NumOnList(pListHead);
+  // WILBUR
+  // printf ("There are %d triangles in the extend\n",num/3);
+
+  /* Go through the list triangle by triangle */
+       temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 0);
+       temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 1);
+       temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 2);
+       
+  /* Next triangle for lookahead */
+  temp4 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 3);
+         
+
+  /*    There is only one polygon in the strip */
+  if (temp4 == NULL)
+  {
+    /* Data might be mixed and we do not have textures for some of the vertices */
+    if ((text) &&  (vt[temp3->face_id] == 0))
+      cptexture = FALSE;
+    if ((norm) && (!cptexture))
+      fprintf(output,"%d//%d %d//%d %d//%d",temp3->face_id+1,vn[temp3->face_id]+1,
+                temp2->face_id+1,vn[temp2->face_id]+1,
+                temp1->face_id+1,vn[temp1->face_id]+1);
+    else if ((cptexture) && (!norm))
+      fprintf(output,"%d/%d %d/%d %d/%d",temp3->face_id+1,vt[temp3->face_id]+1,
+                temp2->face_id+1,vt[temp2->face_id]+1,
+                temp1->face_id+1,vt[temp1->face_id]+1);
+    else if ((cptexture)&& (norm))
+      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,
+                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);
+    else 
+      fprintf(output,"%d %d %d",temp3->face_id+1,temp2->face_id+1,temp1->face_id+1);
+    Free_Strips();
+         return 1;
+       }
+         
+       /* We have a real strip */
+       temp5 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 4);
+       temp6 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 5);
+         
+       if ((temp1 == NULL) || (temp2 == NULL) || (temp3 == NULL) || (temp5 == NULL) || (temp6 == NULL))
+       {
+         printf("There is an error in the output of the triangles\n");
+         exit(0);
+       }
+
+       /* Find the vertex in the first triangle that is not in the second */
+       vertex1 = Different(temp1->face_id,temp2->face_id,temp3->face_id,temp4->face_id,temp5->face_id,temp6->face_id,&other1,&other2);
+       /* Find the vertex in the second triangle that is not in the first */
+       vertex2 = Different(temp4->face_id,temp5->face_id,temp6->face_id,temp1->face_id,temp2->face_id,temp3->face_id,&other1,&other2);
+
+       /* Lookahead for the correct order of the 2nd and 3rd vertex of the first triangle */
+  temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 6);
+       temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 7);
+       temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 8);
+       
+  if (temp1 != NULL)
+    other1 = Different(temp3->face_id,temp4->face_id,temp5->face_id,temp1->face_id,temp2->face_id,temp3->face_id,&other1,&a);
+          
+       id[index] = vertex1; index = !index;
+       id[index] = other1; index = !index;
+       id[index] = other2; index = !index;
+
+       a = temp4->face_id; 
+       b = temp5->face_id; 
+       c = temp6->face_id;
+
+  /* If we need to rearrange the first sequence because otherwise
+     there would have been a swap.
+  */
+
+  if ((temp3 != NULL) && (text) && ( vt[temp3->face_id]==0))
+    cptexture = FALSE;
+  if ((norm) && (!cptexture))
+    fprintf(output,"%d//%d %d//%d %d//%d ",vertex1+1,vn[vertex1]+1,
+               other1+1,vn[other1]+1,other2+1,vn[other2]+1);
+  else if ((cptexture) && (!norm))
+    fprintf(output,"%d/%d %d/%d %d/%d ",vertex1+1,vt[vertex1]+1,
+               other1+1,vt[other1]+1,other2+1,vt[other2]+1);
+  else if ((cptexture) && (norm))
+    fprintf(output,"%d/%d/%d %d/%d/%d %d/%d/%d ",vertex1+1,vt[vertex1]+1,vn[vertex1]+1,
+              other1+1,vt[other1]+1,vn[other1]+1,other2+1,vt[other2]+1,vn[other2]+1);
+  else {
+    fprintf(output,"%d %d %d ",vertex1+1,other1+1,other2+1);
+  }
+
+  // original line
+  // for (x = 6; x < num ; x = x+3)
+  // Wilbur modified line
+  for (x = 6; x < num ; x = x+3)
+       {
+    /* Get the next triangle */
+         temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, x);
+         temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, x+1);
+         temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, x+2);
+
+    /* Error checking */
+         if (!(member(id[0],a,b,c)) || !(member(id[1],a,b,c)) || !(member(vertex2,a,b,c)))
+         {
+                 /* If we used partial we might have a break in the middle of a strip */
+                 fprintf(output,"\nt ");
+           /* Find the vertex in the first triangle that is not in the second */
+           vertex1 = Different(a,b,c,temp1->face_id,temp2->face_id,temp3->face_id,&other1,&other2);
+           /* Find the vertex in the second triangle that is not in the first */
+           vertex2 = Different(temp1->face_id,temp2->face_id,temp3->face_id,a,b,c,&other1,&other2);
+          
+           id[index] = vertex1; index = !index;
+           id[index] = other1; index = !index;
+           id[index] = other2; index = !index;
+         }
+
+         if ((temp1 == NULL ) || (temp2 == NULL) || (temp3 == NULL))
+         {
+                 printf("There is an error in the triangle list \n");
+                 exit(0);
+         }
+         
+    if ((id[0] == id[1]) || (id[0] == vertex2))
+      continue;
+
+    if ( (member(id[index],temp1->face_id,temp2->face_id,temp3->face_id)) )
+    {
+      if ((text) && ( vt[id[index]]==0)) {
+        cptexture = FALSE;
+      }
+      if ((!norm) && (!cptexture)) {
+        fprintf(output,"%d ",id[index]+1);
+      } else if ((norm) && (!cptexture)) {
+        fprintf(output,"%d//%d ",id[index]+1,vn[id[index]]+1);
+      } else if ((!norm) && (cptexture)) {
+        fprintf(output,"%d/%d ",id[index]+1,vt[id[index]]+1);
+      } else {
+        fprintf(output,"%d/%d/%d ",id[index]+1,vt[id[index]]+1,vn[id[index]]+1);
+      }
+
+      index = !index;
+      *swap = *swap + 1;
+    }
+           
+    if ((text) && ( vt[vertex2]==0))
+      cptexture = FALSE;
+         if ((!norm) && (!cptexture))
+      fprintf(output,"\nq %d ",vertex2+1);
+    else if ((norm) && (!cptexture))
+      fprintf(output,"\nq %d//%d ",vertex2+1,vn[vertex2]+1);
+    else if ((!norm) && (cptexture))
+      fprintf(output,"\nq %d/%d ",vertex2+1,vt[vertex2]+1);
+    else
+      fprintf(output,"\nq %d/%d/%d ",vertex2+1,vt[vertex2]+1,vn[vertex2]+1);
+
+    id[index] = vertex2; index = !index;
+
+         /* Get the next vertex not in common */
+         vertex2 = Different(temp1->face_id,temp2->face_id,temp3->face_id,a,b,c,&other1,&other2);
+         a = temp1->face_id;
+         b = temp2->face_id;
+         c = temp3->face_id;
+       }
+
+  /* Do the last vertex */
+  if ((!norm) && (!cptexture))
+    fprintf(output,"\nq %d ",vertex2+1);
+  else if ((norm) && (!cptexture))
+    fprintf(output,"\nq %d//%d ",vertex2+1,vn[vertex2]+1);
+  else if ((!norm) && (cptexture))
+    fprintf(output,"\nq %d/%d ",vertex2+1,vt[vertex2]+1);
+  else
+    fprintf(output,"\nq %d/%d/%d ",vertex2+1,vt[vertex2]+1,vn[vertex2]+1);
+
+  Free_Strips();
+  return (num/3);
+}
+
+
+
+
+
+void Output_Tri(int id1, int id2, int id3,FILE *bands, int color1, int color2, int color3,BOOL end)
+{
+     /*   We will save everything into a list, rather than output at once,
+            as was done in the old routine. This way for future modifications
+            we can change the strips later on if we want to.
+     */
+
+    int temp1,temp2,temp3;
+    
+    /*  Make sure we do not have an error */
+    /*    There are degeneracies in some of the files */
+       if ( (id1 == id2) || (id1 == id3) || (id2 == id3))
+       {
+               printf("Degenerate triangle %d %d %d\n",id1,id2,id3);
+               exit(0);
+       }
+     else
+     {
+          Last_Edge(&temp1,&temp2,&temp3,0);
+            Add_Id_Strips(id1,end);
+            Add_Id_Strips(id2,end);
+            Add_Id_Strips(id3,end);
+            Last_Edge(&id1,&id2,&id3,1);
+     }
+}
+
+
+int Polygon_Output(P_ADJACENCIES temp,int face_id,int bucket,
+                                       ListHead *pListHead, BOOL first, int *swaps,
+                         FILE *bands,int color1,int color2,int color3,BOOL global, BOOL end)
+{
+       ListHead *pListFace;
+       PF_FACES face;
+       P_ADJACENCIES pfNode;
+       int next_face_id,next_bucket,e1,e2,e3,other1,other2,other3;
+       P_ADJACENCIES lpListInfo; 
+     int ties=0;
+     
+     /* We have a polygon to output, the id is face id, and the number
+          of adjacent polygons to it is bucket. This routine extends the patches from
+        either end to make longer triangle strips.
+       */
+                
+                   
+     /*  Now get the edge */
+     Last_Edge(&e1,&e2,&e3,0);
+    
+     /*  Get the polygon with id face_id */
+       pListFace  = PolFaces[face_id];
+       face = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
+
+     /*  We can't go any more */
+     if ((face->nPolSize == 1) || ((face->nPolSize == 4) && (global))) /* if global, then we are still doing patches */
+     {
+        /*     Remove it from the list so we do not have to waste
+               time visiting it in the future, or winding up in an infinite loop
+               if it is the first on that we are looking at for a possible strip
+        */
+        if (face->nPolSize == 1)
+             RemoveList(pListHead,(PLISTINFO) temp);
+        if (first)
+             return 0;
+        else
+             return (Finished(swaps,bands,global));
+    }
+
+    if (face->nPolSize == 3)
+    {
+               /*      It is already a triangle */
+               if (bucket == 0)
+               {
+                       /*      It is not adjacent to anything so we do not have to
+                                  worry about the order of the sides or updating adjacencies
+                       */
+                           
+                 next_face_id = Different(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2),
+                                             e1,e2,e3,&other1,&other2);  
+                       face->nPolSize = 1;
+                       
+               /* If this is the first triangle in the strip */
+               if ((e2 == 0) && (e3 ==0))
+               {
+                    e2 = other1;
+                    e3 = other2;
+               }
+
+               Output_Tri(e2,e3,next_face_id,bands,color1,color2,color3,end);
+               RemoveList(pListHead,(PLISTINFO) temp);
+               return (Finished(swaps,bands,global));
+          }
+               
+        
+          /*  It is a triangle with adjacencies. This means that we
+                   have to:
+                               1. Update the adjacencies in the list, because we are
+                                       using this polygon and it will be deleted.
+                               2. Get the next polygon.
+               */
+               else
+               {
+                       /*   Return the face_id of the next polygon we will be using,
+                               while updating the adjacency list by decrementing the
+                               adjacencies of everything adjacent to the current triangle.
+                       */
+            
+               next_face_id = Update_Adjacencies(face_id, &next_bucket, &e1,&e2,&ties);
+               /*  Maybe we deleted something in a patch and could not find an adj polygon */
+               if (next_face_id == -1)
+               {
+                       Output_Tri(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2),bands,color1,
+                                  color2,color3,end);
+                       face->nPolSize = 1;
+                       RemoveList(pListHead,(PLISTINFO) temp);
+                       return (Finished(swaps,bands,global));
+               }
+                 
+                    /*      Find the other vertex to transmit in the triangle */
+                    e3 = Return_Other(face->pPolygon,e1,e2);
+                 Last_Edge(&other1,&other2,&other3,0);
+           
+                 if ((other2 != 0) && (other3 != 0))
+                 {
+                     /*   See which vertex in the output edge is not in the input edge */
+                     if ((e1 != other2) && (e1 != other3))
+                           e3 = e1;
+                     else if ((e2 != other2) && (e2 != other3))
+                            e3 = e2;
+                     else
+                     {
+                           printf("There is an error in the tri with adj\n");
+                           exit(0);
+                     }
+
+                     /*   See which vertex of the input edge is not in the output edge */
+                     if ((other2 != e1) && (other2 != e2))
+                     {
+                           other1 = other2;
+                           other2 = other3;
+                     }
+                     else if ((other3 != e1) && (other3 != e2))
+                           other1 = other3;
+                     else
+                     {
+                           printf("There is an error in getting the tri with adj\n");
+                           exit(0);
+                     }
+                     
+                 }
+               else
+               {
+                  /*     We are the first triangle in the strip and the starting edge
+                         has not been set yet
+                  */
+                  /*  Maybe we deleted something in a patch and could not find an adj polygon */
+                  if (next_face_id == -1)
+                  {
+                       Output_Tri(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2),bands,color1,
+                                  color2,color3,end);
+                       face->nPolSize = 1;
+                       RemoveList(pListHead,(PLISTINFO) temp);
+                       return (Finished(swaps,bands,global));
+                  }
+
+                  other1 = e3;
+                  e3 = e2;
+                  other2 = e1;
+               }
+          
+                 /*   At this point the adjacencies have been updated  and we
+                               have the next polygon id 
+                 */
+
+               Output_Tri(other1,other2,e3,bands,color1,color2,color3,end);
+               face->nPolSize = 1;
+                    RemoveList(pListHead,(PLISTINFO) temp);
+                 
+               /*  Maybe we deleted something in a patch and could not find an adj polygon */
+               if (next_face_id == -1)
+                    return (Finished(swaps,bands,global));
+        
+               if (Done(next_face_id,59,&next_bucket) == NULL)
+                    {
+                            printf("We deleted the next face 4%d\n",next_face_id);
+                            exit(0);
+                 }
+
+                       pListHead = array[next_bucket];
+                       pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+                       if ( pfNode )
+                               pfNode->face_id = next_face_id;
+                       lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+                               (int (*)(void *,void *)) (Compare)));
+                       if (lpListInfo == NULL)
+                       {
+                               printf("There is an error finding the next polygon3 %d\n",next_face_id);
+                               exit(0);
+                       }
+                       return (Polygon_Output(lpListInfo,next_face_id,next_bucket,
+                                                    pListHead, FALSE, swaps,bands,color1,color2,color3,global,end));
+
+               }
+       }
+
+       else
+       {
+               /*   It is not a triangle, we have to triangulate it .
+                       Since it is not adjacent to anything we can triangulate it
+                       blindly
+               */
+               if (bucket == 0)
+               {
+                         /*   It is the first polygon in the strip, therefore there is no
+                         input edge to start with.
+                    */
+                    if ((e2 == 0) && (e3 ==0))
+                       Blind_Triangulate(face->nPolSize,face->pPolygon,bands,
+                                                 TRUE,1,color1,color2,color3);
+
+                    else
+                       Blind_Triangulate(face->nPolSize,face->pPolygon,bands,
+                                                 FALSE,1,color1,color2,color3);
+
+                            RemoveList(pListHead,(PLISTINFO) temp);
+                                      
+                    /*      We will be at the beginning of the next strip. */
+                    face->nPolSize = 1;
+                    return (Finished(swaps,bands,global));
+               }
+
+
+               else
+               {
+                       
+             
+               /*  WHOLE triangulation */
+                 /*  It is not a triangle and has adjacencies. 
+                               This means that we have to:
+                               1. Triangulate this polygon, not blindly because
+                                       we have an edge that we want to come out on, that
+                                       is the edge that is adjacent to a polygon with the
+                                       least number of adjacencies. Also we must come in
+                                       on the last seen edge.
+                               2. Update the adjacencies in the list, because we are
+                                       using this polygon .
+                               3. Get the next polygon.
+                       */
+                       /*      Return the face_id of the next polygon we will be using,
+                               while updating the adjacency list by decrementing the
+                               adjacencies of everything adjacent to the current polygon.
+                       */
+                               
+               next_face_id = Update_Adjacencies(face_id, &next_bucket, &e1,&e2,&ties);
+           
+               /*  Maybe we deleted something in a patch and could not find an adj polygon */
+               if (next_face_id == -1)
+               {
+                    /*   If we are at the first polygon in the strip and there is no input
+                         edge, then begin is TRUE
+                    */
+                    if ((e2 == 0) && (e3 == 0))
+                         Blind_Triangulate(face->nPolSize,face->pPolygon,
+                                                   bands,TRUE,1,color1,color2,color3);
+
+                    else
+                         Blind_Triangulate(face->nPolSize,face->pPolygon,
+                                                   bands,FALSE,1,color1,color2,color3);
+
+                         RemoveList(pListHead,(PLISTINFO) temp);
+                             
+                      /*      We will be at the beginning of the next strip. */
+                    face->nPolSize = 1;
+                    return (Finished(swaps,bands,global));
+               }
+
+               if (Done(next_face_id,59,&next_bucket) == NULL)
+                 {
+                           printf("We deleted the next face 6 %d %d\n",next_face_id,face_id);
+                           exit(0);
+                    }
+                       
+                       Non_Blind_Triangulate(face->nPolSize,face->pPolygon, 
+                                                bands,next_face_id,face_id,1,color1,color2,color3);
+                                    
+               RemoveList(pListHead,(PLISTINFO) temp);
+               face->nPolSize = 1;
+                       pListHead = array[next_bucket];
+                       pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+                       if ( pfNode )
+                               pfNode->face_id = next_face_id;
+                       lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+                                          (int (*)(void *,void *)) (Compare)));
+                       if (lpListInfo == NULL)
+                    {
+                               printf("There is an error finding the next polygon2 %d %d\n",next_face_id,next_bucket);
+                               exit(0);
+                       }
+                       return (Polygon_Output(lpListInfo,next_face_id,next_bucket,
+                                                    pListHead, FALSE, swaps,bands,color1,color2,color3,global,end));
+               }
+
+       }
+    Last_Edge(&e1,&e2,&e3,0);
+
+}       
+
+
+int Extend_Face(int face_id,int e1,int e2,int *swaps,FILE *bands,
+                int color1,int color2,int color3,int *vert_norm, int normals,
+                int *vert_texture, int texture)
+{
+    int dummy=0,next_bucket;
+    P_ADJACENCIES pfNode,lpListInfo;
+    ListHead *pListHead;
+
+    /*    Try to extend backwards off of the local strip that we just found */
+    
+    vn = vert_norm;
+    vt = vert_texture;
+    norm = normals;
+    text = texture;
+
+    *swaps = 0;
+    /* Find the face that is adjacent to the edge and is not the
+               current face.
+    */
+    face_id = Find_Face(face_id, e1, e2,&next_bucket);
+    if (face_id == -1)
+          return 0;
+                       
+    pListHead = array[next_bucket];
+    pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+    if ( pfNode )
+               pfNode->face_id = face_id;
+    lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+                      (int (*)(void *,void *)) (Compare)));
+    if (lpListInfo == NULL)
+    {
+               printf("There is an error finding the next polygon3 %d\n",face_id);
+               exit(0);
+    }
+    Last_Edge(&dummy,&e1,&e2,1);
+    
+    /*  Find a strip extending from the patch and return the cost */
+    return (Polygon_Output(lpListInfo,face_id,next_bucket,pListHead,TRUE,swaps,bands,color1,color2,color3,TRUE,TRUE));
+}
+
+
diff --git a/Stripe_w/output.h b/Stripe_w/output.h
new file mode 100644 (file)
index 0000000..fd4b34c
--- /dev/null
@@ -0,0 +1,34 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: output.h
+-----------------------------------------------------------------------*/
+
+
+#include "polverts.h"
+
+#define TRIANGLE 3
+#define MAGNITUDE 1000000
+
+void Output_Tri(int id1, int id2, int id3,FILE *bands, int color1, 
+               int color2, int color3,BOOL end);
+void Sgi_Test();
+int Polygon_Output(P_ADJACENCIES temp,int face_id,int bucket,
+                  ListHead *pListHead, BOOL first, int *swaps,
+                  FILE *bands,int color1,int color2,int color3,
+                  BOOL global, BOOL end);
+void Last_Edge();
+void Extend_Backwards();
+int Finished(int *swap, FILE *output, BOOL global);
+int Extend_Face(int face_id,int e1,int e2,int *swaps,FILE *bands,
+                int color1,int color2,int color3,int *vert_norm, int normals,
+                int *vert_texture, int texture);
+void Fast_Reset();
+
+
diff --git a/Stripe_w/outputex.c b/Stripe_w/outputex.c
new file mode 100644 (file)
index 0000000..10bfb74
--- /dev/null
@@ -0,0 +1,514 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: outputex.c
+     This file contains routines that are used for various functions in
+     the local algorithm.
+*/
+/*---------------------------------------------------------------------*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "global.h"
+#include "outputex.h"
+#include "triangulatex.h"
+#include "polverts.h"
+#include "ties.h"
+#include "partial.h"
+#include "sturctsex.h"
+#include "options.h"
+#include "output.h"
+#include "common.h"
+#include "util.h"
+
+
+void Output_TriEx(int id1, int id2, int id3, FILE *output, int next_face, int flag,
+               int where)
+{
+   /* We will save everything into a list, rather than output at once,
+      as was done in the old routine. This way for future modifications
+      we can change the strips later on if we want to.
+   */
+
+  int swap,temp1,temp2,temp3;
+  static int total=0;
+  static int tri=0;
+  static int strips = 0;
+  static int cost = 0;
+
+  if (flag == -20)
+  {
+    cost = cost + where+total+tri+strips+strips;
+    printf("We will need to send %d vertices to the renderer\n",cost);
+    total = 0;
+    tri = 0;
+    strips = 0;
+    return ;
+  }
+
+
+  if (flag == -10) /* We are finished, now is time to output the triangle list */
+  {
+    fprintf(output,"\nt ");
+    tri = tri + Finished(&swap,output,FALSE);
+    total = total + swap;
+    strips++;
+    /*printf("There are %d swaps %d tri %d strips\n",total,tri,strips);*/
+  }
+   
+  else
+  {
+    Last_Edge(&temp1,&temp2,&temp3,0);
+    Add_Id_Strips(id1,where);
+    Add_Id_Strips(id2,where);
+    Add_Id_Strips(id3,where);
+    Last_Edge(&id1,&id2,&id3,1);
+  }
+}
+
+               
+
+
+void Extend_BackwardsEx(int face_id, FILE *output, FILE *strip, int *ties, 
+                       int tie, int triangulate, int swaps, int *next_id)
+{
+    /*  We just made a strip, now we are going to see if we can extend
+          backwards from the starting face, which had 2 or more adjacencies
+          to start with.
+    */
+    int bucket,next_face,num,x,y,z,c,max,f;
+    ListHead *pListFace;
+    PF_FACES face;
+    P_ADJACENCIES temp;
+
+    /*  Get the first triangle that we have saved the the strip data 
+          structure, so we can see if there are any polygons adjacent
+          to this edge or a neighboring one
+    */
+    First_Edge(&x,&y,&z); 
+    
+    pListFace  = PolFaces[face_id];
+    face = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
+
+    num = face->nPolSize;
+
+    /*  Go through the edges to see if there is an adjacency
+          with a vertex in common to the first triangle that was
+          outputted in the strip. (maybe edge was deleted....)
+    */
+    for (c=0; c<num ; c++)
+    {
+          
+       if ( (c != (num-1)) && 
+            (( (*(face->pPolygon+c) == x) && (*(face->pPolygon+c+1) == y)) ||
+               (*(face->pPolygon+c) == y) && (*(face->pPolygon+c+1) == x)))
+       {
+           /*  Input edge is still there see if there is an adjacency */
+           next_face = Find_Face(face_id, x, y, &bucket);
+           if (next_face == -1)
+               /*  Could not find a face adjacent to the edge */
+               break;
+           pListFace = array[bucket];
+           max = NumOnList(pListFace);
+           for (f=0;;f++)
+           {
+                       temp = (P_ADJACENCIES) PeekList(pListFace,LISTHEAD,f);  
+                    if (temp->face_id == next_face)
+                    {
+                         Last_Edge(&z,&y,&x,1);
+                         Polygon_OutputEx(temp,temp->face_id,bucket,pListFace,
+                                                      output,strip,ties,tie,triangulate,swaps,next_id,0);
+                         return;
+                    }
+
+                       if (temp == NULL)
+                       {
+                                       printf("Error in the new buckets%d %d %d\n",bucket,max,0);
+                                       exit(0);
+                       }
+           }
+
+       }
+       else if ( (c == (num -1)) &&
+          ( ((*(face->pPolygon) == x) && (*(face->pPolygon+num-1) == y)) ||
+             (*(face->pPolygon) == y) && (*(face->pPolygon+num-1) == x)))
+       {
+            next_face = Find_Face(face_id,x,y,&bucket);
+            if (next_face == -1)
+               /*  Could not find a face adjacent to the edge */
+                    break;
+               pListFace = array[bucket];
+               max = NumOnList(pListFace);
+               for (f=0;;f++)
+               {
+                       temp = (P_ADJACENCIES) PeekList(pListFace,LISTHEAD,f);
+                    if (temp->face_id == next_face)
+                    {
+                         Last_Edge(&z,&y,&x,1);
+                         Polygon_OutputEx(temp,temp->face_id,bucket,pListFace,
+                                                   output,strip,ties,tie,triangulate,swaps,next_id,0);
+                         return;
+                    }
+
+                       if (temp == NULL)
+                       {
+                                       printf("Error in the new buckets%d %d %d\n",bucket,max,0);
+                                       exit(0);
+                       }
+           }
+       }
+    
+    }
+
+}
+
+void Polygon_OutputEx(P_ADJACENCIES temp,int face_id,int bucket,
+                     ListHead *pListHead, FILE *output, FILE *strips,
+                     int *ties, int tie, int triangulate, int swaps,
+                     int *next_id, int where)
+{
+       ListHead *pListFace;
+       PF_FACES face;
+       P_ADJACENCIES pfNode;
+       static BOOL begin = TRUE;
+       int old_face,next_face_id,next_bucket,e1,e2,e3,other1,other2,other3;
+       P_ADJACENCIES lpListInfo; 
+
+       /*      We have a polygon to output, the id is face id, and the number
+                  of adjacent polygons to it is bucket.
+       */
+
+     Last_Edge(&e1,&e2,&e3,0);
+    
+     /*  Get the polygon with id face_id */
+       pListFace  = PolFaces[face_id];
+       face = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
+
+     if (face->nPolSize == 3)
+       {
+               /*      It is already a triangle */
+               if (bucket == 0)
+               {
+                       /*      It is not adjacent to anything so we do not have to
+                                  worry about the order of the sides or updating adjacencies
+                       */
+                           
+                 Last_Edge(&e1,&e2,&e3,0);
+                 next_face_id = Different(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2),
+                                             e1,e2,e3,&other1,&other2);
+                 /*  No input edge, at the start */
+                 if ((e2 ==0) && (e3 == 0))
+                 {
+                         e2 = other1;
+                         e3 = other2;
+                 }
+           
+                       Output_TriEx(e2,e3,next_face_id,strips,-1,begin,where);
+                       RemoveList(pListHead,(PLISTINFO) temp);
+                       /*      We will be at the beginning of the next strip. */
+                       begin = TRUE;
+               }
+               /*      It is a triangle with adjacencies. This means that we
+                          have to:
+                               1. Update the adjacencies in the list, because we are
+                                       using this polygon and it will be deleted.
+                               2. Get the next polygon.
+               */
+               else
+               {
+                       /*   Return the face_id of the next polygon we will be using,
+                               while updating the adjacency list by decrementing the
+                               adjacencies of everything adjacent to the current triangle.
+                       */
+            
+               next_face_id = Update_AdjacenciesEx(face_id, &next_bucket, &e1,&e2,ties);
+                       old_face = next_face_id;
+                                       
+              /*  Break the tie,  if there was one */
+                   if (tie != FIRST)
+                               old_face = Get_Next_Face(tie,face_id,triangulate);
+
+              if (next_face_id == -1)
+              {
+                    Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie, 
+                           triangulate,swaps,next_id,where);
+                    return;
+              }
+
+
+               /*  We are using a different face */
+               if ((tie != FIRST) && (old_face != next_face_id) && (swaps == ON))
+             {
+                       next_face_id = old_face;
+                       /*  Get the new output edge, since e1 and e2 are for the
+                           original next face that we got.
+                       */
+                  e3 = Get_EdgeEx(&e1,&e2,face->pPolygon,next_face_id,face->nPolSize,0,0);
+               }
+                       
+                  /*      Find the other vertex to transmit in the triangle */
+                  e3 = Return_Other(face->pPolygon,e1,e2);
+               Last_Edge(&other1,&other2,&other3,0);
+           
+               if ((other1 != 0) && (other2 != 0))
+               {
+                      /*   See which vertex in the output edge is not in the input edge */
+                      if ((e1 != other2) && (e1 != other3))
+                              e3 = e1;
+                      else if ((e2 != other2) && (e2 != other3))
+                              e3 = e2;
+                      /* can happen with > 2 polys on an edge  but won't form a good strip so stop
+                       the strip here
+                    */
+                    else
+                      {
+                         Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie, 
+                                                  triangulate,swaps,next_id,where);
+                         return;
+              }
+
+              /*   See which vertex of the input edge is not in the output edge */
+              if ((other2 != e1) && (other2 != e2))
+              {
+                         other1 = other2;
+                         other2 = other3;
+              }
+              else if ((other3 != e1) && (other3 != e2))
+                         other1 = other3;
+              else
+              {
+                 /* Degenerate triangle just return*/
+               Output_TriEx(other1,other2,e3,strips,next_face_id,begin,where);
+                       RemoveList(pListHead,(PLISTINFO) temp);
+                       begin = FALSE;
+               return;
+              }
+                     
+          }
+          
+          /*   There was not an input edge, we are the first triangle in a strip */
+          else 
+          {
+              /*   Find the correct order to transmit the triangle, what is
+                      the output edge that we want ?
+              */
+              other1 = e3;
+              e3 = e2;
+              other2 = e1;
+          }
+          
+          /*   At this point the adjacencies have been updated  and we
+                  have the next polygon id 
+          */
+        Output_TriEx(other1,other2,e3,strips,next_face_id,begin,where);
+          RemoveList(pListHead,(PLISTINFO) temp);
+          begin = FALSE;
+
+          if (Done(next_face_id,59,&next_bucket) == NULL)
+               return;
+
+        pListHead = array[next_bucket];
+          pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+          if ( pfNode )
+               pfNode->face_id = next_face_id;
+          lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+                                (int (*)(void *,void *)) (Compare)));
+          if (lpListInfo == NULL)
+          {
+                               printf("There is an error finding the next polygon3 %d\n",next_face_id);
+                               exit(0);
+          }
+          Polygon_OutputEx(lpListInfo,next_face_id,next_bucket,
+                                       pListHead, output, strips,ties,tie,triangulate,swaps,next_id,where);
+
+       }
+}
+
+       else
+       {
+               /*      It is not a triangle, we have to triangulate it .
+                          Since it is not adjacent to anything we can triangulate it
+                          blindly
+               */
+               if (bucket == 0)
+               {
+                       /*  Check to see if there is not an input edge */
+                 Last_Edge(&other1,&other2,&other3,0);
+                 if ((other1 == 0) && (other2 ==0))
+                         Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips,
+                                                         output,TRUE,where);
+                 else
+                         Blind_TriangulateEx(face->nPolSize,face->pPolygon,strips,
+                                                output,FALSE,where);
+
+                       RemoveList(pListHead,(PLISTINFO) temp);
+                       /*      We will be at the beginning of the next strip. */
+                       begin = TRUE;
+               }
+
+                /*  If we have specified PARTIAL triangulation then
+                       we will go to special routines that will break the
+                       polygon and update the data structure. Else everything
+                       below will simply triangulate the whole polygon 
+               */
+               else if (triangulate == PARTIAL)
+               {
+           
+                 /*  Return the face_id of the next polygon we will be using,
+                       */
+                       next_face_id = Min_Face_AdjEx(face_id,&next_bucket,ties);
+
+               
+                       /* Don't do it partially, because we can go inside and get
+                       less adjacencies, for a quad we can do the whole thing.
+                 */
+                 if ((face_id == next_face_id) && (face->nPolSize == 4)  && (swaps == ON))
+                 {
+                    next_face_id = Update_AdjacenciesEx(face_id, &next_bucket, &e1,&e2,ties);
+                         if (next_face_id == -1)
+                         {
+                              /*  There is no sequential face to go to, end the strip */
+                              Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie, 
+                                                        triangulate,swaps,next_id,where);
+                              return;
+                         }
+               
+                    /* Break the tie,  if there was one */
+                         if (tie != FIRST)
+                                 next_face_id = Get_Next_Face(tie,face_id,triangulate);
+                         Non_Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips,
+                                                             output,next_face_id,face_id,where);
+                            RemoveList(pListHead,(PLISTINFO) temp);
+                 }
+          
+                 /*   Was not a quad but we still do not want to do it partially for
+                         now, since we want to only do one triangle at a time
+                 */
+                 else if ((face_id == next_face_id) && (swaps == ON))
+                      Inside_Polygon(face->nPolSize,face->pPolygon,strips,output,
+                                        next_face_id,face_id,next_id,pListHead,temp,where);
+
+                 else
+                 {
+                                        if ((tie != FIRST) && (swaps == ON))
+                                                next_face_id = Get_Next_Face(tie,face_id,triangulate);
+                                        Partial_Triangulate(face->nPolSize,face->pPolygon,strips,
+                                                               output,next_face_id,face_id,next_id,pListHead,temp,where);
+                                       /*    Check the next bucket again ,maybe it changed 
+                                                We calculated one less, but that might not be the case
+                                       */
+               }
+
+                       if (Done(next_face_id,59,&next_bucket) == NULL)
+                       {
+                       /*  Check to see if there is not an input edge */
+                      Last_Edge(&other1,&other2,&other3,0);
+                      if ((other1 == 0) && (other2 ==0))
+                              Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips,
+                                                              output,TRUE,where);
+                      else
+                              Blind_TriangulateEx(face->nPolSize,face->pPolygon,strips,
+                                                     output,FALSE,where);
+                    
+                    if (Done(face_id,59,&bucket) != NULL)
+                    {
+                         pListHead = array[bucket];
+                                 pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+                                 if ( pfNode )
+                                         pfNode->face_id = face_id;
+                                 lpListInfo = (P_ADJACENCIES) (SearchList(array[bucket], pfNode,
+                                                 (int (*)(void *,void *)) (Compare)));
+                                 RemoveList(pListHead,(PLISTINFO)lpListInfo);
+                    }
+                    begin = TRUE;
+                               return;
+                       }
+                       
+                       begin = FALSE;
+                       pListHead = array[next_bucket];
+                       pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+                       if ( pfNode )
+                               pfNode->face_id = next_face_id;
+                       lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+                                       (int (*)(void *,void *)) (Compare)));
+                       if (lpListInfo == NULL)
+                       {
+                               printf("There is an error finding the next polygon1 %d %d\n",next_face_id,next_bucket);
+                               exit(0);
+                       }
+                       Polygon_OutputEx(lpListInfo,next_face_id,next_bucket,
+                                           pListHead, output, strips,ties,tie,triangulate,swaps,next_id,where);
+               }
+
+          
+               else
+               {
+                       /*  WHOLE triangulation */
+                 /*  It is not a triangle and has adjacencies. 
+                               This means that we have to:
+                               1. TriangulateEx this polygon, not blindly because
+                                       we have an edge that we want to come out on, that
+                                       is the edge that is adjacent to a polygon with the
+                                       least number of adjacencies. Also we must come in
+                                       on the last seen edge.
+                               2. Update the adjacencies in the list, because we are
+                                       using this polygon .
+                               3. Get the next polygon.
+                       */
+                       /*   Return the face_id of the next polygon we will be using,
+                               while updating the adjacency list by decrementing the
+                               adjacencies of everything adjacent to the current polygon.
+                       */
+                               
+               next_face_id = Update_AdjacenciesEx(face_id, &next_bucket, &e1,&e2,ties);
+
+               if (Done(next_face_id,59,&next_bucket) == NULL)
+               {
+                    Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie, 
+                                             triangulate,swaps,next_id,where);
+                    /*    Because maybe there was more than 2 polygons on the edge */
+                    return;
+                    }
+
+                    /*      Break the tie,  if there was one */
+                       else if (tie != FIRST)
+                               next_face_id = Get_Next_Face(tie,face_id,triangulate);
+                               
+                       Non_Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips,
+                                                        output,next_face_id,face_id,where);
+                       RemoveList(pListHead,(PLISTINFO) temp);
+                       begin = FALSE;
+                       pListHead = array[next_bucket];
+                       pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+                       if ( pfNode )
+                               pfNode->face_id = next_face_id;
+                       lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+                                          (int (*)(void *,void *)) (Compare)));
+                       if (lpListInfo == NULL)
+                    {
+                                       printf("There is an error finding the next polygon2 %d %d\n",next_face_id,next_bucket);
+                                       exit(0);
+               }
+                       Polygon_OutputEx(lpListInfo,next_face_id,next_bucket,
+                                              pListHead, output, strips,ties,tie,triangulate,swaps,next_id,where);
+               }
+
+       }
+    Last_Edge(&e1,&e2,&e3,0);
+
+}       
+
+
+
+       
+
+
+
+
diff --git a/Stripe_w/outputex.h b/Stripe_w/outputex.h
new file mode 100644 (file)
index 0000000..f59f7e7
--- /dev/null
@@ -0,0 +1,31 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: outputex.h
+-----------------------------------------------------------------------*/
+
+
+#include "polverts.h"
+
+
+#define TRIANGLE 3
+#define MAGNITUDE 1000000
+
+void Output_TriEx(int id1, int id2, int id3, FILE *output, int next_face, 
+                 int flag, int where);
+void Sgi_Test();
+void Polygon_OutputEx(P_ADJACENCIES temp,int face_id,int bucket,
+                     ListHead *pListHead, FILE *output, FILE *strips,
+                     int *ties, int tie, int triangulate, int swaps,
+                     int *next_id, int where);
+void Extend_BackwardsEx(int face_id, FILE *output, FILE *strip, int *ties, 
+                       int tie, int triangulate, int swaps,int *next_id);
+void FinishedEx();
+
+
diff --git a/Stripe_w/partial.c b/Stripe_w/partial.c
new file mode 100644 (file)
index 0000000..847b405
--- /dev/null
@@ -0,0 +1,668 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: partial.c
+     This file contains routines that are used partial triangulation of polygons
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "global.h"
+#include "outputex.h"
+#include "polyvertsex.h"
+#include "triangulatex.h"
+#include "sturctsex.h"
+#include "polverts.h"
+#include "common.h"
+#include "util.h"
+
+void P_Triangulate_Quad(int out_edge1,int out_edge2,int in_edge1,
+                                         int in_edge2,int size,int *index,
+                                         FILE *output,FILE *fp,int reversed,int face_id,
+                                         int *next_id,ListHead *pListHead, 
+                                         P_ADJACENCIES temp,
+                      int where)
+{
+    int vertex4,vertex5,dummy=60;
+       
+    /* This routine will nonblindly triangulate a quad, meaning
+               that there is a definite input and a definite output
+               edge that we must adhere to. Reversed will tell the orientation
+               of the input edge. (Reversed is -1 is we do not have an input
+               edge, in other words we are at the beginning of a strip.)
+               Out_edge* is the output edge, and in_edge* is the input edge. 
+               Index are the edges of the polygon
+               and size is the size of the polygon. Begin is whether we are
+               at the start of a new strip.
+               Note that we will not necessarily triangulate the whole quad;
+               maybe we will do half and leave the other half (a triangle)
+               for later.
+       */
+       
+
+    /* If we do not have an input edge, then we can make our input
+               edge whatever we like, therefore it will be easier to come
+               out on the output edge. In this case the whole quad is done.
+       */
+       if (reversed == -1)
+       {
+               vertex4 = AdjacentEx(out_edge1,out_edge2,index,size);
+               vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index);
+               Output_TriEx(vertex5,vertex4,out_edge1,output,-1,-1,where);
+               Output_TriEx(vertex4,out_edge1,out_edge2,output,-1,-1,where);
+               dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy);
+               RemoveList(pListHead,(PLISTINFO) temp);
+               return;
+       }
+       
+       /*      These are the 5 cases that we can have for the output edge */
+       
+       /*  Are they consecutive so that we form a triangle to
+               peel off, but cannot use the whole quad?
+       */
+
+       if (in_edge2 == out_edge1) 
+       {
+               /*      Output the triangle that comes out the correct
+                       edge. Save the other half for later.
+               */
+               vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index);
+          Output_TriEx(in_edge1,in_edge2,out_edge2,output,-1,-1,where);
+               /*      Now we have a triangle used, and a triangle that is
+                       left for later.
+               */
+               
+               /*      Now delete the adjacencies by one for all the faces
+                       that are adjacent to the triangle that we just outputted.
+               */
+               Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,
+                               face_id,&dummy,&dummy,&dummy);
+               Delete_AdjEx(out_edge2,in_edge2,&dummy,&dummy, 
+                               face_id,&dummy,&dummy,&dummy);
+               /*      Put the new face in the proper bucket of adjacencies 
+                       There are 2 edges that need to be checked for the triangle
+                       that was just outputted. For the output edge we definitely
+                       will be decreasing the adjacency, but we must check for the
+                       input edge.
+               */
+
+               dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE);
+               dummy = Change_FaceEx(face_id,in_edge2,out_edge2,pListHead,temp,TRUE);
+               
+               /*      Update the face data structure, by deleting the old
+                       face and putting in the triangle as the new face 
+               */
+               New_Face(face_id,in_edge1,out_edge2,vertex4);
+               return;                                                                   
+       }
+       else if (in_edge1 == out_edge1)
+       {
+               /*      We want to output the first triangle (whose output
+                       edge is not the one that we want.
+                       We have to find the vertex that we need, which is
+                       the other vertex which we do not have.
+               */                                              
+               vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index);
+               Output_TriEx(in_edge2,in_edge1,out_edge2,output,-1,-1,where);
+               /*      Now we have a triangle used, and a triangle that is
+                       left for later.
+               */
+               
+               /*      Now delete the adjacencies by one for all the faces
+                       that are adjacent to the triangle that we just outputted.
+               */
+               Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+                               &dummy,&dummy,&dummy);
+               Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 
+                               face_id,&dummy,&dummy,&dummy);
+               
+               /*      Put the new face in the proper bucket of adjacencies */
+               dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE);
+               dummy = Change_FaceEx(face_id,in_edge1,out_edge2,pListHead,temp,TRUE);
+               
+               /*      Update the face data structure, by deleting the old
+                       face and putting in the triangle as the new face 
+               */
+               New_Face(face_id,in_edge2,out_edge2,vertex4);
+               return;
+       }
+       
+       /*      Consecutive cases again, but with the output edge reversed */
+       else if (in_edge1 == out_edge2)
+       {
+               vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
+               Output_TriEx(in_edge2,in_edge1,out_edge1,output,-1,-1,where);
+               /*      Now we have a triangle used, and a triangle that is
+                       left for later.
+               */
+               
+               /*      Now delete the adjacencies by one for all the faces
+                       that are adjacent to the triangle that we just outputted.
+               */
+               Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+                               &dummy,&dummy,&dummy);
+               Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 
+                               face_id,&dummy,&dummy,&dummy);
+               
+               /*      Put the new face in the proper bucket of adjacencies */
+               dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE);
+               dummy = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp,TRUE);
+               
+               /*      Update the face data structure, by deleting the old
+                       face and putting in the triangle as the new face 
+               */
+               New_Face(face_id,in_edge2,out_edge1,vertex4);
+          return;
+       }
+       else if (in_edge2 == out_edge2)
+       {
+               vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
+               Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where);
+               /*      Now we have a triangle used, and a triangle that is
+                       left for later.
+               */
+               /*      Now delete the adjacencies by one for all the faces
+                       that are adjacent to the triangle that we just outputted.
+               */
+               Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+                               &dummy,&dummy,&dummy);
+               Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 
+                               face_id,&dummy,&dummy,&dummy);
+               
+               /*      Put the new face in the proper bucket of adjacencies */
+               dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE);
+               dummy = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp,TRUE);
+               
+               /*      Update the face data structure, by deleting the old
+                       face and putting in the triangle as the new face 
+               */
+               New_Face(face_id,in_edge1,out_edge1,vertex4);
+               return;
+       }
+
+       /*      The final case is where we want to come out the opposite
+               edge.
+       */
+       else
+       {
+        if( ((!reversed) && (out_edge1 == (AdjacentEx(in_edge1,in_edge2,index,size)))) ||
+                    ((reversed) && (out_edge2 == (AdjacentEx(in_edge2,in_edge1,index,size)))))
+               {
+                       /*      We need to know the orientation of the input
+                               edge, so we know which way to put the diagonal.
+                And also the output edge, so that we triangulate
+                correctly. Does not need partial.
+             */
+                       Output_TriEx(in_edge1,in_edge2,out_edge2,output,-1,-1,where);
+                       Output_TriEx(in_edge2,out_edge2,out_edge1,output,-1,-1,where);
+                       dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy);
+                       RemoveList(pListHead,(PLISTINFO) temp);
+               }
+               else
+               {
+                       /*      Input and output orientation was reversed, so diagonal will
+                                       be reversed from above.
+                       */
+                       Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where);
+                       Output_TriEx(in_edge2,out_edge1,out_edge2,output,-1,-1,where);
+                       dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy);
+                       RemoveList(pListHead,(PLISTINFO) temp);
+               }
+               return;
+       }
+}
+
+void P_Triangulate_Polygon(int out_edge1,int out_edge2,int in_edge1,
+                                                  int in_edge2,int size,
+                                                 int *index,FILE *output,FILE *fp,
+                                                 int reversed,int face_id,int *next_id,
+                                                 ListHead *pListHead, P_ADJACENCIES temp2,
+                          int where)
+{
+       /*      We have a polygon greater than 4 sides, which we wish
+               to partially triangulate
+       */
+       int next_bucket,vertex4,dummy = 60;
+       int *temp;
+       P_ADJACENCIES pfNode;
+
+               
+    /* Since we are calling this recursively, we have to check whether         
+               we are down to the case of the quad.
+       */
+       if (size == 4)
+       {
+               P_Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size,
+                                                       index,output,fp,reversed,face_id,next_id,
+                                                       pListHead,temp2,where);
+               return;
+       }
+       
+       /*      We do not have a specified input edge, and therefore we
+               can make it anything we like, as long as we still come out 
+               the output edge that we want.
+       */
+       if (reversed  == -1)
+       {
+               /*      Get the vertex for the last triangle, which is
+                       the one coming out the output edge, before we do
+                       any deletions to the list. We will be doing this
+                       bottom up.
+               */
+               vertex4 = AdjacentEx(out_edge1,out_edge2,index,size);
+               temp = (int *) malloc(sizeof(int) * size);
+               memcpy(temp,index,sizeof(int)*size);
+               Delete_From_ListEx(out_edge2,index,size);
+               /*      We do not have to partially triangulate, since
+                       we will do the whole thing, so use the whole routine
+               */
+               /* Triangulate_PolygonEx(vertex4,out_edge1,in_edge2,
+                                     vertex4,size-1,index,output,fp,reversed,
+                                     face_id,next_id,pListHead,temp2,where); */
+               Triangulate_PolygonEx(vertex4,out_edge1,in_edge2,
+                                     vertex4,size-1,index,output,fp,reversed,
+                                     face_id,where);
+               memcpy(index,temp,sizeof(int)*size);
+               /*      Lastly do the triangle that comes out the output
+                       edge.
+               */
+               Output_TriEx(vertex4,out_edge1,out_edge2,output,-1,-1,where);
+               /*      We were able to do the whole polygon, now we
+                       can delete the whole thing from our data structure.
+               */
+               dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy);
+               RemoveList(pListHead,(PLISTINFO) temp2);
+               return;
+       }         
+
+       /*      These are the 5 cases that we can have for the output edge */
+       
+       /*  Are they consecutive so that we form a triangle to
+               peel off that comes out the correct output edge, 
+               but we cannot use the whole polygon?
+       */
+       if (in_edge2 == out_edge1) 
+       {
+               Output_TriEx(in_edge1,out_edge1,out_edge2,output,-1,-1,where);
+               
+               /*      Now delete the adjacencies by one for all the faces
+                       that are adjacent to the triangle that we just outputted.
+               */
+               Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+                               &dummy,&dummy,&dummy);
+               Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 
+                               face_id,&dummy,&dummy,&dummy);
+               
+               /*      Put the new face in the proper bucket of adjacencies */
+               next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+               next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE);
+               
+               /*      Create a new edgelist without the triangle that
+                       was just outputted.
+               */
+          Delete_From_ListEx(in_edge2,index,size);
+               /*      Update the face data structure, by deleting the old
+                       face and putting in the polygon minus the triangle 
+                       as the new face, here we will be decrementing the size
+                       by one.
+               */
+               New_Size_Face(face_id);
+               return;
+       }
+
+       /*      Next case is where it is again consecutive, but the triangle
+               formed by the consecutive edges do not come out of the
+               correct output edge. (the input edge will be reversed in
+               the next triangle)
+       */
+       else if (in_edge1 == out_edge1)
+       {
+               /*      Get vertex adjacent to in_edge2, but is not in_edge1 */
+               Output_TriEx(in_edge2,in_edge1,out_edge2,output,-1,-1,where);
+               
+               /*      Now delete the adjacencies by one for all the faces
+                       that are adjacent to the triangle that we just outputted.
+               */
+               Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+                               &dummy,&dummy,&dummy);
+               Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 
+                               face_id,&dummy,&dummy,&dummy);
+               
+               /*      Put the new face in the proper bucket of adjacencies */
+               next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+               next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE);
+               
+               /*      Create a new edgelist without the triangle that
+                       was just outputted.
+               */
+          Delete_From_ListEx(in_edge1,index,size);
+               /*      Update the face data structure, by deleting the old
+                       face and putting in the polygon minus the triangle 
+                       as the new face, here we will be decrementing the size
+                       by one.
+               */
+               New_Size_Face(face_id);
+               return;
+       }
+       
+       /*      Consecutive cases again, but with the output edge reversed */
+       else if (in_edge1 == out_edge2)
+       {
+               Output_TriEx(in_edge2,in_edge1,out_edge1,output,-1,-1,where);
+               
+               /*      Now delete the adjacencies by one for all the faces
+                       that are adjacent to the triangle that we just outputted.
+               */
+               Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+                               &dummy,&dummy,&dummy);
+               Delete_AdjEx(out_edge1,out_edge2,&dummy,&dummy, 
+                               face_id,&dummy,&dummy,&dummy);
+               
+               /*      Put the new face in the proper bucket of adjacencies */
+               next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+               next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE);
+               
+               /*      Create a new edgelist without the triangle that
+                       was just outputted.
+               */
+        Delete_From_ListEx(in_edge1,index,size);
+               /*      Update the face data structure, by deleting the old
+                       face and putting in the polygon minus the triangle 
+                       as the new face, here we will be decrementing the size
+                       by one.
+               */
+               New_Size_Face(face_id);
+               return;
+       }
+       else if (in_edge2 == out_edge2)
+       {
+               Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where);
+               
+               /*      Now delete the adjacencies by one for all the faces
+                       that are adjacent to the triangle that we just outputted.
+               */
+               Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+                               &dummy,&dummy,&dummy);
+               Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 
+                               face_id,&dummy,&dummy,&dummy);
+               
+               /*      Put the new face in the proper bucket of adjacencies */
+               next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+               next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE);
+               
+               /*      Create a new edgelist without the triangle that
+                       was just outputted.
+               */
+          Delete_From_ListEx(in_edge2,index,size);
+               /*      Update the face data structure, by deleting the old
+                       face and putting in the polygon minus the triangle 
+                       as the new face, here we will be decrementing the size
+                       by one.
+               */
+               New_Size_Face(face_id);
+               return;
+       }
+
+       /*      Else the edge is not consecutive, and it is sufficiently
+               far away, for us not to make a conclusion at this time.
+               So we can take off a triangle and recursively call this
+               function.
+       */
+       else
+       {
+          if (!reversed)
+               {
+                       vertex4 = AdjacentEx(in_edge2,in_edge1,index,size);
+                       Output_TriEx(in_edge1,in_edge2,vertex4,output,-1,-1,where);
+                       
+                       /*      Now delete the adjacencies by one for all the faces
+                               that are adjacent to the triangle that we just outputted.
+                       */
+                       Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+                               &dummy,&dummy,&dummy);
+                       Delete_AdjEx(in_edge1,vertex4,&dummy,&dummy, 
+                               face_id,&dummy,&dummy,&dummy);
+                       
+                       /*      Put the new face in the proper bucket of adjacencies */
+                       next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+                       next_bucket = Change_FaceEx(face_id,in_edge1,vertex4,pListHead,temp2,FALSE);
+                       
+                       /*      Create a new edgelist without the triangle that
+                               was just outputted.
+                       */
+                       Delete_From_ListEx(in_edge1,index,size);
+                       /*      Update the face data structure, by deleting the old
+                               face and putting in the polygon minus the triangle 
+                               as the new face, here we will be decrementing the size
+                               by one.
+                       */
+                       New_Size_Face(face_id);
+
+                       /*      Save the info for the new bucket, we will need it on
+                               the next pass for the variables, pListHead and temp 
+                       */
+                       pListHead = array[next_bucket];
+                       pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+                       if ( pfNode )
+                               pfNode->face_id = face_id;
+                       temp2 = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+                               (int (*)(void *,void *)) (Compare)));
+                       if (temp2 == NULL)
+                       {
+                               printf("There is an error finding the next polygon10 %d %d\n",next_bucket,face_id);
+                               exit(0);
+                       }
+
+                       P_Triangulate_Polygon(out_edge1,out_edge2,in_edge2,
+                                                vertex4,size-1,index,output,fp,!reversed,
+                                                face_id,next_id,pListHead,temp2,where);
+               }
+               else
+               {
+                       vertex4 = AdjacentEx(in_edge1,in_edge2,index,size);
+                       Output_TriEx(in_edge2,in_edge1,vertex4,output,-1,-1,where);
+
+                       /*      Now delete the adjacencies by one for all the faces
+                               that are adjacent to the triangle that we just outputted.
+                       */
+                       Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+                               &dummy,&dummy,&dummy);
+                       Delete_AdjEx(in_edge2,vertex4,&dummy,&dummy, 
+                               face_id,&dummy,&dummy,&dummy);
+                       
+                       /*      Put the new face in the proper bucket of adjacencies */
+                       next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+                       next_bucket = Change_FaceEx(face_id,in_edge2,vertex4,pListHead,temp2,FALSE);
+                       
+                       /*      Create a new edgelist without the triangle that
+                               was just outputted.
+                       */
+                       Delete_From_ListEx(in_edge2,index,size);
+                       
+                       /*      Update the face data structure, by deleting the old
+                               face and putting in the polygon minus the triangle 
+                               as the new face, here we will be decrementing the size
+                               by one.
+                       */
+                       New_Size_Face(face_id);
+                       
+                       /*      Save the info for the new bucket, we will need it on
+                               the next pass for the variables, pListHead and temp 
+                       */
+                       pListHead = array[next_bucket];
+                       pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+                       if ( pfNode )
+                               pfNode->face_id = face_id;
+                       temp2 = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
+                               (int (*)(void *,void *)) (Compare)));
+                       if (temp2 == NULL)
+                       {
+                               printf("There is an error finding the next polygon11 %d %d\n",face_id,next_bucket);
+                               exit(0);
+                       }
+
+                       P_Triangulate_Polygon(out_edge1,out_edge2,vertex4,
+                                                      in_edge1,size-1,index,output,fp,!reversed,
+                                                      face_id,next_id,pListHead,temp2,where);
+               }
+               return;
+       }
+}
+
+void P_Triangulate(int out_edge1,int out_edge2,int in_edge1,
+                                int in_edge2,int size,int *index,
+                                FILE *fp,FILE *output,int reversed,int face_id,
+                                int *next_id,ListHead *pListHead, 
+                                P_ADJACENCIES temp,int where)
+{
+               
+       if (size == 4)
+               P_Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size,
+                                     index,fp,output,reversed,face_id,next_id,pListHead, temp,where);
+       else
+               P_Triangulate_Polygon(out_edge1,out_edge2,in_edge1,in_edge2,size,
+                                        index,fp,output,reversed,face_id,next_id,pListHead,temp,where);
+}
+
+ void Partial_Triangulate(int size,int *index, FILE *fp,
+                                                FILE *output,int next_face_id,int face_id,
+                                                int *next_id,ListHead *pListHead,
+                                                P_ADJACENCIES temp, int where)
+{
+       int id1,id2,id3;
+       int nedge1,nedge2;
+       int reversed;
+
+       /*      We have a polygon that has to be triangulated and we cannot
+               do it blindly, ie we will try to come out on the edge that
+               has the least number of adjacencies, But also we do not
+               want to triangulate the whole polygon now, so that means 
+               we will output the least number of triangles that we can
+               and then update the data structures, with the polygon
+               that is left after we are done.
+       */
+       Last_Edge(&id1,&id2,&id3,0);
+       
+       /*      Find the edge that is adjacent to the new face ,
+               also return whether the orientation is reversed in the
+               face of the input edge, which is id2 and id3.
+       */
+       reversed = Get_EdgeEx(&nedge1,&nedge2,index,next_face_id,size,id2,id3);
+       
+       /*   Input edge and output edge can be the same if there are more than
+          one polygon on an edge 
+     */
+     if ( ((nedge1 == id2) && (nedge2 == id3)) ||
+          ((nedge1 == id3) && (nedge2 == id2)) )
+          /*   Set output edge arbitrarily but when come out of here the
+               next face will be on the old output edge (identical one)
+          */
+          nedge2 = Return_Other(index,id2,id3);
+
+          /*   Do the triangulation */ 
+       P_Triangulate(nedge1,nedge2,id2,id3,size,index,fp,output,reversed,
+                        face_id,next_id,pListHead,temp,where);
+}
+
+ void Input_Edge(int face_id, int *index, int size, int in_edge1, int in_edge2, 
+                FILE *fp, FILE *output,ListHead *pListHead, P_ADJACENCIES temp2,
+                int where)
+ {
+     /* The polygon had an input edge, specified by input1 and input2 */
+    
+     int output1;
+     int vertex4, vertex5,dummy=60;
+
+     output1 = Get_Output_Edge(face_id,size,index,in_edge1,in_edge2);
+       vertex5 = AdjacentEx(in_edge2,in_edge1,index,size); 
+     vertex4 = AdjacentEx(in_edge1,in_edge2,index,size);
+
+     if (vertex4 == output1)
+     {
+               Output_TriEx(in_edge2,in_edge1,output1,output,-1,-1,where);
+               /*      Now delete the adjacencies by one for all the faces
+                       that are adjacent to the triangle that we just outputted.
+               */
+               Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+                               &dummy,&dummy,&dummy);
+               Delete_AdjEx(in_edge2,output1,&dummy,&dummy, 
+                               face_id,&dummy,&dummy,&dummy);
+               /*      Put the new face in the proper bucket of adjacencies */
+               Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+               Change_FaceEx(face_id,in_edge2,output1,pListHead,temp2,FALSE);
+               
+               /*      Create a new edgelist without the triangle that
+                       was just outputted.
+               */
+          Delete_From_ListEx(in_edge2,index,size);
+
+    }  
+    else if (vertex5 == output1)
+    {
+          Output_TriEx(in_edge1,in_edge2,vertex5,output,-1,-1,where);
+               /*      Now delete the adjacencies by one for all the faces
+                       that are adjacent to the triangle that we just outputted.
+               */
+               Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
+                               &dummy,&dummy,&dummy);
+               Delete_AdjEx(in_edge1,vertex5,&dummy,&dummy, 
+                               face_id,&dummy,&dummy,&dummy);
+               /*      Put the new face in the proper bucket of adjacencies */
+               Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+               Change_FaceEx(face_id,in_edge1,vertex5,pListHead,temp2,FALSE);
+               
+               /*      Create a new edgelist without the triangle that
+                       was just outputted.
+               */
+          Delete_From_ListEx(in_edge1,index,size);
+    }
+               
+    /* Update the face data structure, by deleting the old
+               face and putting in the polygon minus the triangle 
+               as the new face, here we will be decrementing the size
+               by one.
+    */
+    New_Size_Face(face_id);
+    return;
+ }
+ void Inside_Polygon(int size,int *index,FILE *fp,FILE *output,
+                   int next_face_id,int face_id,int *next_id,
+                   ListHead *pListHead,P_ADJACENCIES temp, int where)
+ {
+     /* We know that we have a polygon that is greater than 4 sides, and
+        that it is better for us to go inside the polygon for the next
+        one, since inside will have less adjacencies than going outside.
+        So, we are not doing partial for a part of the polygon.
+      */
+    int id1,id2,id3;
+    int new1,new2;
+
+    Last_Edge(&id1,&id2,&id3,0);
+
+    /*  See if the input edge existed in the polygon, that will help us */
+       if (Exist(face_id,id2,id3))
+        Input_Edge(face_id,index,size,id2,id3,output,fp,pListHead,temp,where);
+    else
+    {
+        /*  Make one of the input edges 
+            We will choose it by trying to get an edge that has something
+            in common with the last triangle, or by getting the edge that
+            is adjacent to the least number of thigs, with preference given
+            to the first option
+        */
+               
+        Get_Input_Edge(index,id1,id2,id3,&new1,&new2,size,face_id);
+        Input_Edge(face_id,index,size,new1,new2,output,fp,pListHead,temp,where);
+    }
+ }
+
+
diff --git a/Stripe_w/partial.h b/Stripe_w/partial.h
new file mode 100644 (file)
index 0000000..6a4e3a5
--- /dev/null
@@ -0,0 +1,20 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: partial.h
+-----------------------------------------------------------------------*/
+
+void Partial_Triangulate(int size,int *index, FILE *fp,
+                        FILE *output,int next_face_id,int face_id,
+                        int *next_id,ListHead *pListHead,
+                        P_ADJACENCIES temp, int where);
+void Inside_Polygon(int size,int *index,FILE *fp,FILE *output,
+                   int next_face_id,int face_id,int *next_id,
+                   ListHead *pListHead,P_ADJACENCIES temp, int where);
+
diff --git a/Stripe_w/polverts.h b/Stripe_w/polverts.h
new file mode 100644 (file)
index 0000000..b3979eb
--- /dev/null
@@ -0,0 +1,108 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: polverts.h
+-----------------------------------------------------------------------*/
+
+
+#ifndef _POLVERTS_H
+#define _POLVERTS_H
+
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include "queue.h"
+
+#ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+#else
+#  include <malloc.h>
+#endif
+
+
+typedef struct adjacencies
+{
+       Node ListNode;
+       int face_id;
+} ADJACENCIES,*P_ADJACENCIES;
+
+typedef struct FVerts
+{
+       Node ListNode;
+       int *pPolygon;
+       int nPolSize;
+       int nId;
+} F_VERTS, *PF_VERTS;
+
+/*Every time we need to use this, cast it ( ListInfo*)*/
+
+typedef struct FEdges
+{
+       Node ListNode;
+       int edge[3];
+}F_EDGES,*PF_EDGES;
+
+typedef struct FFaces
+{
+       Node ListNode;
+       int *pPolygon;
+       int *pNorms;
+    int     seen;
+    int seen2;
+    int seen3;
+       int nPolSize;
+       F_EDGES **VertandId;
+       int *marked;
+               int *walked;
+} F_FACES,*PF_FACES;
+       
+
+typedef struct Strips
+{
+       Node ListNode;
+       int face_id;
+} Strips,*P_STRIPS;
+
+
+     struct vert_added
+     {
+          int num;
+          int *normal;
+     };
+
+
+/*      external functions */
+void Find_Adjacencies(int num_faces);
+void Test_Adj_Struct();
+void Test_SGI_Struct();
+void Write_Edges();
+void Build_SGI_Table(int num_verts,int num_faces);
+void Save_Walks(int numfaces);
+void Find_Bands(int numfaces, FILE *output_file, int *swaps, int *bands, 
+                int *cost, int *tri, int norms, int *vert_norms, int texture,
+               int *vert_texture);
+void Save_Rest(int *numfaces);
+void Assign_Walk(int lastvert, PF_FACES temp2, int front_walk,int y,
+                               int back_walk);
+void Save_Walks(int numfaces);
+       
+
+/*      Globals */
+extern ListHead **PolVerts;
+extern ListHead **PolFaces;
+extern ListHead **PolEdges;
+extern ListHead *array[60];
+extern int     id_array[60];
+extern ListHead *strips[1];
+extern ListHead *all_strips[100000]; /*  Assume max 100000 strips */
+
+
+#endif _POLVERTS_H
diff --git a/Stripe_w/polyvertsex.h b/Stripe_w/polyvertsex.h
new file mode 100644 (file)
index 0000000..8e05a7d
--- /dev/null
@@ -0,0 +1,34 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: polvertsex.h
+-----------------------------------------------------------------------*/
+
+#include "queue.h"
+#include <malloc.h>
+
+
+/*      external functions */
+void Start_Vert_Struct();
+void Start_Face_StructEx();
+void Start_Edge_StructEx();
+void AddNewNode();
+void AddNewFaceEx();      
+void Find_AdjacenciesEx();
+void Test_Adj_Struct();
+void Test_SGI_Struct();
+void Write_Edges();
+void End_Verts_Struct();
+void End_Face_StructEx();
+void End_Edge_StructEx();
+void Build_SGI_TableEx();
+void Add_AdjEdgeEx();
+
+
+
diff --git a/Stripe_w/queue.c b/Stripe_w/queue.c
new file mode 100644 (file)
index 0000000..966f203
--- /dev/null
@@ -0,0 +1,226 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: queue.c
+     This file contains the routines used in the data structures lists, which
+     are queues.
+*/
+/*---------------------------------------------------------------------*/
+
+ #include "queue.h"
+
+
+/*----------------------------------------------------------------------------
+ * InitList:
+ */
+BOOL  InitList  (PLISTHEAD LHead)
+{
+  if (LHead == NULL) return(FALSE);
+
+  LHead->LHeaders[LISTHEAD] = LHead->LHeaders[LISTTAIL] = NULL;
+  LHead->NumList = 0;
+  return(TRUE);
+}
+
+/*----------------------------------------------------------------------------
+ * AddHead:
+ */
+BOOL  AddHead(PLISTHEAD LHead, PLISTINFO LInfo)
+{
+     if (LHead == NULL || LInfo == NULL)
+          return(FALSE);
+     if (EMPTYLIST(LHead))
+          LHead->LHeaders[LISTTAIL] = LInfo;
+     else LHead->LHeaders[LISTHEAD]->ListNode.Previous = (void  *) LInfo;
+
+     LInfo->ListNode.Next = (void  *) LHead->LHeaders[LISTHEAD];
+     LHead->LHeaders[LISTHEAD] = LInfo;
+     LInfo->ListNode.Previous = NULL;
+     LHead->NumList++;
+     return(TRUE);
+}
+
+/*----------------------------------------------------------------------------
+ * AddTail
+ */
+BOOL  AddTail(PLISTHEAD LHead, PLISTINFO LInfo)
+{
+     if (LHead == NULL || LInfo == NULL)
+          return(FALSE);
+     if (EMPTYLIST(LHead))
+          LHead->LHeaders[LISTHEAD] = LInfo;
+     else LHead->LHeaders[LISTTAIL]->ListNode.Next = (void *) LInfo;
+
+     LInfo->ListNode.Previous = (void  *) LHead->LHeaders[LISTTAIL];
+     LHead->LHeaders[LISTTAIL] = LInfo;
+     LInfo->ListNode.Next = NULL;
+     LHead->NumList++;
+     return(TRUE);
+}
+
+
+BOOL  InsertNode( PLISTHEAD LHead, int nPos, PLISTINFO LInfo )
+{
+PLISTINFO LAddNode;
+
+     if ( LHead == NULL || LInfo == NULL || nPos > NumOnList( LHead ) ) 
+          return( FALSE );
+
+     if ( nPos == 0 )
+          AddHead( LHead, LInfo );
+     else if ( nPos == NumOnList( LHead ) ) 
+          AddTail( LHead, LInfo );
+     else
+     {
+          if ( (LAddNode = PeekList( LHead, LISTHEAD, nPos - 1 )) == NULL )
+               return( FALSE );
+          
+          ((PLISTINFO)LAddNode->ListNode.Next)->ListNode.Previous = LInfo;
+          LInfo->ListNode.Next      = LAddNode->ListNode.Next;
+          LInfo->ListNode.Previous  = LAddNode;
+          LAddNode->ListNode.Next   = LInfo;
+          
+          LHead->NumList++;
+     }
+
+     return( TRUE );
+}
+
+
+
+
+/*----------------------------------------------------------------------------
+ *  RemHead:
+ */
+PLISTINFO  RemHead(PLISTHEAD LHead)
+{
+     PLISTINFO t, t1;
+
+     if ( LHead == NULL || EMPTYLIST(LHead) )
+          return(NULL);
+
+     t = LHead->LHeaders[LISTHEAD];
+     LHead->LHeaders[LISTHEAD] = (PLISTINFO) t->ListNode.Next;
+
+     if (LHead->LHeaders[LISTHEAD] != NULL)
+     {
+          t1 = (PLISTINFO) t->ListNode.Next;
+          t1->ListNode.Previous = NULL;
+     }
+     else
+          LHead->LHeaders[LISTTAIL] = NULL;
+
+     LHead->NumList--;
+
+     return(t);
+}
+
+/*----------------------------------------------------------------------------
+ *  RemTail:
+ */
+PLISTINFO  RemTail(PLISTHEAD   LHead)
+{
+     PLISTINFO   t, t1;
+
+     if ( LHead == NULL || EMPTYLIST(LHead) )
+          return(NULL);
+
+     t = LHead->LHeaders[LISTTAIL];
+     LHead->LHeaders[LISTTAIL] = (PLISTINFO) t->ListNode.Previous;
+     if (LHead->LHeaders[LISTTAIL] != NULL)
+     {
+          t1 = (PLISTINFO) t->ListNode.Previous;
+          t1->ListNode.Next = NULL;
+     }
+     else
+          LHead->LHeaders[LISTHEAD] = NULL;
+
+     LHead->NumList--;
+     return(t);
+}
+
+/*----------------------------------------------------------------------------
+ * PeekList:
+ */
+PLISTINFO  PeekList(PLISTHEAD LHead, int wch, int index )
+{
+     PLISTINFO  t;
+
+     if (LHead == NULL)
+          return(NULL);
+     if ( (t = LHead->LHeaders[wch]) == NULL )
+          return(NULL);
+
+     for (; t != NULL && index > 0; index-- )
+          t = (wch == LISTHEAD)  ? (PLISTINFO) t->ListNode.Next  :
+                                   (PLISTINFO) t->ListNode.Previous;
+     return(t);
+}
+
+
+/*----------------------------------------------------------------------------
+ * RemoveList:
+ */
+PLISTINFO   RemoveList( PLISTHEAD LHead, PLISTINFO LInfo )
+{
+     PLISTINFO     t, t1;
+
+     t = LInfo;
+     if (LHead == NULL)
+          return(NULL);
+     if (LHead->LHeaders[LISTHEAD] == t)
+          t = (PLISTINFO) RemHead(LHead);
+     else if (LHead->LHeaders[LISTTAIL] == t)
+          t = (PLISTINFO) RemTail(LHead);
+     else
+     {
+          t1                    = (PLISTINFO) t->ListNode.Previous;
+          t1->ListNode.Next     = t->ListNode.Next;
+          t1                    = (PLISTINFO) t->ListNode.Next;
+          t1->ListNode.Previous = t->ListNode.Previous;
+          LHead->NumList--;
+     }
+
+     return(t);
+}
+
+/*----------------------------------------------------------------------------
+ * SearchList:
+ *       Try to find a specific node in the queue whose key matches with
+ *  searching key. Return the pointer to that node if found, return NULL
+ *  otherwise
+ *
+ *  Input:
+ *    lpHashTbl       => a far pointer to the hash table
+ *    lpKey           => a far poniter to searching key
+ *    CompareCallBack => comparision function
+ *
+ *  Output: a far pointer to the node to be found
+ *
+ */
+PLISTINFO  SearchList(
+                        PLISTHEAD lpListHead,
+                        PVOID lpSKey,
+                        int (* CompareCallBack) ( PVOID, PVOID ) )
+{
+PLISTINFO lpListInfo;
+
+     lpListInfo = PeekList( lpListHead, LISTHEAD, 0);
+     while ( lpListInfo != NULL )
+     {
+          if ( CompareCallBack( lpListInfo, lpSKey ) )
+               break;
+          lpListInfo = GetNextNode( lpListInfo );
+     }
+
+     return( lpListInfo );
+}
diff --git a/Stripe_w/queue.h b/Stripe_w/queue.h
new file mode 100644 (file)
index 0000000..0bf926e
--- /dev/null
@@ -0,0 +1,283 @@
+
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE:queue.h
+-----------------------------------------------------------------------*/
+
+#ifndef QUEUE_INCLUDED
+#define QUEUE_INCLUDED
+
+/*        %%s  Node      */
+/*****************************************************************
+     This structure is used to store the List linkage information of a
+ListInfo structure.  It contains all the necessary information for the
+List functions to function properly.  This structure must be the first
+one defined in any block of memory to be linked with the List functions.
+for an example of the used of The Node structure look in the files
+ipd2dms.c and ipd2man.h
+******************************************************************/
+#include <stdio.h>
+#define FALSE 0
+#define TRUE  1
+typedef struct
+{
+     void  *Next;
+     void  *Previous;
+}
+     Node, * PNODE;
+
+/*****************************************************************
+     Next     :  is a pointer to the next structure in this List.
+     Previous :  is a pointer to the previous structure in this List.
+     priority :  this is the priority of this structure in the List.  The
+                 highest priority is 0.  This field is only used by the
+                 functions EnQue and DeQue.
+******************************************************************/
+/*        %%e       */
+
+
+/*        %%s  ListInfo      */
+
+/*****************************************************************
+      This is the general means of linking application defined information into
+Lists and queues.  All structures must begin with the Node Structure.  All
+other data in the structure is user definable.
+******************************************************************/
+
+typedef struct List
+{
+     Node     ListNode;       /*  link to the next Listinfo Structure  */
+     /*  user definable data  */
+}    ListInfo, *PLISTINFO;
+
+/*****************************************************************
+     ListNode  :  this is the required node structure for the List
+                  mainpulation functions.  This must be the first
+                  element of a user definable structure.
+
+     In order for an application to use the List routines, it must define
+a structure with all the needed information.  The first element in the
+user definable structure must be a Node structure.  The Node structure
+contains all the necessary information for the List routines to do their
+magic.  For an example of a user defined List structure see the file
+ipd2i.h.  The User definable structure can be passed to any List function
+that excepts a pointer to a ListInfo structure.
+
+example:
+
+typedef  mstruct
+{
+     Node   ListNode;
+     int    a,b,c,d,e,f,g;
+}
+     mystruct;
+
+     the user definable portion of the above structure is represented by
+the integers a,b,c,d,e,f,g.  When passing this structure to a List
+function a cast of (ListInfo *) must be made to satisify the "C" complier.
+******************************************************************/
+/*        %%e       */
+
+
+/*        %%s ListHead        */
+/*****************************************************************
+     ListHead is used as a header to a List.  LHeaders[0] points to the
+head of the List.  LHeaders[1] points the tail of the list.  When
+accessing these variables use the defines  LISTHEAD, LISTTAIL.
+******************************************************************/
+
+typedef struct LHead
+{
+     PLISTINFO  LHeaders[2];
+     int         NumList;
+}
+ListHead, *PLISTHEAD;
+
+/*****************************************************************
+     LHeaders   :  this is an array of two pointers to ListInfo structures.
+                   This information is used to point to the head and tail of
+                   a list.
+     NumList    :  this integer hold the number of structures linked into this
+                   list.
+
+ListHead #define:
+
+     LISTHEAD  :  when Peeking down a list this specifies you should
+                  start at the Head of the list and search downward.
+
+     LISTTAIL  :  when Peeking down a list this specifies you should
+                  start at the tail of the list and search foward.
+ ******************************************************************/
+
+#define  LISTHEAD  0
+
+#define  LISTTAIL  1
+/*        %%e       */ 
+
+typedef int BOOL;
+typedef void * PVOID;
+
+#define PEEKFROMHEAD( lh, ind )     ( PeekList( (lh), LISTHEAD, (ind) ) )
+#define PEEKFROMTAIL( lh, ind )     ( PeekList( (lh), LISTTAIL, (ind) ) )
+#define EMPTYLIST( lh )             ( ( (lh)->LHeaders[LISTHEAD] == NULL ) )
+
+/*   General utility routines   */
+/*        %%s QueRoutines          */
+BOOL    InitList      ( PLISTHEAD );
+
+/*****************************************************************
+     InitList :  Initialize a new list structure for use with the List
+                 routines
+
+     INPUTS   :  LHead : a pointer to a ListHead structure.
+     OUTPUT   :  a boolean value TRUE if no errors occured FALSE
+                 otherwise
+******************************************************************/
+
+
+PLISTINFO  PeekList      ( PLISTHEAD, int, int   );
+
+/*****************************************************************
+     PeekList :  This funciton peeks down a list for the N'th element
+                 from the HEAD or TAIL of the list
+
+     INPUTS   :  LHead    :  a pointer to a List head structure.
+                 from     :  can either search from the HEAD or TAIL
+                             of the list
+                 where    :  how many nodes from the begining should the
+                             List routines look.
+     OUTPUT   :  a pointer to a ListInfo structure identified by
+                 from/where or NULL if an error occurred.
+******************************************************************/
+
+
+PLISTINFO   RemoveList( PLISTHEAD LHead, PLISTINFO LInfo );
+
+
+/*****************************************************************
+     RemoveList: Remove a ListInfo structure from a List.
+
+     INPUTS    : LHead  :  a pointer to a ListHead structure.
+                 LInfo  :  a pointer to the ListInfo structure to remove
+                           from the list.
+     OUTPUT    : a pointer to the ListInfo structure that was removed or
+                 NULL if an error occurred.
+******************************************************************/
+
+BOOL  InsertNode( PLISTHEAD LHead, int nPos, PLISTINFO LInfo );
+
+/*****************************************************************
+     InsertNode: add a node to a list after a given node
+     
+     INPUTS    : LHead : a pointer to a ListHead structure.
+                 nPos  : the position to insert the node into
+                 LInfo : a pointer to the new node to add to the list.
+     OUTPUT: a boolean value TRUE if all goes well false otherwise
+*****************************************************************/
+
+BOOL   AddHead       ( PLISTHEAD, PLISTINFO );
+
+/*****************************************************************
+     AddHead   : add a ListInfo structure to the HEAD of a list.
+
+     INPUTS    : LHead  : a pointer to a ListHead structure of the list
+                          to add to.
+                 LInfo  : a pointer to the ListInfo structure to add to
+                          the list.
+     OUTPUT    : A boolean value TRUE if no errors occurred FALSE
+                 otherwise.
+******************************************************************/
+
+
+BOOL     AddTail       ( PLISTHEAD, PLISTINFO );
+
+/*****************************************************************
+     AddTail   : Add a ListInfo structure to the TAIL of a list.
+
+     INPUTS    : LHead  : a pointer to a ListHead structure of the List
+                          to add to.
+                 LInfo  : a pointer to the ListInfo structure to add to
+                          the List.
+     OUTPUT    : a boolean value TRUE if no errors occurred FALSE
+                 otherwise.
+******************************************************************/
+
+
+PLISTINFO  RemTail       ( PLISTHEAD );
+
+/*****************************************************************
+     RemTail   : Remove a ListInfo structure from the TAIL of a List.
+
+     INPUTS    : LHead  : a pointer to a ListHead structure of the List
+                          to remove from.
+     OUTPUT    : a pointer to the ListInfo structure that was removed
+                 or NULL if an error occurred.
+******************************************************************/
+
+
+PLISTINFO  RemHead       ( PLISTHEAD );
+
+/*****************************************************************
+     RemHead   : Remove a ListInfo structure from the Head of a List.
+
+     INPUTS    : LHead  : a pointer to a ListHead structure of the List
+                          to remove from.
+     OUTPUT    : a pointer to the ListInfo structure that was removed or
+                 NULL if an error occurred.
+******************************************************************/
+
+PLISTINFO  SearchList(
+                        PLISTHEAD lpListHead,
+                        PVOID lpSKey,
+                        int ( * CompareCallBack) ( PVOID, PVOID ) );
+
+/*****************************************************************
+  SearchList:
+        Try to find a specific node in the queue whose key matches with
+   searching key. Return the pointer to that node if found, return NULL
+   otherwise
+
+   Input:
+     lpHashTbl       => a far pointer to the hash table
+     lpKey           => a far poniter to searching key
+     CompareCallBack => comparision function
+
+   Output: a far pointer to the node to be found
+
+ ******************************************************************/
+
+#define           NumOnList(lh) ( ((lh)->NumList)        )
+
+/*****************************************************************
+     NumOnList: Returns the number of Nodes linked to a ListHead
+                structure.  This number is maintained by the List
+                routines.
+******************************************************************/
+
+#define           GetNextNode(pli) ( ((pli)->ListNode.Next) )
+
+/********************************************************
+     GetNextNode: This macro returns the Next Structure in this list.
+                  This macro will return NULL if no more structures are
+                  in the List.
+*********************************************************/
+
+#define           GetPrevNode(pli) ( ((pli)->ListNode.Previous) )
+
+/********************************************************
+     GetPrevNode: This macro returns the Previous Structure in this list.
+                  This macro will reutrn NULL if no more structures are
+                  in the List.
+********************************************************/
+/*        %%e       */
+
+#endif
+
+
diff --git a/Stripe_w/sgi_triang.c b/Stripe_w/sgi_triang.c
new file mode 100644 (file)
index 0000000..1a13090
--- /dev/null
@@ -0,0 +1,628 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: sgi_triang.c
+     File contains the routines that do the whole triangulation
+     of polygons.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "global.h"
+#include "output.h"
+#include "polverts.h"
+#include "sturcts.h"
+#include "common.h"
+#include "util.h"
+#include "init.h"
+
+int Adjacent(int id2,int id1, int *list, int size)
+{
+       /*      Return the vertex that is adjacent to id1,
+               but is not id2, in the list of integers.
+       */
+
+       register int x=0;
+       
+       while (x < size)
+       {
+               if (*(list+x) == id1)
+               {
+                       if ((x != (size -1)) && (x != 0))
+                       {
+                               if ( *(list+x+1) != id2)
+                                       return *(list+x+1);
+                               else
+                                       return *(list+x-1);
+                       }
+                       else if (x == (size -1))
+                       {
+                               if (*(list) != id2)
+                                       return *(list);
+                               else
+                                       return *(list+x-1);
+                       }
+                       else
+                       {
+                               if (*(list+size-1) != id2)
+                                       return *(list+size-1);
+                               else
+                                       return *(list+x+1);
+                       }
+               }
+               x++;
+       }
+       /*   if there are degeneracies */
+     return id1;
+}
+
+
+void Rearrange_Index(int *index, int size)
+{
+       /*      If we are in the middle of a strip we must find the
+               edge to start on, which is the last edge that we had
+               transmitted.
+       */
+       int x,f,y,e1,e2,e3;
+       register int increment = 1;
+     int *temp;
+
+       /*      Find where the input edge is in the input list */
+       Last_Edge(&e1,&e2,&e3,0);
+       for (y = 0; y < size; y++)
+       {
+               if (*(index+y) == e2)
+               {
+                       if ((y != (size - 1)) && (*(index+y+1) == e3))
+                               break;
+                       else if ((y == (size - 1)) && (*(index) == e3))
+                               break;
+               else if ((y != 0) && (*(index+y-1) == e3))
+               {
+                    increment = -1;
+                    break;
+               }
+               else if ((y==0) && (*(index+size-1) == e3))
+               {
+                    increment = -1;
+                    break;
+               }
+               }
+               if (*(index+y) == e3)
+               {
+                       if ((y != (size - 1)) && (*(index+y+1) == e2))
+                               break;
+                       else if ((y == (size - 1)) && (*(index) == e2))
+                               break;
+            else if ((y != 0) && (*(index+y-1) == e2))
+            {
+                increment = -1;
+                break;
+            }
+            else if ((y==0) && (*(index+size-1) == e2))
+            {
+                increment = -1;
+                break;
+            }
+               }
+               /*      Edge is not here, we are at the beginning */
+               if ((y == (size-1)) && (increment != -1))
+                       return;
+       }
+       
+       /*      Now put the list into a new list, starting with the
+               input edge. Increment tells us whether we have to go 
+               forward or backward.
+       */
+       /*      Was in good position already */
+       if ((y == 0) && (increment == 1)) 
+               return;
+       
+     temp = (int *) malloc(sizeof(int) * size);
+     memcpy(temp,index,sizeof(int)*size);
+
+       if (increment == 1)
+       {
+               x=0;
+               for (f = y ; f< size; f++)
+               {
+                       *(index+x) = *(temp+f);
+                       x++;
+               }
+               /*      Finish the rest of the list */  
+               for(f = 0; f < y ; f++)
+               {
+                       *(index+x) = *(temp+f);
+                       x++;
+               }
+       }
+       else
+       {
+               x=0;
+               for (f = y ; f >= 0; f--)
+               {
+                       *(index+x) = *(temp+f);
+                       x++;
+               }
+               /*      Finish the rest of the list */  
+               for(f = (size - 1); f > y ; f--)
+               {
+                       *(index+x) = *(temp+f);
+                       x++;
+               }
+       }
+}
+
+void Delete_From_List(int id,int *list, int *size)
+{
+       /*      Delete the occurence of id in the list.
+               (list has size size)
+       */
+
+       int *temp;
+       register int x,y=0;
+
+       temp = (int *) malloc(sizeof(int) * (*size));
+       for (x=0; x<(*size); x++)
+       {
+               if (*(list+x) != id)
+               {
+                       *(temp+y) = *(list+x);
+                       y++;
+               }
+       }
+       *(temp+y) = -1;
+     *size = *size - (*size - y - 1);
+       memcpy(list,temp,sizeof(int)*(*size));
+}
+
+
+void Build_SGI_Table(int num_verts,int num_faces)
+{
+       /*      Build a table that has the polygons sorted by the
+               number of adjacent polygons.
+       */
+       int x,y,size,tally=0;
+       ListHead *pListHead;
+       PF_FACES temp = NULL;
+
+       /* For each face....*/
+       for (x=0;x < num_faces;x++)
+       {
+               pListHead = PolFaces[x];
+               temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+               /*   Check each edge of the face and tally the number of adjacent
+                       polygons to this face. 
+               */                      
+               if ( temp != NULL )
+               {
+                       /*      Size of the polygon */
+                       size = temp->nPolSize;
+                       if (size != 1)
+      {
+        for (y = 0; y< size; y++)
+                         {
+                                 if (y != (size-1))
+                                         tally += Num_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1));
+                                 else
+                                         tally += Num_Adj(*(temp->pPolygon),*(temp->pPolygon+(size-1)));
+        }
+                       
+                         /* Tally is the number of polygons that is adjacent to
+                                  the current polygon. 
+                         */
+                         /* Now put the face in the proper bucket depending on tally. */
+                         Add_Sgi_Adj(tally,x);
+                         temp = NULL;
+                         tally=0;
+      }
+               }
+       }
+}
+
+
+void Triangulate_Quad(int out_edge1,int out_edge2,int in_edge1,
+                                         int in_edge2,int size,int *index,
+                                         FILE *output,int reversed,int face_id,
+                      int where,int color1,int color2,int color3)
+{
+       int vertex4,vertex5;
+       
+       /*      This routine will nonblindly triangulate a quad, meaning
+               that there is a definite input and a definite output
+               edge that we must adhere to. Reversed will tell the orientation
+               of the input edge. (Reversed is -1 is we do not have an input
+               edge, in other words we are at the beginning of a strip.)
+               Out_edge* is the output edge, and in_edge* is the input edge. 
+               Index are the edges of the polygon
+               and size is the size of the polygon. Begin is whether we are
+               at the start of a new strip.
+       */
+       
+       /*      If we do not have an input edge, then we can make our input
+               edge whatever we like, therefore it will be easier to come
+               out on the output edge.
+       */
+       if (reversed == -1)
+       {
+               vertex4 = Adjacent(out_edge1,out_edge2,index,size);
+               vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index);
+               Output_Tri(vertex5,vertex4,out_edge1,output,color1,color2,color3,where);
+               Output_Tri(vertex4,out_edge1,out_edge2,output,color1,color2,color3,where);
+               return;
+       }
+       
+       /*      These are the 5 cases that we can have for the output edge */
+       
+       /*  Are they consecutive so that we form a triangle to
+               peel off, but cannot use the whole quad?
+       */
+
+       if (in_edge2 == out_edge1) 
+       {
+               /* Output the triangle that comes out the correct
+                        edge last. First output the triangle that comes out
+                        the wrong edge.
+               */
+               vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index);
+    Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where);
+    Output_Tri(vertex4,in_edge2,out_edge2,output,color1,color2,color3,where);
+               return;
+       }
+       /* The next case is where it is impossible to come out the
+                edge that we want. So we will have to start a new strip to
+                come out on that edge. We will output the one triangle
+                that we can, and then start the new strip with the triangle
+                that comes out on the edge that we want to come out on.
+       */
+       else if (in_edge1 == out_edge1)
+       {
+               /* We want to output the first triangle (whose output
+                        edge is not the one that we want.
+                        We have to find the vertex that we need, which is
+                        the other vertex which we do not have.
+               */
+               vertex4 = Get_Other_Vertex(in_edge2,in_edge1,out_edge2,index);
+               Output_Tri(in_edge2,in_edge1,vertex4,output,color1,color2,color3,where);
+               Output_Tri(vertex4,in_edge1,out_edge2,output,color1,color2,color3,where);
+               return;
+       }
+       
+       /*      Consecutive cases again, but with the output edge reversed */
+       else if (in_edge1 == out_edge2)
+       {
+               vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
+               Output_Tri(in_edge2,in_edge1,vertex4,output,color1,color2,color3,where);
+               Output_Tri(vertex4,in_edge1,out_edge1,output,color1,color2,color3,where);
+               return;
+       }
+       else if (in_edge2 == out_edge2)
+       {
+               vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
+               Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where);
+               Output_Tri(vertex4,in_edge2,out_edge1,output,color1,color2,color3,where);
+               return;
+       }
+
+       /*      The final case is where we want to come out the opposite
+               edge.
+       */
+       else
+       {
+    if( ((!reversed) && (out_edge1 == (Adjacent(in_edge1,in_edge2,index,size)))) ||
+        ((reversed) && (out_edge2 == (Adjacent(in_edge2,in_edge1,index,size)))))
+               {
+                 /* We need to know the orientation of the input
+                                edge, so we know which way to put the diagonal.
+         And also the output edge, so that we triangulate
+         correctly.
+      */
+                       Output_Tri(in_edge1,in_edge2,out_edge2,output,color1,color2,color3,where);
+                       Output_Tri(in_edge2,out_edge2,out_edge1,output,color1,color2,color3,where);
+               }
+               else
+               {
+                       /* Input and output orientation was reversed, so diagonal will
+                                be reversed from above.
+                       */
+                       Output_Tri(in_edge1,in_edge2,out_edge1,output,color1,color2,color3,where);
+                       Output_Tri(in_edge2,out_edge1,out_edge2,output,color1,color2,color3,where);
+               }
+               return;
+       }
+}
+
+void Triangulate_Polygon(int out_edge1, int out_edge2, int in_edge1,
+                                          int in_edge2, int size, int *index,
+                                                            FILE *output, int reversed, int face_id,
+                         int where, int color1, int color2, int color3)
+{
+       /* We have a polygon that we need to nonblindly triangulate.
+                We will recursively try to triangulate it, until we are left
+                with a polygon of size 4, which can use the quad routine
+                from above. We will be taking off a triangle at a time
+                and outputting it. We will have 3 cases similar to the
+                cases for the quad above. The inputs to this routine
+                are the same as for the quad routine.
+       */
+
+       int vertex4;
+       int *temp;
+               
+       /* Since we are calling this recursively, we have to check whether
+                we are down to the case of the quad.
+       */
+       
+  if (size == 4)
+       {
+         Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size,
+                               index,output,reversed,face_id,where,color1,color2,color3);
+               return;
+       }
+
+    
+       
+       /*      We do not have a specified input edge, and therefore we
+               can make it anything we like, as long as we still come out 
+               the output edge that we want.
+       */
+       if (reversed  == -1)
+       {
+               /*      Get the vertex for the last triangle, which is
+                       the one coming out the output edge, before we do
+                       any deletions to the list. We will be doing this
+                       bottom up.
+               */
+               vertex4 = Adjacent(out_edge1,out_edge2,index,size);
+               temp = (int *) malloc(sizeof(int) * size);
+               memcpy(temp,index,sizeof(int)*size);
+               Delete_From_List(out_edge2,index,&size);
+               Triangulate_Polygon(out_edge1,vertex4,in_edge2,
+                                                vertex4,size-1,index,output,reversed,face_id,where,color1,color2,color3);
+               memcpy(index,temp,sizeof(int)*size);
+               /*      Lastly do the triangle that comes out the output
+                       edge.
+               */
+               Output_Tri(vertex4,out_edge1,out_edge2,output,color1,color2,color3,where);
+               return;
+       }
+
+       /*      These are the 5 cases that we can have for the output edge */
+       
+       /*  Are they consecutive so that we form a triangle to
+               peel off that comes out the correct output edge, 
+               but we cannot use the whole polygon?
+       */
+       if (in_edge2 == out_edge1) 
+       {
+               /*      Output the triangle that comes out the correct
+                       edge last. First recursively do the rest of the
+                       polygon.
+               */
+               /*      Do the rest of the polygon without the triangle. 
+                       We will be doing a fan triangulation.
+               */
+               /*      Get the vertex adjacent to in_edge1, but is not
+                       in_edge2.
+               */
+               vertex4 = Adjacent(in_edge2,in_edge1,index,size);
+               Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where);
+               /*      Create a new edgelist without the triangle that
+                       was just outputted.
+               */
+               temp = (int *) malloc(sizeof(int) * size);
+               memcpy(temp,index,sizeof(int)*size);
+          Delete_From_List(in_edge1,index,&size);
+               Triangulate_Polygon(out_edge1,out_edge2,in_edge2,
+                                               vertex4,size-1,index,output,!reversed,face_id,where,color1,color2,color3);
+               memcpy(index,temp,sizeof(int)*size);
+               return;
+       }
+
+       /*      Next case is where it is again consecutive, but the triangle
+               formed by the consecutive edges do not come out of the
+               correct output edge. For this case, we can not do much to
+               keep it sequential. Try and do the fan.
+       */
+       else if (in_edge1 == out_edge1)
+       {
+               /*      Get vertex adjacent to in_edge2, but is not in_edge1 */
+               vertex4 = Adjacent(in_edge1,in_edge2,index,size);
+               Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where);
+               /*      Since that triangle goes out of the polygon (the
+                       output edge of it), we can make our new input edge
+                       anything we like, so we will try to make it good for
+                       the strip. (This will be like starting a new strip,
+                       all so that we can go out the correct output edge.)
+               */
+               temp = (int *) malloc(sizeof(int) * size);
+               memcpy(temp,index,sizeof(int)*size);
+               Delete_From_List(in_edge2,index,&size);
+               Triangulate_Polygon(out_edge1,out_edge2,in_edge1,
+                                               vertex4,size-1,index,output,reversed,face_id,where,color1,color2,color3);
+               memcpy(index,temp,sizeof(int)*size);
+               return;
+       }
+       /*      Consecutive cases again, but with the output edge reversed */
+       else if (in_edge1 == out_edge2)
+       {
+               /*      Get vertex adjacent to in_edge2, but is not in_edge1 */
+               vertex4 = Adjacent(in_edge1,in_edge2,index,size);
+               Output_Tri(in_edge2,in_edge1,vertex4,output,color1,color2,color3,where);
+               temp = (int *) malloc(sizeof(int) * size);
+               memcpy(temp,index,sizeof(int)*size);
+               Delete_From_List(in_edge2,index,&size);
+          Triangulate_Polygon(out_edge1,out_edge2,in_edge1,
+                                               vertex4,size-1,index,output,reversed,face_id,where,color1,color2,color3);
+               memcpy(index,temp,sizeof(int)*size);
+               return;
+       }
+       else if (in_edge2 == out_edge2)
+       {
+               /*      Get vertex adjacent to in_edge2, but is not in_edge1 */
+               vertex4 = Adjacent(in_edge2,in_edge1,index,size);
+               Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where);
+               temp = (int *) malloc(sizeof(int) * size);
+               memcpy(temp,index,sizeof(int)*size);
+               Delete_From_List(in_edge1,index,&size);
+          Triangulate_Polygon(out_edge1,out_edge2,vertex4,
+                                               in_edge2,size-1,index,output,reversed,face_id,where,color1,color2,color3);
+               memcpy(index,temp,sizeof(int)*size);
+               return;
+       }
+
+       /*      Else the edge is not consecutive, and it is sufficiently
+               far away, for us not to make a conclusion at this time.
+               So we can take off a triangle and recursively call this
+               function.
+       */
+       else
+       {
+                       vertex4 = Adjacent(in_edge2,in_edge1,index,size);
+                       Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where);
+                       temp = (int *) malloc(sizeof(int) * size);
+                       memcpy(temp,index,sizeof(int)*size);
+                       Delete_From_List(in_edge1,index,&size);
+               Triangulate_Polygon(out_edge1,out_edge2,in_edge2,
+                                                    vertex4,size-1,index,output,!reversed,face_id,where,color1,color2,color3);
+                       memcpy(index,temp,sizeof(int)*size);
+                    return;
+       }
+}
+
+void Triangulate(int out_edge1,int out_edge2,int in_edge1,
+                                int in_edge2,int size,int *index,
+                                FILE *output,int reversed,int face_id, int where,
+                     int color1, int color2,int color3)
+{
+       /*      We have the info we need to triangulate a polygon */
+
+       if (size == 4)
+               Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size,
+                                   index,output,reversed,face_id,where,color1,color2,color3);
+       else
+               Triangulate_Polygon(out_edge1,out_edge2,in_edge1,in_edge2,size,
+                                      index,output,reversed,face_id,where,color1,color2,color3);
+}
+
+void Non_Blind_Triangulate(int size,int *index,
+                                         FILE *output,int next_face_id,int face_id,int where,
+                           int color1,int color2,int color3)
+{
+       int id1,id2,id3;
+       int nedge1,nedge2;
+       int reversed;
+       /*      We have a polygon that has to be triangulated and we cannot
+               do it blindly, ie we will try to come out on the edge that
+               has the least number of adjacencies
+       */
+
+       Last_Edge(&id1,&id2,&id3,0);
+       /*      Find the edge that is adjacent to the new face ,
+               also return whether the orientation is reversed in the
+               face of the input edge, which is id2 and id3.
+       */
+       if (next_face_id == -1)
+     {
+        printf("The face is -1 and the size is %d\n",size);
+        exit(0);
+     }
+    
+     reversed = Get_Edge(&nedge1,&nedge2,index,next_face_id,size,id2,id3);
+       /*      Do the triangulation */
+       
+       /*      If reversed is -1, the input edge is not in the polygon, therefore we can have the
+               input edge to be anything we like, since we are at the beginning
+               of a strip
+       */
+       Triangulate(nedge1,nedge2,id2,id3,size,index,output,reversed,
+                      face_id, where,color1,color2,color3);
+}
+
+
+
+void Blind_Triangulate(int size, int *index, FILE *output,
+                                  BOOL begin, int where ,int color1,int color2,
+                       int color3)
+{
+       /*      save sides in temp array, we need it so we know
+               about swaps.
+       */
+       int mode, decreasing,increasing,e1,e2,e3;
+
+       /*      Rearrange the index list so that the input edge is first
+       */
+       if (!begin)
+               Rearrange_Index(index,size);
+       
+       /*      We are given a polygon of more than 3 sides
+               and want to triangulate it. We will output the
+               triangles to the output file.
+       */
+       
+    /* Find where the input edge is in the input list */
+       Last_Edge(&e1,&e2,&e3,0);
+     if (( (!begin) && (*(index) == e2) ) || (begin))
+     {
+           Output_Tri(*(index+0),*(index+1),*(index+size-1),output,color1,color2,color3,where);
+        /*     If we have a quad, (chances are yes), then we know that
+                    we can just add one diagonal and be done. (divide the
+                    quad into 2 triangles.
+        */
+        if (size == 4)
+        {
+                   Output_Tri(*(index+1),*(index+size-1),*(index+2),output,color1,color2,color3,where);
+              return;
+        }
+        increasing = 1;
+        mode = 1;
+
+    }
+    else if (!begin)
+    {
+        Output_Tri(*(index+1),*(index+0),*(index+size-1),output,color1,color2,color3,where);
+        if (size == 4)
+        {
+            Output_Tri(*(index+0),*(index+size-1),*(index+2),output,color1,color2,color3,where);
+            return;
+        }
+        Output_Tri(*(index+0),*(index+size-1),*(index+2),output,color1,color2,color3,where);
+        increasing = 2;
+        mode = 0;
+    }
+    if (size != 4)
+    {
+               /*      We do not have a quad, we have something bigger. */
+               decreasing = size - 1;          
+               do
+               {
+                       /*      Will be alternating diagonals, so we will be increasing
+                               and decreasing around the polygon.
+                       */
+                       if (mode)
+                       {
+                               Output_Tri(*(index+increasing),*(index+decreasing),*(index+increasing+1),output,color1,color2,color3,where);
+                               increasing++;
+                       }
+                       else
+                       {
+                               Output_Tri(*(index+decreasing),*(index+increasing),*(index+decreasing-1),output,color1,color2,color3,where);
+                    decreasing--;
+               }
+                       mode = !mode;
+               } while ((decreasing - increasing) >= 2);
+
+       }
+}
+
+
+
+
diff --git a/Stripe_w/sgi_triangex.c b/Stripe_w/sgi_triangex.c
new file mode 100644 (file)
index 0000000..9f153a1
--- /dev/null
@@ -0,0 +1,582 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: sgi_triangex.c
+     This file contains routines that are used for various functions in
+     the local algorithm.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "global.h"
+#include "outputex.h"
+#include "polverts.h"
+#include "sturctsex.h"
+#include "common.h"
+#include "util.h"
+
+
+int AdjacentEx(int id2,int id1, int *list, int size)
+{
+       /*      Return the vertex that is adjacent to id1,
+               but is not id2, in the list of integers.
+       */
+
+       register int x=0;
+       
+       while (x < size)
+       {
+               if (*(list+x) == id1)
+               {
+                       if ((x != (size -1)) && (x != 0))
+                       {
+                               if ( *(list+x+1) != id2)
+                                       return *(list+x+1);
+                               else
+                                       return *(list+x-1);
+                       }
+                       else if (x == (size -1))
+                       {
+                               if (*(list) != id2)
+                                       return *(list);
+                               else
+                                       return *(list+x-1);
+                       }
+                       else
+                       {
+                               if (*(list+size-1) != id2)
+                                       return *(list+size-1);
+                               else
+                                       return *(list+x+1);
+                       }
+               }
+               x++;
+       }
+       printf("Error in the list\n");
+       exit(0);
+}
+
+
+void Delete_From_ListEx(int id,int *list, int size)
+{
+       /*      Delete the occurence of id in the list.
+               (list has size size)
+       */
+
+       int *temp;
+       register int x,y=0;
+
+       temp = (int *) malloc(sizeof(int) * size);
+       for (x=0; x<size; x++)
+       {
+               if (*(list+x) != id)
+               {
+                       *(temp+y) = *(list+x);
+                       y++;
+               }
+       }
+       if(y != (size-1))
+       {
+               printf("There is an error in the delete\n");
+               exit(0);
+       }
+       *(temp+size-1) = -1;
+       memcpy(list,temp,sizeof(int)*size);
+
+}
+
+
+void Triangulate_QuadEx(int out_edge1,int out_edge2,int in_edge1,
+                                         int in_edge2,int size,int *index,
+                                         FILE *output,FILE *fp,int reversed,int face_id,
+                      int where)
+{
+       int vertex4,vertex5;
+       
+       /*      This routine will nonblindly triangulate a quad, meaning
+               that there is a definite input and a definite output
+               edge that we must adhere to. Reversed will tell the orientation
+               of the input edge. (Reversed is -1 is we do not have an input
+               edge, in other words we are at the beginning of a strip.)
+               Out_edge* is the output edge, and in_edge* is the input edge. 
+               Index are the edges of the polygon
+               and size is the size of the polygon. Begin is whether we are
+               at the start of a new strip.
+       */
+       
+       /*      If we do not have an input edge, then we can make our input
+               edge whatever we like, therefore it will be easier to come
+               out on the output edge.
+       */
+       if (reversed == -1)
+       {
+               vertex4 = AdjacentEx(out_edge1,out_edge2,index,size);
+               vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index);
+               Output_TriEx(vertex5,vertex4,out_edge1,output,-1,-1,where);
+               Output_TriEx(vertex4,out_edge1,out_edge2,output,-1,-1,where);
+               return;
+       }
+       
+       /*      These are the 5 cases that we can have for the output edge */
+       
+       /*   Are they consecutive so that we form a triangle to
+               peel off, but cannot use the whole quad?
+       */
+
+       if (in_edge2 == out_edge1) 
+       {
+               /*      Output the triangle that comes out the correct
+                       edge last. First output the triangle that comes out
+                       the wrong edge.
+               */
+               vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index);
+          Output_TriEx(in_edge1,in_edge2,vertex4,output,-1,-1,where);
+          Output_TriEx(vertex4,in_edge2,out_edge2,output,-1,-1,where);
+               return;
+       }
+       /*      The next case is where it is impossible to come out the
+               edge that we want. So we will have to start a new strip to
+               come out on that edge. We will output the one triangle
+               that we can, and then start the new strip with the triangle
+               that comes out on the edge that we want to come out on.
+       */
+       else if (in_edge1 == out_edge1)
+       {
+               /*      We want to output the first triangle (whose output
+                       edge is not the one that we want.
+                       We have to find the vertex that we need, which is
+                       the other vertex which we do not have.
+               */
+               vertex4 = Get_Other_Vertex(in_edge2,in_edge1,out_edge2,index);
+               Output_TriEx(in_edge2,in_edge1,vertex4,output,-1,-1,where);
+               Output_TriEx(vertex4,in_edge1,out_edge2,output,-1,-1,where);
+               return;
+       }
+       
+       /*      Consecutive cases again, but with the output edge reversed */
+       else if (in_edge1 == out_edge2)
+       {
+               vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
+               Output_TriEx(in_edge2,in_edge1,vertex4,output,-1,-1,where);
+               Output_TriEx(vertex4,in_edge1,out_edge1,output,-1,-1,where);
+               return;
+       }
+       else if (in_edge2 == out_edge2)
+       {
+               vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
+               Output_TriEx(in_edge1,in_edge2,vertex4,output,-1,-1,where);
+               Output_TriEx(vertex4,in_edge2,out_edge1,output,-1,-1,where);
+               return;
+       }
+
+       /*      The final case is where we want to come out the opposite edge.*/
+       else
+       {
+           if( ((!reversed) && (out_edge1 == (AdjacentEx(in_edge1,in_edge2,index,size)))) ||
+                    ((reversed) && (out_edge2 == (AdjacentEx(in_edge2,in_edge1,index,size)))))
+                {
+                       /*      We need to know the orientation of the input
+                               edge, so we know which way to put the diagonal.
+                    And also the output edge, so that we triangulate correctly.
+               */
+                       Output_TriEx(in_edge1,in_edge2,out_edge2,output,-1,-1,where);
+                       Output_TriEx(in_edge2,out_edge2,out_edge1,output,-1,-1,where);
+                }
+               else
+               {
+                       /*   Input and output orientation was reversed, so diagonal will
+                               be reversed from above.
+                       */
+                       Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where);
+                       Output_TriEx(in_edge2,out_edge1,out_edge2,output,-1,-1,where);
+               }
+               return;
+       }
+}
+
+void Triangulate_PolygonEx(int out_edge1,int out_edge2,int in_edge1,
+                                         int in_edge2,int size,int *index,
+                                         FILE *output,FILE *fp,int reversed,int face_id,
+                           int where)
+{
+       /*      We have a polygon that we need to nonblindly triangulate.
+               We will recursively try to triangulate it, until we are left
+               with a polygon of size 4, which can use the quad routine
+               from above. We will be taking off a triangle at a time
+               and outputting it. We will have 3 cases similar to the
+               cases for the quad above. The inputs to this routine
+               are the same as for the quad routine.
+       */
+
+       int vertex4;
+       int *temp;
+
+               
+       /*      Since we are calling this recursively, we have to check whether
+               we are down to the case of the quad.
+       */
+       
+    if (size == 4)
+       {
+               Triangulate_QuadEx(out_edge1,out_edge2,in_edge1,in_edge2,size,
+                                           index,output,fp,reversed,face_id,where);
+               return;
+       }
+
+    
+       
+       /*      We do not have a specified input edge, and therefore we
+               can make it anything we like, as long as we still come out 
+               the output edge that we want.
+       */
+       if (reversed  == -1)
+       {
+               /*      Get the vertex for the last triangle, which is
+                       the one coming out the output edge, before we do
+                       any deletions to the list. We will be doing this
+                       bottom up.
+               */
+               vertex4 = AdjacentEx(out_edge1,out_edge2,index,size);
+               temp = (int *) malloc(sizeof(int) * size);
+               memcpy(temp,index,sizeof(int)*size);
+               Delete_From_ListEx(out_edge2,index,size);
+               Triangulate_PolygonEx(out_edge1,vertex4,in_edge2,
+                                                 vertex4,size-1,index,output,fp,reversed,face_id,where);
+               memcpy(index,temp,sizeof(int)*size);
+               /*      Lastly do the triangle that comes out the output
+                       edge.
+               */
+               Output_TriEx(vertex4,out_edge1,out_edge2,output,-1,-1,where);
+               return;
+       }
+
+       /*      These are the 5 cases that we can have for the output edge */
+       
+       /*  Are they consecutive so that we form a triangle to
+               peel off that comes out the correct output edge, 
+               but we cannot use the whole polygon?
+       */
+       if (in_edge2 == out_edge1) 
+       {
+               /*      Output the triangle that comes out the correct
+                       edge last. First recursively do the rest of the
+                       polygon.
+               */
+               /*      Do the rest of the polygon without the triangle. 
+                       We will be doing a fan triangulation.
+               */
+               /*      Get the vertex adjacent to in_edge1, but is not
+                       in_edge2.
+               */
+               vertex4 = AdjacentEx(in_edge2,in_edge1,index,size);
+               Output_TriEx(in_edge1,in_edge2,vertex4,output,-1,-1,where);
+               /*      Create a new edgelist without the triangle that
+                       was just outputted.
+               */
+               temp = (int *) malloc(sizeof(int) * size);
+               memcpy(temp,index,sizeof(int)*size);
+          Delete_From_ListEx(in_edge1,index,size);
+               Triangulate_PolygonEx(out_edge1,out_edge2,in_edge2,
+                                                 vertex4,size-1,index,output,fp,!reversed,face_id,where);
+               memcpy(index,temp,sizeof(int)*size);
+               return;
+       }
+
+       /*      Next case is where it is again consecutive, but the triangle
+               formed by the consecutive edges do not come out of the
+               correct output edge. For this case, we can not do much to
+               keep it sequential. Try and do the fan.
+       */
+       else if (in_edge1 == out_edge1)
+       {
+               /*      Get vertex adjacent to in_edge2, but is not in_edge1 */
+               vertex4 = AdjacentEx(in_edge1,in_edge2,index,size);
+               Output_TriEx(in_edge1,in_edge2,vertex4,fp,-1,-1,where);
+               /*      Since that triangle goes out of the polygon (the
+                       output edge of it), we can make our new input edge
+                       anything we like, so we will try to make it good for
+                       the strip. (This will be like starting a new strip,
+                       all so that we can go out the correct output edge.)
+               */
+               temp = (int *) malloc(sizeof(int) * size);
+               memcpy(temp,index,sizeof(int)*size);
+               Delete_From_ListEx(in_edge2,index,size);
+               Triangulate_PolygonEx(out_edge1,out_edge2,in_edge1,
+                                                 vertex4,size-1,index,output,fp,reversed,face_id,where);
+               memcpy(index,temp,sizeof(int)*size);
+               return;
+       }
+       /*      Consecutive cases again, but with the output edge reversed */
+       else if (in_edge1 == out_edge2)
+       {
+               /*      Get vertex adjacent to in_edge2, but is not in_edge1 */
+               vertex4 = AdjacentEx(in_edge1,in_edge2,index,size);
+               Output_TriEx(in_edge2,in_edge1,vertex4,fp,-1,-1,where);
+               temp = (int *) malloc(sizeof(int) * size);
+               memcpy(temp,index,sizeof(int)*size);
+               Delete_From_ListEx(in_edge2,index,size);
+          Triangulate_PolygonEx(out_edge1,out_edge2,in_edge1,
+                                      vertex4,size-1,index,output,fp,reversed,face_id,where);
+               memcpy(index,temp,sizeof(int)*size);
+               return;
+       }
+       else if (in_edge2 == out_edge2)
+       {
+               /*      Get vertex adjacent to in_edge2, but is not in_edge1 */
+               vertex4 = AdjacentEx(in_edge2,in_edge1,index,size);
+               Output_TriEx(in_edge1,in_edge2,vertex4,fp,-1,-1,where);
+               temp = (int *) malloc(sizeof(int) * size);
+               memcpy(temp,index,sizeof(int)*size);
+               Delete_From_ListEx(in_edge1,index,size);
+          Triangulate_PolygonEx(out_edge1,out_edge2,vertex4,
+                                                 in_edge2,size-1,index,output,fp,reversed,face_id,where);
+               memcpy(index,temp,sizeof(int)*size);
+               return;
+       }
+
+       /*      Else the edge is not consecutive, and it is sufficiently
+               far away, for us not to make a conclusion at this time.
+               So we can take off a triangle and recursively call this
+               function.
+       */
+       else
+       {
+                       vertex4 = AdjacentEx(in_edge2,in_edge1,index,size);
+                       Output_TriEx(in_edge1,in_edge2,vertex4,fp,-1,-1,where);
+                       temp = (int *) malloc(sizeof(int) * size);
+                       memcpy(temp,index,sizeof(int)*size);
+                       Delete_From_ListEx(in_edge1,index,size);
+               Triangulate_PolygonEx(out_edge1,out_edge2,in_edge2,
+                                                      vertex4,size-1,index,output,fp,!reversed,face_id,where);
+                       memcpy(index,temp,sizeof(int)*size);
+                    return;
+       }
+}
+
+void TriangulateEx(int out_edge1,int out_edge2,int in_edge1,
+                                int in_edge2,int size,int *index,
+                                FILE *fp,FILE *output,int reversed,int face_id, int where)
+{
+       /*      We have the info we need to triangulate a polygon */
+
+       if (size == 4)
+               Triangulate_QuadEx(out_edge1,out_edge2,in_edge1,in_edge2,size,
+                                     index,fp,output,reversed,face_id,where);
+       else
+               Triangulate_PolygonEx(out_edge1,out_edge2,in_edge1,in_edge2,size,
+                                        index,fp,output,reversed,face_id,where);
+}
+
+void Non_Blind_TriangulateEx(int size,int *index, FILE *fp,
+                                                FILE *output,int next_face_id,int face_id,int where)
+{
+       int id1,id2,id3;
+       int nedge1,nedge2;
+       int reversed;
+       /*      We have a polygon that has to be triangulated and we cannot
+               do it blindly, ie we will try to come out on the edge that
+               has the least number of adjacencies
+       */
+
+       Last_Edge(&id1,&id2,&id3,0);
+       /*      Find the edge that is adjacent to the new face ,
+               also return whether the orientation is reversed in the
+               face of the input edge, which is id2 and id3.
+       */
+       if (next_face_id == -1)
+    {
+        printf("The face is -1 and the size is %d\n",size);
+        exit(0);
+    }
+    
+    reversed = Get_EdgeEx(&nedge1,&nedge2,index,next_face_id,size,id2,id3);
+       /*      Do the triangulation */
+       
+       /*      If reversed is -1, the input edge is not in the polygon, therefore we can have the
+               input edge to be anything we like, since we are at the beginning
+               of a strip
+       */
+       TriangulateEx(nedge1,nedge2,id2,id3,size,index,fp,output,reversed,
+                        face_id, where);
+}
+
+void Rearrange_IndexEx(int *index, int size)
+{
+       /*      If we are in the middle of a strip we must find the
+               edge to start on, which is the last edge that we had
+               transmitted.
+       */
+       int x,f,y,e1,e2,e3;
+       int increment = 1;
+     int *temp;
+
+       /*      Find where the input edge is in the input list */
+       Last_Edge(&e1,&e2,&e3,0);
+       for (y = 0; y < size; y++)
+       {
+               if (*(index+y) == e2)
+               {
+                       if ((y != (size - 1)) && (*(index+y+1) == e3))
+                               break;
+                       else if ((y == (size - 1)) && (*(index) == e3))
+                               break;
+               else if ((y != 0) && (*(index+y-1) == e3))
+               {
+                   increment = -1;
+                   break;
+               }
+               else if ((y==0) && (*(index+size-1) == e3))
+               {
+                   increment = -1;
+                   break;
+               }
+               }
+               if (*(index+y) == e3)
+               {
+                       if ((y != (size - 1)) && (*(index+y+1) == e2))
+                               break;
+                       else if ((y == (size - 1)) && (*(index) == e2))
+                               break;
+               else if ((y != 0) && (*(index+y-1) == e2))
+               {
+                   increment = -1;
+                   break;
+               }
+               else if ((y==0) && (*(index+size-1) == e2))
+               {
+                   increment = -1;
+                   break;
+               }
+               }
+               /*      Edge is not here, we are at the beginning */
+               if ((y == (size-1)) && (increment != -1))
+                       return;
+       }
+       
+       /*      Now put the list into a new list, starting with the
+               input edge. Increment tells us whether we have to go 
+               forward or backward.
+       */
+       /*      Was in good position already */
+       if ((y == 0) && (increment == 1)) 
+               return;
+       
+                   
+    temp = (int *) malloc(sizeof(int) * size);
+    memcpy(temp,index,sizeof(int)*size);
+
+       if (increment == 1)
+       {
+               x=0;
+               for (f = y ; f< size; f++)
+               {
+                       *(index+x) = *(temp+f);
+                       x++;
+               }
+               /*      Finish the rest of the list */  
+               for(f = 0; f < y ; f++)
+               {
+                       *(index+x) = *(temp+f);
+                       x++;
+               }
+       }
+       else
+       {
+               x=0;
+               for (f = y ; f >= 0; f--)
+               {
+                       *(index+x) = *(temp+f);
+                       x++;
+               }
+               /*      Finish the rest of the list */  
+               for(f = (size - 1); f > y ; f--)
+               {
+                       *(index+x) = *(temp+f);
+                       x++;
+               }
+       }
+}
+
+void Blind_TriangulateEx(int size, int *index, FILE *fp,
+                                                FILE *output, BOOL begin, int where )
+{
+       /*      save sides in temp array, we need it so we know
+               about swaps.
+       */
+       int mode, decreasing,increasing,e1,e2,e3;
+
+       /*      Rearrange the index list so that the input edge is first
+       */
+       if (!begin)
+               Rearrange_IndexEx(index,size);
+       
+       /*      We are given a polygon of more than 3 sides
+               and want to triangulate it. We will output the
+               triangles to the output file.
+       */
+       
+    /* Find where the input edge is in the input list */
+       Last_Edge(&e1,&e2,&e3,0);
+     if (( (!begin) && (*(index) == e2) ) || (begin))
+     {
+           Output_TriEx(*(index+0),*(index+1),*(index+size-1),fp,-1,-1,where);
+        /*     If we have a quad, (chances are yes), then we know that
+               we can just add one diagonal and be done. (divide the
+               quad into 2 triangles.
+        */
+        if (size == 4)
+        {
+                   Output_TriEx(*(index+1),*(index+size-1),*(index+2),fp,-1,-1,where);
+              return;
+        }
+        increasing = 1;
+        mode = 1;
+
+    }
+    else if (!begin)
+    {
+        Output_TriEx(*(index+1),*(index+0),*(index+size-1),fp,-1,-1,where);
+        if (size == 4)
+        {
+            Output_TriEx(*(index+0),*(index+size-1),*(index+2),fp,-1,-1,where);
+            return;
+        }
+        Output_TriEx(*(index+0),*(index+size-1),*(index+2),fp,-1,-1,where);
+        increasing = 2;
+        mode = 0;
+    }
+       if (size != 4)
+       {
+               /*      We do not have a quad, we have something bigger. */
+               decreasing = size - 1;
+               
+               do
+               {
+                       /*      Will be alternating diagonals, so we will be increasing
+                               and decreasing around the polygon.
+                       */
+                       if (mode)
+                       {
+                               Output_TriEx(*(index+increasing),*(index+decreasing),*(index+increasing+1),fp,-1,-1,where);
+                               increasing++;
+                       }
+                       else
+                       {
+                               Output_TriEx(*(index+decreasing),*(index+increasing),*(index+decreasing-1),fp,-1,-1,where);
+                    decreasing--;
+               }
+                       mode = !mode;
+               } while ((decreasing - increasing) >= 2);
+
+       }
+}
+
+
diff --git a/Stripe_w/struct.c b/Stripe_w/struct.c
new file mode 100644 (file)
index 0000000..7010012
--- /dev/null
@@ -0,0 +1,549 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: struct.c
+     Contains routines that update structures, and micellaneous routines.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <string.h>
+#include "polverts.h"
+#include "ties.h"
+#include "output.h"
+#include "triangulate.h"
+#include "sturcts.h"
+#include "options.h"
+#include "common.h"
+#include "util.h"
+
+int out1 = -1;
+int out2 = -1;
+
+int Get_Edge(int *edge1,int *edge2,int *index,int face_id,
+               int size, int id1, int id2)
+{
+       /*      Put the edge that is adjacent to face_id into edge1
+               and edge2. For each edge see if it is adjacent to
+               face_id. Id1 and id2 is the input edge, so see if 
+               the orientation is reversed, and save it in reversed.
+       */
+       register int x;
+       int reversed = -1;
+       BOOL set = FALSE;
+    
+     for (x=0; x< size; x++)
+       {
+               if (x == (size-1))
+               {
+                       if ((*(index) == id1) && (*(index+size-1)==id2))
+                       {
+                               if (set)
+                         return 1;
+                               reversed = 1;
+                       }
+                       else if ((*(index) == id2) && (*(index+size-1)==id1))
+                       {
+                               if (set)
+                         return 0;
+                               reversed = 0;
+                       }
+                               
+                       if (Look_Up(*(index),*(index+size-1),face_id))
+                       {
+                               if ( (out1 != -1) && ( (out1 == *(index)) || (out1 == *(index+size-1)) ) &&
+                       ( (out2 == *(index)) || (out2 == *(index+size-1)) ))
+                    {
+                         set = TRUE;
+                         *edge1 = *(index);
+                         *edge2 = *(index+size-1);
+                    }
+                               else if (out1 == -1)
+                    {
+                         set = TRUE;
+                         *edge1 = *(index);
+                         *edge2 = *(index+size-1);
+                    }
+                               if ((reversed != -1) && (set))  
+                                       return reversed;
+                       }
+               }               
+               else
+               {
+                       if ((*(index+x) == id1) && (*(index+x+1)==id2))
+                       {
+                               if (set)
+                         return 0;
+                               reversed = 0;
+                       }
+                       else if ((*(index+x) == id2) && (*(index+x+1)==id1))
+                       {
+                               if (set)
+                                       return 1;
+                               reversed = 1;
+                       }
+
+                       if (Look_Up(*(index+x),*(index+x+1),face_id))
+                       {
+                               if ( (out1 != -1) && ( (out1 == *(index+x)) || (out1 == *(index+x+1)) ) &&
+                         ((out2 == *(index+x)) || (out2 == *(index+x+1))))
+                    {
+                         set = TRUE;
+                         *edge1 = *(index+x);
+                         *edge2 = *(index+x+1);
+                    }
+                               else if (out1 == -1)
+                    {
+                         set = TRUE;
+                         *edge1 = *(index+x);
+                                    *edge2 = *(index+x + 1);
+                    }
+                               if ((reversed != -1) && (set))
+                         return reversed;
+                       }
+               }
+       }                       
+       if ((x == size) && (reversed != -1))
+       {
+               /*      Could not find the output edge */
+               printf("Error in the Lookup %d %d %d %d %d %d %d %d\n",face_id,id1,id2,reversed,*edge1,*edge2,out1,out2);
+               exit(0);
+       }
+       return reversed;
+}
+
+
+void Update_Face(int *next_bucket, int *min_face, int face_id, int *e1,
+                                int *e2,int temp1,int temp2,int *ties)
+{
+       /*      We have a face id that needs to be decremented.
+               We have to determine where it is in the structure,
+               so that we can decrement it.
+       */
+       /*      The number of adjacencies may have changed, so to locate
+               it may be a little tricky. However we know that the number
+               of adjacencies is less than or equal to the original number
+               of adjacencies,
+       */
+       int y,size;
+       ListHead *pListHead;
+       PF_FACES temp = NULL;
+       PLISTINFO lpListInfo;
+       static int each_poly = 0;
+       BOOL there = FALSE;
+
+       pListHead = PolFaces[face_id];
+       temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+       /*      Check each edge of the face and tally the number of adjacent
+               polygons to this face. 
+       */                      
+       if ( temp != NULL )
+       {
+               /*      Size of the polygon */
+        size = temp->nPolSize;
+        /*  We did it already */
+        if (size == 1)
+            return;
+        for (y = 0; y< size; y++)
+          {
+                       /*      If we are doing partial triangulation, we must check
+                               to see whether the edge is still there in the polygon,
+                               since we might have done a portion of the polygon
+                               and saved the rest for later.
+                       */
+            if (y != (size-1))
+                 {
+                               if( ((temp1 == *(temp->pPolygon+y)) && (temp2 ==*(temp->pPolygon+y+1)))
+                                       || ((temp2 == *(temp->pPolygon+y)) && (temp1 ==*(temp->pPolygon+y+1))))
+                                       /*      edge is still there we are ok */
+                                       there = TRUE;
+                 }
+                 else
+                 {
+                               if( ((temp1 == *(temp->pPolygon)) && (temp2 == *(temp->pPolygon+size-1)))
+                                       || ((temp2 == *(temp->pPolygon)) && (temp1 ==*(temp->pPolygon+size-1))))
+                                       /*      edge is still there we are ok */
+                                       there = TRUE;
+                 }
+        }
+               
+      if (!there)
+               /*      Original edge was already used, we cannot use this polygon */
+                       return;
+               
+       /*      We have a starting point to start our search to locate
+               this polygon. 
+       */
+
+       /*      Check to see if this polygon was done */
+       lpListInfo = Done(face_id,59,&y);
+
+       if (lpListInfo == NULL)
+               return;
+
+     /*  Was not done, but there is an error in the adjacency calculations */
+     if (y == 0)
+     {
+            printf("There is an error in finding the adjacencies\n");
+            exit(0);
+     }
+
+     /*        Now put the face in the proper bucket depending on tally. */
+       /*      First add it to the new bucket, then remove it from the old */
+       Add_Sgi_Adj(y-1,face_id);
+       RemoveList(array[y],lpListInfo);
+        
+     /*        Save it if it was the smallest seen so far since then
+               it will be the next face 
+               Here we will have different options depending on
+               what we want for resolving ties:
+                       1) First one we see we will use
+                       2) Random resolving
+                       3) Look ahead
+                       4) Alternating direction
+       */
+       /*      At a new strip */
+       if (*next_bucket == 60)
+               *ties = *ties + each_poly;
+       /*      Have a tie */
+       if (*next_bucket == (y-1))
+       {
+               Add_Ties(face_id);
+               each_poly++;
+       }
+       /*      At a new minimum */
+       if (*next_bucket > (y-1))
+       {
+               *next_bucket = y-1;
+               *min_face = face_id;
+               *e1 = temp1;
+               *e2 = temp2;
+               each_poly = 0;
+               Clear_Ties();
+               Add_Ties(face_id);
+       }
+     }
+}
+
+
+void Delete_Adj(int id1, int id2,int *next_bucket,int *min_face, 
+                        int current_face,int *e1,int *e2,int *ties)
+{
+       /*      Find the face that is adjacent to the edge and is not the
+               current face. Delete one adjacency from it. Save the min
+               adjacency seen so far.
+       */
+       register int count=0;
+       PF_EDGES temp = NULL;
+       ListHead *pListHead;
+       int next_face;
+
+       /*      Always want smaller id first */
+       switch_lower(&id1,&id2);
+       
+       pListHead = PolEdges[id1];
+       temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     if (temp == NULL)
+       /*      It could be a new edge that we created. So we can
+               exit, since there is not a face adjacent to it.
+       */
+               return;
+       while (temp->edge[0] != id2)
+     {
+               count++;
+               temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+          if (temp == NULL)
+                       /*      Was a new edge that was created and therefore
+                               does not have anything adjacent to it
+                       */
+                       return;
+     }
+       /*      Was not adjacent to anything else except itself */
+       if (temp->edge[2] == -1)
+               return;
+
+       /*      Was adjacent to something */
+       else
+       {
+               if (temp->edge[2] == current_face)
+                       next_face =  temp->edge[1];
+               else 
+                       next_face = temp->edge[2];
+       }
+       /*      We have the other face adjacent to this edge, it is 
+               next_face. Now we need to decrement this faces' adjacencies.
+       */
+       Update_Face(next_bucket, min_face, next_face,e1,e2,id1,id2,ties);
+}
+
+
+int Change_Face(int face_id,int in1,int in2,
+                                ListHead *pListHead, P_ADJACENCIES temp, BOOL no_check)
+{
+       /*      We are doing a partial triangulation and we need to
+               put the new face of triangle into the correct bucket
+       */
+       int input_adj,y;
+       
+       /*      Find the old number of adjacencies to this face,
+               so we know where to delete it from
+       */
+       y = Old_Adj(face_id);
+       
+       /*      Do we need to change the adjacency? Maybe the edge on the triangle
+               that was outputted was not adjacent to anything. We know if we
+               have to check by "check". We came out on the output edge
+               that we needed, then we know that the adjacencies will decrease
+               by exactly one.
+       */
+       if (!no_check)
+       {
+               input_adj = Number_Adj(in1,in2,face_id);
+               /*      If there weren't any then don't do anything */
+               if (input_adj == 0)
+                       return y;
+       }
+
+       RemoveList(pListHead,(PLISTINFO)temp);
+       /*      Before we had a quad with y adjacencies. The in edge
+               did not have an adjacency, since it was just deleted,
+               since we came in on it. The outedge must have an adjacency
+               otherwise we would have a bucket 0, and would not be in this
+               routine. Therefore the new adjacency must be y-1
+       */
+    
+    Add_Sgi_Adj(y-1,face_id);
+    return (y-1);
+}
+
+int Update_Adjacencies(int face_id, int *next_bucket, int *e1, int *e2,
+                                          int *ties)
+{
+       /*      Give the face with id face_id, we want to decrement
+               all the faces that are adjacent to it, since we will
+               be deleting face_id from the data structure.
+               We will return the face that has the least number
+               of adjacencies.
+       */
+       PF_FACES temp = NULL;
+       ListHead *pListHead;
+       int size,y,min_face = -1;
+       
+     *next_bucket = 60;
+       pListHead = PolFaces[face_id];
+       temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+       
+       if ( temp == NULL )
+       {
+               printf("The face was already deleted, there is an error\n");
+               exit(0);
+       }
+       
+       /*      Size of the polygon */
+       size = temp->nPolSize;
+       for (y = 0; y< size; y++)
+       {
+               if (y != (size-1))
+                       Delete_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),
+                               next_bucket,&min_face,face_id,e1,e2,ties);
+               else
+                       Delete_Adj(*(temp->pPolygon),*(temp->pPolygon+(size-1)),
+                               next_bucket,&min_face,face_id,e1,e2,ties);
+       }
+       return (min_face);
+}
+
+
+void Find_Adj_Tally(int id1, int id2,int *next_bucket,int *min_face, 
+                               int current_face,int *ties)
+{
+       /*      Find the face that is adjacent to the edge and is not the
+               current face. Save the min adjacency seen so far.
+       */
+       int size,each_poly=0,y,count=0;
+       PF_EDGES temp = NULL;
+       PF_FACES temp2 = NULL;
+       ListHead *pListHead;
+       int next_face;
+       BOOL there = FALSE;
+
+    
+    /* Always want smaller id first */
+       switch_lower(&id1,&id2);
+       
+       pListHead = PolEdges[id1];
+       temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     if (temp == NULL)
+     /*        This was a new edge that was created, so it is
+               adjacent to nothing.
+       */
+               return;
+
+       while (temp->edge[0] != id2)
+     {
+               count++;
+               temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+          if (temp == NULL)
+                       /*      This was a new edge that we created */
+                       return;
+     }
+       /*      Was not adjacent to anything else except itself */
+       if (temp->edge[2] == -1)
+               return;
+       else
+       {
+               if (temp->edge[2] == current_face)
+                       next_face =  temp->edge[1];
+               else 
+                       next_face = temp->edge[2];
+       }
+       /*      We have the other face adjacent to this edge, it is 
+               next_face. Find how many faces it is adjacent to.
+       */
+       pListHead = PolFaces[next_face];
+       temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+       /*      Check each edge of the face and tally the number of adjacent 
+               polygons to this face. This will be the original number of
+               polygons adjacent to this polygon, we must then see if this
+               number has been decremented
+       */                      
+       if ( temp2 != NULL )
+       {
+               /*      Size of the polygon */
+               size = temp2->nPolSize;
+               /*  We did it already */
+          if (size == 1)
+            return;
+          for (y = 0; y< size; y++)
+               {
+                       /*      Make sure that the edge is still in the
+                               polygon and was not deleted, because if the edge was
+                               deleted, then we used it already.
+                       */
+                       if (y != (size-1))
+                       {
+                               if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1)))
+                                       || ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1))))
+                                       /*      edge is still there we are ok */
+                                       there = TRUE;
+                       }
+                       else
+                       {               
+                               if( ((id1 == *(temp2->pPolygon)) && (id2 ==*(temp2->pPolygon+size-1)))
+                                       || ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1))))
+                                       /*      edge is still there we are ok */
+                                       there = TRUE;
+                       }
+               }
+               
+               if (!there)
+                       /*      Edge already used and deleted from the polygon*/
+                       return;
+               
+               /*      See if the face was already deleted, and where
+                       it is if it was not
+               */
+               if (Done(next_face,size,&y) == NULL)
+                       return;
+               
+               /*      Save it if it was the smallest seen so far since then
+                       it will be the next face 
+                       Here we will have different options depending on
+                       what we want for resolving ties:
+                       1) First one we see we will use
+                       2) Random resolving
+                       3) Look ahead
+                       4) Alternating direction
+               */
+               
+               /*      At a new strip */
+               if (*next_bucket == 60)
+                       *ties = *ties + each_poly;
+               /*      Have a tie */
+               if (*next_bucket == (y-1))
+               {
+                       Add_Ties(next_face);
+                       each_poly++;
+               }
+               /*      At a new minimum */
+               if (*next_bucket > (y-1))
+               {
+                       *next_bucket = y-1;
+                       *min_face = next_face;
+                       each_poly = 0;
+                       Clear_Ties();
+                       Add_Ties(next_face);
+               }
+       }
+}
+
+
+int Min_Face_Adj(int face_id, int *next_bucket, int *ties)
+{
+       /*      Used for the Partial triangulation to find the next
+               face. It will return the minimum adjacency face id
+               found at this face.
+       */
+       PF_FACES temp = NULL;
+       ListHead *pListHead;
+       int size,y,min_face,test_face;
+       
+       *next_bucket = 60;
+       pListHead = PolFaces[face_id];
+       temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+       
+       if ( temp == NULL )
+       {
+               printf("The face was already deleted, there is an error\n");
+               exit(0);
+       }
+       
+       /*      Size of the polygon */
+       size = temp->nPolSize;
+       for (y = 0; y< size; y++)
+       {
+               if (y != (size-1))
+                       Find_Adj_Tally(*(temp->pPolygon+y),*(temp->pPolygon+y+1),
+                               next_bucket,&min_face,face_id,ties);
+               else
+                       Find_Adj_Tally(*(temp->pPolygon),*(temp->pPolygon+(size-1)),
+                               next_bucket,&min_face,face_id,ties);
+       }
+       /*    Maybe we can do better by triangulating the face, because
+          by triangulating the face we will go to a polygon of lesser
+          adjacencies
+    */
+    if (size == 4)
+    {
+         /*    Checking for a quad whether to do the whole polygon will
+               result in better performance because the triangles in the polygon
+               have less adjacencies
+         */
+         Check_In_Quad(face_id,&test_face);
+         if (*next_bucket > test_face)
+              /*    We can do better by going through the polygon */
+              min_face = face_id;
+    }
+
+    /*  We have a polygon with greater than 4 sides, check to see if going
+        inside is better than going outside the polygon for the output edge.
+    */
+    else
+    {
+        Check_In_Polygon(face_id,&test_face,size);
+        if (*next_bucket > test_face)
+            /*  We can do better by going through the polygon */
+            min_face = face_id;
+    }
+    
+    return (min_face);
+}
+
+
+
diff --git a/Stripe_w/structex.c b/Stripe_w/structex.c
new file mode 100644 (file)
index 0000000..70359dd
--- /dev/null
@@ -0,0 +1,553 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: structex.c
+     This file contains routines that are used for various functions in
+     the local algorithm.
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <string.h>
+#include "polverts.h"
+#include "ties.h"
+#include "outputex.h"
+#include "triangulatex.h"
+#include "sturctsex.h"
+#include "options.h"
+#include "common.h"
+#include "util.h"
+
+int out1Ex = -1;
+int out2Ex = -1;
+
+int Get_EdgeEx(int *edge1,int *edge2,int *index,int face_id,
+                       int size, int id1, int id2)
+{
+       /*      Put the edge that is adjacent to face_id into edge1
+               and edge2. For each edge see if it is adjacent to
+               face_id. Id1 and id2 is the input edge, so see if 
+               the orientation is reversed, and save it in reversed.
+       */
+       int x;
+       int reversed = -1;
+       BOOL set = FALSE;
+
+     for (x=0; x< size; x++)
+       {
+               if (x == (size-1))
+               {
+                       if ((*(index) == id1) && (*(index+size-1)==id2))
+                       {
+                               if (set)
+                         return 1;
+                               reversed = 1;
+                       }
+                       else if ((*(index) == id2) && (*(index+size-1)==id1))
+                       {
+                               if (set)
+                         return 0;
+                               reversed = 0;
+                       }
+                               
+                       if (Look_Up(*(index),*(index+size-1),face_id))
+                       {
+                               if ( (out1Ex != -1) && ( (out1Ex == *(index)) || (out1Ex == *(index+size-1)) ) &&
+                       ( (out2Ex == *(index)) || (out2Ex == *(index+size-1)) ))
+                    {
+                         set = TRUE;
+                         *edge1 = *(index);
+                         *edge2 = *(index+size-1);
+                    }
+                               else if (out1Ex == -1)
+                    {
+                         set = TRUE;
+                         *edge1 = *(index);
+                         *edge2 = *(index+size-1);
+                    }
+                               if ((reversed != -1) && (set))  
+                                       return reversed;
+                       }
+               }               
+               else
+               {
+                       if ((*(index+x) == id1) && (*(index+x+1)==id2))
+                       {
+                               if (set)
+                         return 0;
+                               reversed = 0;
+                       }
+                       else if ((*(index+x) == id2) && (*(index+x+1)==id1))
+                       {
+                               if (set)
+                                       return 1;
+                               reversed = 1;
+                       }
+
+                       if (Look_Up(*(index+x),*(index+x+1),face_id))
+                       {
+                               if ( (out1Ex != -1) && ( (out1Ex == *(index+x)) || (out1Ex == *(index+x+1)) ) &&
+                        ((out2Ex == *(index+x)) || (out2Ex == *(index+x+1))))
+                    {
+                         set = TRUE;
+                         *edge1 = *(index+x);
+                         *edge2 = *(index+x+1);
+                    }
+                               else if (out1Ex == -1)
+                    {
+                         set = TRUE;
+                         *edge1 = *(index+x);
+                                    *edge2 = *(index+x + 1);
+                    }
+                               if ((reversed != -1) && (set))
+                         return reversed;
+                       }
+               }
+       }                       
+       if ((x == size) && (reversed != -1))
+       {
+               /*      Could not find the output edge */
+               printf("Error in the Lookup %d %d %d %d %d %d %d %d\n",face_id,id1,id2,reversed,*edge1,*edge2,out1Ex,out2Ex);
+               exit(0);
+       }
+       return reversed;
+}
+
+
+void Update_FaceEx(int *next_bucket, int *min_face, int face_id, int *e1,
+                           int *e2,int temp1,int temp2,int *ties)
+{
+       /*      We have a face id that needs to be decremented.
+               We have to determine where it is in the structure,
+               so that we can decrement it.
+       */
+       /*      The number of adjacencies may have changed, so to locate
+               it may be a little tricky. However we know that the number
+               of adjacencies is less than or equal to the original number
+               of adjacencies,
+       */
+       int y,size;
+       ListHead *pListHead;
+       PF_FACES temp = NULL;
+       PLISTINFO lpListInfo;
+       static int each_poly = 0;
+       BOOL there = FALSE;
+
+       pListHead = PolFaces[face_id];
+       temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+       /*      Check each edge of the face and tally the number of adjacent
+               polygons to this face. 
+       */                      
+       if ( temp != NULL )
+       {
+               /*      Size of the polygon */
+        size = temp->nPolSize;
+        for (y = 0; y< size; y++)
+               {
+                       /*      If we are doing partial triangulation, we must check
+                               to see whether the edge is still there in the polygon,
+                               since we might have done a portion of the polygon
+                               and saved the rest for later.
+                       */
+               if (y != (size-1))
+                       {
+                               if( ((temp1 == *(temp->pPolygon+y)) && (temp2 ==*(temp->pPolygon+y+1)))
+                                       || ((temp2 == *(temp->pPolygon+y)) && (temp1 ==*(temp->pPolygon+y+1))))
+                                       /*      edge is still there we are ok */
+                                       there = TRUE;
+                       }
+                       else
+                       {
+                               if( ((temp1 == *(temp->pPolygon)) && (temp2 == *(temp->pPolygon+size-1)))
+                                       || ((temp2 == *(temp->pPolygon)) && (temp1 ==*(temp->pPolygon+size-1))))
+                                       /*      edge is still there we are ok */
+                                       there = TRUE;
+                       }
+               }
+               
+          if (!there)
+               /*      Original edge was already used, we cannot use this polygon */
+                       return;
+               
+               /*      We have a starting point to start our search to locate
+                       this polygon. 
+               */
+
+               /*      Check to see if this polygon was done */
+               lpListInfo = Done(face_id,59,&y);
+
+               if (lpListInfo == NULL)
+                       return;
+
+          /*  Was not done, but there is an error in the adjacency calculations */
+          /*     If more than one edge is adj to it then maybe it was not updated */
+          if (y == 0)
+            return;
+                       
+               /*      Now put the face in the proper bucket depending on tally. */
+               /*      First add it to the new bucket, then remove it from the old */
+               Add_Sgi_Adj(y-1,face_id);
+               RemoveList(array[y],lpListInfo);
+        
+          /*   Save it if it was the smallest seen so far since then
+                       it will be the next face 
+                       Here we will have different options depending on
+                       what we want for resolving ties:
+                       1) First one we see we will use
+                       2) Random resolving
+                       3) Look ahead
+                       4) Alternating direction
+               */
+               /*      At a new strip */
+               if (*next_bucket == 60)
+                       *ties = *ties + each_poly;
+               /*      Have a tie */
+               if (*next_bucket == (y-1))
+               {
+                       Add_Ties(face_id);
+                       each_poly++;
+               }
+               /*      At a new minimum */
+               if (*next_bucket > (y-1))
+               {
+                       *next_bucket = y-1;
+                       *min_face = face_id;
+                       *e1 = temp1;
+                       *e2 = temp2;
+                       each_poly = 0;
+                       Clear_Ties();
+                       Add_Ties(face_id);
+               }
+       }
+}
+
+
+void Delete_AdjEx(int id1, int id2,int *next_bucket,int *min_face, 
+                               int current_face,int *e1,int *e2,int *ties)
+{
+       /*      Find the face that is adjacent to the edge and is not the
+               current face. Delete one adjacency from it. Save the min
+               adjacency seen so far.
+       */
+       register int count=0;
+       PF_EDGES temp = NULL;
+       ListHead *pListHead;
+       int next_face;
+
+       /*      Always want smaller id first */
+       switch_lower(&id1,&id2);
+       
+       pListHead = PolEdges[id1];
+       temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     if (temp == NULL)
+       /*      It could be a new edge that we created. So we can
+               exit, since there is not a face adjacent to it.
+       */
+               return;
+     while (temp->edge[0] != id2)
+     {
+               count++;
+               temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+          if (temp == NULL)
+                       /*      Was a new edge that was created and therefore
+                               does not have anything adjacent to it
+                       */
+                       return;
+    }
+       /*      Was not adjacent to anything else except itself */
+    if (temp->edge[2] == -1)
+               return;
+
+    /* Was adjacent to something */
+    else
+    {
+               if (temp->edge[2] == current_face)
+                       next_face =  temp->edge[1];
+               else 
+                       next_face = temp->edge[2];
+       }
+       /*      We have the other face adjacent to this edge, it is 
+               next_face. Now we need to decrement this faces' adjacencies.
+       */
+       Update_FaceEx(next_bucket, min_face, next_face,e1,e2,id1,id2,ties);
+}
+
+int Change_FaceEx(int face_id,int in1,int in2,
+                                ListHead *pListHead, P_ADJACENCIES temp, BOOL no_check)
+{
+       /*      We are doing a partial triangulation and we need to
+               put the new face of triangle into the correct bucket
+       */
+       int input_adj,y;
+     P_ADJACENCIES pfNode,lpListInfo;
+       
+     /*        Find the old number of adjacencies to this face,
+               so we know where to delete it from
+       */
+       y = Old_Adj(face_id);
+       pListHead = array[y];
+
+     pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+       if ( pfNode )
+               pfNode->face_id = face_id;
+       lpListInfo = (P_ADJACENCIES) (SearchList(array[y], pfNode,
+                  (int (*)(void *,void *)) (Compare)));
+       if (lpListInfo == NULL)
+       {
+               printf("There is an error finding the next polygon3 %d\n",face_id);
+               exit(0);
+       }
+
+     /*        Do we need to change the adjacency? Maybe the edge on the triangle
+               that was outputted was not adjacent to anything. We know if we
+               have to check by "check". We came out on the output edge
+               that we needed, then we know that the adjacencies will decrease
+               by exactly one.
+       */
+       if (!no_check)
+       {
+               input_adj = Number_Adj(in1,in2,face_id);
+               /*      If there weren't any then don't do anything */
+               if (input_adj == 0)
+                       return y;
+       }
+     
+       RemoveList(pListHead,(PLISTINFO)/*(temp*/lpListInfo);
+       /*      Before we had a quad with y adjacencies. The in edge
+               did not have an adjacency, since it was just deleted,
+               since we came in on it. The outedge must have an adjacency
+               otherwise we would have a bucket 0, and would not be in this
+               routine. Therefore the new adjacency must be y-1
+       */
+    
+    Add_Sgi_Adj(y-1,face_id);
+    return (y-1);
+}
+
+int Update_AdjacenciesEx(int face_id, int *next_bucket, int *e1, int *e2,
+                                       int *ties)
+{
+       /*      Give the face with id face_id, we want to decrement
+               all the faces that are adjacent to it, since we will
+               be deleting face_id from the data structure.
+               We will return the face that has the least number
+               of adjacencies.
+       */
+       PF_FACES temp = NULL;
+       ListHead *pListHead;
+       int size,y,min_face = -1;
+       
+     *next_bucket = 60;
+       pListHead = PolFaces[face_id];
+       temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+       
+       if ( temp == NULL )
+       {
+               printf("The face was already deleted, there is an error\n");
+               exit(0);
+       }
+       
+       /*      Size of the polygon */
+       size = temp->nPolSize;
+       for (y = 0; y< size; y++)
+       {
+               if (y != (size-1))
+                       Delete_AdjEx(*(temp->pPolygon+y),*(temp->pPolygon+y+1),
+                               next_bucket,&min_face,face_id,e1,e2,ties);
+               else
+                       Delete_AdjEx(*(temp->pPolygon),*(temp->pPolygon+(size-1)),
+                               next_bucket,&min_face,face_id,e1,e2,ties);
+       }
+       return (min_face);
+}
+
+
+
+void Find_Adj_TallyEx(int id1, int id2,int *next_bucket,int *min_face, 
+                              int current_face,int *ties)
+{
+       /*      Find the face that is adjacent to the edge and is not the
+               current face. Save the min adjacency seen so far.
+       */
+       int size,each_poly=0,y,tally=0,count=0;
+       PF_EDGES temp = NULL;
+       PF_FACES temp2 = NULL;
+       ListHead *pListHead;
+       int next_face;
+       BOOL there = FALSE;
+
+    
+    /* Always want smaller id first */
+       switch_lower(&id1,&id2);
+       
+       pListHead = PolEdges[id1];
+       temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+     if (temp == NULL)
+     /*        This was a new edge that was created, so it is
+               adjacent to nothing.
+       */
+               return;
+       while (temp->edge[0] != id2)
+     {
+               count++;
+               temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
+          if (temp == NULL)
+                       /*      This was a new edge that we created */
+                       return;
+     }
+       /*      Was not adjacent to anything else except itself */
+       if (temp->edge[2] == -1)
+               return;
+       else
+       {
+               if (temp->edge[2] == current_face)
+                       next_face =  temp->edge[1];
+               else 
+                       next_face = temp->edge[2];
+       }
+       /*      We have the other face adjacent to this edge, it is 
+               next_face. Find how many faces it is adjacent to.
+       */
+       pListHead = PolFaces[next_face];
+       temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+       /*      Check each edge of the face and tally the number of adjacent 
+               polygons to this face. This will be the original number of
+               polygons adjacent to this polygon, we must then see if this
+               number has been decremented
+       */                      
+       if ( temp2 != NULL )
+       {
+               /*      Size of the polygon */
+               size = temp2->nPolSize;
+               for (y = 0; y< size; y++)
+               {
+                       /*      Make sure that the edge is still in the
+                               polygon and was not deleted, because if the edge was
+                               deleted, then we used it already.
+                       */
+                       if (y != (size-1))
+                       {
+                               if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1)))
+                                       || ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1))))
+                                       /*      edge is still there we are ok */
+                                       there = TRUE;
+                       }
+                       else
+                       {               
+                               if( ((id1 == *(temp2->pPolygon)) && (id2 ==*(temp2->pPolygon+size-1)))
+                                       || ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1))))
+                                       /*      edge is still there we are ok */
+                                       there = TRUE;
+                       }
+               }
+               
+               if (!there)
+                       /*      Edge already used and deleted from the polygon*/
+                       return;
+               
+               /*      See if the face was already deleted, and where
+                       it is if it was not
+               */
+               if (Done(next_face,size,&y) == NULL)
+                       return;
+               
+               /*      Save it if it was the smallest seen so far since then
+                       it will be the next face 
+                       Here we will have different options depending on
+                       what we want for resolving ties:
+                       1) First one we see we will use
+                       2) Random resolving
+                       3) Look ahead
+                       4) Alternating direction
+               */
+                                       
+               /*      At a new strip */
+               if (*next_bucket == 60)
+                       *ties = *ties + each_poly;
+               /*      Have a tie */
+               if (*next_bucket == (y-1))
+               {
+                       Add_Ties(next_face);
+                       each_poly++;
+               }
+               /*      At a new minimum */
+               if (*next_bucket > (y-1))
+               {
+                       *next_bucket = y-1;
+                       *min_face = next_face;
+                       each_poly = 0;
+                       Clear_Ties();
+                       Add_Ties(next_face);
+               }
+       }
+}
+
+
+int Min_Face_AdjEx(int face_id, int *next_bucket, int *ties)
+{
+       /*      Used for the Partial triangulation to find the next
+               face. It will return the minimum adjacency face id
+               found at this face.
+       */
+       PF_FACES temp = NULL;
+       ListHead *pListHead;
+       int size,y,min_face,test_face;
+       
+       *next_bucket = 60;
+       pListHead = PolFaces[face_id];
+       temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+       
+       if ( temp == NULL )
+       {
+               printf("The face was already deleted, there is an error\n");
+               exit(0);
+       }
+       
+       /*      Size of the polygon */
+       size = temp->nPolSize;
+       for (y = 0; y< size; y++)
+       {
+               if (y != (size-1))
+                       Find_Adj_TallyEx(*(temp->pPolygon+y),*(temp->pPolygon+y+1),
+                               next_bucket,&min_face,face_id,ties);
+               else
+                       Find_Adj_TallyEx(*(temp->pPolygon),*(temp->pPolygon+(size-1)),
+                               next_bucket,&min_face,face_id,ties);
+       }
+       /*    Maybe we can do better by triangulating the face, because
+          by triangulating the face we will go to a polygon of lesser
+          adjacencies
+    */
+    if (size == 4)
+    {
+         /*    Checking for a quad whether to do the whole polygon will
+               result in better performance because the triangles in the polygon
+               have less adjacencies
+         */
+         Check_In_Quad(face_id,&test_face);
+         if (*next_bucket > test_face)
+              /*    We can do better by going through the polygon */
+              min_face = face_id;
+    }
+
+    /*  We have a polygon with greater than 4 sides, check to see if going
+        inside is better than going outside the polygon for the output edge.
+    */
+    else
+    {
+        Check_In_Polygon(face_id,&test_face,size);
+        if (*next_bucket > test_face)
+            /*  We can do better by going through the polygon */
+            min_face = face_id;
+    }
+    
+    return (min_face);
+}
+
+
diff --git a/Stripe_w/sturcts.h b/Stripe_w/sturcts.h
new file mode 100644 (file)
index 0000000..57490a6
--- /dev/null
@@ -0,0 +1,36 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: sturcts.h
+-----------------------------------------------------------------------*/
+
+#define EVEN(x) (((x) & 1) == 0)
+
+int Get_Edge(int *edge1,int *edge2,int *index,int face_id,
+            int size, int id1, int id2);
+void add_vert_id();
+void Update_Face(int *next_bucket, int *min_face, int face_id, int *e1,
+                int *e2,int temp1,int temp2,int *ties);
+int Min_Adj();
+int Min_Face_Adj(int face_id, int *next_bucket, int *ties);
+int Change_Face(int face_id,int in1,int in2, ListHead *pListHead, 
+               P_ADJACENCIES temp, BOOL no_check);
+void Delete_Adj(int id1, int id2,int *next_bucket,int *min_face, 
+               int current_face,int *e1,int *e2,int *ties);
+int Update_Adjacencies(int face_id, int *next_bucket, int *e1, int *e2,
+                      int *ties);
+int Get_Output_Edge();
+int Find_Face();
+
+
+
+
+
+
+
diff --git a/Stripe_w/sturctsex.h b/Stripe_w/sturctsex.h
new file mode 100644 (file)
index 0000000..6a4a76d
--- /dev/null
@@ -0,0 +1,33 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE:sturctsex.h
+-----------------------------------------------------------------------*/
+
+#define EVEN(x) (((x) & 1) == 0)
+
+int Get_EdgeEx(int *edge1,int *edge2,int *index,int face_id,
+              int size, int id1, int id2);
+void add_vert_idEx();
+void Update_FaceEx(int *next_bucket, int *min_face, int face_id, int *e1,
+                  int *e2,int temp1,int temp2,int *ties);
+int Min_Face_AdjEx(int face_id, int *next_bucket, int *ties);
+int Change_FaceEx(int face_id,int in1,int in2,
+                 ListHead *pListHead, P_ADJACENCIES temp, BOOL no_check);
+void Delete_AdjEx(int id1, int id2,int *next_bucket,int *min_face, 
+                 int current_face,int *e1,int *e2,int *ties);
+int Number_AdjEx();
+int Update_AdjacenciesEx(int face_id, int *next_bucket, int *e1, int *e2,
+                        int *ties);
+
+
+
+
+
+
diff --git a/Stripe_w/ties.c b/Stripe_w/ties.c
new file mode 100644 (file)
index 0000000..e3fd31f
--- /dev/null
@@ -0,0 +1,304 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*     STRIPE: ties.c
+     This file will contain all the routines used to determine the next face if there
+       is a tie
+*/
+/*---------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include "polverts.h"
+#include "ties.h"
+#include "sturctsex.h"
+#include "triangulatex.h"
+#include "options.h"
+#include "common.h"
+#include "util.h"
+
+#define MAX_TIE 60
+int ties_array[60];
+int last = 0;
+
+void Clear_Ties()
+{
+       /*      Clear the buffer, because we do not have the tie
+               any more that we had before */
+       last = 0;
+}
+
+void Add_Ties(int id)
+{
+       /*      We have a tie to add to the buffer */
+       ties_array[last++] = id;
+}
+
+int Alternate_Tie()
+{
+       /*      Alternate in what we choose to break the tie 
+               We are just alternating between the first and
+               second thing that we found
+       */
+       static int x = 0;
+       register int t;
+       
+       t = ties_array[x];
+       x++;
+       if (x == 2)
+               x = 0;
+       return t;
+}
+
+int Random_Tie()
+{
+       /*      Randomly choose the next face with which
+               to break the tie
+       */
+       register int num;
+
+       num = rand();
+       while (num >= last)
+               num = num/20;
+       return (ties_array[num]);
+}
+
+int Look_Ahead(int id)
+{
+       /*      Look ahead at this face and save the minimum
+               adjacency of all the faces that are adjacent to
+               this face.
+       */
+       return Min_Adj(id);
+}
+
+int Random_Look(int id[],int count)
+{
+       /*      We had a tie within a tie in the lookahead, 
+               break it randomly 
+       */
+       register int num;
+
+       num = rand();
+       while (num >= count)
+               num = num/20;
+       return (id[num]);
+}
+
+
+int Look_Ahead_Tie()
+{
+       /*      Look ahead and find the face to go to that
+               will give the least number of adjacencies
+       */
+       int id[60],t,x,f=0,min = 60;
+
+       for (x = 0; x < last; x++)
+       {
+               t = Look_Ahead(ties_array[x]);
+               /*      We have a tie */
+               if (t == min)
+                       id[f++] = ties_array[x];
+               if (t < min)
+               {
+                       f = 0;
+                       min = t;
+                       id[f++] = ties_array[x];
+               }
+       }
+       /*      No tie within the tie */
+       if ( f == 1)
+               return id[0];
+       /*      Or ties, but we are at the end of strips */
+       if (min == 0)
+               return id[0];
+       return (Random_Look(id,f));
+}
+
+
+int Sequential_Tri(int *index)
+{
+    /*  We have a triangle and need to break the ties at it.
+        We will choose the edge that is sequential. There
+        is definitely one since we know we have a triangle
+        and that there is a tie and there are only 2 edges
+        for the tie.
+    */
+    int e1,e2,e3,output1,output2,output3,output4;
+
+    /*  e2 and e3 are the input edge to the triangle */
+    Last_Edge(&e1,&e2,&e3,0);
+    
+    if ((e2 == 0) && (e3 == 0))
+        /*  Starting the strip, don't need to do this */
+        return ties_array[0];
+
+    /*  For the 2 ties find the edge adjacent to face id */
+    Get_EdgeEx(&output1,&output2,index,ties_array[0],3,0,0);
+    Get_EdgeEx(&output3,&output4,index,ties_array[1],3,0,0);
+
+    if ((output1 == e3) || (output2 == e3))
+        return ties_array[0];
+    if ((output3 == e3) || (output4 == e3))
+        return ties_array[1];
+    printf("There is an error trying to break sequential triangle \n");
+}
+
+int Sequential_Quad(int *index,        int triangulate)
+{
+    /*  We have a quad that need to break its ties, we will try
+        and choose a side that is sequential, otherwise use lookahead
+    */
+    int output1,output2,x,e1,e2,e3;
+
+    /*  e2 and e3 are the input edge to the quad */
+    Last_Edge(&e1,&e2,&e3,0);
+
+    /*  No input edge */
+    if ((e2 == 0) && (e3 == 0))
+        return ties_array[0];
+
+       /*  Go through the ties and see if there is a sequential one */
+    for (x = 0; x < last; x++)
+       {
+        Get_EdgeEx(&output1,&output2,index,ties_array[x],4,0,0);
+        /*  Partial and whole triangulation will have different requirements */
+        if (((output1 == e3) || (output2 == e3)) && (triangulate == PARTIAL))
+            return ties_array[x];
+        if (((output1 != e3) && (output1 != e2) &&
+                (output2 != e3) && (output2 != e2)))
+            return ties_array[x];
+    }
+    /*  There was not a tie that was sequential */
+       return Look_Ahead_Tie();
+}
+
+void Whole_Output(int in1,int in2, int *index, int size, int *out1, int *out2)
+{
+    /*  Used to sequentially break ties in the whole triangulation for polygons
+        greater than 4 sides. We will find the output edge that is good
+        for sequential triangulation.
+    */
+
+    int half;
+    
+    /*  Put the input edge first in the list */
+    Rearrange_IndexEx(index,size);
+
+    if (!(EVEN(size)))
+    {
+        if (*(index) == in1)
+            half = size/2 ;
+        else
+            half = size/2 +1;
+    }
+    else
+        half = size/2;
+
+    *out1 = *(index+half);
+    *out2 = *(index+half+1);
+}
+
+int Sequential_Poly(int size, int *index, int triangulate)
+{
+    /*  We have a polygon of greater than 4 sides and wish to break the
+        tie in the most sequential manner.
+    */
+
+    int x,output1,output2,e1,e2,e3,saved1=-1,saved2=-1,output3,output4;
+    
+    /*  e2 and e3 are the input edge to the quad */
+    Last_Edge(&e1,&e2,&e3,0);
+
+    /*  If we are using whole, find the output edge that is sequential */
+    if (triangulate == WHOLE)
+        Whole_Output(e2,e3,index,size,&output3,&output4);
+
+    /*  No input edge */
+    if ((e2 == 0) && (e3 == 0))
+        return ties_array[0];
+    
+    for (x = 0; x < last ; x++)
+    {
+        Get_EdgeEx(&output1,&output2,index,ties_array[x],size,0,0);
+        /*  Partial that can be removed in just one triangle */
+        if (((output1 == e3) || (output2 == e3)) && (triangulate == PARTIAL))
+            saved1 = ties_array[x];
+        /*  Partial removed in more than one triangle */
+        if ((output1 != e3) && (output1 != e2) && (output2 != e3) && (output2 != e2) &&
+            (triangulate == PARTIAL) && (saved2 != -1))
+            saved2 = ties_array[x];
+        /*  Whole is not so easy, since the whole polygon must be done. Given
+            an input edge there is only one way to come out, approximately half
+            way around the polygon.
+        */
+        if (((output1 == output3) && (output2 == output4)) ||
+            ((output1 == output4) && (output2 == output3)) &&
+            (triangulate == WHOLE))
+            return ties_array[x];
+    }
+    
+    if (saved1 != -1)
+        return saved1;
+    if (saved2 != -1)
+        return saved2;
+    
+    /*  There was not a tie that was sequential */
+    return Look_Ahead_Tie();
+}
+
+int Sequential_Tie(int face_id, int triangulate)
+{
+    /*  Break the tie by choosing the face that will
+        not give us a swap and is sequential. If there
+        is not one, then do the lookahead to break the
+        tie.
+    */
+    /*  Separate into 3 cases for simplicity, if the current
+        polygon has 3 sides, 4 sides or if the sides were 
+        greater. We can do the smaller cases faster, so that
+        is why I separated the cases.
+    */
+
+     ListHead *pListFace;
+       PF_FACES face;
+
+    /* Get the polygon with id face_id */
+       pListFace  = PolFaces[face_id];
+       face = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
+
+     if (face->nPolSize == 3)
+        return(Sequential_Tri(face->pPolygon));
+     if (face->nPolSize == 4)
+        return(Sequential_Quad(face->pPolygon,triangulate));
+     else
+        return(Sequential_Poly(face->nPolSize,face->pPolygon,triangulate));
+
+}
+
+int Get_Next_Face(int t, int face_id, int triangulate)
+{
+       /*      Get the next face depending on what
+               the user specified
+       */
+       
+       /*      Did not have a tie, don't do anything */
+       if (last == 1)
+               return(ties_array[0]);
+       if (t == RANDOM)
+               return Random_Tie();
+       if (t == ALTERNATE)
+               return Alternate_Tie();
+       if (t == LOOK)
+               return Look_Ahead_Tie();
+     if (t == SEQUENTIAL)
+        return Sequential_Tie(face_id,triangulate);
+
+       printf("Illegal option specified for ties, using first \n");
+     return (ties_array[0]);
+}
diff --git a/Stripe_w/ties.h b/Stripe_w/ties.h
new file mode 100644 (file)
index 0000000..502aabf
--- /dev/null
@@ -0,0 +1,15 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: ties.h
+-----------------------------------------------------------------------*/
+
+void Clear_Ties();
+void Add_Ties(int id);
+int Get_Next_Face(int t, int face_id, int triangulate);
diff --git a/Stripe_w/triangulate.h b/Stripe_w/triangulate.h
new file mode 100644 (file)
index 0000000..1f67743
--- /dev/null
@@ -0,0 +1,27 @@
+
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: triangulate.h
+-----------------------------------------------------------------------*/
+
+void Blind_Triangulate(int size, int *index, FILE *output,
+                      BOOL begin, int where ,int color1,int color2,
+                       int color3);
+void Non_Blind_Triangulate(int size,int *index, FILE *output,
+                          int next_face_id,int face_id,int where,
+                           int color1,int color2,int color3);
+int Adjacent(int id2,int id1, int *list, int size);
+void Delete_From_List(int id,int *list, int *size);
+void Triangulate_Polygon(int out_edge1, int out_edge2, int in_edge1,
+                        int in_edge2, int size, int *index,
+                        FILE *output, int reversed, int face_id,
+                         int where, int color1, int color2, int color3);
+void Rearrange_Index(int *index, int size);
+void Find_Local_Strips();
diff --git a/Stripe_w/triangulatex.h b/Stripe_w/triangulatex.h
new file mode 100644 (file)
index 0000000..3b2d8fb
--- /dev/null
@@ -0,0 +1,28 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: triangulatex.h
+-----------------------------------------------------------------------*/
+
+enum swap_type
+{ ON, OFF};
+
+void SGI_StripEx();
+void Blind_TriangulateEx(int size, int *index, FILE *fp, FILE *output, 
+                        BOOL begin, int where );
+void Non_Blind_TriangulateEx(int size,int *index, FILE *fp, FILE *output,
+                            int next_face_id,int face_id,int where);
+int AdjacentEx(int id2,int id1, int *list, int size);
+void Delete_From_ListEx(int id,int *list, int size);
+void Triangulate_PolygonEx(int out_edge1,int out_edge2,int in_edge1,
+                          int in_edge2,int size,int *index,
+                          FILE *output,FILE *fp,int reversed,int face_id,
+                           int where);
+void Rearrange_IndexEx(int *index, int size);
+void Find_StripsEx();
diff --git a/Stripe_w/util.c b/Stripe_w/util.c
new file mode 100644 (file)
index 0000000..f17fe5f
--- /dev/null
@@ -0,0 +1,272 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: util.c
+     This file contains routines that are used for various functions
+*/
+/*---------------------------------------------------------------------*/
+
+
+#include <stdlib.h>
+#include "polverts.h"
+
+void switch_lower (int *x, int *y)
+{
+       register int temp;
+       
+       /*      Put lower value in x */
+       if (*y < *x)
+       {
+               temp = *x;
+               *x = *y;
+               *y = temp;
+       }
+}
+
+BOOL member(int x , int id1, int id2, int id3)
+{
+    /*  Is x in the triangle specified by id1,id2,id3 */
+    if ((x != id1) && (x != id2) && (x != id3))
+       return FALSE;
+    return TRUE;
+}
+
+
+int Compare (P_ADJACENCIES node1, P_ADJACENCIES node2)
+{
+       /*      This will only return whether 2 adjacency nodes
+               are equivalent.                                                           
+       */
+       if (node1->face_id == node2->face_id)
+               return TRUE;
+       else
+               return FALSE;
+}
+
+
+BOOL Exist(int face_id, int id1, int id2)
+{
+       /*      Does the edge specified by id1 and id2 exist in this
+               face currently? Maybe we deleted in partial triangulation
+       */
+       ListHead *pListHead;
+       PF_FACES temp;
+       register int x,size;
+       BOOL a=FALSE,b =FALSE; 
+
+       pListHead = PolFaces[face_id];
+       temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
+       size = temp->nPolSize;
+       for (x=0; x<size; x++)
+       {
+               if (*(temp->pPolygon+x) == id1)
+                       a = TRUE;
+               if (*(temp->pPolygon+x) == id2)
+                       b = TRUE;
+               if (a && b)
+                       return TRUE;
+       }
+       return FALSE;
+}
+
+int Get_Next_Id(int *index,int e3, int size)
+{
+    /*  Return the id following e3 in the list of vertices */
+
+    register int x;
+
+    for (x = 0; x< size; x++)
+    {
+        if ((*(index+x) == e3) && (x != (size-1)))
+            return *(index+x+1);
+        else if (*(index+x) == e3)
+            return *(index);
+    }
+    printf("There is an error in the next id\n");
+    exit(0);
+}
+
+int Different (int id1,int id2,int id3,int id4,int id5, int id6, int *x, int *y)
+{
+    /*    Find the vertex in the first 3 numbers that does not exist in 
+            the last three numbers
+    */
+    if ((id1 != id4) && (id1 != id5) && (id1 != id6))
+    {
+       *x = id2;
+       *y = id3;
+       return id1;
+    }
+    if ((id2 != id4) && (id2 != id5) && (id2 != id6))
+    {
+       *x = id1;
+       *y = id3;
+       return id2;
+    }
+    if ((id3 != id4) && (id3 != id5) && (id3 != id6))
+    {
+       *x = id1;
+       *y = id2;
+       return id3;
+    }
+    
+    /*  Because there are degeneracies in the data, this might occur */
+    *x = id5;
+    *y = id6;
+    return id4;
+}
+
+int Return_Other(int *index,int e1,int e2)
+{
+       /*   We have a triangle and want to know the third vertex of it */
+       register int x;
+
+       for (x=0;x<3;x++)
+       {
+               if ((*(index+x) != e1) && (*(index+x) != e2))
+                       return *(index+x);
+       }
+     /*   If there is a degenerate triangle return arbitrary */
+     return e1;
+}
+
+int Get_Other_Vertex(int id1,int id2,int id3,int *index)
+{
+       /*      We have a list index of 4 numbers and we wish to
+          return the number that is not id1,id2 or id3
+       */
+       register int x;
+
+       for (x=0; x<4; x++)
+       {
+               if ((*(index+x) != id1) && (*(index+x) != id2) &&
+                       (*(index+x) != id3))
+                       return *(index+x);
+       }
+       /*   If there is some sort of degeneracy this might occur,
+          return arbitrary 
+     */
+     if (x==4)
+          return id1;
+}
+
+
+PLISTINFO Done(int face_id, int size, int *bucket)
+{
+       /*      Check to see whether the polygon with face_id was used
+               already, return NULL if it was, otherwise return a pointer to the face.
+       */
+       P_ADJACENCIES pfNode;
+       register int y;
+       PLISTINFO lpListInfo;
+       
+       pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
+       if ( pfNode )
+               pfNode->face_id = face_id;
+               
+       for (y=size; ; y--)
+       {
+               lpListInfo = SearchList(array[y], pfNode,
+                       (int (*)(void *,void *)) (Compare));
+               if (lpListInfo != NULL)
+               {
+                       *bucket = y;
+                       return lpListInfo;
+               }
+               if (y == 0)
+               /*      This adjacent face was done already */
+                       return lpListInfo;
+       }
+       free (pfNode);
+}
+
+void Output_Edge(int *index,int e2,int e3,int *output1,int *output2)
+{
+    /*  Given a quad and an input edge return the other 2 vertices of the
+        quad.
+    */
+    
+    *output1 = -1;
+    *output2 = -1;
+
+    if ((*(index) != e2) && (*(index) != e3))
+        *output1 = *(index);
+
+    if ((*(index+1) != e2) && (*(index+1) != e3))
+    {
+        if (*output1 == -1)
+            *output1 = *(index+1);
+        else
+        {
+            *output2 = *(index+1);
+            return;
+        }
+    }
+
+    if ((*(index+2) != e2) && (*(index+2) != e3))
+    {
+        if (*output1 == -1)
+            *output1 = *(index+2);
+        else
+        {
+            *output2 = *(index+2);
+            return;
+        }
+    }
+
+    *output2 = *(index+3);
+}
+
+
+void First_Edge(int *id1,int *id2, int *id3)
+{
+    /*  Get the first triangle in the strip we just found, we will use this to
+          try to extend backwards in the strip
+    */
+
+    ListHead *pListHead;
+    register int num;
+    P_STRIPS temp1,temp2,temp3;
+        
+    pListHead = strips[0];
+    num = NumOnList(pListHead);
+     
+    /*    Did not have a strip */
+    if (num < 3)
+         return;
+         
+    temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 0);
+    temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 1);
+    temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 2);
+    *id1 = temp1->face_id;
+    *id2 = temp2->face_id;
+    *id3 = temp3->face_id;
+}
+
+void Last_Edge(int *id1, int *id2, int *id3, BOOL save)
+{
+       /*   We need the last edge that we had  */
+       static int v1, v2, v3;
+
+       if (save)
+       {
+               v1 = *id1;
+               v2 = *id2;
+               v3 = *id3;
+       }
+       else
+       {
+               *id1 = v1;
+               *id2 = v2;
+               *id3 = v3;
+       }
+}
+
+
diff --git a/Stripe_w/util.h b/Stripe_w/util.h
new file mode 100644 (file)
index 0000000..64c2f23
--- /dev/null
@@ -0,0 +1,24 @@
+/********************************************************************/
+/*   STRIPE: converting a polygonal model to triangle strips    
+     Francine Evans, 1996.
+     SUNY @ Stony Brook
+     Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/*   STRIPE: util.h
+-----------------------------------------------------------------------*/
+
+void switch_lower (int *x, int *y);
+int Compare (P_ADJACENCIES node1, P_ADJACENCIES node2);
+BOOL Exist(int face_id, int id1, int id2);
+int Get_Next_Id(int *index,int e3, int size);
+int Different(int id1,int id2,int id3,int id4,int id5, int id6, int *x, int *y);
+int Return_Other(int *index,int e1,int e2);
+int Get_Other_Vertex(int id1,int id2,int id3,int *index);
+PLISTINFO Done(int face_id, int size, int *bucket);
+void Output_Edge(int *index,int e2,int e3,int *output1,int *output2);
+void Last_Edge(int *id1, int *id2, int *id3, BOOL save);
+void First_Edge(int *id1,int *id2, int *id3);
+BOOL member(int x , int id1, int id2, int id3);