1
0
Fork 0

Initial revision.

This commit is contained in:
curt 1998-04-09 01:58:04 +00:00
parent 784960bd8f
commit 8deb5c5804
44 changed files with 10299 additions and 0 deletions

29
Stripe_u/Makefile.am Normal file
View file

@ -0,0 +1,29 @@
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

349
Stripe_u/Makefile.in Normal file
View file

@ -0,0 +1,349 @@
# 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:

386
Stripe_u/add.c Normal file
View file

@ -0,0 +1,386 @@
/********************************************************************/
/* 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;
}

25
Stripe_u/add.h Normal file
View file

@ -0,0 +1,25 @@
/********************************************************************/
/* 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();

549
Stripe_u/bands.c Normal file
View file

@ -0,0 +1,549 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: 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",&center[0],&center[1],&center[2]);
fprintf(bands,"vt %f %f %f\n",center[0],center[1],center[2]);
}
else
{
sscanf (ptr+2,"%lf%lf%lf",
&(pvertices->x),
&(pvertices->y),
&(pvertices->z));
fprintf(bands,"v %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();
}

811
Stripe_u/common.c Normal file
View file

@ -0,0 +1,811 @@
/********************************************************************/
/* 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;
}
}
}

41
Stripe_u/common.h Normal file
View file

@ -0,0 +1,41 @@
/********************************************************************/
/* 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 ();

13
Stripe_u/define.h Normal file
View file

@ -0,0 +1,13 @@
#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 */
};

17
Stripe_u/extend.h Normal file
View file

@ -0,0 +1,17 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: extend.h
-----------------------------------------------------------------------*/
int Bottom_Left();
int Top_Left();
void Start_Edge();

110
Stripe_u/free.c Normal file
View file

@ -0,0 +1,110 @@
/********************************************************************/
/* 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);
}

22
Stripe_u/free.h Normal file
View file

@ -0,0 +1,22 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: free.h
-----------------------------------------------------------------------*/
void Free_All_Strips();
void ParseAndFreeList();
void FreePolygonNode();
void Free_Strips();
void FreeFaceTable();
void FreeEdgeTable();
void End_Face_Struct();
void End_Edge_Struct();

37
Stripe_u/global.h Normal file
View file

@ -0,0 +1,37 @@
/********************************************************************/
/* 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;

151
Stripe_u/glove.h Normal file
View file

@ -0,0 +1,151 @@
/*
* 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);

217
Stripe_u/init.c Normal file
View file

@ -0,0 +1,217 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: init.c
This file contains the initialization of data structures.
*/
/*---------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include "global.h"
#include "polverts.h"
void init_vert_norms(int num_vert)
{
/* Initialize vertex/normal array to have all zeros to
start with.
*/
register int x;
for (x = 0; x < num_vert; x++)
*(vert_norms + x) = 0;
}
void init_vert_texture(int num_vert)
{
/* Initialize vertex/normal array to have all zeros to
start with.
*/
register int x;
for (x = 0; x < num_vert; x++)
*(vert_texture + x) = 0;
}
BOOL InitVertTable( int nSize )
{
register int nIndex;
/* Initialize the vertex table */
PolVerts = (ListHead**) malloc(sizeof(ListHead*) * nSize );
if ( PolVerts )
{
for ( nIndex=0; nIndex < nSize; nIndex++ )
{
PolVerts[nIndex] = NULL;
}
return( TRUE );
}
return( FALSE );
}
BOOL InitFaceTable( int nSize )
{
register int nIndex;
/* Initialize the face table */
PolFaces = (ListHead**) malloc(sizeof(ListHead*) * nSize );
if ( PolFaces )
{
for ( nIndex=0; nIndex < nSize; nIndex++ )
{
PolFaces[nIndex] = NULL;
}
return( TRUE );
}
return( FALSE );
}
BOOL InitEdgeTable( int nSize )
{
register int nIndex;
/* Initialize the edge table */
PolEdges = (ListHead**) malloc(sizeof(ListHead*) * nSize );
if ( PolEdges )
{
for ( nIndex=0; nIndex < nSize; nIndex++ )
{
PolEdges[nIndex] = NULL;
}
return( TRUE );
}
return( FALSE );
}
void InitStripTable( )
{
PLISTHEAD pListHead;
/* Initialize the strip table */
pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
if ( pListHead )
{
InitList( pListHead );
strips[0] = pListHead;
}
else
{
printf("Out of memory !\n");
exit(0);
}
}
void Init_Table_SGI()
{
PLISTHEAD pListHead;
int max_adj = 60;
register int x;
/* This routine will initialize the table that will
have the faces sorted by the number of adjacent polygons
to it.
*/
for (x=0; x< max_adj; x++)
{
/* We are allowing the max number of sides of a polygon
to be max_adj.
*/
pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
if ( pListHead )
{
InitList( pListHead );
array[x] = pListHead;
}
else
{
printf("Out of memory !\n");
exit(0);
}
}
}
void BuildVertTable( int nSize )
{
register int nIndex;
PLISTHEAD pListHead;
for ( nIndex=0; nIndex < nSize; nIndex++ )
{
pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
if ( pListHead )
{
InitList( pListHead );
PolVerts[nIndex] = pListHead;
}
else
return;
}
}
void BuildFaceTable( int nSize )
{
register int nIndex;
PLISTHEAD pListHead;
for ( nIndex=0; nIndex < nSize; nIndex++ )
{
pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
if ( pListHead )
{
InitList( pListHead );
PolFaces[nIndex] = pListHead;
}
else
return;
}
}
void BuildEdgeTable( int nSize )
{
register int nIndex;
PLISTHEAD pListHead;
for ( nIndex=0; nIndex < nSize; nIndex++ )
{
pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
if ( pListHead )
{
InitList( pListHead );
PolEdges[nIndex] = pListHead;
}
else
return;
}
}
void Start_Face_Struct(int numfaces)
{
if (InitFaceTable(numfaces))
{
BuildFaceTable(numfaces);
}
}
void Start_Edge_Struct(int numverts)
{
if (InitEdgeTable(numverts))
{
BuildEdgeTable(numverts);
}
}

30
Stripe_u/init.h Normal file
View file

@ -0,0 +1,30 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: init.h
-----------------------------------------------------------------------*/
void init_vert_norms();
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();

123
Stripe_u/local.c Normal file
View file

@ -0,0 +1,123 @@
/********************************************************************/
/* 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);
}

19
Stripe_u/local.h Normal file
View file

@ -0,0 +1,19 @@
/********************************************************************/
/* 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();

3
Stripe_u/my_global.h Normal file
View file

@ -0,0 +1,3 @@
int change_in_stripEx = 0;
int change_in_strip = 0;

1667
Stripe_u/newpolve.c Normal file

File diff suppressed because it is too large Load diff

181
Stripe_u/options.c Normal file
View file

@ -0,0 +1,181 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: options.c
This file contains routines that are used to determine the options
that were specified by the user
*/
/*---------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include "options.h"
#include "global.h"
int power_10(int power)
{
/* Raise 10 to the power */
register int i,p;
p = 1;
for (i = 1; i <= power; ++i)
p = p * 10;
return p;
}
float power_negative(int power)
{
/* Raise 10 to the negative power */
register int i;
float p;
p = (float)1;
for (i = 1; i<=power; i++)
p = p * (float).1;
return p;
}
float convert_array(int num[],int stack_size)
{
/* Convert an array of characters to an integer */
register int counter,c;
float temp =(float)0.0;
for (c=(stack_size-1), counter = 0; c>=0; c--, counter++)
{
if (num[c] == -1)
/* We are at the decimal point, convert to decimal
less than 1
*/
{
counter = -1;
temp = power_negative(stack_size - c - 1) * temp;
}
else
temp += power_10(counter) * num[c];
}
return(temp);
}
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;
}

17
Stripe_u/options.h Normal file
View file

@ -0,0 +1,17 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: options.h
-----------------------------------------------------------------------*/
float get_options();
enum file_options {ASCII,BINARY};
enum tie_options {FIRST, RANDOM, ALTERNATE, LOOK, SEQUENTIAL};
enum triangulation_options {PARTIAL,WHOLE};

582
Stripe_u/output.c Normal file
View file

@ -0,0 +1,582 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: 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));
}

26
Stripe_u/output.h Normal file
View file

@ -0,0 +1,26 @@
/********************************************************************/
/* 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();

518
Stripe_u/outputex.c Normal file
View file

@ -0,0 +1,518 @@
/********************************************************************/
/* 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);
}

23
Stripe_u/outputex.h Normal file
View file

@ -0,0 +1,23 @@
/********************************************************************/
/* 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();

665
Stripe_u/partial.c Normal file
View file

@ -0,0 +1,665 @@
/********************************************************************/
/* 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);
}
}

15
Stripe_u/partial.h Normal file
View file

@ -0,0 +1,15 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: partial.h
-----------------------------------------------------------------------*/
void Partial_Triangulate();
void Inside_Polygon();

87
Stripe_u/polverts.h Normal file
View file

@ -0,0 +1,87 @@
/********************************************************************/
/* 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 */

34
Stripe_u/polvertsex.h Normal file
View file

@ -0,0 +1,34 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: polvertsex.h
-----------------------------------------------------------------------*/
#include "queue.h"
#include <malloc.h>
/* external functions */
void Start_Vert_Struct();
void Start_Face_StructEx();
void Start_Edge_StructEx();
void AddNewNode();
void AddNewFaceEx();
void Find_AdjacenciesEx();
void Test_Adj_Struct();
void Test_SGI_Struct();
void Write_Edges();
void End_Verts_Struct();
void End_Face_StructEx();
void End_Edge_StructEx();
void Build_SGI_TableEx();
void Add_AdjEdgeEx();

226
Stripe_u/queue.c Normal file
View file

@ -0,0 +1,226 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: queue.c
This file contains the routines used in the data structures lists, which
are queues.
*/
/*---------------------------------------------------------------------*/
#include "queue.h"
/*----------------------------------------------------------------------------
* InitList:
*/
BOOL InitList (PLISTHEAD LHead)
{
if (LHead == NULL) return(FALSE);
LHead->LHeaders[LISTHEAD] = LHead->LHeaders[LISTTAIL] = NULL;
LHead->NumList = 0;
return(TRUE);
}
/*----------------------------------------------------------------------------
* AddHead:
*/
BOOL AddHead(PLISTHEAD LHead, PLISTINFO LInfo)
{
if (LHead == NULL || LInfo == NULL)
return(FALSE);
if (EMPTYLIST(LHead))
LHead->LHeaders[LISTTAIL] = LInfo;
else LHead->LHeaders[LISTHEAD]->ListNode.Previous = (void *) LInfo;
LInfo->ListNode.Next = (void *) LHead->LHeaders[LISTHEAD];
LHead->LHeaders[LISTHEAD] = LInfo;
LInfo->ListNode.Previous = NULL;
LHead->NumList++;
return(TRUE);
}
/*----------------------------------------------------------------------------
* AddTail
*/
BOOL AddTail(PLISTHEAD LHead, PLISTINFO LInfo)
{
if (LHead == NULL || LInfo == NULL)
return(FALSE);
if (EMPTYLIST(LHead))
LHead->LHeaders[LISTHEAD] = LInfo;
else LHead->LHeaders[LISTTAIL]->ListNode.Next = (void *) LInfo;
LInfo->ListNode.Previous = (void *) LHead->LHeaders[LISTTAIL];
LHead->LHeaders[LISTTAIL] = LInfo;
LInfo->ListNode.Next = NULL;
LHead->NumList++;
return(TRUE);
}
BOOL InsertNode( PLISTHEAD LHead, int nPos, PLISTINFO LInfo )
{
PLISTINFO LAddNode;
if ( LHead == NULL || LInfo == NULL || nPos > NumOnList( LHead ) )
return( FALSE );
if ( nPos == 0 )
AddHead( LHead, LInfo );
else if ( nPos == NumOnList( LHead ) )
AddTail( LHead, LInfo );
else
{
if ( (LAddNode = PeekList( LHead, LISTHEAD, nPos - 1 )) == NULL )
return( FALSE );
((PLISTINFO)LAddNode->ListNode.Next)->ListNode.Previous = LInfo;
LInfo->ListNode.Next = LAddNode->ListNode.Next;
LInfo->ListNode.Previous = LAddNode;
LAddNode->ListNode.Next = LInfo;
LHead->NumList++;
}
return( TRUE );
}
/*----------------------------------------------------------------------------
* RemHead:
*/
PLISTINFO RemHead(PLISTHEAD LHead)
{
PLISTINFO t, t1;
if ( LHead == NULL || EMPTYLIST(LHead) )
return(NULL);
t = LHead->LHeaders[LISTHEAD];
LHead->LHeaders[LISTHEAD] = (PLISTINFO) t->ListNode.Next;
if (LHead->LHeaders[LISTHEAD] != NULL)
{
t1 = (PLISTINFO) t->ListNode.Next;
t1->ListNode.Previous = NULL;
}
else
LHead->LHeaders[LISTTAIL] = NULL;
LHead->NumList--;
return(t);
}
/*----------------------------------------------------------------------------
* RemTail:
*/
PLISTINFO RemTail(PLISTHEAD LHead)
{
PLISTINFO t, t1;
if ( LHead == NULL || EMPTYLIST(LHead) )
return(NULL);
t = LHead->LHeaders[LISTTAIL];
LHead->LHeaders[LISTTAIL] = (PLISTINFO) t->ListNode.Previous;
if (LHead->LHeaders[LISTTAIL] != NULL)
{
t1 = (PLISTINFO) t->ListNode.Previous;
t1->ListNode.Next = NULL;
}
else
LHead->LHeaders[LISTHEAD] = NULL;
LHead->NumList--;
return(t);
}
/*----------------------------------------------------------------------------
* PeekList:
*/
PLISTINFO PeekList(PLISTHEAD LHead, int wch, int index )
{
PLISTINFO t;
if (LHead == NULL)
return(NULL);
if ( (t = LHead->LHeaders[wch]) == NULL )
return(NULL);
for (; t != NULL && index > 0; index-- )
t = (wch == LISTHEAD) ? (PLISTINFO) t->ListNode.Next :
(PLISTINFO) t->ListNode.Previous;
return(t);
}
/*----------------------------------------------------------------------------
* RemoveList:
*/
PLISTINFO RemoveList( PLISTHEAD LHead, PLISTINFO LInfo )
{
PLISTINFO t, t1;
t = LInfo;
if (LHead == NULL)
return(NULL);
if (LHead->LHeaders[LISTHEAD] == t)
t = (PLISTINFO) RemHead(LHead);
else if (LHead->LHeaders[LISTTAIL] == t)
t = (PLISTINFO) RemTail(LHead);
else
{
t1 = (PLISTINFO) t->ListNode.Previous;
t1->ListNode.Next = t->ListNode.Next;
t1 = (PLISTINFO) t->ListNode.Next;
t1->ListNode.Previous = t->ListNode.Previous;
LHead->NumList--;
}
return(t);
}
/*----------------------------------------------------------------------------
* SearchList:
* Try to find a specific node in the queue whose key matches with
* searching key. Return the pointer to that node if found, return NULL
* otherwise
*
* Input:
* lpHashTbl => a far pointer to the hash table
* lpKey => a far poniter to searching key
* CompareCallBack => comparision function
*
* Output: a far pointer to the node to be found
*
*/
PLISTINFO SearchList(
PLISTHEAD lpListHead,
PVOID lpSKey,
int (* CompareCallBack) ( PVOID, PVOID ) )
{
PLISTINFO lpListInfo;
lpListInfo = PeekList( lpListHead, LISTHEAD, 0);
while ( lpListInfo != NULL )
{
if ( CompareCallBack( lpListInfo, lpSKey ) )
break;
lpListInfo = GetNextNode( lpListInfo );
}
return( lpListInfo );
}

283
Stripe_u/queue.h Normal file
View file

@ -0,0 +1,283 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE:queue.h
-----------------------------------------------------------------------*/
#ifndef QUEUE_INCLUDED
#define QUEUE_INCLUDED
/* %%s Node */
/*****************************************************************
This structure is used to store the List linkage information of a
ListInfo structure. It contains all the necessary information for the
List functions to function properly. This structure must be the first
one defined in any block of memory to be linked with the List functions.
for an example of the used of The Node structure look in the files
ipd2dms.c and ipd2man.h
******************************************************************/
#include <stdio.h>
#define FALSE 0
#define TRUE 1
typedef struct
{
void *Next;
void *Previous;
}
Node, * PNODE;
/*****************************************************************
Next : is a pointer to the next structure in this List.
Previous : is a pointer to the previous structure in this List.
priority : this is the priority of this structure in the List. The
highest priority is 0. This field is only used by the
functions EnQue and DeQue.
******************************************************************/
/* %%e */
/* %%s ListInfo */
/*****************************************************************
This is the general means of linking application defined information into
Lists and queues. All structures must begin with the Node Structure. All
other data in the structure is user definable.
******************************************************************/
typedef struct List
{
Node ListNode; /* link to the next Listinfo Structure */
/* user definable data */
} ListInfo, *PLISTINFO;
/*****************************************************************
ListNode : this is the required node structure for the List
mainpulation functions. This must be the first
element of a user definable structure.
In order for an application to use the List routines, it must define
a structure with all the needed information. The first element in the
user definable structure must be a Node structure. The Node structure
contains all the necessary information for the List routines to do their
magic. For an example of a user defined List structure see the file
ipd2i.h. The User definable structure can be passed to any List function
that excepts a pointer to a ListInfo structure.
example:
typedef mstruct
{
Node ListNode;
int a,b,c,d,e,f,g;
}
mystruct;
the user definable portion of the above structure is represented by
the integers a,b,c,d,e,f,g. When passing this structure to a List
function a cast of (ListInfo *) must be made to satisify the "C" complier.
******************************************************************/
/* %%e */
/* %%s ListHead */
/*****************************************************************
ListHead is used as a header to a List. LHeaders[0] points to the
head of the List. LHeaders[1] points the tail of the list. When
accessing these variables use the defines LISTHEAD, LISTTAIL.
******************************************************************/
typedef struct LHead
{
PLISTINFO LHeaders[2];
int NumList;
}
ListHead, *PLISTHEAD;
/*****************************************************************
LHeaders : this is an array of two pointers to ListInfo structures.
This information is used to point to the head and tail of
a list.
NumList : this integer hold the number of structures linked into this
list.
ListHead #define:
LISTHEAD : when Peeking down a list this specifies you should
start at the Head of the list and search downward.
LISTTAIL : when Peeking down a list this specifies you should
start at the tail of the list and search foward.
******************************************************************/
#define LISTHEAD 0
#define LISTTAIL 1
/* %%e */
typedef int BOOL;
typedef void * PVOID;
#define PEEKFROMHEAD( lh, ind ) ( PeekList( (lh), LISTHEAD, (ind) ) )
#define PEEKFROMTAIL( lh, ind ) ( PeekList( (lh), LISTTAIL, (ind) ) )
#define EMPTYLIST( lh ) ( ( (lh)->LHeaders[LISTHEAD] == NULL ) )
/* General utility routines */
/* %%s QueRoutines */
BOOL InitList ( PLISTHEAD );
/*****************************************************************
InitList : Initialize a new list structure for use with the List
routines
INPUTS : LHead : a pointer to a ListHead structure.
OUTPUT : a boolean value TRUE if no errors occured FALSE
otherwise
******************************************************************/
PLISTINFO PeekList ( PLISTHEAD, int, int );
/*****************************************************************
PeekList : This funciton peeks down a list for the N'th element
from the HEAD or TAIL of the list
INPUTS : LHead : a pointer to a List head structure.
from : can either search from the HEAD or TAIL
of the list
where : how many nodes from the begining should the
List routines look.
OUTPUT : a pointer to a ListInfo structure identified by
from/where or NULL if an error occurred.
******************************************************************/
PLISTINFO RemoveList( PLISTHEAD LHead, PLISTINFO LInfo );
/*****************************************************************
RemoveList: Remove a ListInfo structure from a List.
INPUTS : LHead : a pointer to a ListHead structure.
LInfo : a pointer to the ListInfo structure to remove
from the list.
OUTPUT : a pointer to the ListInfo structure that was removed or
NULL if an error occurred.
******************************************************************/
BOOL InsertNode( PLISTHEAD LHead, int nPos, PLISTINFO LInfo );
/*****************************************************************
InsertNode: add a node to a list after a given node
INPUTS : LHead : a pointer to a ListHead structure.
nPos : the position to insert the node into
LInfo : a pointer to the new node to add to the list.
OUTPUT: a boolean value TRUE if all goes well false otherwise
*****************************************************************/
BOOL AddHead ( PLISTHEAD, PLISTINFO );
/*****************************************************************
AddHead : add a ListInfo structure to the HEAD of a list.
INPUTS : LHead : a pointer to a ListHead structure of the list
to add to.
LInfo : a pointer to the ListInfo structure to add to
the list.
OUTPUT : A boolean value TRUE if no errors occurred FALSE
otherwise.
******************************************************************/
BOOL AddTail ( PLISTHEAD, PLISTINFO );
/*****************************************************************
AddTail : Add a ListInfo structure to the TAIL of a list.
INPUTS : LHead : a pointer to a ListHead structure of the List
to add to.
LInfo : a pointer to the ListInfo structure to add to
the List.
OUTPUT : a boolean value TRUE if no errors occurred FALSE
otherwise.
******************************************************************/
PLISTINFO RemTail ( PLISTHEAD );
/*****************************************************************
RemTail : Remove a ListInfo structure from the TAIL of a List.
INPUTS : LHead : a pointer to a ListHead structure of the List
to remove from.
OUTPUT : a pointer to the ListInfo structure that was removed
or NULL if an error occurred.
******************************************************************/
PLISTINFO RemHead ( PLISTHEAD );
/*****************************************************************
RemHead : Remove a ListInfo structure from the Head of a List.
INPUTS : LHead : a pointer to a ListHead structure of the List
to remove from.
OUTPUT : a pointer to the ListInfo structure that was removed or
NULL if an error occurred.
******************************************************************/
PLISTINFO SearchList(
PLISTHEAD lpListHead,
PVOID lpSKey,
int ( * CompareCallBack) ( PVOID, PVOID ) );
/*****************************************************************
SearchList:
Try to find a specific node in the queue whose key matches with
searching key. Return the pointer to that node if found, return NULL
otherwise
Input:
lpHashTbl => a far pointer to the hash table
lpKey => a far poniter to searching key
CompareCallBack => comparision function
Output: a far pointer to the node to be found
******************************************************************/
#define NumOnList(lh) ( ((lh)->NumList) )
/*****************************************************************
NumOnList: Returns the number of Nodes linked to a ListHead
structure. This number is maintained by the List
routines.
******************************************************************/
#define GetNextNode(pli) ( ((pli)->ListNode.Next) )
/********************************************************
GetNextNode: This macro returns the Next Structure in this list.
This macro will return NULL if no more structures are
in the List.
*********************************************************/
#define GetPrevNode(pli) ( ((pli)->ListNode.Previous) )
/********************************************************
GetPrevNode: This macro returns the Previous Structure in this list.
This macro will reutrn NULL if no more structures are
in the List.
********************************************************/
/* %%e */
#endif

631
Stripe_u/sgi_triang.c Normal file
View file

@ -0,0 +1,631 @@
/********************************************************************/
/* 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);
}
}

584
Stripe_u/sgi_triangex.c Normal file
View file

@ -0,0 +1,584 @@
/********************************************************************/
/* 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);
}
}

549
Stripe_u/struct.c Normal file
View file

@ -0,0 +1,549 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: struct.c
Contains routines that update structures, and micellaneous routines.
*/
/*---------------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#include "polverts.h"
#include "ties.h"
#include "output.h"
#include "triangulate.h"
#include "sturcts.h"
#include "options.h"
#include "common.h"
#include "util.h"
int out1 = -1;
int out2 = -1;
int Get_Edge(int *edge1,int *edge2,int *index,int face_id,
int size, int id1, int id2)
{
/* Put the edge that is adjacent to face_id into edge1
and edge2. For each edge see if it is adjacent to
face_id. Id1 and id2 is the input edge, so see if
the orientation is reversed, and save it in reversed.
*/
register int x;
int reversed = -1;
BOOL set = FALSE;
for (x=0; x< size; x++)
{
if (x == (size-1))
{
if ((*(index) == id1) && (*(index+size-1)==id2))
{
if (set)
return 1;
reversed = 1;
}
else if ((*(index) == id2) && (*(index+size-1)==id1))
{
if (set)
return 0;
reversed = 0;
}
if (Look_Up(*(index),*(index+size-1),face_id))
{
if ( (out1 != -1) && ( (out1 == *(index)) || (out1 == *(index+size-1)) ) &&
( (out2 == *(index)) || (out2 == *(index+size-1)) ))
{
set = TRUE;
*edge1 = *(index);
*edge2 = *(index+size-1);
}
else if (out1 == -1)
{
set = TRUE;
*edge1 = *(index);
*edge2 = *(index+size-1);
}
if ((reversed != -1) && (set))
return reversed;
}
}
else
{
if ((*(index+x) == id1) && (*(index+x+1)==id2))
{
if (set)
return 0;
reversed = 0;
}
else if ((*(index+x) == id2) && (*(index+x+1)==id1))
{
if (set)
return 1;
reversed = 1;
}
if (Look_Up(*(index+x),*(index+x+1),face_id))
{
if ( (out1 != -1) && ( (out1 == *(index+x)) || (out1 == *(index+x+1)) ) &&
((out2 == *(index+x)) || (out2 == *(index+x+1))))
{
set = TRUE;
*edge1 = *(index+x);
*edge2 = *(index+x+1);
}
else if (out1 == -1)
{
set = TRUE;
*edge1 = *(index+x);
*edge2 = *(index+x + 1);
}
if ((reversed != -1) && (set))
return reversed;
}
}
}
if ((x == size) && (reversed != -1))
{
/* Could not find the output edge */
printf("Error in the Lookup %d %d %d %d %d %d %d %d\n",face_id,id1,id2,reversed,*edge1,*edge2,out1,out2);
exit(0);
}
return reversed;
}
void Update_Face(int *next_bucket, int *min_face, int face_id, int *e1,
int *e2,int temp1,int temp2,int *ties)
{
/* We have a face id that needs to be decremented.
We have to determine where it is in the structure,
so that we can decrement it.
*/
/* The number of adjacencies may have changed, so to locate
it may be a little tricky. However we know that the number
of adjacencies is less than or equal to the original number
of adjacencies,
*/
int y,size,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);
}

6
Stripe_u/struct.h Normal file
View file

@ -0,0 +1,6 @@
struct vert_struct {
VRDATA x, y, z; /* point coordinates */
};

553
Stripe_u/structex.c Normal file
View file

@ -0,0 +1,553 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: structex.c
This file contains routines that are used for various functions in
the local algorithm.
*/
/*---------------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#include "polverts.h"
#include "ties.h"
#include "outputex.h"
#include "triangulatex.h"
#include "sturctsex.h"
#include "options.h"
#include "common.h"
#include "util.h"
int out1Ex = -1;
int out2Ex = -1;
int Get_EdgeEx(int *edge1,int *edge2,int *index,int face_id,
int size, int id1, int id2)
{
/* Put the edge that is adjacent to face_id into edge1
and edge2. For each edge see if it is adjacent to
face_id. Id1 and id2 is the input edge, so see if
the orientation is reversed, and save it in reversed.
*/
int x;
int reversed = -1;
BOOL set = FALSE;
for (x=0; x< size; x++)
{
if (x == (size-1))
{
if ((*(index) == id1) && (*(index+size-1)==id2))
{
if (set)
return 1;
reversed = 1;
}
else if ((*(index) == id2) && (*(index+size-1)==id1))
{
if (set)
return 0;
reversed = 0;
}
if (Look_Up(*(index),*(index+size-1),face_id))
{
if ( (out1Ex != -1) && ( (out1Ex == *(index)) || (out1Ex == *(index+size-1)) ) &&
( (out2Ex == *(index)) || (out2Ex == *(index+size-1)) ))
{
set = TRUE;
*edge1 = *(index);
*edge2 = *(index+size-1);
}
else if (out1Ex == -1)
{
set = TRUE;
*edge1 = *(index);
*edge2 = *(index+size-1);
}
if ((reversed != -1) && (set))
return reversed;
}
}
else
{
if ((*(index+x) == id1) && (*(index+x+1)==id2))
{
if (set)
return 0;
reversed = 0;
}
else if ((*(index+x) == id2) && (*(index+x+1)==id1))
{
if (set)
return 1;
reversed = 1;
}
if (Look_Up(*(index+x),*(index+x+1),face_id))
{
if ( (out1Ex != -1) && ( (out1Ex == *(index+x)) || (out1Ex == *(index+x+1)) ) &&
((out2Ex == *(index+x)) || (out2Ex == *(index+x+1))))
{
set = TRUE;
*edge1 = *(index+x);
*edge2 = *(index+x+1);
}
else if (out1Ex == -1)
{
set = TRUE;
*edge1 = *(index+x);
*edge2 = *(index+x + 1);
}
if ((reversed != -1) && (set))
return reversed;
}
}
}
if ((x == size) && (reversed != -1))
{
/* Could not find the output edge */
printf("Error in the Lookup %d %d %d %d %d %d %d %d\n",face_id,id1,id2,reversed,*edge1,*edge2,out1Ex,out2Ex);
exit(0);
}
return reversed;
}
void Update_FaceEx(int *next_bucket, int *min_face, int face_id, int *e1,
int *e2,int temp1,int temp2,int *ties)
{
/* We have a face id that needs to be decremented.
We have to determine where it is in the structure,
so that we can decrement it.
*/
/* The number of adjacencies may have changed, so to locate
it may be a little tricky. However we know that the number
of adjacencies is less than or equal to the original number
of adjacencies,
*/
int y,size,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);
}

31
Stripe_u/sturcts.h Normal file
View file

@ -0,0 +1,31 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: 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();

28
Stripe_u/sturctsex.h Normal file
View file

@ -0,0 +1,28 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: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();

304
Stripe_u/ties.c Normal file
View file

@ -0,0 +1,304 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: ties.c
This file will contain all the routines used to determine the next face if there
is a tie
*/
/*---------------------------------------------------------------------*/
#include <stdlib.h>
#include "polverts.h"
#include "ties.h"
#include "sturctsex.h"
#include "triangulatex.h"
#include "options.h"
#include "common.h"
#include "util.h"
#define MAX_TIE 60
int ties_array[60];
int last = 0;
void Clear_Ties()
{
/* Clear the buffer, because we do not have the tie
any more that we had before */
last = 0;
}
void Add_Ties(int id)
{
/* We have a tie to add to the buffer */
ties_array[last++] = id;
}
int Alternate_Tie()
{
/* Alternate in what we choose to break the tie
We are just alternating between the first and
second thing that we found
*/
static int x = 0;
register int t;
t = ties_array[x];
x++;
if (x == 2)
x = 0;
return t;
}
int Random_Tie()
{
/* Randomly choose the next face with which
to break the tie
*/
register int num;
num = rand();
while (num >= last)
num = num/20;
return (ties_array[num]);
}
int Look_Ahead(int id)
{
/* Look ahead at this face and save the minimum
adjacency of all the faces that are adjacent to
this face.
*/
return Min_Adj(id);
}
int Random_Look(int id[],int count)
{
/* We had a tie within a tie in the lookahead,
break it randomly
*/
register int num;
num = rand();
while (num >= count)
num = num/20;
return (id[num]);
}
int Look_Ahead_Tie()
{
/* Look ahead and find the face to go to that
will give the least number of adjacencies
*/
int id[60],t,x,f=0,min = 60;
for (x = 0; x < last; x++)
{
t = Look_Ahead(ties_array[x]);
/* We have a tie */
if (t == min)
id[f++] = ties_array[x];
if (t < min)
{
f = 0;
min = t;
id[f++] = ties_array[x];
}
}
/* No tie within the tie */
if ( f == 1)
return id[0];
/* Or ties, but we are at the end of strips */
if (min == 0)
return id[0];
return (Random_Look(id,f));
}
int Sequential_Tri(int *index)
{
/* We have a triangle and need to break the ties at it.
We will choose the edge that is sequential. There
is definitely one since we know we have a triangle
and that there is a tie and there are only 2 edges
for the tie.
*/
int 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]);
}

15
Stripe_u/ties.h Normal file
View file

@ -0,0 +1,15 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: ties.h
-----------------------------------------------------------------------*/
void Clear_Ties();
void Add_Ties();
int Get_Next_Face();

23
Stripe_u/triangulate.h Normal file
View file

@ -0,0 +1,23 @@
/********************************************************************/
/* 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();

23
Stripe_u/triangulatex.h Normal file
View file

@ -0,0 +1,23 @@
/********************************************************************/
/* 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();

272
Stripe_u/util.c Normal file
View file

@ -0,0 +1,272 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: util.c
This file contains routines that are used for various functions
*/
/*---------------------------------------------------------------------*/
#include <stdlib.h>
#include "polverts.h"
void switch_lower (int *x, int *y)
{
register int temp;
/* Put lower value in x */
if (*y < *x)
{
temp = *x;
*x = *y;
*y = temp;
}
}
BOOL member(int x , int id1, int id2, int id3)
{
/* Is x in the triangle specified by id1,id2,id3 */
if ((x != id1) && (x != id2) && (x != id3))
return FALSE;
return TRUE;
}
int Compare (P_ADJACENCIES node1, P_ADJACENCIES node2)
{
/* This will only return whether 2 adjacency nodes
are equivalent.
*/
if (node1->face_id == node2->face_id)
return TRUE;
else
return FALSE;
}
BOOL Exist(int face_id, int id1, int id2)
{
/* Does the edge specified by id1 and id2 exist in this
face currently? Maybe we deleted in partial triangulation
*/
ListHead *pListHead;
PF_FACES temp;
register int x,size;
BOOL a=FALSE,b =FALSE;
pListHead = PolFaces[face_id];
temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
size = temp->nPolSize;
for (x=0; x<size; x++)
{
if (*(temp->pPolygon+x) == id1)
a = TRUE;
if (*(temp->pPolygon+x) == id2)
b = TRUE;
if (a && b)
return TRUE;
}
return FALSE;
}
int Get_Next_Id(int *index,int e3, int size)
{
/* Return the id following e3 in the list of vertices */
register int x;
for (x = 0; x< size; x++)
{
if ((*(index+x) == e3) && (x != (size-1)))
return *(index+x+1);
else if (*(index+x) == e3)
return *(index);
}
printf("There is an error in the next id\n");
exit(0);
}
int Different (int id1,int id2,int id3,int id4,int id5, int id6, int *x, int *y)
{
/* Find the vertex in the first 3 numbers that does not exist in
the last three numbers
*/
if ((id1 != id4) && (id1 != id5) && (id1 != id6))
{
*x = id2;
*y = id3;
return id1;
}
if ((id2 != id4) && (id2 != id5) && (id2 != id6))
{
*x = id1;
*y = id3;
return id2;
}
if ((id3 != id4) && (id3 != id5) && (id3 != id6))
{
*x = id1;
*y = id2;
return id3;
}
/* Because there are degeneracies in the data, this might occur */
*x = id5;
*y = id6;
return id4;
}
int Return_Other(int *index,int e1,int e2)
{
/* We have a triangle and want to know the third vertex of it */
register int x;
for (x=0;x<3;x++)
{
if ((*(index+x) != e1) && (*(index+x) != e2))
return *(index+x);
}
/* If there is a degenerate triangle return arbitrary */
return e1;
}
int Get_Other_Vertex(int id1,int id2,int id3,int *index)
{
/* We have a list index of 4 numbers and we wish to
return the number that is not id1,id2 or id3
*/
register int x;
for (x=0; x<4; x++)
{
if ((*(index+x) != id1) && (*(index+x) != id2) &&
(*(index+x) != id3))
return *(index+x);
}
/* If there is some sort of degeneracy this might occur,
return arbitrary
*/
if (x==4)
return id1;
}
PLISTINFO Done(int face_id, int size, int *bucket)
{
/* Check to see whether the polygon with face_id was used
already, return NULL if it was, otherwise return a pointer to the face.
*/
P_ADJACENCIES pfNode;
register int y;
PLISTINFO lpListInfo;
pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
if ( pfNode )
pfNode->face_id = face_id;
for (y=size; ; y--)
{
lpListInfo = SearchList(array[y], pfNode,
(int (*)(void *,void *)) (Compare));
if (lpListInfo != NULL)
{
*bucket = y;
return lpListInfo;
}
if (y == 0)
/* This adjacent face was done already */
return lpListInfo;
}
free (pfNode);
}
void Output_Edge(int *index,int e2,int e3,int *output1,int *output2)
{
/* Given a quad and an input edge return the other 2 vertices of the
quad.
*/
*output1 = -1;
*output2 = -1;
if ((*(index) != e2) && (*(index) != e3))
*output1 = *(index);
if ((*(index+1) != e2) && (*(index+1) != e3))
{
if (*output1 == -1)
*output1 = *(index+1);
else
{
*output2 = *(index+1);
return;
}
}
if ((*(index+2) != e2) && (*(index+2) != e3))
{
if (*output1 == -1)
*output1 = *(index+2);
else
{
*output2 = *(index+2);
return;
}
}
*output2 = *(index+3);
}
void First_Edge(int *id1,int *id2, int *id3)
{
/* Get the first triangle in the strip we just found, we will use this to
try to extend backwards in the strip
*/
ListHead *pListHead;
register int num;
P_STRIPS temp1,temp2,temp3;
pListHead = strips[0];
num = NumOnList(pListHead);
/* Did not have a strip */
if (num < 3)
return;
temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 0);
temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 1);
temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 2);
*id1 = temp1->face_id;
*id2 = temp2->face_id;
*id3 = temp3->face_id;
}
void Last_Edge(int *id1, int *id2, int *id3, BOOL save)
{
/* We need the last edge that we had */
static int v1, v2, v3;
if (save)
{
v1 = *id1;
v2 = *id2;
v3 = *id3;
}
else
{
*id1 = v1;
*id2 = v2;
*id3 = v3;
}
}

24
Stripe_u/util.h Normal file
View file

@ -0,0 +1,24 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: util.h
-----------------------------------------------------------------------*/
void switch_lower ();
int 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();