1
0
Fork 0

Initial revision.

This commit is contained in:
curt 1998-07-31 18:27:36 +00:00
parent 801ba133bd
commit 533f072899
39 changed files with 9839 additions and 0 deletions

26
Stripe_w/Makefile.am Normal file
View file

@ -0,0 +1,26 @@
bin_PROGRAMS = strips
strips_SOURCES = \
add.c add.h \
bands.c \
common.c common.h \
extend.h \
free.c free.h \
global.h \
init.c init.h \
local.c local.h \
newpolve.c \
options.c options.h \
output.c output.h \
outputex.c outputex.h \
partial.c partial.h \
polverts.h polyvertsex.h \
queue.c queue.h \
sgi_triang.c sgi_triangex.c \
struct.c \
structex.c \
sturcts.h sturctsex.h \
ties.c ties.h \
triangulate.h triangulatex.h \
util.c util.h

384
Stripe_w/add.c Normal file
View file

@ -0,0 +1,384 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: add.c
This file contains the procedure code that will add information
to our data structures.
*/
/*---------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "global.h"
#include "queue.h"
#include "polverts.h"
#include "triangulate.h"
#include "ties.h"
#include "outputex.h"
#include "options.h"
#include "local.h"
BOOL new_vertex(double difference, int id1,int id2,
struct vert_struct *n)
{
/* Is the difference between id1 and id2 (2 normal vertices that
mapped to the same vertex) greater than the
threshold that was specified?
*/
struct vert_struct *pn1,*pn2;
double dot_product;
double distance1, distance2,distance;
double rad;
char arg1[100];
char arg2[100];
pn1 = n + id1;
pn2 = n + id2;
dot_product = ((pn1->x) * (pn2->x)) +
((pn1->y) * (pn2->y)) +
((pn1->z) * (pn2->z));
/* Get the absolute value */
if (dot_product < 0)
dot_product = dot_product * -1;
distance1 = sqrt( (pn1->x * pn1->x) +
(pn1->y * pn1->y) +
(pn1->z * pn1->z) );
distance2 = sqrt( (pn2->x * pn2->x) +
(pn2->y * pn2->y) +
(pn2->z * pn2->z) );
distance = distance1 * distance2;
rad = acos((double)dot_product/(double)distance);
/* convert to degrees */
rad = (180 * rad)/PI;
if ( rad <= difference)
return FALSE;
/* double checking because of imprecision with floating
point acos function
*/
sprintf( arg1,"%.5f", rad );
sprintf( arg2,"%.5f", difference );
if ( strcmp( arg1, arg2 ) <=0 )
return( FALSE );
if ( rad <= difference)
return FALSE;
else
return TRUE;
}
BOOL Check_VN(int vertex,int normal, struct vert_added *added)
{
/* Check to see if we already added this vertex and normal */
register int x,n;
n = (added+vertex)->num;
for (x = 0; x < n; x++)
{
if (*((added+vertex)->normal+x) == normal)
return TRUE;
}
return FALSE;
}
BOOL norm_array(int id, int vertex, double normal_difference,
struct vert_struct *n, int num_vert)
{
static int last;
static struct vert_added *added;
register int x;
static BOOL first = TRUE;
if (first)
{
/* This is the first time that we are in here, so we will allocate
a structure that will save the vertices that we added, so that we
do not add the same thing twice
*/
first = FALSE;
added = (struct vert_added *) malloc (sizeof (struct vert_added ) * num_vert);
/* The number of vertices added for each vertex must be initialized to
zero
*/
for (x = 0; x < num_vert; x++)
(added+x)->num = 0;
}
if (vertex)
/* Set the pointer to the vertex, we will be calling again with the
normal to fill it with
*/
last = id;
else
{
/* Fill the pointer with the id of the normal */
if (*(vert_norms + last) == 0)
*(vert_norms + last) = id;
else if ((*(vert_norms + last) != id) && ((int)normal_difference != 360))
{
/* difference is big enough, we need to create a new vertex */
if (new_vertex(normal_difference,id,*(vert_norms + last),n))
{
/* First check to see if we added this vertex and normal already */
if (Check_VN(last,id,added))
return FALSE;
/* OK, create the new vertex, and have its id = the number of vertices
and its normal what we have here
*/
vert_norms = realloc(vert_norms, sizeof(int) * (num_vert + 1));
if (!vert_norms)
{
printf("Allocation error - aborting\n");
exit(1);
}
*(vert_norms + num_vert) = id;
/* We created a new vertex, now put it in our added structure so
we do not add the same thing twice
*/
(added+last)->num = (added+last)->num + 1;
if ((added+last)->num == 1)
{
/* First time */
(added+last)->normal = (int *) malloc (sizeof (int ) * 1);
*((added+last)->normal) = id;
}
else
{
/* Not the first time, reallocate space */
(added+last)->normal = realloc((added+last)->normal,sizeof(int) * (added+last)->num);
*((added+last)->normal+((added+last)->num-1)) = id;
}
return TRUE;
}
}
}
return FALSE;
}
void add_texture(int id,BOOL vertex)
{
/* Save the texture with its vertex for future use when outputting */
static int last;
if (vertex)
last = id;
else
*(vert_texture+last) = id;
}
int add_vert_id(int id, int index_count)
{
register int x;
/* Test if degenerate, if so do not add degenerate vertex */
for (x = 1; x < index_count ; x++)
{
if (ids[x] == id)
return 0;
}
ids[index_count] = id;
return 1;
}
void add_norm_id(int id, int index_count)
{
norms[index_count] = id;
}
void AddNewFace(int ids[STRIP_MAX], int vert_count, int face_id,
int norms[STRIP_MAX])
{
PF_FACES pfNode;
int *pTempInt;
int *pnorms;
F_EDGES **pTempVertptr;
int *pTempmarked, *pTempwalked;
register int y,count = 0;
/* Add a new face into our face data structure */
pfNode = (PF_FACES) malloc(sizeof(F_FACES) );
if ( pfNode )
{
pfNode->pPolygon = (int*) malloc(sizeof(int) * (vert_count) );
pfNode->pNorms = (int*) malloc(sizeof(int) * (vert_count) );
pfNode->VertandId = (F_EDGES**)malloc(sizeof(F_EDGES*) * (vert_count));
pfNode->marked = (int*)malloc(sizeof(int) * (vert_count));
pfNode->walked = (int*)malloc(sizeof(int) * (vert_count));
}
pTempInt =pfNode->pPolygon;
pnorms = pfNode->pNorms;
pTempmarked = pfNode->marked;
pTempwalked = pfNode->walked;
pTempVertptr = pfNode->VertandId;
pfNode->nPolSize = vert_count;
pfNode->seen = -1;
pfNode->seen2 = -1;
for (y=1;y<=vert_count;y++)
{
*(pTempInt + count) = ids[y];
*(pnorms + count) = norms[y];
*(pTempmarked + count) = FALSE;
*(pTempwalked + count) = -1;
*(pTempVertptr+count) = NULL;
count++;
}
AddHead(PolFaces[face_id-1],(PLISTINFO) pfNode);
}
void CopyFace(int ids[STRIP_MAX], int vert_count, int face_id,
int norms[STRIP_MAX])
{
PF_FACES pfNode;
int *pTempInt;
int *pnorms;
F_EDGES **pTempVertptr;
int *pTempmarked, *pTempwalked;
register int y,count = 0;
/* Copy a face node into a new node, used after the global algorithm
is run, so that we can save whatever is left into a new structure
*/
pfNode = (PF_FACES) malloc(sizeof(F_FACES) );
if ( pfNode )
{
pfNode->pPolygon = (int*) malloc(sizeof(int) * (vert_count) );
pfNode->pNorms = (int*) malloc(sizeof(int) * (vert_count) );
pfNode->VertandId = (F_EDGES**)malloc(sizeof(F_EDGES*) * (vert_count));
pfNode->marked = (int*)malloc(sizeof(int) * (vert_count));
pfNode->walked = (int*)malloc(sizeof(int) * (vert_count));
}
pTempInt =pfNode->pPolygon;
pnorms = pfNode->pNorms;
pTempmarked = pfNode->marked;
pTempwalked = pfNode->walked;
pTempVertptr = pfNode->VertandId;
pfNode->nPolSize = vert_count;
pfNode->seen = -1;
pfNode->seen2 = -1;
for (y=0;y<vert_count;y++)
{
*(pTempInt + count) = ids[y];
*(pnorms + count) = norms[y];
*(pTempmarked + count) = FALSE;
*(pTempwalked + count) = -1;
*(pTempVertptr+count) = NULL;
count++;
}
AddHead(PolFaces[face_id-1],(PLISTINFO) pfNode);
}
void Add_Edge(int v1,int v2)
{
PF_EDGES temp = NULL;
ListHead *pListHead;
BOOL flag = TRUE;
register int t,count = 0;
/* Add a new edge into the edge data structure */
if (v1 > v2)
{
t = v1;
v1 = v2;
v2 = t;
}
pListHead = PolEdges[v1];
temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
if (temp == NULL)
{
printf("Have the wrong edge \n:");
exit(1);
}
while (flag)
{
if (v2 == temp->edge[0])
return;
else
temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,++count);
}
}
void Add_AdjEdge(int v1,int v2,int fnum,int index1 )
{
PF_EDGES temp = NULL;
PF_FACES temp2 = NULL;
PF_EDGES pfNode;
ListHead *pListHead;
ListHead *pListFace;
BOOL flag = TRUE;
register int count = 0;
register int t,v3 = -1;
if (v1 > v2)
{
t = v1;
v1 = v2;
v2 = t;
}
pListFace = PolFaces[fnum];
temp2 = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
pListHead = PolEdges[v1];
temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
if (temp == NULL)
flag = FALSE;
count++;
while (flag)
{
if (v2 == temp->edge[0])
{
/* If greater than 2 polygons adjacent to an edge, then we will
only save the first 2 that we found. We will have a small performance
hit, but this does not happen often.
*/
if (temp->edge[2] == -1)
temp->edge[2] = fnum;
else
v3 = temp->edge[2];
flag = FALSE;
}
else
{
temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
count++;
if (temp == NULL)
flag = FALSE;
}
}
/* Did not find it */
if (temp == NULL)
{
pfNode = (PF_EDGES) malloc(sizeof(F_EDGES) );
if ( pfNode )
{
pfNode->edge[0] = v2;
pfNode->edge[1] = fnum;
pfNode->edge[2] = v3;
AddTail( PolEdges[v1], (PLISTINFO) pfNode );
}
else
{
printf("Out of memory!\n");
exit(1);
}
*(temp2->VertandId+index1) = pfNode;
}
else
*(temp2->VertandId+index1) = temp;
}

31
Stripe_w/add.h Normal file
View file

@ -0,0 +1,31 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: add.h
-----------------------------------------------------------------------*/
#include "global.h"
BOOL new_vertex(double difference, int id1,int id2,
struct vert_struct *n);
BOOL Check_VN(int vertex,int normal, struct vert_added *added);
BOOL norm_array(int id, int vertex, double normal_difference,
struct vert_struct *n, int num_vert);
void add_texture(int id,BOOL vertex);
int add_vert_id(int id, int index_count);
void add_norm_id(int id, int index_count);
void AddNewFace(int ids[STRIP_MAX], int vert_count, int face_id,
int norms[STRIP_MAX]);
void CopyFace(int ids[STRIP_MAX], int vert_count, int face_id,
int norms[STRIP_MAX]);
void Add_Edge(int v1,int v2);
void Add_AdjEdge(int v1,int v2,int fnum,int index1 );

560
Stripe_w/bands.c Normal file
View file

@ -0,0 +1,560 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: bands.c
This file contains the main procedure code that will read in the
object and then call the routines that produce the triangle strips.
*/
/*---------------------------------------------------------------------*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "global.h"
#include "polverts.h"
#include "triangulate.h"
#include "ties.h"
#include "outputex.h"
#include "options.h"
#include "local.h"
#include "init.h"
#include "free.h"
#include "add.h"
/* TIMING for Windows */
#ifdef WIN32
#include <sys/timeb.h>
#include <time.h>
/* TIMING for UNIX */
#else
#include <sys/types.h>
#include <sys/param.h>
#include <sys/times.h>
extern long times( );
long elapsed()
{
static long total = 0;
long cpu_time, dummy;
struct tms buffer;
times(&buffer);
dummy = buffer.tms_utime + buffer.tms_stime +
buffer.tms_cutime + buffer.tms_cstime;
cpu_time = ((dummy - total) * 1000) / HZ;
total = dummy;
return(cpu_time);
}
#endif
int norms[STRIP_MAX];
int *vert_norms;
int *vert_texture;
void get_time()
{
/* For timing */
#ifdef WIN32
struct timeb timebuffer;
char *timeline;
#else
long timer;
#endif
#ifdef WIN32
ftime( &timebuffer );
timeline = ctime( & ( timebuffer.time ) );
printf( "The time is %.19s.%hu %s", timeline, timebuffer.millitm, &timeline[20] );
#else
timer = elapsed();
printf("The time is %ld\n",timer);
#endif
}
/*
**
Here the main program begins. It will start by loading in a .obj file
then it will convert the polygonal model into triangle strips.
**
*/
int main (int argc,char *argv[])
{
char *fname,*all,buff[255], *ptr, *ptr2;
FILE *file, *bands;
int face_id=0;
int vert_count=0;
int loop=0;
int num=0;
int num2=0;
float center[3];
int temp[STRIP_MAX],vertex,strips, swaps,tempi,cost,triangles;
int f,t,tr,g;
char *file_open;
int num_vert = 0,
num_faces = 0,
num_nvert = 0,
num_edges = 0,
num_texture = 0,
num_tris = 0;
double fra = 0.0;
BOOL texture, normal, normal_and_texture,quads = FALSE;
/* Options variables */
double norm_difference;
/* Structures for the object */
struct vert_struct *vertices = NULL,
*nvertices = NULL,
*pvertices = NULL,
*pnvertices = NULL;
get_time();
/* File that will contain the triangle strip data */
bands = fopen("stripe.objf","w");
/*
Scan the file once to find out the number of vertices,
vertice normals, and faces so we can set up some memory
structures
*/
/* Interpret the options specified */
norm_difference = get_options(argc,argv,&f,&t,&tr,&g);
if (f == BINARY)
file_open = "rb";
else
file_open = "r";
fname = argv[argc-1];
printf ("File: %s\n",fname);
printf ("Scanning...%s ",file_open);
/* File can be in binary for faster reading */
if (file = fopen (fname,file_open))
{
while (!feof (file))
{
/* Read a line */
if (f == BINARY)
fread (buff,sizeof(char) * 255,1, file);
else
fgets (buff, sizeof(char) * 255, file);
num++;
printf("%d\r",num);
/* At a vertex */
if (*buff == 'v')
{
/* At a normal */
if (*(buff+1)=='n')
num_nvert++;
else if (*(buff+1)=='t')
num_texture++;
/* At a regular vertex */
else
num_vert++;
}
/* At a face */
else if (*buff == 'f')
{
num_faces++;
strtok(buff, " ");
tempi = 0;
while (strtok(NULL, " ") != NULL) tempi++;
num_tris += tempi - 2;
}
}
fclose (file);
}
else
{
printf("Error in the file name\n");
exit(1);
}
printf("%s pass 1\n",fname);
/* Allocate structures for the information */
Start_Face_Struct(num_faces);
vertices = (struct vert_struct *)
malloc (sizeof (struct vert_struct) * num_vert);
if (num_nvert > 0) {
nvertices = (struct vert_struct *)
malloc (sizeof (struct vert_struct) * num_nvert);
vert_norms = (int *) malloc (sizeof (int) * num_vert);
/*
Initialize entries to zero, in case there are 2 hits
to the same vertex we will know it - used for determining
the normal difference
*/
init_vert_norms(num_vert);
} else {
nvertices = NULL;
}
if (num_texture > 0) {
vert_texture = (int *) malloc (sizeof(int) * num_vert);
init_vert_texture(num_vert);
}
/*
Set up the temporary 'p' pointers
*/
pvertices = vertices;
pnvertices = nvertices;
/* Load the object into memory */
/*printf (" Loading...");*/
fprintf(bands,"#%s: a triangle strip representation created by STRIPE.\n#This is a .objf file\n#by Francine Evans\n",fname);
/* File will be put in a list for faster execution if file is in binary */
if (file = fopen(fname,file_open)) {
if (f == BINARY) {
all = (char *) malloc (sizeof(char) * 255 * num);
fread(all,sizeof(char) * 255 * num, 1, file);
ptr = all;
} else {
ptr = (char *) malloc (sizeof(char) * 255 * num);
}
}
while (num > 0) {
num--;
printf("%d\r",num);
if (f == ASCII) {
fgets (ptr, sizeof(char) * 255, file);
} else {
ptr = ptr + 255;
}
/* Load in vertices/normals */
if (*ptr == 'v') {
if (*(ptr+1)=='n') {
sscanf (ptr+3,"%lf%lf%lf",
&(pnvertices->x),
&(pnvertices->y),
&(pnvertices->z));
fprintf(bands,"vn %f %f %f\n",
pnvertices->x,pnvertices->y,pnvertices->z);
++pnvertices;
} else if (*(ptr+1)=='t') {
sscanf (ptr+3,"%f%f%f",&center[0],&center[1],&center[2]);
fprintf(bands,"vt %f %f %f\n",center[0],center[1],center[2]);
} else {
sscanf (ptr+2,"%lf%lf%lf",
&(pvertices->x),
&(pvertices->y),
&(pvertices->z));
fprintf(bands,"v %f %f %f\n",
pvertices->x,pvertices->y,pvertices->z);
++pvertices;
}
} else if (*ptr == 'f') {
/* Read in faces */
num2 = 0;
face_id++;
ptr2 = ptr+1;
normal = FALSE; texture = FALSE, normal_and_texture = FALSE;
while (*ptr2) {
if (*ptr2 >='0' && *ptr2 <='9') {
num2++;
++ptr2;
while (*ptr2 && (*ptr2!=' ' && *ptr2!='/')) {
ptr2++;
}
/* There are normals in this line */
if (*ptr2 == '/') {
if (*(ptr2+1) == '/') {
normal = TRUE;
} else {
texture = TRUE;
}
} else if (*ptr2 == ' ') {
if ((num2 == 3) && (texture)) {
normal_and_texture = TRUE;
}
}
} else {
++ptr2;
}
}
ptr2 = ptr+1;
/*
loop on the number of numbers in this line of face data
*/
vert_count = 0;
for (loop=0;loop<num2;loop++) {
/* skip the whitespace */
while (*ptr2<'0' || *ptr2>'9') {
if (*ptr2 == '-') {
break;
}
ptr2++;
}
vertex = atoi(ptr2)-1;
if (vertex < 0) {
vertex = num_vert + vertex;
*ptr2 = ' ';
ptr2++;
}
/*
If there are either normals or textures with the vertices
in this file, the data alternates so we must read it this way
*/
if ( (normal) && (!normal_and_texture)) {
if (loop%2) {
add_norm_id(vertex,vert_count);
/*
Test here to see if we added a new vertex, since the
vertex has more than one normal and the 2 normals are greater
than the threshold specified
*/
if (norm_array(vertex,0,norm_difference,nvertices,num_vert)) {
/*
Add a new vertex and change the
id of the vertex that we just read to the id of the new
vertex that we just added
*/
/*
Put it in the output file, note the added vertices will
be after the normals and separated from the rest of the
vertices. Will not affect our viewer
*/
fprintf(bands,"v %f %f %f\n",
(vertices + temp[vert_count - 1])->x,
(vertices + temp[vert_count - 1])->y,
(vertices + temp[vert_count - 1])->z);
num_vert++;
temp[vert_count - 1] = num_vert - 1;
if (!(add_vert_id(num_vert - 1,vert_count))) {
vert_count--;
}
}
} else {
/* the vertex */
temp[vert_count] = vertex ;
vert_count++;
if (!(add_vert_id(vertex,vert_count))) {
vert_count--;
}
norm_array(vertex,1,norm_difference,nvertices,num_vert);
}
} else if (normal_and_texture) {
/* Else there are vertices and textures with the data */
if( !((loop+1)%3)) {
add_norm_id(vertex,vert_count);
/*
Test here to see if we added a new vertex, since the
vertex has more than one normal and the 2 normals are greater
than the threshold specified
*/
if (norm_array(vertex,0,norm_difference,nvertices,num_vert)) {
/*
Add a new vertex and change the
id of the vertex that we just read to the id of the new
vertex that we just added
*/
/*
Put it in the output file, note the added vertices will
be after the normals and separated from the rest of the
vertices. Will not affect our viewer
*/
fprintf(bands,"v %f %f %f\n",
(vertices + temp[vert_count - 1])->x,
(vertices + temp[vert_count - 1])->y,
(vertices + temp[vert_count - 1])->z);
num_vert++;
temp[vert_count - 1] = num_vert - 1;
if (!(add_vert_id(num_vert - 1,vert_count))) {
vert_count--;
}
}
} else if ((loop == 0) || (*(ptr2-1) == ' ')) {
/* the vertex */
temp[vert_count] = vertex ;
vert_count++;
if (vert_count == 4) {
quads = TRUE;
}
if (!(add_vert_id(vertex,vert_count))) {
vert_count--;
}
add_texture(vertex,TRUE);
norm_array(vertex,1,norm_difference,nvertices,num_vert);
} else {
/* The texture */
add_texture(vertex,FALSE);
}
} else if ( texture ) {
/* the vertex */
if (!(loop%2)) {
temp[vert_count] = vertex ;
vert_count++;
if (vert_count == 4)
quads = TRUE;
add_texture(vertex,TRUE);
if (!(add_vert_id(vertex,vert_count)))
vert_count--;
norm_array(vertex,1,norm_difference,nvertices,num_vert);
} else {
/* texture */
add_texture(vertex,FALSE);
}
} else {
/*** no nvertices ***/
temp[vert_count] = vertex ;
vert_count++;
if (vert_count == 4)
quads = TRUE;
if (!(add_vert_id(vertex,vert_count)))
vert_count--;
}
while (*ptr2>='0' && *ptr2<='9')
ptr2++;
}
/* Done with the polygon */
num_edges += vert_count;
/* add it to face structure */
if (vert_count >= 3)
AddNewFace(ids,vert_count,face_id,norms);
else
face_id--;
if (vert_count == 4)
quads = TRUE;
}
else if ((g == TRUE) && (face_id > 0)
&& ((*ptr == 'g') || (*ptr == 's') || (*ptr == 'm') || (*ptr == 'o')))
{
/*
The user specified that the strips will be contained in each group
from the data file, so we just finished a group and will find the
triangle strips in it.
*/
Start_Edge_Struct(num_vert);
Find_Adjacencies(face_id);
if (quads)
{
Init_Table_SGI();
Build_SGI_Table(num_vert,face_id);
/* Code for lengths of walks in each direction */
/* Save_Walks(face_id,TRUE); */
Save_Walks(face_id);
/* Code for finding the bands */
Find_Bands(face_id,bands,&swaps,&strips,&cost,&triangles,num_nvert,vert_norms,num_texture,vert_texture);
/*
Remove the faces that we did so that we can
run the strip code on the rest of the faces that are left
*/
if (cost != 0)
{
printf("Total %d triangles with %d cost\n",triangles,cost);
Save_Rest(&face_id);
printf("We saved %d .... now doing the local algorithm\n",face_id);
fprintf(bands,"\n#local\n");
End_Edge_Struct(num_vert);
Start_Edge_Struct(num_vert);
Find_Adjacencies(face_id);
}
}
SGI_Strip(num_vert,face_id,bands,t,tr);
/* Get the total cost */
Output_TriEx(-1,-2,-3,NULL,-1,-20,cost);
End_Face_Struct(num_faces);
End_Edge_Struct(num_vert);
cost = 0;
face_id = 0;
quads = FALSE;
Start_Face_Struct(num_faces-face_id);
num_faces = num_faces - face_id;
Free_Strips();
}
}
/* Done reading in all the information into data structures */
num_faces = face_id;
fclose (file);
printf("Input Done.\n\n");
free(vertices);
free(nvertices);
printf ("Vertices: %d\nNormals: %d\nFaces: %d\n",num_vert,num_nvert,num_faces);
Start_Edge_Struct(num_vert);
Find_Adjacencies(num_faces);
/* Initialize it */
Init_Table_SGI();
/* Build it */
Build_SGI_Table(num_vert,num_faces);
InitStripTable();
if (quads) {
/* Code for lengths of walks in each direction */
/* Save_Walks(num_faces,TRUE); */
Save_Walks(num_faces);
/* Code for finding the bands */
Find_Bands(num_faces,bands,&swaps,&strips,&cost,&triangles,num_nvert,vert_norms,num_texture,vert_texture);
/*printf("Total %d triangles with %d cost\n",triangles,cost);*/
/*
Remove the faces that we did so that we can
run the strip code on the rest of the faces that are left
*/
Save_Rest(&num_faces);
/*printf("We saved %d .... now doing the local algorithm\n",num_faces);*/
fprintf(bands,"\n#local\n");
End_Edge_Struct(num_vert);
Start_Edge_Struct(num_vert);
Find_Adjacencies(num_faces);
}
SGI_Strip(num_vert,num_faces,bands,t,tr);
/* Get the total cost */
Output_TriEx(-1,-2,-3,NULL,-1,-20,cost);
End_Face_Struct(num_faces);
End_Edge_Struct(num_vert);
fclose(bands);
get_time();
return(0);
}

810
Stripe_w/common.c Normal file
View file

@ -0,0 +1,810 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: common.c
This file contains common code used in both the local and global algorithm
*/
/*---------------------------------------------------------------------*/
#include <stdlib.h>
#include "polverts.h"
#include "extend.h"
#include "output.h"
#include "triangulate.h"
#include "util.h"
#include "add.h"
int Old_Adj(int face_id)
{
/* Find the bucket that the face_id is currently in,
because maybe we will be deleting it.
*/
PF_FACES temp = NULL;
ListHead *pListHead;
int size,y;
pListHead = PolFaces[face_id];
temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
if ( temp == NULL )
{
printf("The face was already deleted, there is an error\n");
exit(0);
}
size = temp->nPolSize;
if (Done(face_id,size,&y) == NULL)
{
printf("There is an error in finding the face\n");
exit(0);
}
return y;
}
int Number_Adj(int id1, int id2, int curr_id)
{
/* Given edge whose endpoints are specified by id1 and id2,
determine how many polygons share this edge and return that
number minus one (since we do not want to include the polygon
that the caller has already).
*/
int size,y,count=0;
PF_EDGES temp = NULL;
PF_FACES temp2 = NULL;
ListHead *pListHead;
BOOL there= FALSE;
/* Always want smaller id first */
switch_lower(&id1,&id2);
pListHead = PolEdges[id1];
temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
if (temp == NULL)
/* new edge that was created might not be here */
return 0;
while (temp->edge[0] != id2)
{
count++;
temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
if (temp == NULL)
/* This edge was not there in the original, which
mean that we created it in the partial triangulation.
So it is adjacent to nothing.
*/
return 0;
}
/* Was not adjacent to anything else except itself */
if (temp->edge[2] == -1)
return 0;
else
{
/* It was adjacent to another polygon, but maybe we did this
polygon already, and it was done partially so that this edge
could have been done
*/
if (curr_id != temp->edge[1])
{
/* Did we use this polygon already?and it was deleted
completely from the structure
*/
pListHead = PolFaces[temp->edge[1]];
temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
if (Done(temp->edge[1],temp2->nPolSize,&size) == NULL)
return 0;
}
else
{
pListHead = PolFaces[temp->edge[2]];
temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
if (Done(temp->edge[2],temp2->nPolSize,&size)== NULL)
return 0;
}
/* Now we have to check whether it was partially done, before
we can say definitely if it is adjacent.
Check each edge of the face and tally the number of adjacent
polygons to this face.
*/
if ( temp2 != NULL )
{
/* Size of the polygon */
size = temp2->nPolSize;
for (y = 0; y< size; y++)
{
/* If we are doing partial triangulation, we must check
to see whether the edge is still there in the polygon,
since we might have done a portion of the polygon
and saved the rest for later.
*/
if (y != (size-1))
{
if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1)))
|| ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1))))
/* edge is still there we are ok */
there = TRUE;
}
else
{
if( ((id1 == *(temp2->pPolygon)) && (id2 == *(temp2->pPolygon+size-1)))
|| ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1))))
/* edge is still there we are ok */
there = TRUE;
}
}
}
if (there )
return 1;
return 0;
}
}
int Min_Adj(int id)
{
/* Used for the lookahead to break ties. It will
return the minimum adjacency found at this face.
*/
int y,numverts,t,x=60;
PF_FACES temp=NULL;
ListHead *pListHead;
/* If polygon was used then we can't use this face */
if (Done(id,59,&y) == NULL)
return 60;
/* It was not used already */
pListHead = PolFaces[id];
temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
if ( temp != NULL )
{
numverts = temp->nPolSize;
for (y = 0; y< numverts; y++)
{
if (y != (numverts-1))
t = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),id);
else
t = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+(numverts-1)),id);
if (t < x)
x = t;
}
}
if (x == -1)
{
printf("Error in the look\n");
exit(0);
}
return x;
}
void Edge_Least(int *index,int *new1,int *new2,int face_id,int size)
{
/* We had a polygon without an input edge and now we re going to pick one
of the edges with the least number of adjacencies to be the input
edge
*/
register int x,value,smallest=60;
for (x = 0; x<size; x++)
{
if (x != (size -1) )
value = Number_Adj(*(index+x),*(index+x+1),face_id);
else
value = Number_Adj(*(index),*(index+size-1),face_id);
if (value < smallest)
{
smallest = value;
if (x != (size -1))
{
*new1 = *(index+x);
*new2 = *(index+x+1);
}
else
{
*new1 = *(index);
*new2 = *(index+size-1);
}
}
}
if ((smallest == 60) || (smallest < 0))
{
printf("There is an error in getting the least edge\n");
exit(0);
}
}
void Check_In_Polygon(int face_id, int *min, int size)
{
/* Check to see the adjacencies by going into a polygon that has
greater than 4 sides.
*/
ListHead *pListHead;
PF_FACES temp;
int y,id1,id2,id3,x=0,z=0;
int saved[2];
int big_saved[60];
pListHead = PolFaces[face_id];
temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
/* Get the input edge that we came in on */
Last_Edge(&id1,&id2,&id3,0);
/* Find the number of adjacencies to the edges that are adjacent
to the input edge.
*/
for (y=0; y< size; y++)
{
if (y != (size-1))
{
if (((*(temp->pPolygon+y) == id2) && (*(temp->pPolygon+y+1) != id3))
|| ((*(temp->pPolygon+y) == id3) && (*(temp->pPolygon+y+1) != id2)))
{
saved[x++] = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),face_id);
big_saved[z++] = saved[x-1];
}
else
big_saved[z++] = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),face_id);
}
else
{
if (((*(temp->pPolygon) == id2) && (*(temp->pPolygon+size-1) != id3))
|| ((*(temp->pPolygon) == id3) && (*(temp->pPolygon+size-1) != id2)))
{
saved[x++] = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+size-1),face_id);
big_saved[z++] = saved[x-1];
}
else
big_saved[z++] = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+size-1),face_id);
}
}
/* There was an input edge */
if (x == 2)
{
if (saved[0] < saved[1])
/* Count the polygon that we will be cutting as another adjacency*/
*min = saved[0] + 1;
else
*min = saved[1] + 1;
}
/* There was not an input edge */
else
{
if (z != size)
{
printf("There is an error with the z %d %d\n",size,z);
exit(0);
}
*min = 60;
for (x = 0; x < size; x++)
{
if (*min > big_saved[x])
*min = big_saved[x];
}
}
}
void New_Face (int face_id, int v1, int v2, int v3)
{
/* We want to change the face that was face_id, we will
change it to a triangle, since the rest of the polygon
was already outputtted
*/
ListHead *pListHead;
PF_FACES temp = NULL;
pListHead = PolFaces[face_id];
temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0);
/* Check each edge of the face and tally the number of adjacent
polygons to this face.
*/
if ( temp != NULL )
{
/* Size of the polygon */
if (temp->nPolSize != 4)
{
printf("There is a miscalculation in the partial\n");
exit (0);
}
temp->nPolSize = 3;
*(temp->pPolygon) = v1;
*(temp->pPolygon+1) = v2;
*(temp->pPolygon+2) = v3;
}
}
void New_Size_Face (int face_id)
{
/* We want to change the face that was face_id, we will
change it to a triangle, since the rest of the polygon
was already outputtted
*/
ListHead *pListHead;
PF_FACES temp = NULL;
pListHead = PolFaces[face_id];
temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
/* Check each edge of the face and tally the number of adjacent
polygons to this face.
*/
if ( temp != NULL )
(temp->nPolSize)--;
else
printf("There is an error in updating the size\n");
}
void Check_In_Quad(int face_id,int *min)
{
/* Check to see what the adjacencies are for the polygons that
are inside the quad, ie the 2 triangles that we can form.
*/
ListHead *pListHead;
int y,id1,id2,id3,x=0;
int saved[4];
PF_FACES temp;
register int size = 4;
pListHead = PolFaces[face_id];
temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
/* Get the input edge that we came in on */
Last_Edge(&id1,&id2,&id3,0);
/* Now find the adjacencies for the inside triangles */
for (y = 0; y< size; y++)
{
/* Will not do this if the edge is the input edge */
if (y != (size-1))
{
if ((((*(temp->pPolygon+y) == id2) && (*(temp->pPolygon+y+1) == id3))) ||
(((*(temp->pPolygon+y) == id3) && (*(temp->pPolygon+y+1) == id2))))
saved[x++] = -1;
else
{
if (x == 4)
{
printf("There is an error in the check in quad \n");
exit(0);
}
/* Save the number of Adjacent Polygons to this edge */
saved[x++] = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),face_id);
}
}
else if ((((*(temp->pPolygon) == id2) && (*(temp->pPolygon+size-1) == id3))) ||
(((*(temp->pPolygon) == id3) && (*(temp->pPolygon+size-1) == id2))) )
saved[x++] = -1;
else
{
if (x == 4)
{
printf("There is an error in the check in quad \n");
exit(0);
}
/* Save the number of Adjacent Polygons to this edge */
saved[x++] = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+size-1),face_id);
}
}
if (x != 4)
{
printf("Did not enter all the values %d \n",x);
exit(0);
}
*min = 10;
for (x=0; x<4; x++)
{
if (x!= 3)
{
if ((saved[x] != -1) && (saved[x+1] != -1) &&
((saved[x] + saved[x+1]) < *min))
*min = saved[x] + saved[x+1];
}
else
{
if ((saved[0] != -1) && (saved[x] != -1) &&
((saved[x] + saved[0]) < *min))
*min = saved[0] + saved[x];
}
}
}
int Get_Output_Edge(int face_id, int size, int *index,int id2,int id3)
{
/* Return the vertex adjacent to either input1 or input2 that
is adjacent to the least number of polygons on the edge that
is shared with either input1 or input2.
*/
register int x=0,y;
int saved[2];
int edges[2][1];
for (y = 0; y < size; y++)
{
if (y != (size-1))
{
if (((*(index+y) == id2) && (*(index+y+1) != id3))
|| ((*(index+y) == id3) && (*(index+y+1) != id2)))
{
saved[x++] = Number_Adj(*(index+y),*(index+y+1),face_id);
edges[x-1][0] = *(index+y+1);
}
else if (y != 0)
{
if (( (*(index+y) == id2) && (*(index+y-1) != id3) ) ||
( (*(index+y) == id3) && (*(index+y-1) != id2)) )
{
saved[x++] = Number_Adj(*(index+y),*(index+y-1),face_id);
edges[x-1][0] = *(index+y-1);
}
}
else if (y == 0)
{
if (( (*(index) == id2) && (*(index+size-1) != id3) ) ||
( (*(index) == id3) && (*(index+size-1) != id2)) )
{
saved[x++] = Number_Adj(*(index),*(index+size-1),face_id);
edges[x-1][0] = *(index+size-1);
}
}
}
else
{
if (((*(index+size-1) == id2) && (*(index) != id3))
|| ((*(index+size-1) == id3) && (*(index) != id2)))
{
saved[x++] = Number_Adj(*(index),*(index+size-1),face_id);
edges[x-1][0] = *(index);
}
if (( (*(index+size-1) == id2) && (*(index+y-1) != id3) ) ||
( (*(index+size-1) == id3) && (*(index+y-1) != id2)) )
{
saved[x++] = Number_Adj(*(index+size-1),*(index+y-1),face_id);
edges[x-1][0] = *(index+y-1);
}
}
}
if ((x != 2))
{
printf("There is an error in getting the input edge %d \n",x);
exit(0);
}
if (saved[0] < saved[1])
return edges[0][0];
else
return edges[1][0];
}
void Get_Input_Edge(int *index,int id1,int id2,int id3,int *new1,int *new2,int size,
int face_id)
{
/* We had a polygon without an input edge and now we are going to pick one
as the input edge. The last triangle was id1,id2,id3, we will try to
get an edge to have something in common with one of those vertices, otherwise
we will pick the edge with the least number of adjacencies.
*/
register int x;
int saved[3];
saved[0] = -1;
saved[1] = -1;
saved[2] = -1;
/* Go through the edges to see if there is one in common with one
of the vertices of the last triangle that we had, preferably id2 or
id3 since those are the last 2 things in the stack of size 2.
*/
for (x=0; x< size; x++)
{
if (*(index+x) == id1)
{
if (x != (size-1))
saved[0] = *(index+x+1);
else
saved[0] = *(index);
}
if (*(index+x) == id2)
{
if (x != (size-1))
saved[1] = *(index+x+1);
else
saved[1] = *(index);
}
if (*(index+x) == id3)
{
if (x != (size -1))
saved[2] = *(index+x+1);
else
saved[2] = *(index);
}
}
/* Now see what we saved */
if (saved[2] != -1)
{
*new1 = id3;
*new2 = saved[2];
return;
}
else if (saved[1] != -1)
{
*new1 = id2;
*new2 = saved[1];
return;
}
else if (saved[0] != -1)
{
*new1 = id1;
*new2 = saved[0];
return;
}
/* We did not find anything so get the edge with the least number of adjacencies */
Edge_Least(index,new1,new2,face_id,size);
}
int Find_Face(int current_face, int id1, int id2, int *bucket)
{
/* Find the face that is adjacent to the edge and is not the
current face.
*/
register int size,y,count=0;
PF_EDGES temp = NULL;
PF_FACES temp2 = NULL;
ListHead *pListHead;
int next_face;
BOOL there = FALSE;
/* Always want smaller id first */
switch_lower(&id1,&id2);
pListHead = PolEdges[id1];
temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
/* The input edge was a new edge */
if (temp == NULL)
return -1;
while (temp->edge[0] != id2)
{
count++;
temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
/* The input edge was a new edge */
if (temp == NULL)
return -1;
}
/* Was not adjacent to anything else except itself */
if (temp->edge[2] == -1)
return -1;
else
{
if (temp->edge[2] == current_face)
next_face = temp->edge[1];
else
next_face = temp->edge[2];
}
/* We have the other face adjacent to this edge, it is
next_face.
*/
pListHead = PolFaces[next_face];
temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
/* See if the face was already deleted, and where
it is if it was not
*/
if (Done(next_face,59,bucket) == NULL)
return -1;
/* Make sure the edge is still in this polygon, and that it is not
done
*/
/* Size of the polygon */
size = temp2->nPolSize;
for (y = 0; y< size; y++)
{
/* Make sure that the edge is still in the
polygon and was not deleted, because if the edge was
deleted, then we used it already.
*/
if (y != (size-1))
{
if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1)))
|| ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1))))
/* edge is still there we are ok */
there = TRUE;
}
else
{
if( ((id1 == *(temp2->pPolygon)) && (id2 ==*(temp2->pPolygon+size-1)))
|| ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1))))
/* edge is still there we are ok */
there = TRUE;
}
}
if (!there)
/* Edge already used and deleted from the polygon*/
return -1;
else
return next_face;
}
BOOL Look_Up(int id1,int id2,int face_id)
{
/* See if the endpoints of the edge specified by id1 and id2
are adjacent to the face with face_id
*/
register int count = 0;
PF_EDGES temp = NULL;
ListHead *pListHead;
/* Always want smaller id first */
switch_lower(&id1,&id2);
pListHead = PolEdges[id1];
temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
if (temp == NULL)
/* Was a new edge that we created */
return 0;
while (temp->edge[0] != id2)
{
count++;
temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
if (temp == NULL)
/* Was a new edge that we created */
return 0;
}
/* Was not adjacent to anything else except itself */
if ((temp->edge[2] == face_id) || (temp->edge[1] == face_id))
{
/* Edge was adjacent to face, make sure that edge is
still there
*/
if (Exist(face_id,id1,id2))
return 1;
else
return 0;
}
else
return 0;
}
void Add_Id_Strips(int id, int where)
{
/* Just save the triangle for later */
P_STRIPS pfNode;
pfNode = (P_STRIPS) malloc(sizeof(Strips) );
if ( pfNode )
{
pfNode->face_id = id;
if (where == 1)
AddTail(strips[0],(PLISTINFO) pfNode);
/* We are backtracking in the strip */
else
AddHead(strips[0],(PLISTINFO) pfNode);
}
else
{
printf("There is not enough memory to allocate for the strips\n");
exit(0);
}
}
int Num_Adj(int id1, int id2)
{
/* Given edge whose endpoints are specified by id1 and id2,
determine how many polygons share this edge and return that
number minus one (since we do not want to include the polygon
that the caller has already).
*/
PF_EDGES temp = NULL;
ListHead *pListHead;
register count=-1;
/* Always want smaller id first */
switch_lower(&id1,&id2);
pListHead = PolEdges[id1];
temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
if (temp == NULL)
{
printf("There is an error in the creation of the table \n");
exit(0);
}
while (temp->edge[0] != id2)
{
count++;
temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
if (temp == NULL)
{
printf("There is an error in the creation of the table\n");
exit(0);
}
}
/* Was not adjacent to anything else except itself */
if (temp->edge[2] == -1)
return 0;
return 1;
}
void Add_Sgi_Adj(int bucket,int face_id)
{
/* This routine will add the face to the proper bucket,
depending on how many faces are adjacent to it (what the
value bucket should be).
*/
P_ADJACENCIES pfNode;
pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
if ( pfNode )
{
pfNode->face_id = face_id;
AddHead(array[bucket],(PLISTINFO) pfNode);
}
else
{
printf("Out of memory for the SGI adj list!\n");
exit(0);
}
}
void Find_Adjacencies(int num_faces)
{
register int x,y;
register int numverts;
PF_FACES temp=NULL;
ListHead *pListHead;
/* Fill in the adjacencies data structure for all the faces */
for (x=0;x<num_faces;x++)
{
pListHead = PolFaces[x];
temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
if ( temp != NULL )
{
numverts = temp->nPolSize;
if (numverts != 1)
{
for (y = 0; y< numverts; y++)
{
if (y != (numverts-1))
Add_AdjEdge(*(temp->pPolygon+y),*(temp->pPolygon+y+1),x,y);
else
Add_AdjEdge(*(temp->pPolygon),*(temp->pPolygon+(numverts-1)),x,numverts-1);
}
}
temp = NULL;
}
}
}

42
Stripe_w/common.h Normal file
View file

@ -0,0 +1,42 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: common.h
-----------------------------------------------------------------------*/
void Add_AdjEdge(int v1,int v2,int fnum,int index1 );
void Find_Adjacencies(int num_faces);
void Add_Sgi_Adj(int bucket,int face_id);
int Num_Adj(int id1, int id2);
void Add_Id_Strips(int id, int where);
BOOL Look_Up(int id1,int id2,int face_id);
int Number_Adj(int id1, int id2, int curr_id);
int Old_Adj(int face_id);
int Min_Adj(int id);
int Find_Face(int current_face, int id1, int id2, int *bucket);
void Edge_Least(int *index,int *new1,int *new2,int face_id,int size);
void Get_Input_Edge(int *index,int id1,int id2,int id3,int *new1,int *new2,
int size, int face_id);
int Get_Output_Edge(int face_id, int size, int *index,int id2,int id3);
void Check_In_Polygon(int face_id, int *min, int size);
void Check_In_Quad(int face_id,int *min);
void New_Size_Face (int face_id);
void New_Face (int face_id, int v1, int v2, int v3);

17
Stripe_w/extend.h Normal file
View file

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

112
Stripe_w/free.c Normal file
View file

@ -0,0 +1,112 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: free.c
This file contains the code used to free the data structures.
*/
/*---------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include "polverts.h"
ListHead *array[60];
int id_array[60];
ListHead *strips[1];
ListHead *all_strips[100000]; /* Assume max 100000 strips */
void ParseAndFreeList( ListHead *pListHead )
{
register int c,num;
/* Freeing a linked list */
num = NumOnList(pListHead);
for (c = 0; c< num; c++)
RemHead(pListHead);
}
void FreePolygonNode( PF_VERTS pfVerts)
{
/* Free a vertex node */
if ( pfVerts->pPolygon )
free( pfVerts->pPolygon );
free( pfVerts );
}
void Free_Strips()
{
/* Free strips data structure */
if (strips[0] == NULL)
return;
else
ParseAndFreeList(strips[0]);
}
void FreeFaceNode( PF_FACES pfFaces)
{
/* Free face node */
if ( pfFaces->pPolygon )
free( pfFaces->pPolygon );
free( pfFaces );
}
void FreeFaceTable(int nSize)
{
register int nIndex;
for ( nIndex=0; nIndex < nSize; nIndex++ )
{
if ( PolFaces[nIndex] != NULL )
ParseAndFreeList( PolFaces[nIndex] );
}
free( PolFaces );
}
void FreeEdgeTable(int nSize)
{
register int nIndex;
for ( nIndex=0; nIndex < nSize; nIndex++ )
{
if ( PolEdges[nIndex] != NULL )
ParseAndFreeList( PolEdges[nIndex] );
}
free( PolEdges );
}
void Free_All_Strips()
{
ListHead *pListHead;
register int y;
for (y =0; ; y++)
{
pListHead = all_strips[y];
if (pListHead == NULL)
return;
else
ParseAndFreeList(all_strips[y]);
}
}
void End_Face_Struct(int numfaces)
{
FreeFaceTable(numfaces);
}
void End_Edge_Struct(int numverts)
{
FreeEdgeTable(numverts);
}

22
Stripe_w/free.h Normal file
View file

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

44
Stripe_w/global.h Normal file
View file

@ -0,0 +1,44 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: global.h
-----------------------------------------------------------------------*/
#ifndef _GLOBAL_H
#define _GLOBAL_H
#define VRDATA double
#define STRIP_MAX 60
#define TRUE 1
#define FALSE 0
#ifndef PI
#define PI 3.1415926573
#endif
#define ATOI(C) (C -'0')
#define X 0
#define Y 1
#define Z 2
#define EVEN(x) (((x) & 1) == 0)
#define MAX_BAND 10000
struct vert_struct {
VRDATA x, y, z; /* point coordinates */
};
extern int ids[STRIP_MAX];
extern int norms[STRIP_MAX];
extern int *vert_norms;
extern int *vert_texture;
#endif _GLOBAL_H

217
Stripe_w/init.c Normal file
View file

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

30
Stripe_w/init.h Normal file
View file

@ -0,0 +1,30 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: init.h
-----------------------------------------------------------------------*/
void init_vert_norms(int num_vert);
void init_vert_texture(int num_vert);
BOOL InitVertTable( int nSize );
BOOL InitFaceTable( int nSize );
BOOL InitEdgeTable( int nSize );
void InitStripTable( );
void Init_Table_SGI();
void BuildVertTable( int nSize );
void BuildFaceTable( int nSize );
void BuildEdgeTable( int nSize );
void Start_Face_Struct(int numfaces);
void Start_Edge_Struct(int numverts);

119
Stripe_w/local.c Normal file
View file

@ -0,0 +1,119 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: local.c
This file contains the code that initializes the data structures for
the local algorithm, and starts the local algorithm going.
*/
/*---------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include "polverts.h"
#include "local.h"
#include "triangulatex.h"
#include "sturctsex.h"
#include "common.h"
#include "outputex.h"
#include "util.h"
#include "init.h"
void Find_StripsEx(FILE *output, FILE *strip,int *ties, int tie,
int triangulate, int swaps, int *next_id)
{
/* This routine will peel off the strips from the model */
ListHead *pListHead;
P_ADJACENCIES temp = NULL;
register int max,bucket=0;
BOOL whole_flag = TRUE;
int dummy = 0;
/* Set the last known input edge to be null */
Last_Edge(&dummy,&dummy,&dummy,1);
/* Search for lowest adjacency polygon and output strips */
while (whole_flag)
{
bucket = -1;
/* Search for polygons in increasing number of adjacencies */
while (bucket < 59)
{
bucket++;
pListHead = array[bucket];
max = NumOnList(pListHead);
if (max > 0)
{
temp = (P_ADJACENCIES) PeekList(pListHead,LISTHEAD,0);
if (temp == NULL)
{
printf("Error in the buckets%d %d %d\n",bucket,max,0);
exit(0);
}
Polygon_OutputEx(temp,temp->face_id,bucket,pListHead,
output,strip,ties,tie,triangulate,swaps,next_id,1);
/* Try to extend backwards, if the starting polygon in the
strip had 2 or more adjacencies to begin with
*/
if (bucket >= 2)
Extend_BackwardsEx(temp->face_id,output,strip,ties,tie,triangulate,swaps,next_id);
break;
}
}
/* Went through the whole structure, it is empty and we are done.
*/
if ((bucket == 59) && (max == 0))
whole_flag = FALSE;
/* We just finished a strip, send dummy data to signal the end
of the strip so that we can output it.
*/
else
{
Output_TriEx(-1,-2,-3,output,-1,-10,1);
Last_Edge(&dummy,&dummy,&dummy,1);
}
}
}
void SGI_Strip(int num_verts,int num_faces,FILE *output,
int ties,int triangulate)
{
FILE *strip;
int next_id = -1,t=0;
strip = fopen("output.d","w");
/* We are going to output and find triangle strips
according the the method that SGI uses, ie always
choosing as the next triangle in our strip the triangle
that has the least number of adjacencies. We do not have
all triangles and will be triangulating on the fly those
polygons that have more than 3 sides.
*/
/* Build a table that has all the polygons sorted by the number
of polygons adjacent to it.
*/
/* Initialize it */
Init_Table_SGI();
/* Build it */
Build_SGI_Table(num_verts,num_faces);
/* We will have a structure to hold all the strips, until
outputted.
*/
InitStripTable();
/* Now we have the structure built to find the polygons according
to the number of adjacencies. Now use the SGI Method to find
strips according to the adjacencies
*/
Find_StripsEx(output,strip,&t,ties,triangulate,ON,&next_id);
}

20
Stripe_w/local.h Normal file
View file

@ -0,0 +1,20 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE:local.h
-----------------------------------------------------------------------*/
void Local_Polygon_Output();
void Local_Output_Tri();
int Different();
void Local_Non_Blind_Triangulate();
void Local_Blind_Triangulate();
void Local_Triangulate_Polygon();
void SGI_Strip(int num_verts,int num_faces,FILE *output,
int ties,int triangulate);

1659
Stripe_w/newpolve.c Normal file

File diff suppressed because it is too large Load diff

181
Stripe_w/options.c Normal file
View file

@ -0,0 +1,181 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: options.c
This file contains routines that are used to determine the options
that were specified by the user
*/
/*---------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include "options.h"
#include "global.h"
int power_10(int power)
{
/* Raise 10 to the power */
register int i,p;
p = 1;
for (i = 1; i <= power; ++i)
p = p * 10;
return p;
}
float power_negative(int power)
{
/* Raise 10 to the negative power */
register int i;
float p;
p = (float)1;
for (i = 1; i<=power; i++)
p = p * (float).1;
return p;
}
float convert_array(int num[],int stack_size)
{
/* Convert an array of characters to an integer */
register int counter,c;
float temp =(float)0.0;
for (c=(stack_size-1), counter = 0; c>=0; c--, counter++)
{
if (num[c] == -1)
/* We are at the decimal point, convert to decimal
less than 1
*/
{
counter = -1;
temp = power_negative(stack_size - c - 1) * temp;
}
else
temp += power_10(counter) * num[c];
}
return(temp);
}
double get_options(int argc, char **argv, int *f, int *t, int *tr, int *group)
{
char c;
int count = 0;
int buffer[STRIP_MAX];
int next = 0;
/* tie variable */
enum tie_options tie = SEQUENTIAL;
/* triangulation variable */
enum triangulation_options triangulate = PARTIAL;
/* normal difference variable (in degrees) */
float norm_difference = (float)360.0;
/* file-type variable */
enum file_options file_type = ASCII;
/* User has the wrong number of options */
if ((argc > 5) || (argc < 2))
{
printf("Usage: bands -[file_option][ties_option][triangulation_option][normal_difference] file_name\n");
exit(0);
}
/* Interpret the options specified */
while (--argc > 0 && (*++argv)[0] == '-')
{
/* At the next option that was specified */
next = 1;
while (c = *++argv[0])
switch (c)
{
case 'f':
/* Use the first polygon we see. */
tie = FIRST;
break;
case 'r':
/* Randomly choose the next polygon */
tie = RANDOM;
break;
case 'a':
/* Alternate direction in choosing the next polygon */
tie = ALTERNATE;
break;
case 'l':
/* Use lookahead to choose the next polygon */
tie = LOOK;
break;
case 'q':
/* Try to reduce swaps */
tie = SEQUENTIAL;
break;
case 'p':
/* Use partial triangulation of polygons */
triangulate = PARTIAL;
break;
case 'w':
/* Use whole triangulation of polygons */
triangulate = WHOLE;
break;
case 'b':
/* Input file is in binary */
file_type = BINARY;
break;
case 'g':
/* Strips will be grouped according to the groups in
the data file. We will have to restrict strips to be
in the grouping of the data file.
*/
*group = 1;
/* Get each the value of the integer */
/* We have an integer */
default:
if ((c >= '0') && (c <= '9'))
{
/* More than one normal difference specified, use the last one */
if (next == 1)
{
count = 0;
next = 0;
}
buffer[count++] = ATOI(c);
}
/* At the decimal point */
else if (c == '.')
{
/* More than one normal difference specified, use the last one */
if (next == 1)
{
count = 0;
next = 0;
}
buffer[count++] = -1;
}
else
break;
}
}
/* Convert the buffer of characters to a floating pt integer */
if (count != 0)
norm_difference = convert_array(buffer,count);
*f = file_type;
*t = tie;
*tr = triangulate;
return norm_difference;
}

17
Stripe_w/options.h Normal file
View file

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

579
Stripe_w/output.c Normal file
View file

@ -0,0 +1,579 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: output.c
This file contains routines that are finding and outputting the
strips from the local algorithm
*/
/*---------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include "global.h"
#include "polverts.h"
#include "triangulate.h"
#include "partial.h"
#include "sturcts.h"
#include "ties.h"
#include "options.h"
#include "common.h"
#include "util.h"
#include "free.h"
int *vn;
int *vt;
int norm;
int text;
int Finished(int *swap, FILE *output, BOOL global)
{
/* We have finished all the triangles, now is time to output to
the data file. In the strips data structure, every three ids
is a triangle. Now we see whether we can swap, or make a new strip
or continue the strip, and output the data accordingly to the
data file.
*/
int num,x,vertex1,vertex2;
ListHead *pListHead;
int id[2],other1,other2,index = 0,a,b,c;
P_STRIPS temp1,temp2,temp3,temp4,temp5,temp6;
BOOL cptexture;
*swap =0;
cptexture = text;
pListHead = strips[0];
if (pListHead == NULL)
return 0;
num = NumOnList(pListHead);
// WILBUR
// printf ("There are %d triangles in the extend\n",num/3);
/* Go through the list triangle by triangle */
temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 0);
temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 1);
temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 2);
/* Next triangle for lookahead */
temp4 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 3);
/* There is only one polygon in the strip */
if (temp4 == NULL)
{
/* Data might be mixed and we do not have textures for some of the vertices */
if ((text) && (vt[temp3->face_id] == 0))
cptexture = FALSE;
if ((norm) && (!cptexture))
fprintf(output,"%d//%d %d//%d %d//%d",temp3->face_id+1,vn[temp3->face_id]+1,
temp2->face_id+1,vn[temp2->face_id]+1,
temp1->face_id+1,vn[temp1->face_id]+1);
else if ((cptexture) && (!norm))
fprintf(output,"%d/%d %d/%d %d/%d",temp3->face_id+1,vt[temp3->face_id]+1,
temp2->face_id+1,vt[temp2->face_id]+1,
temp1->face_id+1,vt[temp1->face_id]+1);
else if ((cptexture)&& (norm))
fprintf(output,"%d/%d/%d %d/%d/%d %d/%d/%d",temp3->face_id+1,vt[temp3->face_id]+1,vn[temp3->face_id]+1,
temp2->face_id+1,vt[temp2->face_id]+1,vn[temp2->face_id]+1,
temp1->face_id+1,vt[temp1->face_id]+1,vn[temp1->face_id]+1);
else
fprintf(output,"%d %d %d",temp3->face_id+1,temp2->face_id+1,temp1->face_id+1);
Free_Strips();
return 1;
}
/* We have a real strip */
temp5 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 4);
temp6 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 5);
if ((temp1 == NULL) || (temp2 == NULL) || (temp3 == NULL) || (temp5 == NULL) || (temp6 == NULL))
{
printf("There is an error in the output of the triangles\n");
exit(0);
}
/* Find the vertex in the first triangle that is not in the second */
vertex1 = Different(temp1->face_id,temp2->face_id,temp3->face_id,temp4->face_id,temp5->face_id,temp6->face_id,&other1,&other2);
/* Find the vertex in the second triangle that is not in the first */
vertex2 = Different(temp4->face_id,temp5->face_id,temp6->face_id,temp1->face_id,temp2->face_id,temp3->face_id,&other1,&other2);
/* Lookahead for the correct order of the 2nd and 3rd vertex of the first triangle */
temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 6);
temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 7);
temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 8);
if (temp1 != NULL)
other1 = Different(temp3->face_id,temp4->face_id,temp5->face_id,temp1->face_id,temp2->face_id,temp3->face_id,&other1,&a);
id[index] = vertex1; index = !index;
id[index] = other1; index = !index;
id[index] = other2; index = !index;
a = temp4->face_id;
b = temp5->face_id;
c = temp6->face_id;
/* If we need to rearrange the first sequence because otherwise
there would have been a swap.
*/
if ((temp3 != NULL) && (text) && ( vt[temp3->face_id]==0))
cptexture = FALSE;
if ((norm) && (!cptexture))
fprintf(output,"%d//%d %d//%d %d//%d ",vertex1+1,vn[vertex1]+1,
other1+1,vn[other1]+1,other2+1,vn[other2]+1);
else if ((cptexture) && (!norm))
fprintf(output,"%d/%d %d/%d %d/%d ",vertex1+1,vt[vertex1]+1,
other1+1,vt[other1]+1,other2+1,vt[other2]+1);
else if ((cptexture) && (norm))
fprintf(output,"%d/%d/%d %d/%d/%d %d/%d/%d ",vertex1+1,vt[vertex1]+1,vn[vertex1]+1,
other1+1,vt[other1]+1,vn[other1]+1,other2+1,vt[other2]+1,vn[other2]+1);
else {
fprintf(output,"%d %d %d ",vertex1+1,other1+1,other2+1);
}
// original line
// for (x = 6; x < num ; x = x+3)
// Wilbur modified line
for (x = 6; x < num ; x = x+3)
{
/* Get the next triangle */
temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, x);
temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, x+1);
temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, x+2);
/* Error checking */
if (!(member(id[0],a,b,c)) || !(member(id[1],a,b,c)) || !(member(vertex2,a,b,c)))
{
/* If we used partial we might have a break in the middle of a strip */
fprintf(output,"\nt ");
/* Find the vertex in the first triangle that is not in the second */
vertex1 = Different(a,b,c,temp1->face_id,temp2->face_id,temp3->face_id,&other1,&other2);
/* Find the vertex in the second triangle that is not in the first */
vertex2 = Different(temp1->face_id,temp2->face_id,temp3->face_id,a,b,c,&other1,&other2);
id[index] = vertex1; index = !index;
id[index] = other1; index = !index;
id[index] = other2; index = !index;
}
if ((temp1 == NULL ) || (temp2 == NULL) || (temp3 == NULL))
{
printf("There is an error in the triangle list \n");
exit(0);
}
if ((id[0] == id[1]) || (id[0] == vertex2))
continue;
if ( (member(id[index],temp1->face_id,temp2->face_id,temp3->face_id)) )
{
if ((text) && ( vt[id[index]]==0)) {
cptexture = FALSE;
}
if ((!norm) && (!cptexture)) {
fprintf(output,"%d ",id[index]+1);
} else if ((norm) && (!cptexture)) {
fprintf(output,"%d//%d ",id[index]+1,vn[id[index]]+1);
} else if ((!norm) && (cptexture)) {
fprintf(output,"%d/%d ",id[index]+1,vt[id[index]]+1);
} else {
fprintf(output,"%d/%d/%d ",id[index]+1,vt[id[index]]+1,vn[id[index]]+1);
}
index = !index;
*swap = *swap + 1;
}
if ((text) && ( vt[vertex2]==0))
cptexture = FALSE;
if ((!norm) && (!cptexture))
fprintf(output,"\nq %d ",vertex2+1);
else if ((norm) && (!cptexture))
fprintf(output,"\nq %d//%d ",vertex2+1,vn[vertex2]+1);
else if ((!norm) && (cptexture))
fprintf(output,"\nq %d/%d ",vertex2+1,vt[vertex2]+1);
else
fprintf(output,"\nq %d/%d/%d ",vertex2+1,vt[vertex2]+1,vn[vertex2]+1);
id[index] = vertex2; index = !index;
/* Get the next vertex not in common */
vertex2 = Different(temp1->face_id,temp2->face_id,temp3->face_id,a,b,c,&other1,&other2);
a = temp1->face_id;
b = temp2->face_id;
c = temp3->face_id;
}
/* Do the last vertex */
if ((!norm) && (!cptexture))
fprintf(output,"\nq %d ",vertex2+1);
else if ((norm) && (!cptexture))
fprintf(output,"\nq %d//%d ",vertex2+1,vn[vertex2]+1);
else if ((!norm) && (cptexture))
fprintf(output,"\nq %d/%d ",vertex2+1,vt[vertex2]+1);
else
fprintf(output,"\nq %d/%d/%d ",vertex2+1,vt[vertex2]+1,vn[vertex2]+1);
Free_Strips();
return (num/3);
}
void Output_Tri(int id1, int id2, int id3,FILE *bands, int color1, int color2, int color3,BOOL end)
{
/* We will save everything into a list, rather than output at once,
as was done in the old routine. This way for future modifications
we can change the strips later on if we want to.
*/
int temp1,temp2,temp3;
/* Make sure we do not have an error */
/* There are degeneracies in some of the files */
if ( (id1 == id2) || (id1 == id3) || (id2 == id3))
{
printf("Degenerate triangle %d %d %d\n",id1,id2,id3);
exit(0);
}
else
{
Last_Edge(&temp1,&temp2,&temp3,0);
Add_Id_Strips(id1,end);
Add_Id_Strips(id2,end);
Add_Id_Strips(id3,end);
Last_Edge(&id1,&id2,&id3,1);
}
}
int Polygon_Output(P_ADJACENCIES temp,int face_id,int bucket,
ListHead *pListHead, BOOL first, int *swaps,
FILE *bands,int color1,int color2,int color3,BOOL global, BOOL end)
{
ListHead *pListFace;
PF_FACES face;
P_ADJACENCIES pfNode;
int next_face_id,next_bucket,e1,e2,e3,other1,other2,other3;
P_ADJACENCIES lpListInfo;
int ties=0;
/* We have a polygon to output, the id is face id, and the number
of adjacent polygons to it is bucket. This routine extends the patches from
either end to make longer triangle strips.
*/
/* Now get the edge */
Last_Edge(&e1,&e2,&e3,0);
/* Get the polygon with id face_id */
pListFace = PolFaces[face_id];
face = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
/* We can't go any more */
if ((face->nPolSize == 1) || ((face->nPolSize == 4) && (global))) /* if global, then we are still doing patches */
{
/* Remove it from the list so we do not have to waste
time visiting it in the future, or winding up in an infinite loop
if it is the first on that we are looking at for a possible strip
*/
if (face->nPolSize == 1)
RemoveList(pListHead,(PLISTINFO) temp);
if (first)
return 0;
else
return (Finished(swaps,bands,global));
}
if (face->nPolSize == 3)
{
/* It is already a triangle */
if (bucket == 0)
{
/* It is not adjacent to anything so we do not have to
worry about the order of the sides or updating adjacencies
*/
next_face_id = Different(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2),
e1,e2,e3,&other1,&other2);
face->nPolSize = 1;
/* If this is the first triangle in the strip */
if ((e2 == 0) && (e3 ==0))
{
e2 = other1;
e3 = other2;
}
Output_Tri(e2,e3,next_face_id,bands,color1,color2,color3,end);
RemoveList(pListHead,(PLISTINFO) temp);
return (Finished(swaps,bands,global));
}
/* It is a triangle with adjacencies. This means that we
have to:
1. Update the adjacencies in the list, because we are
using this polygon and it will be deleted.
2. Get the next polygon.
*/
else
{
/* Return the face_id of the next polygon we will be using,
while updating the adjacency list by decrementing the
adjacencies of everything adjacent to the current triangle.
*/
next_face_id = Update_Adjacencies(face_id, &next_bucket, &e1,&e2,&ties);
/* Maybe we deleted something in a patch and could not find an adj polygon */
if (next_face_id == -1)
{
Output_Tri(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2),bands,color1,
color2,color3,end);
face->nPolSize = 1;
RemoveList(pListHead,(PLISTINFO) temp);
return (Finished(swaps,bands,global));
}
/* Find the other vertex to transmit in the triangle */
e3 = Return_Other(face->pPolygon,e1,e2);
Last_Edge(&other1,&other2,&other3,0);
if ((other2 != 0) && (other3 != 0))
{
/* See which vertex in the output edge is not in the input edge */
if ((e1 != other2) && (e1 != other3))
e3 = e1;
else if ((e2 != other2) && (e2 != other3))
e3 = e2;
else
{
printf("There is an error in the tri with adj\n");
exit(0);
}
/* See which vertex of the input edge is not in the output edge */
if ((other2 != e1) && (other2 != e2))
{
other1 = other2;
other2 = other3;
}
else if ((other3 != e1) && (other3 != e2))
other1 = other3;
else
{
printf("There is an error in getting the tri with adj\n");
exit(0);
}
}
else
{
/* We are the first triangle in the strip and the starting edge
has not been set yet
*/
/* Maybe we deleted something in a patch and could not find an adj polygon */
if (next_face_id == -1)
{
Output_Tri(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2),bands,color1,
color2,color3,end);
face->nPolSize = 1;
RemoveList(pListHead,(PLISTINFO) temp);
return (Finished(swaps,bands,global));
}
other1 = e3;
e3 = e2;
other2 = e1;
}
/* At this point the adjacencies have been updated and we
have the next polygon id
*/
Output_Tri(other1,other2,e3,bands,color1,color2,color3,end);
face->nPolSize = 1;
RemoveList(pListHead,(PLISTINFO) temp);
/* Maybe we deleted something in a patch and could not find an adj polygon */
if (next_face_id == -1)
return (Finished(swaps,bands,global));
if (Done(next_face_id,59,&next_bucket) == NULL)
{
printf("We deleted the next face 4%d\n",next_face_id);
exit(0);
}
pListHead = array[next_bucket];
pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
if ( pfNode )
pfNode->face_id = next_face_id;
lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
(int (*)(void *,void *)) (Compare)));
if (lpListInfo == NULL)
{
printf("There is an error finding the next polygon3 %d\n",next_face_id);
exit(0);
}
return (Polygon_Output(lpListInfo,next_face_id,next_bucket,
pListHead, FALSE, swaps,bands,color1,color2,color3,global,end));
}
}
else
{
/* It is not a triangle, we have to triangulate it .
Since it is not adjacent to anything we can triangulate it
blindly
*/
if (bucket == 0)
{
/* It is the first polygon in the strip, therefore there is no
input edge to start with.
*/
if ((e2 == 0) && (e3 ==0))
Blind_Triangulate(face->nPolSize,face->pPolygon,bands,
TRUE,1,color1,color2,color3);
else
Blind_Triangulate(face->nPolSize,face->pPolygon,bands,
FALSE,1,color1,color2,color3);
RemoveList(pListHead,(PLISTINFO) temp);
/* We will be at the beginning of the next strip. */
face->nPolSize = 1;
return (Finished(swaps,bands,global));
}
else
{
/* WHOLE triangulation */
/* It is not a triangle and has adjacencies.
This means that we have to:
1. Triangulate this polygon, not blindly because
we have an edge that we want to come out on, that
is the edge that is adjacent to a polygon with the
least number of adjacencies. Also we must come in
on the last seen edge.
2. Update the adjacencies in the list, because we are
using this polygon .
3. Get the next polygon.
*/
/* Return the face_id of the next polygon we will be using,
while updating the adjacency list by decrementing the
adjacencies of everything adjacent to the current polygon.
*/
next_face_id = Update_Adjacencies(face_id, &next_bucket, &e1,&e2,&ties);
/* Maybe we deleted something in a patch and could not find an adj polygon */
if (next_face_id == -1)
{
/* If we are at the first polygon in the strip and there is no input
edge, then begin is TRUE
*/
if ((e2 == 0) && (e3 == 0))
Blind_Triangulate(face->nPolSize,face->pPolygon,
bands,TRUE,1,color1,color2,color3);
else
Blind_Triangulate(face->nPolSize,face->pPolygon,
bands,FALSE,1,color1,color2,color3);
RemoveList(pListHead,(PLISTINFO) temp);
/* We will be at the beginning of the next strip. */
face->nPolSize = 1;
return (Finished(swaps,bands,global));
}
if (Done(next_face_id,59,&next_bucket) == NULL)
{
printf("We deleted the next face 6 %d %d\n",next_face_id,face_id);
exit(0);
}
Non_Blind_Triangulate(face->nPolSize,face->pPolygon,
bands,next_face_id,face_id,1,color1,color2,color3);
RemoveList(pListHead,(PLISTINFO) temp);
face->nPolSize = 1;
pListHead = array[next_bucket];
pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
if ( pfNode )
pfNode->face_id = next_face_id;
lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
(int (*)(void *,void *)) (Compare)));
if (lpListInfo == NULL)
{
printf("There is an error finding the next polygon2 %d %d\n",next_face_id,next_bucket);
exit(0);
}
return (Polygon_Output(lpListInfo,next_face_id,next_bucket,
pListHead, FALSE, swaps,bands,color1,color2,color3,global,end));
}
}
Last_Edge(&e1,&e2,&e3,0);
}
int Extend_Face(int face_id,int e1,int e2,int *swaps,FILE *bands,
int color1,int color2,int color3,int *vert_norm, int normals,
int *vert_texture, int texture)
{
int dummy=0,next_bucket;
P_ADJACENCIES pfNode,lpListInfo;
ListHead *pListHead;
/* Try to extend backwards off of the local strip that we just found */
vn = vert_norm;
vt = vert_texture;
norm = normals;
text = texture;
*swaps = 0;
/* Find the face that is adjacent to the edge and is not the
current face.
*/
face_id = Find_Face(face_id, e1, e2,&next_bucket);
if (face_id == -1)
return 0;
pListHead = array[next_bucket];
pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
if ( pfNode )
pfNode->face_id = face_id;
lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
(int (*)(void *,void *)) (Compare)));
if (lpListInfo == NULL)
{
printf("There is an error finding the next polygon3 %d\n",face_id);
exit(0);
}
Last_Edge(&dummy,&e1,&e2,1);
/* Find a strip extending from the patch and return the cost */
return (Polygon_Output(lpListInfo,face_id,next_bucket,pListHead,TRUE,swaps,bands,color1,color2,color3,TRUE,TRUE));
}

34
Stripe_w/output.h Normal file
View file

@ -0,0 +1,34 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: output.h
-----------------------------------------------------------------------*/
#include "polverts.h"
#define TRIANGLE 3
#define MAGNITUDE 1000000
void Output_Tri(int id1, int id2, int id3,FILE *bands, int color1,
int color2, int color3,BOOL end);
void Sgi_Test();
int Polygon_Output(P_ADJACENCIES temp,int face_id,int bucket,
ListHead *pListHead, BOOL first, int *swaps,
FILE *bands,int color1,int color2,int color3,
BOOL global, BOOL end);
void Last_Edge();
void Extend_Backwards();
int Finished(int *swap, FILE *output, BOOL global);
int Extend_Face(int face_id,int e1,int e2,int *swaps,FILE *bands,
int color1,int color2,int color3,int *vert_norm, int normals,
int *vert_texture, int texture);
void Fast_Reset();

514
Stripe_w/outputex.c Normal file
View file

@ -0,0 +1,514 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: outputex.c
This file contains routines that are used for various functions in
the local algorithm.
*/
/*---------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include "global.h"
#include "outputex.h"
#include "triangulatex.h"
#include "polverts.h"
#include "ties.h"
#include "partial.h"
#include "sturctsex.h"
#include "options.h"
#include "output.h"
#include "common.h"
#include "util.h"
void Output_TriEx(int id1, int id2, int id3, FILE *output, int next_face, int flag,
int where)
{
/* We will save everything into a list, rather than output at once,
as was done in the old routine. This way for future modifications
we can change the strips later on if we want to.
*/
int swap,temp1,temp2,temp3;
static int total=0;
static int tri=0;
static int strips = 0;
static int cost = 0;
if (flag == -20)
{
cost = cost + where+total+tri+strips+strips;
printf("We will need to send %d vertices to the renderer\n",cost);
total = 0;
tri = 0;
strips = 0;
return ;
}
if (flag == -10) /* We are finished, now is time to output the triangle list */
{
fprintf(output,"\nt ");
tri = tri + Finished(&swap,output,FALSE);
total = total + swap;
strips++;
/*printf("There are %d swaps %d tri %d strips\n",total,tri,strips);*/
}
else
{
Last_Edge(&temp1,&temp2,&temp3,0);
Add_Id_Strips(id1,where);
Add_Id_Strips(id2,where);
Add_Id_Strips(id3,where);
Last_Edge(&id1,&id2,&id3,1);
}
}
void Extend_BackwardsEx(int face_id, FILE *output, FILE *strip, int *ties,
int tie, int triangulate, int swaps, int *next_id)
{
/* We just made a strip, now we are going to see if we can extend
backwards from the starting face, which had 2 or more adjacencies
to start with.
*/
int bucket,next_face,num,x,y,z,c,max,f;
ListHead *pListFace;
PF_FACES face;
P_ADJACENCIES temp;
/* Get the first triangle that we have saved the the strip data
structure, so we can see if there are any polygons adjacent
to this edge or a neighboring one
*/
First_Edge(&x,&y,&z);
pListFace = PolFaces[face_id];
face = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
num = face->nPolSize;
/* Go through the edges to see if there is an adjacency
with a vertex in common to the first triangle that was
outputted in the strip. (maybe edge was deleted....)
*/
for (c=0; c<num ; c++)
{
if ( (c != (num-1)) &&
(( (*(face->pPolygon+c) == x) && (*(face->pPolygon+c+1) == y)) ||
(*(face->pPolygon+c) == y) && (*(face->pPolygon+c+1) == x)))
{
/* Input edge is still there see if there is an adjacency */
next_face = Find_Face(face_id, x, y, &bucket);
if (next_face == -1)
/* Could not find a face adjacent to the edge */
break;
pListFace = array[bucket];
max = NumOnList(pListFace);
for (f=0;;f++)
{
temp = (P_ADJACENCIES) PeekList(pListFace,LISTHEAD,f);
if (temp->face_id == next_face)
{
Last_Edge(&z,&y,&x,1);
Polygon_OutputEx(temp,temp->face_id,bucket,pListFace,
output,strip,ties,tie,triangulate,swaps,next_id,0);
return;
}
if (temp == NULL)
{
printf("Error in the new buckets%d %d %d\n",bucket,max,0);
exit(0);
}
}
}
else if ( (c == (num -1)) &&
( ((*(face->pPolygon) == x) && (*(face->pPolygon+num-1) == y)) ||
(*(face->pPolygon) == y) && (*(face->pPolygon+num-1) == x)))
{
next_face = Find_Face(face_id,x,y,&bucket);
if (next_face == -1)
/* Could not find a face adjacent to the edge */
break;
pListFace = array[bucket];
max = NumOnList(pListFace);
for (f=0;;f++)
{
temp = (P_ADJACENCIES) PeekList(pListFace,LISTHEAD,f);
if (temp->face_id == next_face)
{
Last_Edge(&z,&y,&x,1);
Polygon_OutputEx(temp,temp->face_id,bucket,pListFace,
output,strip,ties,tie,triangulate,swaps,next_id,0);
return;
}
if (temp == NULL)
{
printf("Error in the new buckets%d %d %d\n",bucket,max,0);
exit(0);
}
}
}
}
}
void Polygon_OutputEx(P_ADJACENCIES temp,int face_id,int bucket,
ListHead *pListHead, FILE *output, FILE *strips,
int *ties, int tie, int triangulate, int swaps,
int *next_id, int where)
{
ListHead *pListFace;
PF_FACES face;
P_ADJACENCIES pfNode;
static BOOL begin = TRUE;
int old_face,next_face_id,next_bucket,e1,e2,e3,other1,other2,other3;
P_ADJACENCIES lpListInfo;
/* We have a polygon to output, the id is face id, and the number
of adjacent polygons to it is bucket.
*/
Last_Edge(&e1,&e2,&e3,0);
/* Get the polygon with id face_id */
pListFace = PolFaces[face_id];
face = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
if (face->nPolSize == 3)
{
/* It is already a triangle */
if (bucket == 0)
{
/* It is not adjacent to anything so we do not have to
worry about the order of the sides or updating adjacencies
*/
Last_Edge(&e1,&e2,&e3,0);
next_face_id = Different(*(face->pPolygon),*(face->pPolygon+1),*(face->pPolygon+2),
e1,e2,e3,&other1,&other2);
/* No input edge, at the start */
if ((e2 ==0) && (e3 == 0))
{
e2 = other1;
e3 = other2;
}
Output_TriEx(e2,e3,next_face_id,strips,-1,begin,where);
RemoveList(pListHead,(PLISTINFO) temp);
/* We will be at the beginning of the next strip. */
begin = TRUE;
}
/* It is a triangle with adjacencies. This means that we
have to:
1. Update the adjacencies in the list, because we are
using this polygon and it will be deleted.
2. Get the next polygon.
*/
else
{
/* Return the face_id of the next polygon we will be using,
while updating the adjacency list by decrementing the
adjacencies of everything adjacent to the current triangle.
*/
next_face_id = Update_AdjacenciesEx(face_id, &next_bucket, &e1,&e2,ties);
old_face = next_face_id;
/* Break the tie, if there was one */
if (tie != FIRST)
old_face = Get_Next_Face(tie,face_id,triangulate);
if (next_face_id == -1)
{
Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie,
triangulate,swaps,next_id,where);
return;
}
/* We are using a different face */
if ((tie != FIRST) && (old_face != next_face_id) && (swaps == ON))
{
next_face_id = old_face;
/* Get the new output edge, since e1 and e2 are for the
original next face that we got.
*/
e3 = Get_EdgeEx(&e1,&e2,face->pPolygon,next_face_id,face->nPolSize,0,0);
}
/* Find the other vertex to transmit in the triangle */
e3 = Return_Other(face->pPolygon,e1,e2);
Last_Edge(&other1,&other2,&other3,0);
if ((other1 != 0) && (other2 != 0))
{
/* See which vertex in the output edge is not in the input edge */
if ((e1 != other2) && (e1 != other3))
e3 = e1;
else if ((e2 != other2) && (e2 != other3))
e3 = e2;
/* can happen with > 2 polys on an edge but won't form a good strip so stop
the strip here
*/
else
{
Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie,
triangulate,swaps,next_id,where);
return;
}
/* See which vertex of the input edge is not in the output edge */
if ((other2 != e1) && (other2 != e2))
{
other1 = other2;
other2 = other3;
}
else if ((other3 != e1) && (other3 != e2))
other1 = other3;
else
{
/* Degenerate triangle just return*/
Output_TriEx(other1,other2,e3,strips,next_face_id,begin,where);
RemoveList(pListHead,(PLISTINFO) temp);
begin = FALSE;
return;
}
}
/* There was not an input edge, we are the first triangle in a strip */
else
{
/* Find the correct order to transmit the triangle, what is
the output edge that we want ?
*/
other1 = e3;
e3 = e2;
other2 = e1;
}
/* At this point the adjacencies have been updated and we
have the next polygon id
*/
Output_TriEx(other1,other2,e3,strips,next_face_id,begin,where);
RemoveList(pListHead,(PLISTINFO) temp);
begin = FALSE;
if (Done(next_face_id,59,&next_bucket) == NULL)
return;
pListHead = array[next_bucket];
pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
if ( pfNode )
pfNode->face_id = next_face_id;
lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
(int (*)(void *,void *)) (Compare)));
if (lpListInfo == NULL)
{
printf("There is an error finding the next polygon3 %d\n",next_face_id);
exit(0);
}
Polygon_OutputEx(lpListInfo,next_face_id,next_bucket,
pListHead, output, strips,ties,tie,triangulate,swaps,next_id,where);
}
}
else
{
/* It is not a triangle, we have to triangulate it .
Since it is not adjacent to anything we can triangulate it
blindly
*/
if (bucket == 0)
{
/* Check to see if there is not an input edge */
Last_Edge(&other1,&other2,&other3,0);
if ((other1 == 0) && (other2 ==0))
Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips,
output,TRUE,where);
else
Blind_TriangulateEx(face->nPolSize,face->pPolygon,strips,
output,FALSE,where);
RemoveList(pListHead,(PLISTINFO) temp);
/* We will be at the beginning of the next strip. */
begin = TRUE;
}
/* If we have specified PARTIAL triangulation then
we will go to special routines that will break the
polygon and update the data structure. Else everything
below will simply triangulate the whole polygon
*/
else if (triangulate == PARTIAL)
{
/* Return the face_id of the next polygon we will be using,
*/
next_face_id = Min_Face_AdjEx(face_id,&next_bucket,ties);
/* Don't do it partially, because we can go inside and get
less adjacencies, for a quad we can do the whole thing.
*/
if ((face_id == next_face_id) && (face->nPolSize == 4) && (swaps == ON))
{
next_face_id = Update_AdjacenciesEx(face_id, &next_bucket, &e1,&e2,ties);
if (next_face_id == -1)
{
/* There is no sequential face to go to, end the strip */
Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie,
triangulate,swaps,next_id,where);
return;
}
/* Break the tie, if there was one */
if (tie != FIRST)
next_face_id = Get_Next_Face(tie,face_id,triangulate);
Non_Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips,
output,next_face_id,face_id,where);
RemoveList(pListHead,(PLISTINFO) temp);
}
/* Was not a quad but we still do not want to do it partially for
now, since we want to only do one triangle at a time
*/
else if ((face_id == next_face_id) && (swaps == ON))
Inside_Polygon(face->nPolSize,face->pPolygon,strips,output,
next_face_id,face_id,next_id,pListHead,temp,where);
else
{
if ((tie != FIRST) && (swaps == ON))
next_face_id = Get_Next_Face(tie,face_id,triangulate);
Partial_Triangulate(face->nPolSize,face->pPolygon,strips,
output,next_face_id,face_id,next_id,pListHead,temp,where);
/* Check the next bucket again ,maybe it changed
We calculated one less, but that might not be the case
*/
}
if (Done(next_face_id,59,&next_bucket) == NULL)
{
/* Check to see if there is not an input edge */
Last_Edge(&other1,&other2,&other3,0);
if ((other1 == 0) && (other2 ==0))
Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips,
output,TRUE,where);
else
Blind_TriangulateEx(face->nPolSize,face->pPolygon,strips,
output,FALSE,where);
if (Done(face_id,59,&bucket) != NULL)
{
pListHead = array[bucket];
pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
if ( pfNode )
pfNode->face_id = face_id;
lpListInfo = (P_ADJACENCIES) (SearchList(array[bucket], pfNode,
(int (*)(void *,void *)) (Compare)));
RemoveList(pListHead,(PLISTINFO)lpListInfo);
}
begin = TRUE;
return;
}
begin = FALSE;
pListHead = array[next_bucket];
pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
if ( pfNode )
pfNode->face_id = next_face_id;
lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
(int (*)(void *,void *)) (Compare)));
if (lpListInfo == NULL)
{
printf("There is an error finding the next polygon1 %d %d\n",next_face_id,next_bucket);
exit(0);
}
Polygon_OutputEx(lpListInfo,next_face_id,next_bucket,
pListHead, output, strips,ties,tie,triangulate,swaps,next_id,where);
}
else
{
/* WHOLE triangulation */
/* It is not a triangle and has adjacencies.
This means that we have to:
1. TriangulateEx this polygon, not blindly because
we have an edge that we want to come out on, that
is the edge that is adjacent to a polygon with the
least number of adjacencies. Also we must come in
on the last seen edge.
2. Update the adjacencies in the list, because we are
using this polygon .
3. Get the next polygon.
*/
/* Return the face_id of the next polygon we will be using,
while updating the adjacency list by decrementing the
adjacencies of everything adjacent to the current polygon.
*/
next_face_id = Update_AdjacenciesEx(face_id, &next_bucket, &e1,&e2,ties);
if (Done(next_face_id,59,&next_bucket) == NULL)
{
Polygon_OutputEx(temp,face_id,0,pListHead,output,strips,ties,tie,
triangulate,swaps,next_id,where);
/* Because maybe there was more than 2 polygons on the edge */
return;
}
/* Break the tie, if there was one */
else if (tie != FIRST)
next_face_id = Get_Next_Face(tie,face_id,triangulate);
Non_Blind_TriangulateEx(face->nPolSize,face->pPolygon, strips,
output,next_face_id,face_id,where);
RemoveList(pListHead,(PLISTINFO) temp);
begin = FALSE;
pListHead = array[next_bucket];
pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
if ( pfNode )
pfNode->face_id = next_face_id;
lpListInfo = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
(int (*)(void *,void *)) (Compare)));
if (lpListInfo == NULL)
{
printf("There is an error finding the next polygon2 %d %d\n",next_face_id,next_bucket);
exit(0);
}
Polygon_OutputEx(lpListInfo,next_face_id,next_bucket,
pListHead, output, strips,ties,tie,triangulate,swaps,next_id,where);
}
}
Last_Edge(&e1,&e2,&e3,0);
}

31
Stripe_w/outputex.h Normal file
View file

@ -0,0 +1,31 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: outputex.h
-----------------------------------------------------------------------*/
#include "polverts.h"
#define TRIANGLE 3
#define MAGNITUDE 1000000
void Output_TriEx(int id1, int id2, int id3, FILE *output, int next_face,
int flag, int where);
void Sgi_Test();
void Polygon_OutputEx(P_ADJACENCIES temp,int face_id,int bucket,
ListHead *pListHead, FILE *output, FILE *strips,
int *ties, int tie, int triangulate, int swaps,
int *next_id, int where);
void Extend_BackwardsEx(int face_id, FILE *output, FILE *strip, int *ties,
int tie, int triangulate, int swaps,int *next_id);
void FinishedEx();

668
Stripe_w/partial.c Normal file
View file

@ -0,0 +1,668 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: partial.c
This file contains routines that are used partial triangulation of polygons
*/
/*---------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "global.h"
#include "outputex.h"
#include "polyvertsex.h"
#include "triangulatex.h"
#include "sturctsex.h"
#include "polverts.h"
#include "common.h"
#include "util.h"
void P_Triangulate_Quad(int out_edge1,int out_edge2,int in_edge1,
int in_edge2,int size,int *index,
FILE *output,FILE *fp,int reversed,int face_id,
int *next_id,ListHead *pListHead,
P_ADJACENCIES temp,
int where)
{
int vertex4,vertex5,dummy=60;
/* This routine will nonblindly triangulate a quad, meaning
that there is a definite input and a definite output
edge that we must adhere to. Reversed will tell the orientation
of the input edge. (Reversed is -1 is we do not have an input
edge, in other words we are at the beginning of a strip.)
Out_edge* is the output edge, and in_edge* is the input edge.
Index are the edges of the polygon
and size is the size of the polygon. Begin is whether we are
at the start of a new strip.
Note that we will not necessarily triangulate the whole quad;
maybe we will do half and leave the other half (a triangle)
for later.
*/
/* If we do not have an input edge, then we can make our input
edge whatever we like, therefore it will be easier to come
out on the output edge. In this case the whole quad is done.
*/
if (reversed == -1)
{
vertex4 = AdjacentEx(out_edge1,out_edge2,index,size);
vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index);
Output_TriEx(vertex5,vertex4,out_edge1,output,-1,-1,where);
Output_TriEx(vertex4,out_edge1,out_edge2,output,-1,-1,where);
dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy);
RemoveList(pListHead,(PLISTINFO) temp);
return;
}
/* These are the 5 cases that we can have for the output edge */
/* Are they consecutive so that we form a triangle to
peel off, but cannot use the whole quad?
*/
if (in_edge2 == out_edge1)
{
/* Output the triangle that comes out the correct
edge. Save the other half for later.
*/
vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index);
Output_TriEx(in_edge1,in_edge2,out_edge2,output,-1,-1,where);
/* Now we have a triangle used, and a triangle that is
left for later.
*/
/* Now delete the adjacencies by one for all the faces
that are adjacent to the triangle that we just outputted.
*/
Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,
face_id,&dummy,&dummy,&dummy);
Delete_AdjEx(out_edge2,in_edge2,&dummy,&dummy,
face_id,&dummy,&dummy,&dummy);
/* Put the new face in the proper bucket of adjacencies
There are 2 edges that need to be checked for the triangle
that was just outputted. For the output edge we definitely
will be decreasing the adjacency, but we must check for the
input edge.
*/
dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE);
dummy = Change_FaceEx(face_id,in_edge2,out_edge2,pListHead,temp,TRUE);
/* Update the face data structure, by deleting the old
face and putting in the triangle as the new face
*/
New_Face(face_id,in_edge1,out_edge2,vertex4);
return;
}
else if (in_edge1 == out_edge1)
{
/* We want to output the first triangle (whose output
edge is not the one that we want.
We have to find the vertex that we need, which is
the other vertex which we do not have.
*/
vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index);
Output_TriEx(in_edge2,in_edge1,out_edge2,output,-1,-1,where);
/* Now we have a triangle used, and a triangle that is
left for later.
*/
/* Now delete the adjacencies by one for all the faces
that are adjacent to the triangle that we just outputted.
*/
Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
&dummy,&dummy,&dummy);
Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy,
face_id,&dummy,&dummy,&dummy);
/* Put the new face in the proper bucket of adjacencies */
dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE);
dummy = Change_FaceEx(face_id,in_edge1,out_edge2,pListHead,temp,TRUE);
/* Update the face data structure, by deleting the old
face and putting in the triangle as the new face
*/
New_Face(face_id,in_edge2,out_edge2,vertex4);
return;
}
/* Consecutive cases again, but with the output edge reversed */
else if (in_edge1 == out_edge2)
{
vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
Output_TriEx(in_edge2,in_edge1,out_edge1,output,-1,-1,where);
/* Now we have a triangle used, and a triangle that is
left for later.
*/
/* Now delete the adjacencies by one for all the faces
that are adjacent to the triangle that we just outputted.
*/
Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
&dummy,&dummy,&dummy);
Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy,
face_id,&dummy,&dummy,&dummy);
/* Put the new face in the proper bucket of adjacencies */
dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE);
dummy = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp,TRUE);
/* Update the face data structure, by deleting the old
face and putting in the triangle as the new face
*/
New_Face(face_id,in_edge2,out_edge1,vertex4);
return;
}
else if (in_edge2 == out_edge2)
{
vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where);
/* Now we have a triangle used, and a triangle that is
left for later.
*/
/* Now delete the adjacencies by one for all the faces
that are adjacent to the triangle that we just outputted.
*/
Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
&dummy,&dummy,&dummy);
Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy,
face_id,&dummy,&dummy,&dummy);
/* Put the new face in the proper bucket of adjacencies */
dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp,FALSE);
dummy = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp,TRUE);
/* Update the face data structure, by deleting the old
face and putting in the triangle as the new face
*/
New_Face(face_id,in_edge1,out_edge1,vertex4);
return;
}
/* The final case is where we want to come out the opposite
edge.
*/
else
{
if( ((!reversed) && (out_edge1 == (AdjacentEx(in_edge1,in_edge2,index,size)))) ||
((reversed) && (out_edge2 == (AdjacentEx(in_edge2,in_edge1,index,size)))))
{
/* We need to know the orientation of the input
edge, so we know which way to put the diagonal.
And also the output edge, so that we triangulate
correctly. Does not need partial.
*/
Output_TriEx(in_edge1,in_edge2,out_edge2,output,-1,-1,where);
Output_TriEx(in_edge2,out_edge2,out_edge1,output,-1,-1,where);
dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy);
RemoveList(pListHead,(PLISTINFO) temp);
}
else
{
/* Input and output orientation was reversed, so diagonal will
be reversed from above.
*/
Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where);
Output_TriEx(in_edge2,out_edge1,out_edge2,output,-1,-1,where);
dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy);
RemoveList(pListHead,(PLISTINFO) temp);
}
return;
}
}
void P_Triangulate_Polygon(int out_edge1,int out_edge2,int in_edge1,
int in_edge2,int size,
int *index,FILE *output,FILE *fp,
int reversed,int face_id,int *next_id,
ListHead *pListHead, P_ADJACENCIES temp2,
int where)
{
/* We have a polygon greater than 4 sides, which we wish
to partially triangulate
*/
int next_bucket,vertex4,dummy = 60;
int *temp;
P_ADJACENCIES pfNode;
/* Since we are calling this recursively, we have to check whether
we are down to the case of the quad.
*/
if (size == 4)
{
P_Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size,
index,output,fp,reversed,face_id,next_id,
pListHead,temp2,where);
return;
}
/* We do not have a specified input edge, and therefore we
can make it anything we like, as long as we still come out
the output edge that we want.
*/
if (reversed == -1)
{
/* Get the vertex for the last triangle, which is
the one coming out the output edge, before we do
any deletions to the list. We will be doing this
bottom up.
*/
vertex4 = AdjacentEx(out_edge1,out_edge2,index,size);
temp = (int *) malloc(sizeof(int) * size);
memcpy(temp,index,sizeof(int)*size);
Delete_From_ListEx(out_edge2,index,size);
/* We do not have to partially triangulate, since
we will do the whole thing, so use the whole routine
*/
/* Triangulate_PolygonEx(vertex4,out_edge1,in_edge2,
vertex4,size-1,index,output,fp,reversed,
face_id,next_id,pListHead,temp2,where); */
Triangulate_PolygonEx(vertex4,out_edge1,in_edge2,
vertex4,size-1,index,output,fp,reversed,
face_id,where);
memcpy(index,temp,sizeof(int)*size);
/* Lastly do the triangle that comes out the output
edge.
*/
Output_TriEx(vertex4,out_edge1,out_edge2,output,-1,-1,where);
/* We were able to do the whole polygon, now we
can delete the whole thing from our data structure.
*/
dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy);
RemoveList(pListHead,(PLISTINFO) temp2);
return;
}
/* These are the 5 cases that we can have for the output edge */
/* Are they consecutive so that we form a triangle to
peel off that comes out the correct output edge,
but we cannot use the whole polygon?
*/
if (in_edge2 == out_edge1)
{
Output_TriEx(in_edge1,out_edge1,out_edge2,output,-1,-1,where);
/* Now delete the adjacencies by one for all the faces
that are adjacent to the triangle that we just outputted.
*/
Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
&dummy,&dummy,&dummy);
Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy,
face_id,&dummy,&dummy,&dummy);
/* Put the new face in the proper bucket of adjacencies */
next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE);
/* Create a new edgelist without the triangle that
was just outputted.
*/
Delete_From_ListEx(in_edge2,index,size);
/* Update the face data structure, by deleting the old
face and putting in the polygon minus the triangle
as the new face, here we will be decrementing the size
by one.
*/
New_Size_Face(face_id);
return;
}
/* Next case is where it is again consecutive, but the triangle
formed by the consecutive edges do not come out of the
correct output edge. (the input edge will be reversed in
the next triangle)
*/
else if (in_edge1 == out_edge1)
{
/* Get vertex adjacent to in_edge2, but is not in_edge1 */
Output_TriEx(in_edge2,in_edge1,out_edge2,output,-1,-1,where);
/* Now delete the adjacencies by one for all the faces
that are adjacent to the triangle that we just outputted.
*/
Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
&dummy,&dummy,&dummy);
Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy,
face_id,&dummy,&dummy,&dummy);
/* Put the new face in the proper bucket of adjacencies */
next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE);
/* Create a new edgelist without the triangle that
was just outputted.
*/
Delete_From_ListEx(in_edge1,index,size);
/* Update the face data structure, by deleting the old
face and putting in the polygon minus the triangle
as the new face, here we will be decrementing the size
by one.
*/
New_Size_Face(face_id);
return;
}
/* Consecutive cases again, but with the output edge reversed */
else if (in_edge1 == out_edge2)
{
Output_TriEx(in_edge2,in_edge1,out_edge1,output,-1,-1,where);
/* Now delete the adjacencies by one for all the faces
that are adjacent to the triangle that we just outputted.
*/
Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
&dummy,&dummy,&dummy);
Delete_AdjEx(out_edge1,out_edge2,&dummy,&dummy,
face_id,&dummy,&dummy,&dummy);
/* Put the new face in the proper bucket of adjacencies */
next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE);
/* Create a new edgelist without the triangle that
was just outputted.
*/
Delete_From_ListEx(in_edge1,index,size);
/* Update the face data structure, by deleting the old
face and putting in the polygon minus the triangle
as the new face, here we will be decrementing the size
by one.
*/
New_Size_Face(face_id);
return;
}
else if (in_edge2 == out_edge2)
{
Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where);
/* Now delete the adjacencies by one for all the faces
that are adjacent to the triangle that we just outputted.
*/
Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
&dummy,&dummy,&dummy);
Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy,
face_id,&dummy,&dummy,&dummy);
/* Put the new face in the proper bucket of adjacencies */
next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
next_bucket = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,temp2,TRUE);
/* Create a new edgelist without the triangle that
was just outputted.
*/
Delete_From_ListEx(in_edge2,index,size);
/* Update the face data structure, by deleting the old
face and putting in the polygon minus the triangle
as the new face, here we will be decrementing the size
by one.
*/
New_Size_Face(face_id);
return;
}
/* Else the edge is not consecutive, and it is sufficiently
far away, for us not to make a conclusion at this time.
So we can take off a triangle and recursively call this
function.
*/
else
{
if (!reversed)
{
vertex4 = AdjacentEx(in_edge2,in_edge1,index,size);
Output_TriEx(in_edge1,in_edge2,vertex4,output,-1,-1,where);
/* Now delete the adjacencies by one for all the faces
that are adjacent to the triangle that we just outputted.
*/
Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
&dummy,&dummy,&dummy);
Delete_AdjEx(in_edge1,vertex4,&dummy,&dummy,
face_id,&dummy,&dummy,&dummy);
/* Put the new face in the proper bucket of adjacencies */
next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
next_bucket = Change_FaceEx(face_id,in_edge1,vertex4,pListHead,temp2,FALSE);
/* Create a new edgelist without the triangle that
was just outputted.
*/
Delete_From_ListEx(in_edge1,index,size);
/* Update the face data structure, by deleting the old
face and putting in the polygon minus the triangle
as the new face, here we will be decrementing the size
by one.
*/
New_Size_Face(face_id);
/* Save the info for the new bucket, we will need it on
the next pass for the variables, pListHead and temp
*/
pListHead = array[next_bucket];
pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
if ( pfNode )
pfNode->face_id = face_id;
temp2 = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
(int (*)(void *,void *)) (Compare)));
if (temp2 == NULL)
{
printf("There is an error finding the next polygon10 %d %d\n",next_bucket,face_id);
exit(0);
}
P_Triangulate_Polygon(out_edge1,out_edge2,in_edge2,
vertex4,size-1,index,output,fp,!reversed,
face_id,next_id,pListHead,temp2,where);
}
else
{
vertex4 = AdjacentEx(in_edge1,in_edge2,index,size);
Output_TriEx(in_edge2,in_edge1,vertex4,output,-1,-1,where);
/* Now delete the adjacencies by one for all the faces
that are adjacent to the triangle that we just outputted.
*/
Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
&dummy,&dummy,&dummy);
Delete_AdjEx(in_edge2,vertex4,&dummy,&dummy,
face_id,&dummy,&dummy,&dummy);
/* Put the new face in the proper bucket of adjacencies */
next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
next_bucket = Change_FaceEx(face_id,in_edge2,vertex4,pListHead,temp2,FALSE);
/* Create a new edgelist without the triangle that
was just outputted.
*/
Delete_From_ListEx(in_edge2,index,size);
/* Update the face data structure, by deleting the old
face and putting in the polygon minus the triangle
as the new face, here we will be decrementing the size
by one.
*/
New_Size_Face(face_id);
/* Save the info for the new bucket, we will need it on
the next pass for the variables, pListHead and temp
*/
pListHead = array[next_bucket];
pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
if ( pfNode )
pfNode->face_id = face_id;
temp2 = (P_ADJACENCIES) (SearchList(array[next_bucket], pfNode,
(int (*)(void *,void *)) (Compare)));
if (temp2 == NULL)
{
printf("There is an error finding the next polygon11 %d %d\n",face_id,next_bucket);
exit(0);
}
P_Triangulate_Polygon(out_edge1,out_edge2,vertex4,
in_edge1,size-1,index,output,fp,!reversed,
face_id,next_id,pListHead,temp2,where);
}
return;
}
}
void P_Triangulate(int out_edge1,int out_edge2,int in_edge1,
int in_edge2,int size,int *index,
FILE *fp,FILE *output,int reversed,int face_id,
int *next_id,ListHead *pListHead,
P_ADJACENCIES temp,int where)
{
if (size == 4)
P_Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size,
index,fp,output,reversed,face_id,next_id,pListHead, temp,where);
else
P_Triangulate_Polygon(out_edge1,out_edge2,in_edge1,in_edge2,size,
index,fp,output,reversed,face_id,next_id,pListHead,temp,where);
}
void Partial_Triangulate(int size,int *index, FILE *fp,
FILE *output,int next_face_id,int face_id,
int *next_id,ListHead *pListHead,
P_ADJACENCIES temp, int where)
{
int id1,id2,id3;
int nedge1,nedge2;
int reversed;
/* We have a polygon that has to be triangulated and we cannot
do it blindly, ie we will try to come out on the edge that
has the least number of adjacencies, But also we do not
want to triangulate the whole polygon now, so that means
we will output the least number of triangles that we can
and then update the data structures, with the polygon
that is left after we are done.
*/
Last_Edge(&id1,&id2,&id3,0);
/* Find the edge that is adjacent to the new face ,
also return whether the orientation is reversed in the
face of the input edge, which is id2 and id3.
*/
reversed = Get_EdgeEx(&nedge1,&nedge2,index,next_face_id,size,id2,id3);
/* Input edge and output edge can be the same if there are more than
one polygon on an edge
*/
if ( ((nedge1 == id2) && (nedge2 == id3)) ||
((nedge1 == id3) && (nedge2 == id2)) )
/* Set output edge arbitrarily but when come out of here the
next face will be on the old output edge (identical one)
*/
nedge2 = Return_Other(index,id2,id3);
/* Do the triangulation */
P_Triangulate(nedge1,nedge2,id2,id3,size,index,fp,output,reversed,
face_id,next_id,pListHead,temp,where);
}
void Input_Edge(int face_id, int *index, int size, int in_edge1, int in_edge2,
FILE *fp, FILE *output,ListHead *pListHead, P_ADJACENCIES temp2,
int where)
{
/* The polygon had an input edge, specified by input1 and input2 */
int output1;
int vertex4, vertex5,dummy=60;
output1 = Get_Output_Edge(face_id,size,index,in_edge1,in_edge2);
vertex5 = AdjacentEx(in_edge2,in_edge1,index,size);
vertex4 = AdjacentEx(in_edge1,in_edge2,index,size);
if (vertex4 == output1)
{
Output_TriEx(in_edge2,in_edge1,output1,output,-1,-1,where);
/* Now delete the adjacencies by one for all the faces
that are adjacent to the triangle that we just outputted.
*/
Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
&dummy,&dummy,&dummy);
Delete_AdjEx(in_edge2,output1,&dummy,&dummy,
face_id,&dummy,&dummy,&dummy);
/* Put the new face in the proper bucket of adjacencies */
Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
Change_FaceEx(face_id,in_edge2,output1,pListHead,temp2,FALSE);
/* Create a new edgelist without the triangle that
was just outputted.
*/
Delete_From_ListEx(in_edge2,index,size);
}
else if (vertex5 == output1)
{
Output_TriEx(in_edge1,in_edge2,vertex5,output,-1,-1,where);
/* Now delete the adjacencies by one for all the faces
that are adjacent to the triangle that we just outputted.
*/
Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id,
&dummy,&dummy,&dummy);
Delete_AdjEx(in_edge1,vertex5,&dummy,&dummy,
face_id,&dummy,&dummy,&dummy);
/* Put the new face in the proper bucket of adjacencies */
Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,temp2,FALSE);
Change_FaceEx(face_id,in_edge1,vertex5,pListHead,temp2,FALSE);
/* Create a new edgelist without the triangle that
was just outputted.
*/
Delete_From_ListEx(in_edge1,index,size);
}
/* Update the face data structure, by deleting the old
face and putting in the polygon minus the triangle
as the new face, here we will be decrementing the size
by one.
*/
New_Size_Face(face_id);
return;
}
void Inside_Polygon(int size,int *index,FILE *fp,FILE *output,
int next_face_id,int face_id,int *next_id,
ListHead *pListHead,P_ADJACENCIES temp, int where)
{
/* We know that we have a polygon that is greater than 4 sides, and
that it is better for us to go inside the polygon for the next
one, since inside will have less adjacencies than going outside.
So, we are not doing partial for a part of the polygon.
*/
int id1,id2,id3;
int new1,new2;
Last_Edge(&id1,&id2,&id3,0);
/* See if the input edge existed in the polygon, that will help us */
if (Exist(face_id,id2,id3))
Input_Edge(face_id,index,size,id2,id3,output,fp,pListHead,temp,where);
else
{
/* Make one of the input edges
We will choose it by trying to get an edge that has something
in common with the last triangle, or by getting the edge that
is adjacent to the least number of thigs, with preference given
to the first option
*/
Get_Input_Edge(index,id1,id2,id3,&new1,&new2,size,face_id);
Input_Edge(face_id,index,size,new1,new2,output,fp,pListHead,temp,where);
}
}

20
Stripe_w/partial.h Normal file
View file

@ -0,0 +1,20 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: partial.h
-----------------------------------------------------------------------*/
void Partial_Triangulate(int size,int *index, FILE *fp,
FILE *output,int next_face_id,int face_id,
int *next_id,ListHead *pListHead,
P_ADJACENCIES temp, int where);
void Inside_Polygon(int size,int *index,FILE *fp,FILE *output,
int next_face_id,int face_id,int *next_id,
ListHead *pListHead,P_ADJACENCIES temp, int where);

108
Stripe_w/polverts.h Normal file
View file

@ -0,0 +1,108 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: polverts.h
-----------------------------------------------------------------------*/
#ifndef _POLVERTS_H
#define _POLVERTS_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "queue.h"
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#else
# include <malloc.h>
#endif
typedef struct adjacencies
{
Node ListNode;
int face_id;
} ADJACENCIES,*P_ADJACENCIES;
typedef struct FVerts
{
Node ListNode;
int *pPolygon;
int nPolSize;
int nId;
} F_VERTS, *PF_VERTS;
/*Every time we need to use this, cast it ( ListInfo*)*/
typedef struct FEdges
{
Node ListNode;
int edge[3];
}F_EDGES,*PF_EDGES;
typedef struct FFaces
{
Node ListNode;
int *pPolygon;
int *pNorms;
int seen;
int seen2;
int seen3;
int nPolSize;
F_EDGES **VertandId;
int *marked;
int *walked;
} F_FACES,*PF_FACES;
typedef struct Strips
{
Node ListNode;
int face_id;
} Strips,*P_STRIPS;
struct vert_added
{
int num;
int *normal;
};
/* external functions */
void Find_Adjacencies(int num_faces);
void Test_Adj_Struct();
void Test_SGI_Struct();
void Write_Edges();
void Build_SGI_Table(int num_verts,int num_faces);
void Save_Walks(int numfaces);
void Find_Bands(int numfaces, FILE *output_file, int *swaps, int *bands,
int *cost, int *tri, int norms, int *vert_norms, int texture,
int *vert_texture);
void Save_Rest(int *numfaces);
void Assign_Walk(int lastvert, PF_FACES temp2, int front_walk,int y,
int back_walk);
void Save_Walks(int numfaces);
/* Globals */
extern ListHead **PolVerts;
extern ListHead **PolFaces;
extern ListHead **PolEdges;
extern ListHead *array[60];
extern int id_array[60];
extern ListHead *strips[1];
extern ListHead *all_strips[100000]; /* Assume max 100000 strips */
#endif _POLVERTS_H

34
Stripe_w/polyvertsex.h Normal file
View file

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

226
Stripe_w/queue.c Normal file
View file

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

283
Stripe_w/queue.h Normal file
View file

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

628
Stripe_w/sgi_triang.c Normal file
View file

@ -0,0 +1,628 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: sgi_triang.c
File contains the routines that do the whole triangulation
of polygons.
*/
/*---------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "global.h"
#include "output.h"
#include "polverts.h"
#include "sturcts.h"
#include "common.h"
#include "util.h"
#include "init.h"
int Adjacent(int id2,int id1, int *list, int size)
{
/* Return the vertex that is adjacent to id1,
but is not id2, in the list of integers.
*/
register int x=0;
while (x < size)
{
if (*(list+x) == id1)
{
if ((x != (size -1)) && (x != 0))
{
if ( *(list+x+1) != id2)
return *(list+x+1);
else
return *(list+x-1);
}
else if (x == (size -1))
{
if (*(list) != id2)
return *(list);
else
return *(list+x-1);
}
else
{
if (*(list+size-1) != id2)
return *(list+size-1);
else
return *(list+x+1);
}
}
x++;
}
/* if there are degeneracies */
return id1;
}
void Rearrange_Index(int *index, int size)
{
/* If we are in the middle of a strip we must find the
edge to start on, which is the last edge that we had
transmitted.
*/
int x,f,y,e1,e2,e3;
register int increment = 1;
int *temp;
/* Find where the input edge is in the input list */
Last_Edge(&e1,&e2,&e3,0);
for (y = 0; y < size; y++)
{
if (*(index+y) == e2)
{
if ((y != (size - 1)) && (*(index+y+1) == e3))
break;
else if ((y == (size - 1)) && (*(index) == e3))
break;
else if ((y != 0) && (*(index+y-1) == e3))
{
increment = -1;
break;
}
else if ((y==0) && (*(index+size-1) == e3))
{
increment = -1;
break;
}
}
if (*(index+y) == e3)
{
if ((y != (size - 1)) && (*(index+y+1) == e2))
break;
else if ((y == (size - 1)) && (*(index) == e2))
break;
else if ((y != 0) && (*(index+y-1) == e2))
{
increment = -1;
break;
}
else if ((y==0) && (*(index+size-1) == e2))
{
increment = -1;
break;
}
}
/* Edge is not here, we are at the beginning */
if ((y == (size-1)) && (increment != -1))
return;
}
/* Now put the list into a new list, starting with the
input edge. Increment tells us whether we have to go
forward or backward.
*/
/* Was in good position already */
if ((y == 0) && (increment == 1))
return;
temp = (int *) malloc(sizeof(int) * size);
memcpy(temp,index,sizeof(int)*size);
if (increment == 1)
{
x=0;
for (f = y ; f< size; f++)
{
*(index+x) = *(temp+f);
x++;
}
/* Finish the rest of the list */
for(f = 0; f < y ; f++)
{
*(index+x) = *(temp+f);
x++;
}
}
else
{
x=0;
for (f = y ; f >= 0; f--)
{
*(index+x) = *(temp+f);
x++;
}
/* Finish the rest of the list */
for(f = (size - 1); f > y ; f--)
{
*(index+x) = *(temp+f);
x++;
}
}
}
void Delete_From_List(int id,int *list, int *size)
{
/* Delete the occurence of id in the list.
(list has size size)
*/
int *temp;
register int x,y=0;
temp = (int *) malloc(sizeof(int) * (*size));
for (x=0; x<(*size); x++)
{
if (*(list+x) != id)
{
*(temp+y) = *(list+x);
y++;
}
}
*(temp+y) = -1;
*size = *size - (*size - y - 1);
memcpy(list,temp,sizeof(int)*(*size));
}
void Build_SGI_Table(int num_verts,int num_faces)
{
/* Build a table that has the polygons sorted by the
number of adjacent polygons.
*/
int x,y,size,tally=0;
ListHead *pListHead;
PF_FACES temp = NULL;
/* For each face....*/
for (x=0;x < num_faces;x++)
{
pListHead = PolFaces[x];
temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
/* Check each edge of the face and tally the number of adjacent
polygons to this face.
*/
if ( temp != NULL )
{
/* Size of the polygon */
size = temp->nPolSize;
if (size != 1)
{
for (y = 0; y< size; y++)
{
if (y != (size-1))
tally += Num_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1));
else
tally += Num_Adj(*(temp->pPolygon),*(temp->pPolygon+(size-1)));
}
/* Tally is the number of polygons that is adjacent to
the current polygon.
*/
/* Now put the face in the proper bucket depending on tally. */
Add_Sgi_Adj(tally,x);
temp = NULL;
tally=0;
}
}
}
}
void Triangulate_Quad(int out_edge1,int out_edge2,int in_edge1,
int in_edge2,int size,int *index,
FILE *output,int reversed,int face_id,
int where,int color1,int color2,int color3)
{
int vertex4,vertex5;
/* This routine will nonblindly triangulate a quad, meaning
that there is a definite input and a definite output
edge that we must adhere to. Reversed will tell the orientation
of the input edge. (Reversed is -1 is we do not have an input
edge, in other words we are at the beginning of a strip.)
Out_edge* is the output edge, and in_edge* is the input edge.
Index are the edges of the polygon
and size is the size of the polygon. Begin is whether we are
at the start of a new strip.
*/
/* If we do not have an input edge, then we can make our input
edge whatever we like, therefore it will be easier to come
out on the output edge.
*/
if (reversed == -1)
{
vertex4 = Adjacent(out_edge1,out_edge2,index,size);
vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index);
Output_Tri(vertex5,vertex4,out_edge1,output,color1,color2,color3,where);
Output_Tri(vertex4,out_edge1,out_edge2,output,color1,color2,color3,where);
return;
}
/* These are the 5 cases that we can have for the output edge */
/* Are they consecutive so that we form a triangle to
peel off, but cannot use the whole quad?
*/
if (in_edge2 == out_edge1)
{
/* Output the triangle that comes out the correct
edge last. First output the triangle that comes out
the wrong edge.
*/
vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index);
Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where);
Output_Tri(vertex4,in_edge2,out_edge2,output,color1,color2,color3,where);
return;
}
/* The next case is where it is impossible to come out the
edge that we want. So we will have to start a new strip to
come out on that edge. We will output the one triangle
that we can, and then start the new strip with the triangle
that comes out on the edge that we want to come out on.
*/
else if (in_edge1 == out_edge1)
{
/* We want to output the first triangle (whose output
edge is not the one that we want.
We have to find the vertex that we need, which is
the other vertex which we do not have.
*/
vertex4 = Get_Other_Vertex(in_edge2,in_edge1,out_edge2,index);
Output_Tri(in_edge2,in_edge1,vertex4,output,color1,color2,color3,where);
Output_Tri(vertex4,in_edge1,out_edge2,output,color1,color2,color3,where);
return;
}
/* Consecutive cases again, but with the output edge reversed */
else if (in_edge1 == out_edge2)
{
vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
Output_Tri(in_edge2,in_edge1,vertex4,output,color1,color2,color3,where);
Output_Tri(vertex4,in_edge1,out_edge1,output,color1,color2,color3,where);
return;
}
else if (in_edge2 == out_edge2)
{
vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where);
Output_Tri(vertex4,in_edge2,out_edge1,output,color1,color2,color3,where);
return;
}
/* The final case is where we want to come out the opposite
edge.
*/
else
{
if( ((!reversed) && (out_edge1 == (Adjacent(in_edge1,in_edge2,index,size)))) ||
((reversed) && (out_edge2 == (Adjacent(in_edge2,in_edge1,index,size)))))
{
/* We need to know the orientation of the input
edge, so we know which way to put the diagonal.
And also the output edge, so that we triangulate
correctly.
*/
Output_Tri(in_edge1,in_edge2,out_edge2,output,color1,color2,color3,where);
Output_Tri(in_edge2,out_edge2,out_edge1,output,color1,color2,color3,where);
}
else
{
/* Input and output orientation was reversed, so diagonal will
be reversed from above.
*/
Output_Tri(in_edge1,in_edge2,out_edge1,output,color1,color2,color3,where);
Output_Tri(in_edge2,out_edge1,out_edge2,output,color1,color2,color3,where);
}
return;
}
}
void Triangulate_Polygon(int out_edge1, int out_edge2, int in_edge1,
int in_edge2, int size, int *index,
FILE *output, int reversed, int face_id,
int where, int color1, int color2, int color3)
{
/* We have a polygon that we need to nonblindly triangulate.
We will recursively try to triangulate it, until we are left
with a polygon of size 4, which can use the quad routine
from above. We will be taking off a triangle at a time
and outputting it. We will have 3 cases similar to the
cases for the quad above. The inputs to this routine
are the same as for the quad routine.
*/
int vertex4;
int *temp;
/* Since we are calling this recursively, we have to check whether
we are down to the case of the quad.
*/
if (size == 4)
{
Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size,
index,output,reversed,face_id,where,color1,color2,color3);
return;
}
/* We do not have a specified input edge, and therefore we
can make it anything we like, as long as we still come out
the output edge that we want.
*/
if (reversed == -1)
{
/* Get the vertex for the last triangle, which is
the one coming out the output edge, before we do
any deletions to the list. We will be doing this
bottom up.
*/
vertex4 = Adjacent(out_edge1,out_edge2,index,size);
temp = (int *) malloc(sizeof(int) * size);
memcpy(temp,index,sizeof(int)*size);
Delete_From_List(out_edge2,index,&size);
Triangulate_Polygon(out_edge1,vertex4,in_edge2,
vertex4,size-1,index,output,reversed,face_id,where,color1,color2,color3);
memcpy(index,temp,sizeof(int)*size);
/* Lastly do the triangle that comes out the output
edge.
*/
Output_Tri(vertex4,out_edge1,out_edge2,output,color1,color2,color3,where);
return;
}
/* These are the 5 cases that we can have for the output edge */
/* Are they consecutive so that we form a triangle to
peel off that comes out the correct output edge,
but we cannot use the whole polygon?
*/
if (in_edge2 == out_edge1)
{
/* Output the triangle that comes out the correct
edge last. First recursively do the rest of the
polygon.
*/
/* Do the rest of the polygon without the triangle.
We will be doing a fan triangulation.
*/
/* Get the vertex adjacent to in_edge1, but is not
in_edge2.
*/
vertex4 = Adjacent(in_edge2,in_edge1,index,size);
Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where);
/* Create a new edgelist without the triangle that
was just outputted.
*/
temp = (int *) malloc(sizeof(int) * size);
memcpy(temp,index,sizeof(int)*size);
Delete_From_List(in_edge1,index,&size);
Triangulate_Polygon(out_edge1,out_edge2,in_edge2,
vertex4,size-1,index,output,!reversed,face_id,where,color1,color2,color3);
memcpy(index,temp,sizeof(int)*size);
return;
}
/* Next case is where it is again consecutive, but the triangle
formed by the consecutive edges do not come out of the
correct output edge. For this case, we can not do much to
keep it sequential. Try and do the fan.
*/
else if (in_edge1 == out_edge1)
{
/* Get vertex adjacent to in_edge2, but is not in_edge1 */
vertex4 = Adjacent(in_edge1,in_edge2,index,size);
Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where);
/* Since that triangle goes out of the polygon (the
output edge of it), we can make our new input edge
anything we like, so we will try to make it good for
the strip. (This will be like starting a new strip,
all so that we can go out the correct output edge.)
*/
temp = (int *) malloc(sizeof(int) * size);
memcpy(temp,index,sizeof(int)*size);
Delete_From_List(in_edge2,index,&size);
Triangulate_Polygon(out_edge1,out_edge2,in_edge1,
vertex4,size-1,index,output,reversed,face_id,where,color1,color2,color3);
memcpy(index,temp,sizeof(int)*size);
return;
}
/* Consecutive cases again, but with the output edge reversed */
else if (in_edge1 == out_edge2)
{
/* Get vertex adjacent to in_edge2, but is not in_edge1 */
vertex4 = Adjacent(in_edge1,in_edge2,index,size);
Output_Tri(in_edge2,in_edge1,vertex4,output,color1,color2,color3,where);
temp = (int *) malloc(sizeof(int) * size);
memcpy(temp,index,sizeof(int)*size);
Delete_From_List(in_edge2,index,&size);
Triangulate_Polygon(out_edge1,out_edge2,in_edge1,
vertex4,size-1,index,output,reversed,face_id,where,color1,color2,color3);
memcpy(index,temp,sizeof(int)*size);
return;
}
else if (in_edge2 == out_edge2)
{
/* Get vertex adjacent to in_edge2, but is not in_edge1 */
vertex4 = Adjacent(in_edge2,in_edge1,index,size);
Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where);
temp = (int *) malloc(sizeof(int) * size);
memcpy(temp,index,sizeof(int)*size);
Delete_From_List(in_edge1,index,&size);
Triangulate_Polygon(out_edge1,out_edge2,vertex4,
in_edge2,size-1,index,output,reversed,face_id,where,color1,color2,color3);
memcpy(index,temp,sizeof(int)*size);
return;
}
/* Else the edge is not consecutive, and it is sufficiently
far away, for us not to make a conclusion at this time.
So we can take off a triangle and recursively call this
function.
*/
else
{
vertex4 = Adjacent(in_edge2,in_edge1,index,size);
Output_Tri(in_edge1,in_edge2,vertex4,output,color1,color2,color3,where);
temp = (int *) malloc(sizeof(int) * size);
memcpy(temp,index,sizeof(int)*size);
Delete_From_List(in_edge1,index,&size);
Triangulate_Polygon(out_edge1,out_edge2,in_edge2,
vertex4,size-1,index,output,!reversed,face_id,where,color1,color2,color3);
memcpy(index,temp,sizeof(int)*size);
return;
}
}
void Triangulate(int out_edge1,int out_edge2,int in_edge1,
int in_edge2,int size,int *index,
FILE *output,int reversed,int face_id, int where,
int color1, int color2,int color3)
{
/* We have the info we need to triangulate a polygon */
if (size == 4)
Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size,
index,output,reversed,face_id,where,color1,color2,color3);
else
Triangulate_Polygon(out_edge1,out_edge2,in_edge1,in_edge2,size,
index,output,reversed,face_id,where,color1,color2,color3);
}
void Non_Blind_Triangulate(int size,int *index,
FILE *output,int next_face_id,int face_id,int where,
int color1,int color2,int color3)
{
int id1,id2,id3;
int nedge1,nedge2;
int reversed;
/* We have a polygon that has to be triangulated and we cannot
do it blindly, ie we will try to come out on the edge that
has the least number of adjacencies
*/
Last_Edge(&id1,&id2,&id3,0);
/* Find the edge that is adjacent to the new face ,
also return whether the orientation is reversed in the
face of the input edge, which is id2 and id3.
*/
if (next_face_id == -1)
{
printf("The face is -1 and the size is %d\n",size);
exit(0);
}
reversed = Get_Edge(&nedge1,&nedge2,index,next_face_id,size,id2,id3);
/* Do the triangulation */
/* If reversed is -1, the input edge is not in the polygon, therefore we can have the
input edge to be anything we like, since we are at the beginning
of a strip
*/
Triangulate(nedge1,nedge2,id2,id3,size,index,output,reversed,
face_id, where,color1,color2,color3);
}
void Blind_Triangulate(int size, int *index, FILE *output,
BOOL begin, int where ,int color1,int color2,
int color3)
{
/* save sides in temp array, we need it so we know
about swaps.
*/
int mode, decreasing,increasing,e1,e2,e3;
/* Rearrange the index list so that the input edge is first
*/
if (!begin)
Rearrange_Index(index,size);
/* We are given a polygon of more than 3 sides
and want to triangulate it. We will output the
triangles to the output file.
*/
/* Find where the input edge is in the input list */
Last_Edge(&e1,&e2,&e3,0);
if (( (!begin) && (*(index) == e2) ) || (begin))
{
Output_Tri(*(index+0),*(index+1),*(index+size-1),output,color1,color2,color3,where);
/* If we have a quad, (chances are yes), then we know that
we can just add one diagonal and be done. (divide the
quad into 2 triangles.
*/
if (size == 4)
{
Output_Tri(*(index+1),*(index+size-1),*(index+2),output,color1,color2,color3,where);
return;
}
increasing = 1;
mode = 1;
}
else if (!begin)
{
Output_Tri(*(index+1),*(index+0),*(index+size-1),output,color1,color2,color3,where);
if (size == 4)
{
Output_Tri(*(index+0),*(index+size-1),*(index+2),output,color1,color2,color3,where);
return;
}
Output_Tri(*(index+0),*(index+size-1),*(index+2),output,color1,color2,color3,where);
increasing = 2;
mode = 0;
}
if (size != 4)
{
/* We do not have a quad, we have something bigger. */
decreasing = size - 1;
do
{
/* Will be alternating diagonals, so we will be increasing
and decreasing around the polygon.
*/
if (mode)
{
Output_Tri(*(index+increasing),*(index+decreasing),*(index+increasing+1),output,color1,color2,color3,where);
increasing++;
}
else
{
Output_Tri(*(index+decreasing),*(index+increasing),*(index+decreasing-1),output,color1,color2,color3,where);
decreasing--;
}
mode = !mode;
} while ((decreasing - increasing) >= 2);
}
}

582
Stripe_w/sgi_triangex.c Normal file
View file

@ -0,0 +1,582 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: sgi_triangex.c
This file contains routines that are used for various functions in
the local algorithm.
*/
/*---------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "global.h"
#include "outputex.h"
#include "polverts.h"
#include "sturctsex.h"
#include "common.h"
#include "util.h"
int AdjacentEx(int id2,int id1, int *list, int size)
{
/* Return the vertex that is adjacent to id1,
but is not id2, in the list of integers.
*/
register int x=0;
while (x < size)
{
if (*(list+x) == id1)
{
if ((x != (size -1)) && (x != 0))
{
if ( *(list+x+1) != id2)
return *(list+x+1);
else
return *(list+x-1);
}
else if (x == (size -1))
{
if (*(list) != id2)
return *(list);
else
return *(list+x-1);
}
else
{
if (*(list+size-1) != id2)
return *(list+size-1);
else
return *(list+x+1);
}
}
x++;
}
printf("Error in the list\n");
exit(0);
}
void Delete_From_ListEx(int id,int *list, int size)
{
/* Delete the occurence of id in the list.
(list has size size)
*/
int *temp;
register int x,y=0;
temp = (int *) malloc(sizeof(int) * size);
for (x=0; x<size; x++)
{
if (*(list+x) != id)
{
*(temp+y) = *(list+x);
y++;
}
}
if(y != (size-1))
{
printf("There is an error in the delete\n");
exit(0);
}
*(temp+size-1) = -1;
memcpy(list,temp,sizeof(int)*size);
}
void Triangulate_QuadEx(int out_edge1,int out_edge2,int in_edge1,
int in_edge2,int size,int *index,
FILE *output,FILE *fp,int reversed,int face_id,
int where)
{
int vertex4,vertex5;
/* This routine will nonblindly triangulate a quad, meaning
that there is a definite input and a definite output
edge that we must adhere to. Reversed will tell the orientation
of the input edge. (Reversed is -1 is we do not have an input
edge, in other words we are at the beginning of a strip.)
Out_edge* is the output edge, and in_edge* is the input edge.
Index are the edges of the polygon
and size is the size of the polygon. Begin is whether we are
at the start of a new strip.
*/
/* If we do not have an input edge, then we can make our input
edge whatever we like, therefore it will be easier to come
out on the output edge.
*/
if (reversed == -1)
{
vertex4 = AdjacentEx(out_edge1,out_edge2,index,size);
vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index);
Output_TriEx(vertex5,vertex4,out_edge1,output,-1,-1,where);
Output_TriEx(vertex4,out_edge1,out_edge2,output,-1,-1,where);
return;
}
/* These are the 5 cases that we can have for the output edge */
/* Are they consecutive so that we form a triangle to
peel off, but cannot use the whole quad?
*/
if (in_edge2 == out_edge1)
{
/* Output the triangle that comes out the correct
edge last. First output the triangle that comes out
the wrong edge.
*/
vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index);
Output_TriEx(in_edge1,in_edge2,vertex4,output,-1,-1,where);
Output_TriEx(vertex4,in_edge2,out_edge2,output,-1,-1,where);
return;
}
/* The next case is where it is impossible to come out the
edge that we want. So we will have to start a new strip to
come out on that edge. We will output the one triangle
that we can, and then start the new strip with the triangle
that comes out on the edge that we want to come out on.
*/
else if (in_edge1 == out_edge1)
{
/* We want to output the first triangle (whose output
edge is not the one that we want.
We have to find the vertex that we need, which is
the other vertex which we do not have.
*/
vertex4 = Get_Other_Vertex(in_edge2,in_edge1,out_edge2,index);
Output_TriEx(in_edge2,in_edge1,vertex4,output,-1,-1,where);
Output_TriEx(vertex4,in_edge1,out_edge2,output,-1,-1,where);
return;
}
/* Consecutive cases again, but with the output edge reversed */
else if (in_edge1 == out_edge2)
{
vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
Output_TriEx(in_edge2,in_edge1,vertex4,output,-1,-1,where);
Output_TriEx(vertex4,in_edge1,out_edge1,output,-1,-1,where);
return;
}
else if (in_edge2 == out_edge2)
{
vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index);
Output_TriEx(in_edge1,in_edge2,vertex4,output,-1,-1,where);
Output_TriEx(vertex4,in_edge2,out_edge1,output,-1,-1,where);
return;
}
/* The final case is where we want to come out the opposite edge.*/
else
{
if( ((!reversed) && (out_edge1 == (AdjacentEx(in_edge1,in_edge2,index,size)))) ||
((reversed) && (out_edge2 == (AdjacentEx(in_edge2,in_edge1,index,size)))))
{
/* We need to know the orientation of the input
edge, so we know which way to put the diagonal.
And also the output edge, so that we triangulate correctly.
*/
Output_TriEx(in_edge1,in_edge2,out_edge2,output,-1,-1,where);
Output_TriEx(in_edge2,out_edge2,out_edge1,output,-1,-1,where);
}
else
{
/* Input and output orientation was reversed, so diagonal will
be reversed from above.
*/
Output_TriEx(in_edge1,in_edge2,out_edge1,output,-1,-1,where);
Output_TriEx(in_edge2,out_edge1,out_edge2,output,-1,-1,where);
}
return;
}
}
void Triangulate_PolygonEx(int out_edge1,int out_edge2,int in_edge1,
int in_edge2,int size,int *index,
FILE *output,FILE *fp,int reversed,int face_id,
int where)
{
/* We have a polygon that we need to nonblindly triangulate.
We will recursively try to triangulate it, until we are left
with a polygon of size 4, which can use the quad routine
from above. We will be taking off a triangle at a time
and outputting it. We will have 3 cases similar to the
cases for the quad above. The inputs to this routine
are the same as for the quad routine.
*/
int vertex4;
int *temp;
/* Since we are calling this recursively, we have to check whether
we are down to the case of the quad.
*/
if (size == 4)
{
Triangulate_QuadEx(out_edge1,out_edge2,in_edge1,in_edge2,size,
index,output,fp,reversed,face_id,where);
return;
}
/* We do not have a specified input edge, and therefore we
can make it anything we like, as long as we still come out
the output edge that we want.
*/
if (reversed == -1)
{
/* Get the vertex for the last triangle, which is
the one coming out the output edge, before we do
any deletions to the list. We will be doing this
bottom up.
*/
vertex4 = AdjacentEx(out_edge1,out_edge2,index,size);
temp = (int *) malloc(sizeof(int) * size);
memcpy(temp,index,sizeof(int)*size);
Delete_From_ListEx(out_edge2,index,size);
Triangulate_PolygonEx(out_edge1,vertex4,in_edge2,
vertex4,size-1,index,output,fp,reversed,face_id,where);
memcpy(index,temp,sizeof(int)*size);
/* Lastly do the triangle that comes out the output
edge.
*/
Output_TriEx(vertex4,out_edge1,out_edge2,output,-1,-1,where);
return;
}
/* These are the 5 cases that we can have for the output edge */
/* Are they consecutive so that we form a triangle to
peel off that comes out the correct output edge,
but we cannot use the whole polygon?
*/
if (in_edge2 == out_edge1)
{
/* Output the triangle that comes out the correct
edge last. First recursively do the rest of the
polygon.
*/
/* Do the rest of the polygon without the triangle.
We will be doing a fan triangulation.
*/
/* Get the vertex adjacent to in_edge1, but is not
in_edge2.
*/
vertex4 = AdjacentEx(in_edge2,in_edge1,index,size);
Output_TriEx(in_edge1,in_edge2,vertex4,output,-1,-1,where);
/* Create a new edgelist without the triangle that
was just outputted.
*/
temp = (int *) malloc(sizeof(int) * size);
memcpy(temp,index,sizeof(int)*size);
Delete_From_ListEx(in_edge1,index,size);
Triangulate_PolygonEx(out_edge1,out_edge2,in_edge2,
vertex4,size-1,index,output,fp,!reversed,face_id,where);
memcpy(index,temp,sizeof(int)*size);
return;
}
/* Next case is where it is again consecutive, but the triangle
formed by the consecutive edges do not come out of the
correct output edge. For this case, we can not do much to
keep it sequential. Try and do the fan.
*/
else if (in_edge1 == out_edge1)
{
/* Get vertex adjacent to in_edge2, but is not in_edge1 */
vertex4 = AdjacentEx(in_edge1,in_edge2,index,size);
Output_TriEx(in_edge1,in_edge2,vertex4,fp,-1,-1,where);
/* Since that triangle goes out of the polygon (the
output edge of it), we can make our new input edge
anything we like, so we will try to make it good for
the strip. (This will be like starting a new strip,
all so that we can go out the correct output edge.)
*/
temp = (int *) malloc(sizeof(int) * size);
memcpy(temp,index,sizeof(int)*size);
Delete_From_ListEx(in_edge2,index,size);
Triangulate_PolygonEx(out_edge1,out_edge2,in_edge1,
vertex4,size-1,index,output,fp,reversed,face_id,where);
memcpy(index,temp,sizeof(int)*size);
return;
}
/* Consecutive cases again, but with the output edge reversed */
else if (in_edge1 == out_edge2)
{
/* Get vertex adjacent to in_edge2, but is not in_edge1 */
vertex4 = AdjacentEx(in_edge1,in_edge2,index,size);
Output_TriEx(in_edge2,in_edge1,vertex4,fp,-1,-1,where);
temp = (int *) malloc(sizeof(int) * size);
memcpy(temp,index,sizeof(int)*size);
Delete_From_ListEx(in_edge2,index,size);
Triangulate_PolygonEx(out_edge1,out_edge2,in_edge1,
vertex4,size-1,index,output,fp,reversed,face_id,where);
memcpy(index,temp,sizeof(int)*size);
return;
}
else if (in_edge2 == out_edge2)
{
/* Get vertex adjacent to in_edge2, but is not in_edge1 */
vertex4 = AdjacentEx(in_edge2,in_edge1,index,size);
Output_TriEx(in_edge1,in_edge2,vertex4,fp,-1,-1,where);
temp = (int *) malloc(sizeof(int) * size);
memcpy(temp,index,sizeof(int)*size);
Delete_From_ListEx(in_edge1,index,size);
Triangulate_PolygonEx(out_edge1,out_edge2,vertex4,
in_edge2,size-1,index,output,fp,reversed,face_id,where);
memcpy(index,temp,sizeof(int)*size);
return;
}
/* Else the edge is not consecutive, and it is sufficiently
far away, for us not to make a conclusion at this time.
So we can take off a triangle and recursively call this
function.
*/
else
{
vertex4 = AdjacentEx(in_edge2,in_edge1,index,size);
Output_TriEx(in_edge1,in_edge2,vertex4,fp,-1,-1,where);
temp = (int *) malloc(sizeof(int) * size);
memcpy(temp,index,sizeof(int)*size);
Delete_From_ListEx(in_edge1,index,size);
Triangulate_PolygonEx(out_edge1,out_edge2,in_edge2,
vertex4,size-1,index,output,fp,!reversed,face_id,where);
memcpy(index,temp,sizeof(int)*size);
return;
}
}
void TriangulateEx(int out_edge1,int out_edge2,int in_edge1,
int in_edge2,int size,int *index,
FILE *fp,FILE *output,int reversed,int face_id, int where)
{
/* We have the info we need to triangulate a polygon */
if (size == 4)
Triangulate_QuadEx(out_edge1,out_edge2,in_edge1,in_edge2,size,
index,fp,output,reversed,face_id,where);
else
Triangulate_PolygonEx(out_edge1,out_edge2,in_edge1,in_edge2,size,
index,fp,output,reversed,face_id,where);
}
void Non_Blind_TriangulateEx(int size,int *index, FILE *fp,
FILE *output,int next_face_id,int face_id,int where)
{
int id1,id2,id3;
int nedge1,nedge2;
int reversed;
/* We have a polygon that has to be triangulated and we cannot
do it blindly, ie we will try to come out on the edge that
has the least number of adjacencies
*/
Last_Edge(&id1,&id2,&id3,0);
/* Find the edge that is adjacent to the new face ,
also return whether the orientation is reversed in the
face of the input edge, which is id2 and id3.
*/
if (next_face_id == -1)
{
printf("The face is -1 and the size is %d\n",size);
exit(0);
}
reversed = Get_EdgeEx(&nedge1,&nedge2,index,next_face_id,size,id2,id3);
/* Do the triangulation */
/* If reversed is -1, the input edge is not in the polygon, therefore we can have the
input edge to be anything we like, since we are at the beginning
of a strip
*/
TriangulateEx(nedge1,nedge2,id2,id3,size,index,fp,output,reversed,
face_id, where);
}
void Rearrange_IndexEx(int *index, int size)
{
/* If we are in the middle of a strip we must find the
edge to start on, which is the last edge that we had
transmitted.
*/
int x,f,y,e1,e2,e3;
int increment = 1;
int *temp;
/* Find where the input edge is in the input list */
Last_Edge(&e1,&e2,&e3,0);
for (y = 0; y < size; y++)
{
if (*(index+y) == e2)
{
if ((y != (size - 1)) && (*(index+y+1) == e3))
break;
else if ((y == (size - 1)) && (*(index) == e3))
break;
else if ((y != 0) && (*(index+y-1) == e3))
{
increment = -1;
break;
}
else if ((y==0) && (*(index+size-1) == e3))
{
increment = -1;
break;
}
}
if (*(index+y) == e3)
{
if ((y != (size - 1)) && (*(index+y+1) == e2))
break;
else if ((y == (size - 1)) && (*(index) == e2))
break;
else if ((y != 0) && (*(index+y-1) == e2))
{
increment = -1;
break;
}
else if ((y==0) && (*(index+size-1) == e2))
{
increment = -1;
break;
}
}
/* Edge is not here, we are at the beginning */
if ((y == (size-1)) && (increment != -1))
return;
}
/* Now put the list into a new list, starting with the
input edge. Increment tells us whether we have to go
forward or backward.
*/
/* Was in good position already */
if ((y == 0) && (increment == 1))
return;
temp = (int *) malloc(sizeof(int) * size);
memcpy(temp,index,sizeof(int)*size);
if (increment == 1)
{
x=0;
for (f = y ; f< size; f++)
{
*(index+x) = *(temp+f);
x++;
}
/* Finish the rest of the list */
for(f = 0; f < y ; f++)
{
*(index+x) = *(temp+f);
x++;
}
}
else
{
x=0;
for (f = y ; f >= 0; f--)
{
*(index+x) = *(temp+f);
x++;
}
/* Finish the rest of the list */
for(f = (size - 1); f > y ; f--)
{
*(index+x) = *(temp+f);
x++;
}
}
}
void Blind_TriangulateEx(int size, int *index, FILE *fp,
FILE *output, BOOL begin, int where )
{
/* save sides in temp array, we need it so we know
about swaps.
*/
int mode, decreasing,increasing,e1,e2,e3;
/* Rearrange the index list so that the input edge is first
*/
if (!begin)
Rearrange_IndexEx(index,size);
/* We are given a polygon of more than 3 sides
and want to triangulate it. We will output the
triangles to the output file.
*/
/* Find where the input edge is in the input list */
Last_Edge(&e1,&e2,&e3,0);
if (( (!begin) && (*(index) == e2) ) || (begin))
{
Output_TriEx(*(index+0),*(index+1),*(index+size-1),fp,-1,-1,where);
/* If we have a quad, (chances are yes), then we know that
we can just add one diagonal and be done. (divide the
quad into 2 triangles.
*/
if (size == 4)
{
Output_TriEx(*(index+1),*(index+size-1),*(index+2),fp,-1,-1,where);
return;
}
increasing = 1;
mode = 1;
}
else if (!begin)
{
Output_TriEx(*(index+1),*(index+0),*(index+size-1),fp,-1,-1,where);
if (size == 4)
{
Output_TriEx(*(index+0),*(index+size-1),*(index+2),fp,-1,-1,where);
return;
}
Output_TriEx(*(index+0),*(index+size-1),*(index+2),fp,-1,-1,where);
increasing = 2;
mode = 0;
}
if (size != 4)
{
/* We do not have a quad, we have something bigger. */
decreasing = size - 1;
do
{
/* Will be alternating diagonals, so we will be increasing
and decreasing around the polygon.
*/
if (mode)
{
Output_TriEx(*(index+increasing),*(index+decreasing),*(index+increasing+1),fp,-1,-1,where);
increasing++;
}
else
{
Output_TriEx(*(index+decreasing),*(index+increasing),*(index+decreasing-1),fp,-1,-1,where);
decreasing--;
}
mode = !mode;
} while ((decreasing - increasing) >= 2);
}
}

549
Stripe_w/struct.c Normal file
View file

@ -0,0 +1,549 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: struct.c
Contains routines that update structures, and micellaneous routines.
*/
/*---------------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#include "polverts.h"
#include "ties.h"
#include "output.h"
#include "triangulate.h"
#include "sturcts.h"
#include "options.h"
#include "common.h"
#include "util.h"
int out1 = -1;
int out2 = -1;
int Get_Edge(int *edge1,int *edge2,int *index,int face_id,
int size, int id1, int id2)
{
/* Put the edge that is adjacent to face_id into edge1
and edge2. For each edge see if it is adjacent to
face_id. Id1 and id2 is the input edge, so see if
the orientation is reversed, and save it in reversed.
*/
register int x;
int reversed = -1;
BOOL set = FALSE;
for (x=0; x< size; x++)
{
if (x == (size-1))
{
if ((*(index) == id1) && (*(index+size-1)==id2))
{
if (set)
return 1;
reversed = 1;
}
else if ((*(index) == id2) && (*(index+size-1)==id1))
{
if (set)
return 0;
reversed = 0;
}
if (Look_Up(*(index),*(index+size-1),face_id))
{
if ( (out1 != -1) && ( (out1 == *(index)) || (out1 == *(index+size-1)) ) &&
( (out2 == *(index)) || (out2 == *(index+size-1)) ))
{
set = TRUE;
*edge1 = *(index);
*edge2 = *(index+size-1);
}
else if (out1 == -1)
{
set = TRUE;
*edge1 = *(index);
*edge2 = *(index+size-1);
}
if ((reversed != -1) && (set))
return reversed;
}
}
else
{
if ((*(index+x) == id1) && (*(index+x+1)==id2))
{
if (set)
return 0;
reversed = 0;
}
else if ((*(index+x) == id2) && (*(index+x+1)==id1))
{
if (set)
return 1;
reversed = 1;
}
if (Look_Up(*(index+x),*(index+x+1),face_id))
{
if ( (out1 != -1) && ( (out1 == *(index+x)) || (out1 == *(index+x+1)) ) &&
((out2 == *(index+x)) || (out2 == *(index+x+1))))
{
set = TRUE;
*edge1 = *(index+x);
*edge2 = *(index+x+1);
}
else if (out1 == -1)
{
set = TRUE;
*edge1 = *(index+x);
*edge2 = *(index+x + 1);
}
if ((reversed != -1) && (set))
return reversed;
}
}
}
if ((x == size) && (reversed != -1))
{
/* Could not find the output edge */
printf("Error in the Lookup %d %d %d %d %d %d %d %d\n",face_id,id1,id2,reversed,*edge1,*edge2,out1,out2);
exit(0);
}
return reversed;
}
void Update_Face(int *next_bucket, int *min_face, int face_id, int *e1,
int *e2,int temp1,int temp2,int *ties)
{
/* We have a face id that needs to be decremented.
We have to determine where it is in the structure,
so that we can decrement it.
*/
/* The number of adjacencies may have changed, so to locate
it may be a little tricky. However we know that the number
of adjacencies is less than or equal to the original number
of adjacencies,
*/
int y,size;
ListHead *pListHead;
PF_FACES temp = NULL;
PLISTINFO lpListInfo;
static int each_poly = 0;
BOOL there = FALSE;
pListHead = PolFaces[face_id];
temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
/* Check each edge of the face and tally the number of adjacent
polygons to this face.
*/
if ( temp != NULL )
{
/* Size of the polygon */
size = temp->nPolSize;
/* We did it already */
if (size == 1)
return;
for (y = 0; y< size; y++)
{
/* If we are doing partial triangulation, we must check
to see whether the edge is still there in the polygon,
since we might have done a portion of the polygon
and saved the rest for later.
*/
if (y != (size-1))
{
if( ((temp1 == *(temp->pPolygon+y)) && (temp2 ==*(temp->pPolygon+y+1)))
|| ((temp2 == *(temp->pPolygon+y)) && (temp1 ==*(temp->pPolygon+y+1))))
/* edge is still there we are ok */
there = TRUE;
}
else
{
if( ((temp1 == *(temp->pPolygon)) && (temp2 == *(temp->pPolygon+size-1)))
|| ((temp2 == *(temp->pPolygon)) && (temp1 ==*(temp->pPolygon+size-1))))
/* edge is still there we are ok */
there = TRUE;
}
}
if (!there)
/* Original edge was already used, we cannot use this polygon */
return;
/* We have a starting point to start our search to locate
this polygon.
*/
/* Check to see if this polygon was done */
lpListInfo = Done(face_id,59,&y);
if (lpListInfo == NULL)
return;
/* Was not done, but there is an error in the adjacency calculations */
if (y == 0)
{
printf("There is an error in finding the adjacencies\n");
exit(0);
}
/* Now put the face in the proper bucket depending on tally. */
/* First add it to the new bucket, then remove it from the old */
Add_Sgi_Adj(y-1,face_id);
RemoveList(array[y],lpListInfo);
/* Save it if it was the smallest seen so far since then
it will be the next face
Here we will have different options depending on
what we want for resolving ties:
1) First one we see we will use
2) Random resolving
3) Look ahead
4) Alternating direction
*/
/* At a new strip */
if (*next_bucket == 60)
*ties = *ties + each_poly;
/* Have a tie */
if (*next_bucket == (y-1))
{
Add_Ties(face_id);
each_poly++;
}
/* At a new minimum */
if (*next_bucket > (y-1))
{
*next_bucket = y-1;
*min_face = face_id;
*e1 = temp1;
*e2 = temp2;
each_poly = 0;
Clear_Ties();
Add_Ties(face_id);
}
}
}
void Delete_Adj(int id1, int id2,int *next_bucket,int *min_face,
int current_face,int *e1,int *e2,int *ties)
{
/* Find the face that is adjacent to the edge and is not the
current face. Delete one adjacency from it. Save the min
adjacency seen so far.
*/
register int count=0;
PF_EDGES temp = NULL;
ListHead *pListHead;
int next_face;
/* Always want smaller id first */
switch_lower(&id1,&id2);
pListHead = PolEdges[id1];
temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
if (temp == NULL)
/* It could be a new edge that we created. So we can
exit, since there is not a face adjacent to it.
*/
return;
while (temp->edge[0] != id2)
{
count++;
temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
if (temp == NULL)
/* Was a new edge that was created and therefore
does not have anything adjacent to it
*/
return;
}
/* Was not adjacent to anything else except itself */
if (temp->edge[2] == -1)
return;
/* Was adjacent to something */
else
{
if (temp->edge[2] == current_face)
next_face = temp->edge[1];
else
next_face = temp->edge[2];
}
/* We have the other face adjacent to this edge, it is
next_face. Now we need to decrement this faces' adjacencies.
*/
Update_Face(next_bucket, min_face, next_face,e1,e2,id1,id2,ties);
}
int Change_Face(int face_id,int in1,int in2,
ListHead *pListHead, P_ADJACENCIES temp, BOOL no_check)
{
/* We are doing a partial triangulation and we need to
put the new face of triangle into the correct bucket
*/
int input_adj,y;
/* Find the old number of adjacencies to this face,
so we know where to delete it from
*/
y = Old_Adj(face_id);
/* Do we need to change the adjacency? Maybe the edge on the triangle
that was outputted was not adjacent to anything. We know if we
have to check by "check". We came out on the output edge
that we needed, then we know that the adjacencies will decrease
by exactly one.
*/
if (!no_check)
{
input_adj = Number_Adj(in1,in2,face_id);
/* If there weren't any then don't do anything */
if (input_adj == 0)
return y;
}
RemoveList(pListHead,(PLISTINFO)temp);
/* Before we had a quad with y adjacencies. The in edge
did not have an adjacency, since it was just deleted,
since we came in on it. The outedge must have an adjacency
otherwise we would have a bucket 0, and would not be in this
routine. Therefore the new adjacency must be y-1
*/
Add_Sgi_Adj(y-1,face_id);
return (y-1);
}
int Update_Adjacencies(int face_id, int *next_bucket, int *e1, int *e2,
int *ties)
{
/* Give the face with id face_id, we want to decrement
all the faces that are adjacent to it, since we will
be deleting face_id from the data structure.
We will return the face that has the least number
of adjacencies.
*/
PF_FACES temp = NULL;
ListHead *pListHead;
int size,y,min_face = -1;
*next_bucket = 60;
pListHead = PolFaces[face_id];
temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
if ( temp == NULL )
{
printf("The face was already deleted, there is an error\n");
exit(0);
}
/* Size of the polygon */
size = temp->nPolSize;
for (y = 0; y< size; y++)
{
if (y != (size-1))
Delete_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),
next_bucket,&min_face,face_id,e1,e2,ties);
else
Delete_Adj(*(temp->pPolygon),*(temp->pPolygon+(size-1)),
next_bucket,&min_face,face_id,e1,e2,ties);
}
return (min_face);
}
void Find_Adj_Tally(int id1, int id2,int *next_bucket,int *min_face,
int current_face,int *ties)
{
/* Find the face that is adjacent to the edge and is not the
current face. Save the min adjacency seen so far.
*/
int size,each_poly=0,y,count=0;
PF_EDGES temp = NULL;
PF_FACES temp2 = NULL;
ListHead *pListHead;
int next_face;
BOOL there = FALSE;
/* Always want smaller id first */
switch_lower(&id1,&id2);
pListHead = PolEdges[id1];
temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
if (temp == NULL)
/* This was a new edge that was created, so it is
adjacent to nothing.
*/
return;
while (temp->edge[0] != id2)
{
count++;
temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count);
if (temp == NULL)
/* This was a new edge that we created */
return;
}
/* Was not adjacent to anything else except itself */
if (temp->edge[2] == -1)
return;
else
{
if (temp->edge[2] == current_face)
next_face = temp->edge[1];
else
next_face = temp->edge[2];
}
/* We have the other face adjacent to this edge, it is
next_face. Find how many faces it is adjacent to.
*/
pListHead = PolFaces[next_face];
temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
/* Check each edge of the face and tally the number of adjacent
polygons to this face. This will be the original number of
polygons adjacent to this polygon, we must then see if this
number has been decremented
*/
if ( temp2 != NULL )
{
/* Size of the polygon */
size = temp2->nPolSize;
/* We did it already */
if (size == 1)
return;
for (y = 0; y< size; y++)
{
/* Make sure that the edge is still in the
polygon and was not deleted, because if the edge was
deleted, then we used it already.
*/
if (y != (size-1))
{
if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1)))
|| ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1))))
/* edge is still there we are ok */
there = TRUE;
}
else
{
if( ((id1 == *(temp2->pPolygon)) && (id2 ==*(temp2->pPolygon+size-1)))
|| ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1))))
/* edge is still there we are ok */
there = TRUE;
}
}
if (!there)
/* Edge already used and deleted from the polygon*/
return;
/* See if the face was already deleted, and where
it is if it was not
*/
if (Done(next_face,size,&y) == NULL)
return;
/* Save it if it was the smallest seen so far since then
it will be the next face
Here we will have different options depending on
what we want for resolving ties:
1) First one we see we will use
2) Random resolving
3) Look ahead
4) Alternating direction
*/
/* At a new strip */
if (*next_bucket == 60)
*ties = *ties + each_poly;
/* Have a tie */
if (*next_bucket == (y-1))
{
Add_Ties(next_face);
each_poly++;
}
/* At a new minimum */
if (*next_bucket > (y-1))
{
*next_bucket = y-1;
*min_face = next_face;
each_poly = 0;
Clear_Ties();
Add_Ties(next_face);
}
}
}
int Min_Face_Adj(int face_id, int *next_bucket, int *ties)
{
/* Used for the Partial triangulation to find the next
face. It will return the minimum adjacency face id
found at this face.
*/
PF_FACES temp = NULL;
ListHead *pListHead;
int size,y,min_face,test_face;
*next_bucket = 60;
pListHead = PolFaces[face_id];
temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
if ( temp == NULL )
{
printf("The face was already deleted, there is an error\n");
exit(0);
}
/* Size of the polygon */
size = temp->nPolSize;
for (y = 0; y< size; y++)
{
if (y != (size-1))
Find_Adj_Tally(*(temp->pPolygon+y),*(temp->pPolygon+y+1),
next_bucket,&min_face,face_id,ties);
else
Find_Adj_Tally(*(temp->pPolygon),*(temp->pPolygon+(size-1)),
next_bucket,&min_face,face_id,ties);
}
/* Maybe we can do better by triangulating the face, because
by triangulating the face we will go to a polygon of lesser
adjacencies
*/
if (size == 4)
{
/* Checking for a quad whether to do the whole polygon will
result in better performance because the triangles in the polygon
have less adjacencies
*/
Check_In_Quad(face_id,&test_face);
if (*next_bucket > test_face)
/* We can do better by going through the polygon */
min_face = face_id;
}
/* We have a polygon with greater than 4 sides, check to see if going
inside is better than going outside the polygon for the output edge.
*/
else
{
Check_In_Polygon(face_id,&test_face,size);
if (*next_bucket > test_face)
/* We can do better by going through the polygon */
min_face = face_id;
}
return (min_face);
}

553
Stripe_w/structex.c Normal file
View file

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

36
Stripe_w/sturcts.h Normal file
View file

@ -0,0 +1,36 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: sturcts.h
-----------------------------------------------------------------------*/
#define EVEN(x) (((x) & 1) == 0)
int Get_Edge(int *edge1,int *edge2,int *index,int face_id,
int size, int id1, int id2);
void add_vert_id();
void Update_Face(int *next_bucket, int *min_face, int face_id, int *e1,
int *e2,int temp1,int temp2,int *ties);
int Min_Adj();
int Min_Face_Adj(int face_id, int *next_bucket, int *ties);
int Change_Face(int face_id,int in1,int in2, ListHead *pListHead,
P_ADJACENCIES temp, BOOL no_check);
void Delete_Adj(int id1, int id2,int *next_bucket,int *min_face,
int current_face,int *e1,int *e2,int *ties);
int Update_Adjacencies(int face_id, int *next_bucket, int *e1, int *e2,
int *ties);
int Get_Output_Edge();
int Find_Face();

33
Stripe_w/sturctsex.h Normal file
View file

@ -0,0 +1,33 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE:sturctsex.h
-----------------------------------------------------------------------*/
#define EVEN(x) (((x) & 1) == 0)
int Get_EdgeEx(int *edge1,int *edge2,int *index,int face_id,
int size, int id1, int id2);
void add_vert_idEx();
void Update_FaceEx(int *next_bucket, int *min_face, int face_id, int *e1,
int *e2,int temp1,int temp2,int *ties);
int Min_Face_AdjEx(int face_id, int *next_bucket, int *ties);
int Change_FaceEx(int face_id,int in1,int in2,
ListHead *pListHead, P_ADJACENCIES temp, BOOL no_check);
void Delete_AdjEx(int id1, int id2,int *next_bucket,int *min_face,
int current_face,int *e1,int *e2,int *ties);
int Number_AdjEx();
int Update_AdjacenciesEx(int face_id, int *next_bucket, int *e1, int *e2,
int *ties);

304
Stripe_w/ties.c Normal file
View file

@ -0,0 +1,304 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: ties.c
This file will contain all the routines used to determine the next face if there
is a tie
*/
/*---------------------------------------------------------------------*/
#include <stdlib.h>
#include "polverts.h"
#include "ties.h"
#include "sturctsex.h"
#include "triangulatex.h"
#include "options.h"
#include "common.h"
#include "util.h"
#define MAX_TIE 60
int ties_array[60];
int last = 0;
void Clear_Ties()
{
/* Clear the buffer, because we do not have the tie
any more that we had before */
last = 0;
}
void Add_Ties(int id)
{
/* We have a tie to add to the buffer */
ties_array[last++] = id;
}
int Alternate_Tie()
{
/* Alternate in what we choose to break the tie
We are just alternating between the first and
second thing that we found
*/
static int x = 0;
register int t;
t = ties_array[x];
x++;
if (x == 2)
x = 0;
return t;
}
int Random_Tie()
{
/* Randomly choose the next face with which
to break the tie
*/
register int num;
num = rand();
while (num >= last)
num = num/20;
return (ties_array[num]);
}
int Look_Ahead(int id)
{
/* Look ahead at this face and save the minimum
adjacency of all the faces that are adjacent to
this face.
*/
return Min_Adj(id);
}
int Random_Look(int id[],int count)
{
/* We had a tie within a tie in the lookahead,
break it randomly
*/
register int num;
num = rand();
while (num >= count)
num = num/20;
return (id[num]);
}
int Look_Ahead_Tie()
{
/* Look ahead and find the face to go to that
will give the least number of adjacencies
*/
int id[60],t,x,f=0,min = 60;
for (x = 0; x < last; x++)
{
t = Look_Ahead(ties_array[x]);
/* We have a tie */
if (t == min)
id[f++] = ties_array[x];
if (t < min)
{
f = 0;
min = t;
id[f++] = ties_array[x];
}
}
/* No tie within the tie */
if ( f == 1)
return id[0];
/* Or ties, but we are at the end of strips */
if (min == 0)
return id[0];
return (Random_Look(id,f));
}
int Sequential_Tri(int *index)
{
/* We have a triangle and need to break the ties at it.
We will choose the edge that is sequential. There
is definitely one since we know we have a triangle
and that there is a tie and there are only 2 edges
for the tie.
*/
int e1,e2,e3,output1,output2,output3,output4;
/* e2 and e3 are the input edge to the triangle */
Last_Edge(&e1,&e2,&e3,0);
if ((e2 == 0) && (e3 == 0))
/* Starting the strip, don't need to do this */
return ties_array[0];
/* For the 2 ties find the edge adjacent to face id */
Get_EdgeEx(&output1,&output2,index,ties_array[0],3,0,0);
Get_EdgeEx(&output3,&output4,index,ties_array[1],3,0,0);
if ((output1 == e3) || (output2 == e3))
return ties_array[0];
if ((output3 == e3) || (output4 == e3))
return ties_array[1];
printf("There is an error trying to break sequential triangle \n");
}
int Sequential_Quad(int *index, int triangulate)
{
/* We have a quad that need to break its ties, we will try
and choose a side that is sequential, otherwise use lookahead
*/
int output1,output2,x,e1,e2,e3;
/* e2 and e3 are the input edge to the quad */
Last_Edge(&e1,&e2,&e3,0);
/* No input edge */
if ((e2 == 0) && (e3 == 0))
return ties_array[0];
/* Go through the ties and see if there is a sequential one */
for (x = 0; x < last; x++)
{
Get_EdgeEx(&output1,&output2,index,ties_array[x],4,0,0);
/* Partial and whole triangulation will have different requirements */
if (((output1 == e3) || (output2 == e3)) && (triangulate == PARTIAL))
return ties_array[x];
if (((output1 != e3) && (output1 != e2) &&
(output2 != e3) && (output2 != e2)))
return ties_array[x];
}
/* There was not a tie that was sequential */
return Look_Ahead_Tie();
}
void Whole_Output(int in1,int in2, int *index, int size, int *out1, int *out2)
{
/* Used to sequentially break ties in the whole triangulation for polygons
greater than 4 sides. We will find the output edge that is good
for sequential triangulation.
*/
int half;
/* Put the input edge first in the list */
Rearrange_IndexEx(index,size);
if (!(EVEN(size)))
{
if (*(index) == in1)
half = size/2 ;
else
half = size/2 +1;
}
else
half = size/2;
*out1 = *(index+half);
*out2 = *(index+half+1);
}
int Sequential_Poly(int size, int *index, int triangulate)
{
/* We have a polygon of greater than 4 sides and wish to break the
tie in the most sequential manner.
*/
int x,output1,output2,e1,e2,e3,saved1=-1,saved2=-1,output3,output4;
/* e2 and e3 are the input edge to the quad */
Last_Edge(&e1,&e2,&e3,0);
/* If we are using whole, find the output edge that is sequential */
if (triangulate == WHOLE)
Whole_Output(e2,e3,index,size,&output3,&output4);
/* No input edge */
if ((e2 == 0) && (e3 == 0))
return ties_array[0];
for (x = 0; x < last ; x++)
{
Get_EdgeEx(&output1,&output2,index,ties_array[x],size,0,0);
/* Partial that can be removed in just one triangle */
if (((output1 == e3) || (output2 == e3)) && (triangulate == PARTIAL))
saved1 = ties_array[x];
/* Partial removed in more than one triangle */
if ((output1 != e3) && (output1 != e2) && (output2 != e3) && (output2 != e2) &&
(triangulate == PARTIAL) && (saved2 != -1))
saved2 = ties_array[x];
/* Whole is not so easy, since the whole polygon must be done. Given
an input edge there is only one way to come out, approximately half
way around the polygon.
*/
if (((output1 == output3) && (output2 == output4)) ||
((output1 == output4) && (output2 == output3)) &&
(triangulate == WHOLE))
return ties_array[x];
}
if (saved1 != -1)
return saved1;
if (saved2 != -1)
return saved2;
/* There was not a tie that was sequential */
return Look_Ahead_Tie();
}
int Sequential_Tie(int face_id, int triangulate)
{
/* Break the tie by choosing the face that will
not give us a swap and is sequential. If there
is not one, then do the lookahead to break the
tie.
*/
/* Separate into 3 cases for simplicity, if the current
polygon has 3 sides, 4 sides or if the sides were
greater. We can do the smaller cases faster, so that
is why I separated the cases.
*/
ListHead *pListFace;
PF_FACES face;
/* Get the polygon with id face_id */
pListFace = PolFaces[face_id];
face = (PF_FACES) PeekList(pListFace,LISTHEAD,0);
if (face->nPolSize == 3)
return(Sequential_Tri(face->pPolygon));
if (face->nPolSize == 4)
return(Sequential_Quad(face->pPolygon,triangulate));
else
return(Sequential_Poly(face->nPolSize,face->pPolygon,triangulate));
}
int Get_Next_Face(int t, int face_id, int triangulate)
{
/* Get the next face depending on what
the user specified
*/
/* Did not have a tie, don't do anything */
if (last == 1)
return(ties_array[0]);
if (t == RANDOM)
return Random_Tie();
if (t == ALTERNATE)
return Alternate_Tie();
if (t == LOOK)
return Look_Ahead_Tie();
if (t == SEQUENTIAL)
return Sequential_Tie(face_id,triangulate);
printf("Illegal option specified for ties, using first \n");
return (ties_array[0]);
}

15
Stripe_w/ties.h Normal file
View file

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

27
Stripe_w/triangulate.h Normal file
View file

@ -0,0 +1,27 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: triangulate.h
-----------------------------------------------------------------------*/
void Blind_Triangulate(int size, int *index, FILE *output,
BOOL begin, int where ,int color1,int color2,
int color3);
void Non_Blind_Triangulate(int size,int *index, FILE *output,
int next_face_id,int face_id,int where,
int color1,int color2,int color3);
int Adjacent(int id2,int id1, int *list, int size);
void Delete_From_List(int id,int *list, int *size);
void Triangulate_Polygon(int out_edge1, int out_edge2, int in_edge1,
int in_edge2, int size, int *index,
FILE *output, int reversed, int face_id,
int where, int color1, int color2, int color3);
void Rearrange_Index(int *index, int size);
void Find_Local_Strips();

28
Stripe_w/triangulatex.h Normal file
View file

@ -0,0 +1,28 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: triangulatex.h
-----------------------------------------------------------------------*/
enum swap_type
{ ON, OFF};
void SGI_StripEx();
void Blind_TriangulateEx(int size, int *index, FILE *fp, FILE *output,
BOOL begin, int where );
void Non_Blind_TriangulateEx(int size,int *index, FILE *fp, FILE *output,
int next_face_id,int face_id,int where);
int AdjacentEx(int id2,int id1, int *list, int size);
void Delete_From_ListEx(int id,int *list, int size);
void Triangulate_PolygonEx(int out_edge1,int out_edge2,int in_edge1,
int in_edge2,int size,int *index,
FILE *output,FILE *fp,int reversed,int face_id,
int where);
void Rearrange_IndexEx(int *index, int size);
void Find_StripsEx();

272
Stripe_w/util.c Normal file
View file

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

24
Stripe_w/util.h Normal file
View file

@ -0,0 +1,24 @@
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: util.h
-----------------------------------------------------------------------*/
void switch_lower (int *x, int *y);
int Compare (P_ADJACENCIES node1, P_ADJACENCIES node2);
BOOL Exist(int face_id, int id1, int id2);
int Get_Next_Id(int *index,int e3, int size);
int Different(int id1,int id2,int id3,int id4,int id5, int id6, int *x, int *y);
int Return_Other(int *index,int e1,int e2);
int Get_Other_Vertex(int id1,int id2,int id3,int *index);
PLISTINFO Done(int face_id, int size, int *bucket);
void Output_Edge(int *index,int e2,int e3,int *output1,int *output2);
void Last_Edge(int *id1, int *id2, int *id3, BOOL save);
void First_Edge(int *id1,int *id2, int *id3);
BOOL member(int x , int id1, int id2, int id3);