--- /dev/null
+bin_PROGRAMS = strips
+
+strips_SOURCES = \
+ add.c add.h \
+ bands.c \
+ common.c common.h \
+ define.h \
+ extend.h \
+ free.c free.h \
+ global.h \
+ glove.h \
+ init.c init.h \
+ local.c local.h \
+ my_global.h \
+ newpolve.c \
+ options.c options.h \
+ output.c output.h \
+ outputex.c outputex.h \
+ partial.c partial.h \
+ polverts.h polvertsex.h \
+ queue.c queue.h \
+ sgi_triang.c sgi_triangex.c \
+ struct.c struct.h \
+ structex.c \
+ sturcts.h sturctsex.h \
+ ties.c ties.h \
+ triangulate.h triangulatex.h \
+ util.c util.h
+
--- /dev/null
+# Makefile.in generated automatically by automake 1.2h from Makefile.am
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DISTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+CC = @CC@
+CXX = @CXX@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+NM = @NM@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+
+bin_PROGRAMS = strips
+
+strips_SOURCES = \
+ add.c add.h \
+ bands.c \
+ common.c common.h \
+ define.h \
+ extend.h \
+ free.c free.h \
+ global.h \
+ glove.h \
+ init.c init.h \
+ local.c local.h \
+ my_global.h \
+ newpolve.c \
+ options.c options.h \
+ output.c output.h \
+ outputex.c outputex.h \
+ partial.c partial.h \
+ polverts.h polvertsex.h \
+ queue.c queue.h \
+ sgi_triang.c sgi_triangex.c \
+ struct.c struct.h \
+ structex.c \
+ sturcts.h sturctsex.h \
+ ties.c ties.h \
+ triangulate.h triangulatex.h \
+ util.c util.h
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../Simulator/Include/config.h
+CONFIG_CLEAN_FILES =
+PROGRAMS = $(bin_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../Simulator/Include
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+strips_OBJECTS = add.o bands.o common.o free.o init.o local.o \
+newpolve.o options.o output.o outputex.o partial.o queue.o sgi_triang.o \
+sgi_triangex.o struct.o structex.o ties.o util.o
+strips_LDADD = $(LDADD)
+strips_DEPENDENCIES =
+strips_LDFLAGS =
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON = Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP = --best
+DEP_FILES = .deps/add.P .deps/bands.P .deps/common.P .deps/free.P \
+.deps/init.P .deps/local.P .deps/newpolve.P .deps/options.P \
+.deps/output.P .deps/outputex.P .deps/partial.P .deps/queue.P \
+.deps/sgi_triang.P .deps/sgi_triangex.P .deps/struct.P .deps/structex.P \
+.deps/ties.P .deps/util.P
+SOURCES = $(strips_SOURCES)
+OBJECTS = $(strips_OBJECTS)
+
+all: Makefile $(PROGRAMS)
+
+.SUFFIXES:
+.SUFFIXES: .S .c .lo .o .s
+$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu Tools/Stripe_u/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
+ $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ list='$(bin_PROGRAMS)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+ done
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+strips: $(strips_OBJECTS) $(strips_DEPENDENCIES)
+ @rm -f strips
+ $(LINK) $(strips_LDFLAGS) $(strips_OBJECTS) $(strips_LDADD) $(LIBS)
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = Tools/Stripe_u
+
+distdir: $(DISTFILES)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(top_distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Tools/Stripe_u/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file; \
+ done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+
+maintainer-clean-depend:
+ -rm -rf .deps
+
+%.o: %.c
+ @echo '$(COMPILE) -c $<'; \
+ $(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
+
+%.lo: %.c
+ @echo '$(LTCOMPILE) -c $<'; \
+ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
+ @-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
+ < .deps/$(*F).p > .deps/$(*F).P
+ @-rm -f .deps/$(*F).p
+info:
+dvi:
+check: all
+ $(MAKE)
+installcheck:
+install-exec: install-binPROGRAMS
+ @$(NORMAL_INSTALL)
+
+install-data:
+ @$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+ @:
+
+uninstall: uninstall-binPROGRAMS
+
+install-strip:
+ $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
+installdirs:
+ $(mkinstalldirs) $(DATADIR)$(bindir)
+
+
+mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -rm -f Makefile $(DISTCLEANFILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean: mostlyclean-binPROGRAMS mostlyclean-compile \
+ mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+ mostlyclean-generic
+
+clean: clean-binPROGRAMS clean-compile clean-libtool clean-tags \
+ clean-depend clean-generic mostlyclean
+
+distclean: distclean-binPROGRAMS distclean-compile distclean-libtool \
+ distclean-tags distclean-depend distclean-generic clean
+ -rm -f config.status
+ -rm -f libtool
+
+maintainer-clean: maintainer-clean-binPROGRAMS maintainer-clean-compile \
+ maintainer-clean-libtool maintainer-clean-tags \
+ maintainer-clean-depend maintainer-clean-generic \
+ distclean
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info dvi installcheck install-exec install-data \
+install uninstall all installdirs mostlyclean-generic distclean-generic \
+clean-generic maintainer-clean-generic clean mostlyclean distclean \
+maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null
+/********************************************************************/
+/* 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[MAX1], int vert_count, int face_id, int norms[MAX1])
+{
+PF_FACES pfNode;
+int *pTempInt;
+int *pnorms;
+F_EDGES **pTempVertptr;
+int *pTempmarked, *pTempwalked;
+register int y,count = 0,sum = 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[MAX1], int vert_count, int face_id, int norms[MAX1])
+{
+PF_FACES pfNode;
+int *pTempInt;
+int *pnorms;
+F_EDGES **pTempVertptr;
+int *pTempmarked, *pTempwalked;
+register int y,count = 0,sum = 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;
+
+}
+
+
--- /dev/null
+/********************************************************************/
+/* STRIPE: converting a polygonal model to triangle strips
+ Francine Evans, 1996.
+ SUNY @ Stony Brook
+ Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/* STRIPE: add.h
+-----------------------------------------------------------------------*/
+
+BOOL new_vertex();
+BOOL Check_VN();
+BOOL norm_array();
+void add_texture();
+int add_vert_id();
+void add_norm_id();
+void AddNewFace();
+void CopyFace();
+void Add_Edge();
+void Add_AdjEdge();
+
+
+
--- /dev/null
+/********************************************************************/
+/* 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.
+*/
+/*---------------------------------------------------------------------*/
+
+
+#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"
+
+#define MAX1 60
+/* 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>
+#include <sys/time.h>
+struct timeval tm;
+struct timezone tz;
+double et;
+#define START gettimeofday(&tm,&tz);\
+ et = (tm.tv_sec)+ (0.000001* (tm.tv_usec));
+
+#define STOP gettimeofday(&tm,&tz);\
+ et = (tm.tv_sec)+(0.000001*(tm.tv_usec)) - et;
+#endif
+
+
+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
+ printf("Time for last frame = %lf seconds\n", et);
+ #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.
+**
+*/
+
+void main (int argc,char *argv[])
+{
+ char *fname,*all,buff[255], *ptr, *ptr2;
+ FILE *file, *bands;
+ int face_id=0, vert_count, loop, num=0,num2;
+ float center[3];
+ int temp[MAX1],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 */
+ float norm_difference;
+
+ /* Structures for the object */
+ struct vert_struct *vertices = NULL,
+ *nvertices = NULL,
+ *pvertices = NULL,
+ *pnvertices = NULL;
+
+ get_time();
+ START
+
+ /* File that will contain the triangle strip data */
+ bands = fopen("bands.d","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++;
+ /* 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);
+ }
+
+
+ /* 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--;
+ 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 %lf %lf %lf\n",
+ pnvertices->x,pnvertices->y,pnvertices->z);
+ ++pnvertices;
+ }
+ else if (*(ptr+1)=='t')
+ {
+ sscanf (ptr+3,"%f%f%f",¢er[0],¢er[1],¢er[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 %lf %lf %lf\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 %lf %lf %lf\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--;
+ }
+ }
+ /* the vertex */
+ else
+ {
+ 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 there are vertices and textures with the data */
+ else if (normal_and_texture)
+ {
+ 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 %lf %lf %lf\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--;
+ }
+ }
+ /* the vertex */
+ else if ((loop == 0) || (*(ptr2-1) == ' '))
+ {
+ 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);
+
+ /* 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(" 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);
+
+ /* 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);
+ STOP
+
+ get_time();
+
+}
+
--- /dev/null
+/********************************************************************/
+/* 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,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);
+ /* 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;
+ PF_FACES temp2 = NULL;
+
+ /* 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;
+ }
+ }
+}
+
+
--- /dev/null
+/********************************************************************/
+/* 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();
+void Find_Adjacencies();
+void Add_Sgi_Adj();
+int Num_Adj();
+void Add_Id_Strips();
+BOOL Look_Up();
+int Number_Adj();
+int Old_Adj();
+int Min_Adj();
+int Find_Face();
+void Edge_Least();
+void Get_Input_Edge();
+int Get_Output_Edge();
+void Check_In_Polygon();
+void Check_In_Quad();
+void New_Size_Face ();
+void New_Face ();
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+
+#define VRDATA double
+#define MAX1 60
+
+#define TRUE 1
+#define FALSE 0
+
+#define PI 3.1415926573
+
+struct vert_struct {
+ VRDATA x, y, z; /* point coordinates */
+};
+
--- /dev/null
+/********************************************************************/
+/* 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();
+
+
--- /dev/null
+/********************************************************************/
+/* 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"
+
+void ParseAndFreeList( ListHead *pListHead )
+{
+ PLISTINFO value;
+ register int c,num;
+
+ /* Freeing a linked list */
+ num = NumOnList(pListHead);
+ for (c = 0; c< num; c++)
+ value = RemHead(pListHead);
+}
+
+void FreePolygonNode( PF_VERTS pfVerts)
+{
+ /* Free a vertex node */
+ if ( pfVerts->pPolygon )
+ free( pfVerts->pPolygon );
+ free( pfVerts );
+
+}
+
+void Free_Strips()
+{
+ P_STRIPS temp = NULL;
+
+ /* 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);
+}
+
+
--- /dev/null
+/********************************************************************/
+/* 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();
+void FreePolygonNode();
+void Free_Strips();
+void FreeFaceTable();
+void FreeEdgeTable();
+void End_Face_Struct();
+void End_Edge_Struct();
+
+
--- /dev/null
+/********************************************************************/
+/* STRIPE: converting a polygonal model to triangle strips
+ Francine Evans, 1996.
+ SUNY @ Stony Brook
+ Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/* STRIPE: global.h
+-----------------------------------------------------------------------*/
+
+#define VRDATA double
+#define MAX1 60
+
+#define TRUE 1
+#define FALSE 0
+
+#ifndef PI
+# define PI 3.1415926573
+#endif /* PI */
+#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 */
+};
+
+int ids[MAX1];
+int norms[MAX1];
+int *vert_norms;
+int *vert_texture;
+
--- /dev/null
+/*
+ * dg2lib.h - header file for the DG2 library libdg2.a
+ *
+ * copyright 1988-92 VPL Research Inc.
+ *
+ */
+
+
+
+/******** error returns from the library */
+
+extern int DG2_error; /* for error information */
+extern float DG2_lib_version; /* for the library version */
+extern int DG2_box_version; /* for the firmware version */
+extern int DG2_glove_sensors; /* for the number of sensors in the glove */
+
+/* defines for DG2_error values */
+
+#define DG2_AOK 0
+#define DG2_SETTINGS_FILE -1
+#define DG2_SERIAL_OPEN -2
+#define DG2_SERIAL_PORT -4
+#define DG2_RESET -6
+#define DG2_PARAMETER -7
+#define DG2_FILE_IO -8
+#define DG2_CALIBRATION_FILE -9
+#define DG2_GESTURE_FILE -10
+#define DG2_CAL_GEST_FILES -11
+/* defines for DG2_response() */
+
+#define DATAGLOVE 1
+#define POLHEMUS 2
+#define GESTURE 8
+
+#define DG2_60Hz 1
+#define DG2_30Hz 2
+#define DG2_oneShot 3
+
+/* defines for DG2_DataGlove_select() */
+
+#define THUMB_INNER 0x1
+#define THUMB_OUTER 0x2
+#define INDEX_INNER 0x4
+#define INDEX_OUTER 0x8
+#define MIDDLE_INNER 0x10
+#define MIDDLE_OUTER 0x20
+#define RING_INNER 0x40
+#define RING_OUTER 0x80
+#define LITTLE_INNER 0x100
+#define LITTLE_OUTER 0x200
+#define NORMAL_JOINTS 0x3ff
+#define FLEX11 0x400
+#define FLEX12 0x800
+#define FLEX13 0x1000
+#define FLEX14 0x2000
+#define FLEX15 0x4000
+#define FLEX16 0x8000
+
+
+/* defines for DG2_DataGlove_trans_select() */
+
+#define DG2_TRANSLATED 5
+#define DG2_RAW 6
+
+/* defines for DG2_Polhemus_units() */
+
+#define POL_RAW 0
+#define POL_INCHES 1
+#define POL_CM 2
+
+/* defines for DG2_user_IRQ() */
+
+#define IRQ_ON 1
+#define IRQ_OFF 2
+
+
+/* defines for DG2_get_data() */
+
+#define DG2_report 1
+#define DG2_userport 2
+
+
+/* dg2 command codes*/
+#define LEADINGBYTE 0x24
+#define RPT60 0x41 /* repeat 60 */
+#define RPT30 0x42 /* repeat 30 */
+#define ONESHOT 0x43 /* one shot */
+#define SYSID 0x44 /* system ID */
+#define EPTBUF 0x45 /* empty buffer */
+#define USRRD 0x46 /* user read */
+#define USRIRQ 0x47 /* user IRQ */
+#define QBRT 0x48 /* query bright */
+#define CDRST 0x49 /* cold reset */
+#define WMRST 0x4A /* warm reset */
+#define MEMALLO 0x4B /* memory alloc */
+#define DLTSND 0x4C /* delta send */
+#define SETBRT 0x4D /* set bright */
+#define SETDIM 0x4E /* set dim */
+#define FILBUF 0x4F /* fill buffer */
+#define LDTBL 0x50 /* load table */
+#define LDPOL 0x51 /* send up to 63 bytes to Polhemus */
+#define ANGLE 0x52 /* angles */
+#define NSNSR 0x53 /* num sensors */
+#define SETFB 0x54 /* set feedback */
+#define QCUT 0X55 /* query cutoff*/
+#define SETCUT 0X56 /* set cutoff */
+#define FLXVAL 0X57 /* raw flex values */
+#define USRWR 0X58 /* user write */
+#define JNTMAP 0X59 /* joint map */
+#define ERRMESS 0XFF /* error in command input */
+#define TIMOUT 0XFE /* timed out during command */
+
+/* response structure */
+
+typedef struct DG2_data {
+ char gesture;
+ double location[3]; /* X,Y,Z */
+ double orientation[3]; /* yaw, pitch, roll */
+ short flex[16];
+ char gesture_name[20];
+ short reserved[16];
+ /* user port data: */
+ char user_nibble;
+ char user_analog[3];
+} DG2_data;
+
+
+/**************function prototypes*************/
+/*NOTE: all DG2_ functions return -1 on error*/
+
+extern int DG2_open(char *portname, int baud);
+extern int DG2_close(int filedes);
+extern int DG2_direct(int filedes,char *message,int count);
+extern int DG2_response(int filedes,int devices,int rate);
+extern int DG2_DataGlove_select(int filedes,int flex_sensors);
+extern int DG2_DataGlove_translation(int filedes,int flex_sensors,char table[16][256]);
+extern int DG2_DataGlove_trans_select(int filedes,int status);
+extern int DG2_DataGlove_LED_set(int filedes,int LED);
+extern int DG2_DataGlove_LED_read(int filedes);
+extern int DG2_Polhemus_units(int filedes,char type);
+extern int DG2_Polhemus_direct(int filedes,char *message,int count);
+extern int DG2_user_write(int filedes,int nibble);
+extern int DG2_user_IRQ(int filedes,int mode);
+extern int DG2_user_read(int filedes,DG2_data *data);
+extern int DG2_get_data(int filedes,DG2_data *data);
+extern int DG2_gesture_load(int filedes,char *calib,char *gest);
+
+/*use this with caution since it does not return until it gets a correct
+ *response from the DG2
+*/
+extern int DG2U_get_reply(int filedes,char *buff,int response,int size);
--- /dev/null
+/********************************************************************/
+/* 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);
+ }
+}
+
+
--- /dev/null
+/********************************************************************/
+/* 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();
+void init_vert_texture();
+BOOL InitVertTable();
+BOOL InitFaceTable();
+BOOL InitEdgeTable();
+void InitStripTable();
+void Init_Table_SGI();
+void BuildVertTable();
+void BuildFaceTable();
+void BuildEdgeTable();
+void Start_Face_Struct();
+void Start_Edge_Struct();
+
+
+
+
+
+
--- /dev/null
+/********************************************************************/
+/* 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);
+
+}
--- /dev/null
+/********************************************************************/
+/* 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();
--- /dev/null
+int change_in_stripEx = 0;
+int change_in_strip = 0;
+
--- /dev/null
+/********************************************************************/
+/* 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[MAX1];
+int added_quad = 0;
+BOOL reversed = FALSE;
+int patch = 0;
+int *vn;
+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 t,smallest_so_far,nextvert,max=-1;
+
+ t= lastvert;
+ *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];
+ register int x,y,z=0;
+ int saved[2];
+ static int output1, output2,last_id;
+ BOOL cptexture;
+
+ /* 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.
+ */
+
+ cptexture = texture;
+ if (end)
+ {
+ *edge1 = output1;
+ *edge2 = output2;
+ *face_id = last_id;
+ return;
+ }
+
+ 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)
+{
+ register int walk = 0,count = 0;
+ int previous_edge1,previous_edge2;
+ int static last_seen = 1000;
+ 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,count = 0;
+ int previous_edge1,previous_edge2;
+ int static 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 color = 0,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 (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;
+ register int total_walk, start_back_walk;
+ static int seen = 0;
+ static BOOL first = TRUE;
+ int test;
+ BOOL f = TRUE, wrap = FALSE, set = FALSE;
+ test = lastvert;
+
+ /* In the "Fast_Reset" resetting will be true */
+ if ((resetting) && (first))
+ {
+ seen = 0;
+ first = FALSE;
+ }
+
+ seen++;
+ total_walk = front_walk + back_walk;
+ start_back_walk = back_walk;
+ /* 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);
+ }
+ }
+ }
+ }
+}
+
+
--- /dev/null
+/********************************************************************/
+/* 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);
+}
+
+float get_options(int argc, char **argv, int *f, int *t, int *tr, int *group)
+{
+ char c;
+ int count = 0;
+ int buffer[MAX1];
+ int next = 0;
+ /* tie variable */
+ enum tie_options tie = FIRST;
+ /* triangulation variable */
+ enum triangulation_options triangulate = WHOLE;
+ /* 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;
+}
--- /dev/null
+/********************************************************************/
+/* STRIPE: converting a polygonal model to triangle strips
+ Francine Evans, 1996.
+ SUNY @ Stony Brook
+ Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/* STRIPE: options.h
+-----------------------------------------------------------------------*/
+
+float get_options();
+enum file_options {ASCII,BINARY};
+enum tie_options {FIRST, RANDOM, ALTERNATE, LOOK, SEQUENTIAL};
+enum triangulation_options {PARTIAL,WHOLE};
+
--- /dev/null
+/********************************************************************/
+/* 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.
+ */
+ register int start_swap = 0;
+ 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);
+ /*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);
+
+
+ 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 ((text) && (vt[vertex2]==0))
+ {
+ if (cptexture)
+ fprintf(output,"\nq ");
+ cptexture = FALSE;
+ }
+ if ((!norm) && (!cptexture))
+ fprintf(output,"%d ",vertex2+1);
+ else if ((norm) && (!cptexture))
+ fprintf(output,"%d//%d ",vertex2+1,vn[vertex2]+1);
+ else if ((!norm) && (cptexture))
+ fprintf(output,"%d/%d ",vertex2+1,vt[vertex2]+1);
+ else
+ fprintf(output,"%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;
+ static BOOL begin = TRUE;
+ int old_face,next_face_id,next_bucket,e1,e2,e3,other1,other2,other3;
+ P_ADJACENCIES lpListInfo;
+ int ties=0;
+ int tie = SEQUENTIAL;
+
+ /* 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));
+ }
+
+ old_face = next_face_id;
+ /* 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);
+ begin = FALSE;
+
+ /* 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);
+ begin = FALSE;
+ 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));
+}
+
+
--- /dev/null
+/********************************************************************/
+/* STRIPE: converting a polygonal model to triangle strips
+ Francine Evans, 1996.
+ SUNY @ Stony Brook
+ Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/* STRIPE: output.h
+-----------------------------------------------------------------------*/
+
+
+#define TRIANGLE 3
+#define MAGNITUDE 1000000
+
+void Output_Tri();
+void Sgi_Test();
+int Polygon_Output();
+void Last_Edge();
+void Extend_Backwards();
+int Finished();
+int Extend_Face();
+void Fast_Reset();
+
+
--- /dev/null
+/********************************************************************/
+/* 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,d=1,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);
+
+}
+
+
+
+
+
+
+
+
--- /dev/null
+/********************************************************************/
+/* STRIPE: converting a polygonal model to triangle strips
+ Francine Evans, 1996.
+ SUNY @ Stony Brook
+ Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/* STRIPE: outputex.h
+-----------------------------------------------------------------------*/
+
+
+#define TRIANGLE 3
+#define MAGNITUDE 1000000
+
+void Output_TriEx();
+void Sgi_Test();
+void Polygon_OutputEx();
+void Extend_BackwardsEx();
+void FinishedEx();
+
+
--- /dev/null
+/********************************************************************/
+/* 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 "polvertsex.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);
+ 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\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,next_bucket;
+ 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 */
+ next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+ next_bucket = 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 */
+ next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
+ next_bucket = 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);
+ }
+ }
+
+
--- /dev/null
+/********************************************************************/
+/* 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();
+void Inside_Polygon();
+
--- /dev/null
+/********************************************************************/
+/* STRIPE: converting a polygonal model to triangle strips
+ Francine Evans, 1996.
+ SUNY @ Stony Brook
+ Advisors: Steven Skiena and Amitabh Varshney
+*/
+/********************************************************************/
+
+/*---------------------------------------------------------------------*/
+/* STRIPE: polverts.h
+-----------------------------------------------------------------------*/
+
+#include "queue.h"
+#include <malloc.h>
+
+
+/* external functions */
+void Find_Adjacencies();
+void Test_Adj_Struct();
+void Test_SGI_Struct();
+void Write_Edges();
+void Build_SGI_Table();
+void Save_Walks();
+void Find_Bands();
+void Save_Rest();
+void Assign_Walk();
+void Save_Walks();
+
+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;
+ };
+
+
+/* Globals */
+ListHead **PolVerts;
+ListHead **PolFaces;
+ListHead **PolEdges;
+ListHead *array[60];
+int id_array[60];
+ListHead *strips[1];
+ListHead *all_strips[100000]; /* Assume max 100000 strips */
--- /dev/null
+/********************************************************************/
+/* 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();
+
+
+
--- /dev/null
+/********************************************************************/
+/* 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 );
+}
+
--- /dev/null
+
+/********************************************************************/
+/* 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
+
+
--- /dev/null
+/********************************************************************/
+/* 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,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,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,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,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,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;
+ int x = 0;
+ BOOL flag = FALSE;
+
+ /* 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,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,where);
+ return;
+ }
+ increasing = 1;
+ mode = 1;
+
+ }
+ else if (!begin)
+ {
+ Output_Tri(*(index+1),*(index+0),*(index+size-1),output,color1,color2,color3,where,where);
+ if (size == 4)
+ {
+ Output_Tri(*(index+0),*(index+size-1),*(index+2),output,color1,color2,color3,where,where);
+ return;
+ }
+ Output_Tri(*(index+0),*(index+size-1),*(index+2),output,color1,color2,color3,where,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,where);
+ increasing++;
+ }
+ else
+ {
+ Output_Tri(*(index+decreasing),*(index+increasing),*(index+decreasing-1),output,color1,color2,color3,where,where);
+ decreasing--;
+ }
+ mode = !mode;
+ } while ((decreasing - increasing) >= 2);
+
+ }
+}
+
+
+
+
--- /dev/null
+/********************************************************************/
+/* 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;
+ int x = 0;
+ BOOL flag = FALSE;
+
+ /* 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);
+
+ }
+}
+
+
--- /dev/null
+/********************************************************************/
+/* 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,tally=0;
+ 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,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;
+ /* 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);
+}
+
+
+
--- /dev/null
+
+struct vert_struct {
+ VRDATA x, y, z; /* point coordinates */
+};
+
+
--- /dev/null
+/********************************************************************/
+/* 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,tally=0;
+ 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);
+}
+
+
--- /dev/null
+/********************************************************************/
+/* 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)
+
+BOOL Get_Edge();
+void add_vert_id();
+void Update_Face();
+int Min_Adj();
+int Min_Face_Adj();
+int Change_Face();
+void Delete_Adj();
+int Update_Adjacencies();
+int Get_Output_Edge();
+int Find_Face();
+
+
+
+
+
+
+
--- /dev/null
+/********************************************************************/
+/* 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)
+
+BOOL Get_EdgeEx();
+void add_vert_idEx();
+void Update_FaceEx();
+int Min_Face_AdjEx();
+int Change_FaceEx();
+void Delete_AdjEx();
+int Number_AdjEx();
+int Update_AdjacenciesEx();
+
+
+
+
+
+
--- /dev/null
+/********************************************************************/
+/* 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 reversed, 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 */
+ reversed = Get_EdgeEx(&output1,&output2,index,ties_array[0],3,0,0);
+ reversed = 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 reversed,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++)
+ {
+ reversed = 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,reversed,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++)
+ {
+ reversed = 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]);
+}
--- /dev/null
+/********************************************************************/
+/* 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 Get_Next_Face();
--- /dev/null
+
+/********************************************************************/
+/* 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();
+void Non_Blind_Triangulate();
+int Adjacent();
+void Delete_From_List();
+void Triangulate_Polygon();
+void Rearrange_Index();
+void Find_Local_Strips();
+
+
+
--- /dev/null
+/********************************************************************/
+/* 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();
+void Non_Blind_TriangulateEx();
+int AdjacentEx();
+void Delete_From_ListEx();
+void Triangulate_PolygonEx();
+void Rearrange_IndexEx();
+void Find_StripsEx();
--- /dev/null
+/********************************************************************/
+/* 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;
+ }
+}
+
+
--- /dev/null
+/********************************************************************/
+/* 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 Compare ();
+BOOL Exist();
+int Get_Next_Id();
+int Different();
+int Return_Other();
+int Get_Other_Vertex();
+PLISTINFO Done();
+void Output_Edge();
+void Last_Edge();
+void First_Edge();
+BOOL member();