Initial revision.
This commit is contained in:
parent
784960bd8f
commit
8deb5c5804
44 changed files with 10299 additions and 0 deletions
29
Stripe_u/Makefile.am
Normal file
29
Stripe_u/Makefile.am
Normal 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
349
Stripe_u/Makefile.in
Normal 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
386
Stripe_u/add.c
Normal 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
25
Stripe_u/add.h
Normal 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
549
Stripe_u/bands.c
Normal 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",¢er[0],¢er[1],¢er[2]);
|
||||||
|
fprintf(bands,"vt %f %f %f\n",center[0],center[1],center[2]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sscanf (ptr+2,"%lf%lf%lf",
|
||||||
|
&(pvertices->x),
|
||||||
|
&(pvertices->y),
|
||||||
|
&(pvertices->z));
|
||||||
|
fprintf(bands,"v %lf %lf %lf\n",
|
||||||
|
pvertices->x,pvertices->y,pvertices->z);
|
||||||
|
++pvertices;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (*ptr == 'f')
|
||||||
|
{
|
||||||
|
/* Read in faces */
|
||||||
|
num2 = 0;
|
||||||
|
face_id++;
|
||||||
|
ptr2 = ptr+1;
|
||||||
|
normal = FALSE; texture = FALSE, normal_and_texture = FALSE;
|
||||||
|
while (*ptr2)
|
||||||
|
{
|
||||||
|
if (*ptr2 >='0' && *ptr2 <='9')
|
||||||
|
{
|
||||||
|
num2++;
|
||||||
|
++ptr2;
|
||||||
|
while (*ptr2 && (*ptr2!=' ' && *ptr2!='/'))
|
||||||
|
ptr2++;
|
||||||
|
/* There are normals in this line */
|
||||||
|
if (*ptr2 == '/')
|
||||||
|
{
|
||||||
|
if (*(ptr2+1) == '/')
|
||||||
|
normal = TRUE;
|
||||||
|
else
|
||||||
|
texture = TRUE;
|
||||||
|
}
|
||||||
|
else if (*ptr2 == ' ')
|
||||||
|
{
|
||||||
|
if ((num2 == 3) && (texture))
|
||||||
|
normal_and_texture = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++ptr2;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr2 = ptr+1;
|
||||||
|
|
||||||
|
/* loop on the number of numbers in this line of face data
|
||||||
|
*/
|
||||||
|
vert_count = 0;
|
||||||
|
|
||||||
|
for (loop=0;loop<num2;loop++)
|
||||||
|
{
|
||||||
|
/* skip the whitespace */
|
||||||
|
while (*ptr2<'0' || *ptr2>'9')
|
||||||
|
{
|
||||||
|
if (*ptr2 == '-')
|
||||||
|
break;
|
||||||
|
ptr2++;
|
||||||
|
}
|
||||||
|
vertex = atoi(ptr2)-1;
|
||||||
|
if (vertex < 0)
|
||||||
|
{
|
||||||
|
vertex = num_vert + vertex;
|
||||||
|
*ptr2 = ' ';
|
||||||
|
ptr2++;
|
||||||
|
}
|
||||||
|
/* If there are either normals or textures with the vertices
|
||||||
|
in this file, the data alternates so we must read it this way
|
||||||
|
*/
|
||||||
|
if ( (normal) && (!normal_and_texture))
|
||||||
|
{
|
||||||
|
if (loop%2)
|
||||||
|
{
|
||||||
|
add_norm_id(vertex,vert_count);
|
||||||
|
/* Test here to see if we added a new vertex, since the
|
||||||
|
vertex has more than one normal and the 2 normals are greater
|
||||||
|
than the threshold specified
|
||||||
|
*/
|
||||||
|
if (norm_array(vertex,0,norm_difference,nvertices,num_vert))
|
||||||
|
{
|
||||||
|
/* Add a new vertex and change the
|
||||||
|
id of the vertex that we just read to the id of the new
|
||||||
|
vertex that we just added
|
||||||
|
*/
|
||||||
|
/* Put it in the output file, note the added vertices will
|
||||||
|
be after the normals and separated from the rest of the
|
||||||
|
vertices. Will not affect our viewer
|
||||||
|
*/
|
||||||
|
fprintf(bands,"v %lf %lf %lf\n",
|
||||||
|
(vertices + temp[vert_count - 1])->x,
|
||||||
|
(vertices + temp[vert_count - 1])->y,
|
||||||
|
(vertices + temp[vert_count - 1])->z);
|
||||||
|
num_vert++;
|
||||||
|
temp[vert_count - 1] = num_vert - 1;
|
||||||
|
if (!(add_vert_id(num_vert - 1,vert_count)))
|
||||||
|
vert_count--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* the vertex */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
temp[vert_count] = vertex ;
|
||||||
|
vert_count++;
|
||||||
|
if (!(add_vert_id(vertex,vert_count)))
|
||||||
|
vert_count--;
|
||||||
|
norm_array(vertex,1,norm_difference,nvertices,num_vert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Else there are vertices and textures with the data */
|
||||||
|
else if (normal_and_texture)
|
||||||
|
{
|
||||||
|
if( !((loop+1)%3))
|
||||||
|
{
|
||||||
|
add_norm_id(vertex,vert_count);
|
||||||
|
/* Test here to see if we added a new vertex, since the
|
||||||
|
vertex has more than one normal and the 2 normals are greater
|
||||||
|
than the threshold specified
|
||||||
|
*/
|
||||||
|
if (norm_array(vertex,0,norm_difference,nvertices,num_vert))
|
||||||
|
{
|
||||||
|
/* Add a new vertex and change the
|
||||||
|
id of the vertex that we just read to the id of the new
|
||||||
|
vertex that we just added
|
||||||
|
*/
|
||||||
|
/* Put it in the output file, note the added vertices will
|
||||||
|
be after the normals and separated from the rest of the
|
||||||
|
vertices. Will not affect our viewer
|
||||||
|
*/
|
||||||
|
fprintf(bands,"v %lf %lf %lf\n",
|
||||||
|
(vertices + temp[vert_count - 1])->x,
|
||||||
|
(vertices + temp[vert_count - 1])->y,
|
||||||
|
(vertices + temp[vert_count - 1])->z);
|
||||||
|
num_vert++;
|
||||||
|
temp[vert_count - 1] = num_vert - 1;
|
||||||
|
if (!(add_vert_id(num_vert - 1,vert_count)))
|
||||||
|
vert_count--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* the vertex */
|
||||||
|
else if ((loop == 0) || (*(ptr2-1) == ' '))
|
||||||
|
{
|
||||||
|
temp[vert_count] = vertex ;
|
||||||
|
vert_count++;
|
||||||
|
if (vert_count == 4)
|
||||||
|
quads = TRUE;
|
||||||
|
if (!(add_vert_id(vertex,vert_count)))
|
||||||
|
vert_count--;
|
||||||
|
add_texture(vertex,TRUE);
|
||||||
|
norm_array(vertex,1,norm_difference,nvertices,num_vert);
|
||||||
|
}
|
||||||
|
else /* The texture */
|
||||||
|
add_texture(vertex,FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if ( texture )
|
||||||
|
{
|
||||||
|
/* the vertex */
|
||||||
|
if (!(loop%2))
|
||||||
|
{
|
||||||
|
temp[vert_count] = vertex ;
|
||||||
|
vert_count++;
|
||||||
|
if (vert_count == 4)
|
||||||
|
quads = TRUE;
|
||||||
|
add_texture(vertex,TRUE);
|
||||||
|
if (!(add_vert_id(vertex,vert_count)))
|
||||||
|
vert_count--;
|
||||||
|
norm_array(vertex,1,norm_difference,nvertices,num_vert);
|
||||||
|
}
|
||||||
|
else /* texture */
|
||||||
|
add_texture(vertex,FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*** no nvertices ***/
|
||||||
|
temp[vert_count] = vertex ;
|
||||||
|
vert_count++;
|
||||||
|
if (vert_count == 4)
|
||||||
|
quads = TRUE;
|
||||||
|
if (!(add_vert_id(vertex,vert_count)))
|
||||||
|
vert_count--;
|
||||||
|
}
|
||||||
|
while (*ptr2>='0' && *ptr2<='9')
|
||||||
|
ptr2++;
|
||||||
|
}
|
||||||
|
/* Done with the polygon */
|
||||||
|
num_edges += vert_count;
|
||||||
|
/* add it to face structure */
|
||||||
|
if (vert_count >= 3)
|
||||||
|
AddNewFace(ids,vert_count,face_id,norms);
|
||||||
|
else
|
||||||
|
face_id--;
|
||||||
|
if (vert_count == 4)
|
||||||
|
quads = TRUE;
|
||||||
|
}
|
||||||
|
else if ((g == TRUE) && (face_id > 0)
|
||||||
|
&& ((*ptr == 'g') || (*ptr == 's') || (*ptr == 'm') || (*ptr == 'o')))
|
||||||
|
{
|
||||||
|
/* The user specified that the strips will be contained in each group
|
||||||
|
from the data file, so we just finished a group and will find the
|
||||||
|
triangle strips in it.
|
||||||
|
*/
|
||||||
|
Start_Edge_Struct(num_vert);
|
||||||
|
Find_Adjacencies(face_id);
|
||||||
|
if (quads)
|
||||||
|
{
|
||||||
|
Init_Table_SGI();
|
||||||
|
Build_SGI_Table(num_vert,face_id);
|
||||||
|
/* Code for lengths of walks in each direction */
|
||||||
|
Save_Walks(face_id,TRUE);
|
||||||
|
|
||||||
|
/* Code for finding the bands */
|
||||||
|
Find_Bands(face_id,bands,&swaps,&strips,&cost,&triangles,num_nvert,vert_norms,num_texture,vert_texture);
|
||||||
|
|
||||||
|
/* Remove the faces that we did so that we can
|
||||||
|
run the strip code on the rest of the faces that are left
|
||||||
|
*/
|
||||||
|
if (cost != 0)
|
||||||
|
{
|
||||||
|
printf("Total %d triangles with %d cost\n",triangles,cost);
|
||||||
|
Save_Rest(&face_id);
|
||||||
|
printf("We saved %d .... now doing the local algorithm\n",face_id);
|
||||||
|
fprintf(bands,"\n#local\n");
|
||||||
|
End_Edge_Struct(num_vert);
|
||||||
|
Start_Edge_Struct(num_vert);
|
||||||
|
Find_Adjacencies(face_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SGI_Strip(num_vert,face_id,bands,t,tr);
|
||||||
|
|
||||||
|
/* Get the total cost */
|
||||||
|
Output_TriEx(-1,-2,-3,NULL,-1,-20,cost);
|
||||||
|
|
||||||
|
End_Face_Struct(num_faces);
|
||||||
|
End_Edge_Struct(num_vert);
|
||||||
|
cost = 0;
|
||||||
|
face_id = 0;
|
||||||
|
quads = FALSE;
|
||||||
|
Start_Face_Struct(num_faces-face_id);
|
||||||
|
num_faces = num_faces - face_id;
|
||||||
|
Free_Strips();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Done reading in all the information into data structures */
|
||||||
|
num_faces = face_id;
|
||||||
|
fclose (file);
|
||||||
|
/*printf(" Done.\n\n");*/
|
||||||
|
free(vertices);
|
||||||
|
free(nvertices);
|
||||||
|
|
||||||
|
/*printf ("Vertices: %d\nNormals: %d\nFaces: %d\n",num_vert,num_nvert,num_faces);*/
|
||||||
|
Start_Edge_Struct(num_vert);
|
||||||
|
Find_Adjacencies(num_faces);
|
||||||
|
|
||||||
|
/* Initialize it */
|
||||||
|
Init_Table_SGI();
|
||||||
|
/* Build it */
|
||||||
|
Build_SGI_Table(num_vert,num_faces);
|
||||||
|
|
||||||
|
InitStripTable();
|
||||||
|
|
||||||
|
|
||||||
|
if (quads)
|
||||||
|
{
|
||||||
|
/* Code for lengths of walks in each direction */
|
||||||
|
Save_Walks(num_faces,TRUE);
|
||||||
|
|
||||||
|
/* Code for finding the bands */
|
||||||
|
Find_Bands(num_faces,bands,&swaps,&strips,&cost,&triangles,num_nvert,vert_norms,num_texture,vert_texture);
|
||||||
|
/*printf("Total %d triangles with %d cost\n",triangles,cost);*/
|
||||||
|
|
||||||
|
/* Remove the faces that we did so that we can
|
||||||
|
run the strip code on the rest of the faces that are left
|
||||||
|
*/
|
||||||
|
Save_Rest(&num_faces);
|
||||||
|
/*printf("We saved %d .... now doing the local algorithm\n",num_faces);*/
|
||||||
|
fprintf(bands,"\n#local\n");
|
||||||
|
End_Edge_Struct(num_vert);
|
||||||
|
Start_Edge_Struct(num_vert);
|
||||||
|
Find_Adjacencies(num_faces);
|
||||||
|
}
|
||||||
|
|
||||||
|
SGI_Strip(num_vert,num_faces,bands,t,tr);
|
||||||
|
|
||||||
|
/* Get the total cost */
|
||||||
|
Output_TriEx(-1,-2,-3,NULL,-1,-20,cost);
|
||||||
|
|
||||||
|
End_Face_Struct(num_faces);
|
||||||
|
End_Edge_Struct(num_vert);
|
||||||
|
fclose(bands);
|
||||||
|
STOP
|
||||||
|
|
||||||
|
get_time();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
811
Stripe_u/common.c
Normal file
811
Stripe_u/common.c
Normal 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
41
Stripe_u/common.h
Normal 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
13
Stripe_u/define.h
Normal 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
17
Stripe_u/extend.h
Normal 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
110
Stripe_u/free.c
Normal 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
22
Stripe_u/free.h
Normal 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
37
Stripe_u/global.h
Normal 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
151
Stripe_u/glove.h
Normal 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
217
Stripe_u/init.c
Normal 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
30
Stripe_u/init.h
Normal 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
123
Stripe_u/local.c
Normal 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
19
Stripe_u/local.h
Normal 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
3
Stripe_u/my_global.h
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
int change_in_stripEx = 0;
|
||||||
|
int change_in_strip = 0;
|
||||||
|
|
1667
Stripe_u/newpolve.c
Normal file
1667
Stripe_u/newpolve.c
Normal file
File diff suppressed because it is too large
Load diff
181
Stripe_u/options.c
Normal file
181
Stripe_u/options.c
Normal 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
17
Stripe_u/options.h
Normal 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
582
Stripe_u/output.c
Normal 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
26
Stripe_u/output.h
Normal 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
518
Stripe_u/outputex.c
Normal 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
23
Stripe_u/outputex.h
Normal 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
665
Stripe_u/partial.c
Normal 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
15
Stripe_u/partial.h
Normal 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
87
Stripe_u/polverts.h
Normal 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
34
Stripe_u/polvertsex.h
Normal 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
226
Stripe_u/queue.c
Normal 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
283
Stripe_u/queue.h
Normal 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
631
Stripe_u/sgi_triang.c
Normal 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
584
Stripe_u/sgi_triangex.c
Normal 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
549
Stripe_u/struct.c
Normal 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
6
Stripe_u/struct.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
struct vert_struct {
|
||||||
|
VRDATA x, y, z; /* point coordinates */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
553
Stripe_u/structex.c
Normal file
553
Stripe_u/structex.c
Normal 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
31
Stripe_u/sturcts.h
Normal 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
28
Stripe_u/sturctsex.h
Normal 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
304
Stripe_u/ties.c
Normal 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
15
Stripe_u/ties.h
Normal 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
23
Stripe_u/triangulate.h
Normal 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
23
Stripe_u/triangulatex.h
Normal 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
272
Stripe_u/util.c
Normal 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
24
Stripe_u/util.h
Normal 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();
|
Loading…
Reference in a new issue