Initial revision.
This commit is contained in:
parent
801ba133bd
commit
533f072899
39 changed files with 9839 additions and 0 deletions
26
Stripe_w/Makefile.am
Normal file
26
Stripe_w/Makefile.am
Normal 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
384
Stripe_w/add.c
Normal 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
31
Stripe_w/add.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/********************************************************************/
|
||||
/* STRIPE: converting a polygonal model to triangle strips
|
||||
Francine Evans, 1996.
|
||||
SUNY @ Stony Brook
|
||||
Advisors: Steven Skiena and Amitabh Varshney
|
||||
*/
|
||||
/********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* STRIPE: 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
560
Stripe_w/bands.c
Normal 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",¢er[0],¢er[1],¢er[2]);
|
||||
fprintf(bands,"vt %f %f %f\n",center[0],center[1],center[2]);
|
||||
} else {
|
||||
sscanf (ptr+2,"%lf%lf%lf",
|
||||
&(pvertices->x),
|
||||
&(pvertices->y),
|
||||
&(pvertices->z));
|
||||
fprintf(bands,"v %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
810
Stripe_w/common.c
Normal 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
42
Stripe_w/common.h
Normal 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
17
Stripe_w/extend.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
/********************************************************************/
|
||||
/* STRIPE: converting a polygonal model to triangle strips
|
||||
Francine Evans, 1996.
|
||||
SUNY @ Stony Brook
|
||||
Advisors: Steven Skiena and Amitabh Varshney
|
||||
*/
|
||||
/********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* STRIPE: extend.h
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
int Bottom_Left();
|
||||
int Top_Left();
|
||||
void Start_Edge();
|
||||
|
||||
|
112
Stripe_w/free.c
Normal file
112
Stripe_w/free.c
Normal 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
22
Stripe_w/free.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
/********************************************************************/
|
||||
/* STRIPE: converting a polygonal model to triangle strips
|
||||
Francine Evans, 1996.
|
||||
SUNY @ Stony Brook
|
||||
Advisors: Steven Skiena and Amitabh Varshney
|
||||
*/
|
||||
/********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* STRIPE: free.h
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
void Free_All_Strips();
|
||||
void ParseAndFreeList( 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
44
Stripe_w/global.h
Normal 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
217
Stripe_w/init.c
Normal file
|
@ -0,0 +1,217 @@
|
|||
/********************************************************************/
|
||||
/* STRIPE: converting a polygonal model to triangle strips
|
||||
Francine Evans, 1996.
|
||||
SUNY @ Stony Brook
|
||||
Advisors: Steven Skiena and Amitabh Varshney
|
||||
*/
|
||||
/********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* STRIPE: init.c
|
||||
This file contains the initialization of data structures.
|
||||
*/
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "global.h"
|
||||
#include "polverts.h"
|
||||
|
||||
void init_vert_norms(int num_vert)
|
||||
{
|
||||
/* Initialize vertex/normal array to have all zeros to
|
||||
start with.
|
||||
*/
|
||||
register int x;
|
||||
|
||||
for (x = 0; x < num_vert; x++)
|
||||
*(vert_norms + x) = 0;
|
||||
}
|
||||
|
||||
void init_vert_texture(int num_vert)
|
||||
{
|
||||
/* Initialize vertex/normal array to have all zeros to
|
||||
start with.
|
||||
*/
|
||||
register int x;
|
||||
|
||||
for (x = 0; x < num_vert; x++)
|
||||
*(vert_texture + x) = 0;
|
||||
}
|
||||
|
||||
BOOL InitVertTable( int nSize )
|
||||
{
|
||||
register int nIndex;
|
||||
|
||||
/* Initialize the vertex table */
|
||||
PolVerts = (ListHead**) malloc(sizeof(ListHead*) * nSize );
|
||||
if ( PolVerts )
|
||||
{
|
||||
for ( nIndex=0; nIndex < nSize; nIndex++ )
|
||||
{
|
||||
PolVerts[nIndex] = NULL;
|
||||
}
|
||||
return( TRUE );
|
||||
}
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
BOOL InitFaceTable( int nSize )
|
||||
{
|
||||
register int nIndex;
|
||||
|
||||
/* Initialize the face table */
|
||||
PolFaces = (ListHead**) malloc(sizeof(ListHead*) * nSize );
|
||||
if ( PolFaces )
|
||||
{
|
||||
for ( nIndex=0; nIndex < nSize; nIndex++ )
|
||||
{
|
||||
PolFaces[nIndex] = NULL;
|
||||
}
|
||||
return( TRUE );
|
||||
}
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
BOOL InitEdgeTable( int nSize )
|
||||
{
|
||||
register int nIndex;
|
||||
|
||||
/* Initialize the edge table */
|
||||
PolEdges = (ListHead**) malloc(sizeof(ListHead*) * nSize );
|
||||
if ( PolEdges )
|
||||
{
|
||||
for ( nIndex=0; nIndex < nSize; nIndex++ )
|
||||
{
|
||||
PolEdges[nIndex] = NULL;
|
||||
}
|
||||
return( TRUE );
|
||||
}
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
|
||||
void InitStripTable( )
|
||||
{
|
||||
|
||||
PLISTHEAD pListHead;
|
||||
|
||||
/* Initialize the strip table */
|
||||
pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
|
||||
if ( pListHead )
|
||||
{
|
||||
InitList( pListHead );
|
||||
strips[0] = pListHead;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Out of memory !\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Init_Table_SGI()
|
||||
{
|
||||
PLISTHEAD pListHead;
|
||||
int max_adj = 60;
|
||||
register int x;
|
||||
|
||||
/* This routine will initialize the table that will
|
||||
have the faces sorted by the number of adjacent polygons
|
||||
to it.
|
||||
*/
|
||||
|
||||
for (x=0; x< max_adj; x++)
|
||||
{
|
||||
/* We are allowing the max number of sides of a polygon
|
||||
to be max_adj.
|
||||
*/
|
||||
pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
|
||||
if ( pListHead )
|
||||
{
|
||||
InitList( pListHead );
|
||||
array[x] = pListHead;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Out of memory !\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BuildVertTable( int nSize )
|
||||
{
|
||||
register int nIndex;
|
||||
PLISTHEAD pListHead;
|
||||
|
||||
for ( nIndex=0; nIndex < nSize; nIndex++ )
|
||||
{
|
||||
pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
|
||||
if ( pListHead )
|
||||
{
|
||||
InitList( pListHead );
|
||||
PolVerts[nIndex] = pListHead;
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BuildFaceTable( int nSize )
|
||||
{
|
||||
register int nIndex;
|
||||
PLISTHEAD pListHead;
|
||||
|
||||
for ( nIndex=0; nIndex < nSize; nIndex++ )
|
||||
{
|
||||
pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
|
||||
if ( pListHead )
|
||||
{
|
||||
InitList( pListHead );
|
||||
PolFaces[nIndex] = pListHead;
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void BuildEdgeTable( int nSize )
|
||||
{
|
||||
register int nIndex;
|
||||
PLISTHEAD pListHead;
|
||||
|
||||
for ( nIndex=0; nIndex < nSize; nIndex++ )
|
||||
{
|
||||
pListHead = ( PLISTHEAD ) malloc(sizeof(ListHead));
|
||||
if ( pListHead )
|
||||
{
|
||||
InitList( pListHead );
|
||||
PolEdges[nIndex] = pListHead;
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Start_Face_Struct(int numfaces)
|
||||
{
|
||||
if (InitFaceTable(numfaces))
|
||||
{
|
||||
BuildFaceTable(numfaces);
|
||||
}
|
||||
}
|
||||
|
||||
void Start_Edge_Struct(int numverts)
|
||||
{
|
||||
if (InitEdgeTable(numverts))
|
||||
{
|
||||
BuildEdgeTable(numverts);
|
||||
}
|
||||
}
|
||||
|
||||
|
30
Stripe_w/init.h
Normal file
30
Stripe_w/init.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/********************************************************************/
|
||||
/* STRIPE: converting a polygonal model to triangle strips
|
||||
Francine Evans, 1996.
|
||||
SUNY @ Stony Brook
|
||||
Advisors: Steven Skiena and Amitabh Varshney
|
||||
*/
|
||||
/********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* STRIPE: init.h
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
void init_vert_norms(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
119
Stripe_w/local.c
Normal 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
20
Stripe_w/local.h
Normal 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
1659
Stripe_w/newpolve.c
Normal file
File diff suppressed because it is too large
Load diff
181
Stripe_w/options.c
Normal file
181
Stripe_w/options.c
Normal file
|
@ -0,0 +1,181 @@
|
|||
/********************************************************************/
|
||||
/* STRIPE: converting a polygonal model to triangle strips
|
||||
Francine Evans, 1996.
|
||||
SUNY @ Stony Brook
|
||||
Advisors: Steven Skiena and Amitabh Varshney
|
||||
*/
|
||||
/********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* STRIPE: options.c
|
||||
This file contains routines that are used to determine the options
|
||||
that were specified by the user
|
||||
*/
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "options.h"
|
||||
#include "global.h"
|
||||
|
||||
int power_10(int power)
|
||||
{
|
||||
/* Raise 10 to the power */
|
||||
register int i,p;
|
||||
|
||||
p = 1;
|
||||
for (i = 1; i <= power; ++i)
|
||||
p = p * 10;
|
||||
return p;
|
||||
}
|
||||
|
||||
float power_negative(int power)
|
||||
{
|
||||
/* Raise 10 to the negative power */
|
||||
|
||||
register int i;
|
||||
float p;
|
||||
|
||||
p = (float)1;
|
||||
for (i = 1; i<=power; i++)
|
||||
p = p * (float).1;
|
||||
return p;
|
||||
}
|
||||
|
||||
float convert_array(int num[],int stack_size)
|
||||
{
|
||||
/* Convert an array of characters to an integer */
|
||||
|
||||
register int counter,c;
|
||||
float temp =(float)0.0;
|
||||
|
||||
for (c=(stack_size-1), counter = 0; c>=0; c--, counter++)
|
||||
{
|
||||
if (num[c] == -1)
|
||||
/* We are at the decimal point, convert to decimal
|
||||
less than 1
|
||||
*/
|
||||
{
|
||||
counter = -1;
|
||||
temp = power_negative(stack_size - c - 1) * temp;
|
||||
}
|
||||
else
|
||||
temp += power_10(counter) * num[c];
|
||||
}
|
||||
|
||||
return(temp);
|
||||
}
|
||||
|
||||
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
17
Stripe_w/options.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
/********************************************************************/
|
||||
/* STRIPE: converting a polygonal model to triangle strips
|
||||
Francine Evans, 1996.
|
||||
SUNY @ Stony Brook
|
||||
Advisors: Steven Skiena and Amitabh Varshney
|
||||
*/
|
||||
/********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* STRIPE: options.h
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
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
579
Stripe_w/output.c
Normal 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
34
Stripe_w/output.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/********************************************************************/
|
||||
/* STRIPE: converting a polygonal model to triangle strips
|
||||
Francine Evans, 1996.
|
||||
SUNY @ Stony Brook
|
||||
Advisors: Steven Skiena and Amitabh Varshney
|
||||
*/
|
||||
/********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* STRIPE: 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
514
Stripe_w/outputex.c
Normal 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
31
Stripe_w/outputex.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/********************************************************************/
|
||||
/* STRIPE: converting a polygonal model to triangle strips
|
||||
Francine Evans, 1996.
|
||||
SUNY @ Stony Brook
|
||||
Advisors: Steven Skiena and Amitabh Varshney
|
||||
*/
|
||||
/********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* STRIPE: 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
668
Stripe_w/partial.c
Normal 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
20
Stripe_w/partial.h
Normal 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
108
Stripe_w/polverts.h
Normal 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
34
Stripe_w/polyvertsex.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/********************************************************************/
|
||||
/* STRIPE: converting a polygonal model to triangle strips
|
||||
Francine Evans, 1996.
|
||||
SUNY @ Stony Brook
|
||||
Advisors: Steven Skiena and Amitabh Varshney
|
||||
*/
|
||||
/********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* STRIPE: polvertsex.h
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
#include "queue.h"
|
||||
#include <malloc.h>
|
||||
|
||||
|
||||
/* external functions */
|
||||
void Start_Vert_Struct();
|
||||
void Start_Face_StructEx();
|
||||
void Start_Edge_StructEx();
|
||||
void AddNewNode();
|
||||
void AddNewFaceEx();
|
||||
void Find_AdjacenciesEx();
|
||||
void Test_Adj_Struct();
|
||||
void Test_SGI_Struct();
|
||||
void Write_Edges();
|
||||
void End_Verts_Struct();
|
||||
void End_Face_StructEx();
|
||||
void End_Edge_StructEx();
|
||||
void Build_SGI_TableEx();
|
||||
void Add_AdjEdgeEx();
|
||||
|
||||
|
||||
|
226
Stripe_w/queue.c
Normal file
226
Stripe_w/queue.c
Normal file
|
@ -0,0 +1,226 @@
|
|||
/********************************************************************/
|
||||
/* STRIPE: converting a polygonal model to triangle strips
|
||||
Francine Evans, 1996.
|
||||
SUNY @ Stony Brook
|
||||
Advisors: Steven Skiena and Amitabh Varshney
|
||||
*/
|
||||
/********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* STRIPE: queue.c
|
||||
This file contains the routines used in the data structures lists, which
|
||||
are queues.
|
||||
*/
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
#include "queue.h"
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* InitList:
|
||||
*/
|
||||
BOOL InitList (PLISTHEAD LHead)
|
||||
|
||||
{
|
||||
if (LHead == NULL) return(FALSE);
|
||||
|
||||
LHead->LHeaders[LISTHEAD] = LHead->LHeaders[LISTTAIL] = NULL;
|
||||
LHead->NumList = 0;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* AddHead:
|
||||
*/
|
||||
BOOL AddHead(PLISTHEAD LHead, PLISTINFO LInfo)
|
||||
{
|
||||
if (LHead == NULL || LInfo == NULL)
|
||||
return(FALSE);
|
||||
if (EMPTYLIST(LHead))
|
||||
LHead->LHeaders[LISTTAIL] = LInfo;
|
||||
else LHead->LHeaders[LISTHEAD]->ListNode.Previous = (void *) LInfo;
|
||||
|
||||
LInfo->ListNode.Next = (void *) LHead->LHeaders[LISTHEAD];
|
||||
LHead->LHeaders[LISTHEAD] = LInfo;
|
||||
LInfo->ListNode.Previous = NULL;
|
||||
LHead->NumList++;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* AddTail
|
||||
*/
|
||||
BOOL AddTail(PLISTHEAD LHead, PLISTINFO LInfo)
|
||||
{
|
||||
if (LHead == NULL || LInfo == NULL)
|
||||
return(FALSE);
|
||||
if (EMPTYLIST(LHead))
|
||||
LHead->LHeaders[LISTHEAD] = LInfo;
|
||||
else LHead->LHeaders[LISTTAIL]->ListNode.Next = (void *) LInfo;
|
||||
|
||||
LInfo->ListNode.Previous = (void *) LHead->LHeaders[LISTTAIL];
|
||||
LHead->LHeaders[LISTTAIL] = LInfo;
|
||||
LInfo->ListNode.Next = NULL;
|
||||
LHead->NumList++;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
BOOL InsertNode( PLISTHEAD LHead, int nPos, PLISTINFO LInfo )
|
||||
{
|
||||
PLISTINFO LAddNode;
|
||||
|
||||
if ( LHead == NULL || LInfo == NULL || nPos > NumOnList( LHead ) )
|
||||
return( FALSE );
|
||||
|
||||
if ( nPos == 0 )
|
||||
AddHead( LHead, LInfo );
|
||||
else if ( nPos == NumOnList( LHead ) )
|
||||
AddTail( LHead, LInfo );
|
||||
else
|
||||
{
|
||||
if ( (LAddNode = PeekList( LHead, LISTHEAD, nPos - 1 )) == NULL )
|
||||
return( FALSE );
|
||||
|
||||
((PLISTINFO)LAddNode->ListNode.Next)->ListNode.Previous = LInfo;
|
||||
LInfo->ListNode.Next = LAddNode->ListNode.Next;
|
||||
LInfo->ListNode.Previous = LAddNode;
|
||||
LAddNode->ListNode.Next = LInfo;
|
||||
|
||||
LHead->NumList++;
|
||||
}
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* RemHead:
|
||||
*/
|
||||
PLISTINFO RemHead(PLISTHEAD LHead)
|
||||
{
|
||||
PLISTINFO t, t1;
|
||||
|
||||
if ( LHead == NULL || EMPTYLIST(LHead) )
|
||||
return(NULL);
|
||||
|
||||
t = LHead->LHeaders[LISTHEAD];
|
||||
LHead->LHeaders[LISTHEAD] = (PLISTINFO) t->ListNode.Next;
|
||||
|
||||
if (LHead->LHeaders[LISTHEAD] != NULL)
|
||||
{
|
||||
t1 = (PLISTINFO) t->ListNode.Next;
|
||||
t1->ListNode.Previous = NULL;
|
||||
}
|
||||
else
|
||||
LHead->LHeaders[LISTTAIL] = NULL;
|
||||
|
||||
LHead->NumList--;
|
||||
|
||||
return(t);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* RemTail:
|
||||
*/
|
||||
PLISTINFO RemTail(PLISTHEAD LHead)
|
||||
{
|
||||
PLISTINFO t, t1;
|
||||
|
||||
if ( LHead == NULL || EMPTYLIST(LHead) )
|
||||
return(NULL);
|
||||
|
||||
t = LHead->LHeaders[LISTTAIL];
|
||||
LHead->LHeaders[LISTTAIL] = (PLISTINFO) t->ListNode.Previous;
|
||||
if (LHead->LHeaders[LISTTAIL] != NULL)
|
||||
{
|
||||
t1 = (PLISTINFO) t->ListNode.Previous;
|
||||
t1->ListNode.Next = NULL;
|
||||
}
|
||||
else
|
||||
LHead->LHeaders[LISTHEAD] = NULL;
|
||||
|
||||
LHead->NumList--;
|
||||
return(t);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* PeekList:
|
||||
*/
|
||||
PLISTINFO PeekList(PLISTHEAD LHead, int wch, int index )
|
||||
{
|
||||
PLISTINFO t;
|
||||
|
||||
if (LHead == NULL)
|
||||
return(NULL);
|
||||
if ( (t = LHead->LHeaders[wch]) == NULL )
|
||||
return(NULL);
|
||||
|
||||
for (; t != NULL && index > 0; index-- )
|
||||
t = (wch == LISTHEAD) ? (PLISTINFO) t->ListNode.Next :
|
||||
(PLISTINFO) t->ListNode.Previous;
|
||||
return(t);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* RemoveList:
|
||||
*/
|
||||
PLISTINFO RemoveList( PLISTHEAD LHead, PLISTINFO LInfo )
|
||||
{
|
||||
PLISTINFO t, t1;
|
||||
|
||||
t = LInfo;
|
||||
if (LHead == NULL)
|
||||
return(NULL);
|
||||
if (LHead->LHeaders[LISTHEAD] == t)
|
||||
t = (PLISTINFO) RemHead(LHead);
|
||||
else if (LHead->LHeaders[LISTTAIL] == t)
|
||||
t = (PLISTINFO) RemTail(LHead);
|
||||
else
|
||||
{
|
||||
t1 = (PLISTINFO) t->ListNode.Previous;
|
||||
t1->ListNode.Next = t->ListNode.Next;
|
||||
t1 = (PLISTINFO) t->ListNode.Next;
|
||||
t1->ListNode.Previous = t->ListNode.Previous;
|
||||
LHead->NumList--;
|
||||
}
|
||||
|
||||
return(t);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* SearchList:
|
||||
* Try to find a specific node in the queue whose key matches with
|
||||
* searching key. Return the pointer to that node if found, return NULL
|
||||
* otherwise
|
||||
*
|
||||
* Input:
|
||||
* lpHashTbl => a far pointer to the hash table
|
||||
* lpKey => a far poniter to searching key
|
||||
* CompareCallBack => comparision function
|
||||
*
|
||||
* Output: a far pointer to the node to be found
|
||||
*
|
||||
*/
|
||||
PLISTINFO SearchList(
|
||||
PLISTHEAD lpListHead,
|
||||
PVOID lpSKey,
|
||||
int (* CompareCallBack) ( PVOID, PVOID ) )
|
||||
{
|
||||
PLISTINFO lpListInfo;
|
||||
|
||||
lpListInfo = PeekList( lpListHead, LISTHEAD, 0);
|
||||
while ( lpListInfo != NULL )
|
||||
{
|
||||
if ( CompareCallBack( lpListInfo, lpSKey ) )
|
||||
break;
|
||||
lpListInfo = GetNextNode( lpListInfo );
|
||||
}
|
||||
|
||||
return( lpListInfo );
|
||||
}
|
||||
|
283
Stripe_w/queue.h
Normal file
283
Stripe_w/queue.h
Normal file
|
@ -0,0 +1,283 @@
|
|||
|
||||
/********************************************************************/
|
||||
/* STRIPE: converting a polygonal model to triangle strips
|
||||
Francine Evans, 1996.
|
||||
SUNY @ Stony Brook
|
||||
Advisors: Steven Skiena and Amitabh Varshney
|
||||
*/
|
||||
/********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* STRIPE:queue.h
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
#ifndef QUEUE_INCLUDED
|
||||
#define QUEUE_INCLUDED
|
||||
|
||||
/* %%s Node */
|
||||
/*****************************************************************
|
||||
This structure is used to store the List linkage information of a
|
||||
ListInfo structure. It contains all the necessary information for the
|
||||
List functions to function properly. This structure must be the first
|
||||
one defined in any block of memory to be linked with the List functions.
|
||||
for an example of the used of The Node structure look in the files
|
||||
ipd2dms.c and ipd2man.h
|
||||
******************************************************************/
|
||||
#include <stdio.h>
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
typedef struct
|
||||
{
|
||||
void *Next;
|
||||
void *Previous;
|
||||
}
|
||||
Node, * PNODE;
|
||||
|
||||
/*****************************************************************
|
||||
Next : is a pointer to the next structure in this List.
|
||||
Previous : is a pointer to the previous structure in this List.
|
||||
priority : this is the priority of this structure in the List. The
|
||||
highest priority is 0. This field is only used by the
|
||||
functions EnQue and DeQue.
|
||||
******************************************************************/
|
||||
/* %%e */
|
||||
|
||||
|
||||
/* %%s ListInfo */
|
||||
|
||||
/*****************************************************************
|
||||
This is the general means of linking application defined information into
|
||||
Lists and queues. All structures must begin with the Node Structure. All
|
||||
other data in the structure is user definable.
|
||||
******************************************************************/
|
||||
|
||||
typedef struct List
|
||||
{
|
||||
Node ListNode; /* link to the next Listinfo Structure */
|
||||
/* user definable data */
|
||||
} ListInfo, *PLISTINFO;
|
||||
|
||||
/*****************************************************************
|
||||
ListNode : this is the required node structure for the List
|
||||
mainpulation functions. This must be the first
|
||||
element of a user definable structure.
|
||||
|
||||
In order for an application to use the List routines, it must define
|
||||
a structure with all the needed information. The first element in the
|
||||
user definable structure must be a Node structure. The Node structure
|
||||
contains all the necessary information for the List routines to do their
|
||||
magic. For an example of a user defined List structure see the file
|
||||
ipd2i.h. The User definable structure can be passed to any List function
|
||||
that excepts a pointer to a ListInfo structure.
|
||||
|
||||
example:
|
||||
|
||||
typedef mstruct
|
||||
{
|
||||
Node ListNode;
|
||||
int a,b,c,d,e,f,g;
|
||||
}
|
||||
mystruct;
|
||||
|
||||
the user definable portion of the above structure is represented by
|
||||
the integers a,b,c,d,e,f,g. When passing this structure to a List
|
||||
function a cast of (ListInfo *) must be made to satisify the "C" complier.
|
||||
******************************************************************/
|
||||
/* %%e */
|
||||
|
||||
|
||||
/* %%s ListHead */
|
||||
/*****************************************************************
|
||||
ListHead is used as a header to a List. LHeaders[0] points to the
|
||||
head of the List. LHeaders[1] points the tail of the list. When
|
||||
accessing these variables use the defines LISTHEAD, LISTTAIL.
|
||||
******************************************************************/
|
||||
|
||||
typedef struct LHead
|
||||
{
|
||||
PLISTINFO LHeaders[2];
|
||||
int NumList;
|
||||
}
|
||||
ListHead, *PLISTHEAD;
|
||||
|
||||
/*****************************************************************
|
||||
LHeaders : this is an array of two pointers to ListInfo structures.
|
||||
This information is used to point to the head and tail of
|
||||
a list.
|
||||
NumList : this integer hold the number of structures linked into this
|
||||
list.
|
||||
|
||||
ListHead #define:
|
||||
|
||||
LISTHEAD : when Peeking down a list this specifies you should
|
||||
start at the Head of the list and search downward.
|
||||
|
||||
LISTTAIL : when Peeking down a list this specifies you should
|
||||
start at the tail of the list and search foward.
|
||||
******************************************************************/
|
||||
|
||||
#define LISTHEAD 0
|
||||
|
||||
#define LISTTAIL 1
|
||||
/* %%e */
|
||||
|
||||
typedef int BOOL;
|
||||
typedef void * PVOID;
|
||||
|
||||
#define PEEKFROMHEAD( lh, ind ) ( PeekList( (lh), LISTHEAD, (ind) ) )
|
||||
#define PEEKFROMTAIL( lh, ind ) ( PeekList( (lh), LISTTAIL, (ind) ) )
|
||||
#define EMPTYLIST( lh ) ( ( (lh)->LHeaders[LISTHEAD] == NULL ) )
|
||||
|
||||
/* General utility routines */
|
||||
/* %%s QueRoutines */
|
||||
BOOL InitList ( PLISTHEAD );
|
||||
|
||||
/*****************************************************************
|
||||
InitList : Initialize a new list structure for use with the List
|
||||
routines
|
||||
|
||||
INPUTS : LHead : a pointer to a ListHead structure.
|
||||
OUTPUT : a boolean value TRUE if no errors occured FALSE
|
||||
otherwise
|
||||
******************************************************************/
|
||||
|
||||
|
||||
PLISTINFO PeekList ( PLISTHEAD, int, int );
|
||||
|
||||
/*****************************************************************
|
||||
PeekList : This funciton peeks down a list for the N'th element
|
||||
from the HEAD or TAIL of the list
|
||||
|
||||
INPUTS : LHead : a pointer to a List head structure.
|
||||
from : can either search from the HEAD or TAIL
|
||||
of the list
|
||||
where : how many nodes from the begining should the
|
||||
List routines look.
|
||||
OUTPUT : a pointer to a ListInfo structure identified by
|
||||
from/where or NULL if an error occurred.
|
||||
******************************************************************/
|
||||
|
||||
|
||||
PLISTINFO RemoveList( PLISTHEAD LHead, PLISTINFO LInfo );
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
RemoveList: Remove a ListInfo structure from a List.
|
||||
|
||||
INPUTS : LHead : a pointer to a ListHead structure.
|
||||
LInfo : a pointer to the ListInfo structure to remove
|
||||
from the list.
|
||||
OUTPUT : a pointer to the ListInfo structure that was removed or
|
||||
NULL if an error occurred.
|
||||
******************************************************************/
|
||||
|
||||
BOOL InsertNode( PLISTHEAD LHead, int nPos, PLISTINFO LInfo );
|
||||
|
||||
/*****************************************************************
|
||||
InsertNode: add a node to a list after a given node
|
||||
|
||||
INPUTS : LHead : a pointer to a ListHead structure.
|
||||
nPos : the position to insert the node into
|
||||
LInfo : a pointer to the new node to add to the list.
|
||||
OUTPUT: a boolean value TRUE if all goes well false otherwise
|
||||
*****************************************************************/
|
||||
|
||||
BOOL AddHead ( PLISTHEAD, PLISTINFO );
|
||||
|
||||
/*****************************************************************
|
||||
AddHead : add a ListInfo structure to the HEAD of a list.
|
||||
|
||||
INPUTS : LHead : a pointer to a ListHead structure of the list
|
||||
to add to.
|
||||
LInfo : a pointer to the ListInfo structure to add to
|
||||
the list.
|
||||
OUTPUT : A boolean value TRUE if no errors occurred FALSE
|
||||
otherwise.
|
||||
******************************************************************/
|
||||
|
||||
|
||||
BOOL AddTail ( PLISTHEAD, PLISTINFO );
|
||||
|
||||
/*****************************************************************
|
||||
AddTail : Add a ListInfo structure to the TAIL of a list.
|
||||
|
||||
INPUTS : LHead : a pointer to a ListHead structure of the List
|
||||
to add to.
|
||||
LInfo : a pointer to the ListInfo structure to add to
|
||||
the List.
|
||||
OUTPUT : a boolean value TRUE if no errors occurred FALSE
|
||||
otherwise.
|
||||
******************************************************************/
|
||||
|
||||
|
||||
PLISTINFO RemTail ( PLISTHEAD );
|
||||
|
||||
/*****************************************************************
|
||||
RemTail : Remove a ListInfo structure from the TAIL of a List.
|
||||
|
||||
INPUTS : LHead : a pointer to a ListHead structure of the List
|
||||
to remove from.
|
||||
OUTPUT : a pointer to the ListInfo structure that was removed
|
||||
or NULL if an error occurred.
|
||||
******************************************************************/
|
||||
|
||||
|
||||
PLISTINFO RemHead ( PLISTHEAD );
|
||||
|
||||
/*****************************************************************
|
||||
RemHead : Remove a ListInfo structure from the Head of a List.
|
||||
|
||||
INPUTS : LHead : a pointer to a ListHead structure of the List
|
||||
to remove from.
|
||||
OUTPUT : a pointer to the ListInfo structure that was removed or
|
||||
NULL if an error occurred.
|
||||
******************************************************************/
|
||||
|
||||
PLISTINFO SearchList(
|
||||
PLISTHEAD lpListHead,
|
||||
PVOID lpSKey,
|
||||
int ( * CompareCallBack) ( PVOID, PVOID ) );
|
||||
|
||||
/*****************************************************************
|
||||
SearchList:
|
||||
Try to find a specific node in the queue whose key matches with
|
||||
searching key. Return the pointer to that node if found, return NULL
|
||||
otherwise
|
||||
|
||||
Input:
|
||||
lpHashTbl => a far pointer to the hash table
|
||||
lpKey => a far poniter to searching key
|
||||
CompareCallBack => comparision function
|
||||
|
||||
Output: a far pointer to the node to be found
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#define NumOnList(lh) ( ((lh)->NumList) )
|
||||
|
||||
/*****************************************************************
|
||||
NumOnList: Returns the number of Nodes linked to a ListHead
|
||||
structure. This number is maintained by the List
|
||||
routines.
|
||||
******************************************************************/
|
||||
|
||||
#define GetNextNode(pli) ( ((pli)->ListNode.Next) )
|
||||
|
||||
/********************************************************
|
||||
GetNextNode: This macro returns the Next Structure in this list.
|
||||
This macro will return NULL if no more structures are
|
||||
in the List.
|
||||
*********************************************************/
|
||||
|
||||
#define GetPrevNode(pli) ( ((pli)->ListNode.Previous) )
|
||||
|
||||
/********************************************************
|
||||
GetPrevNode: This macro returns the Previous Structure in this list.
|
||||
This macro will reutrn NULL if no more structures are
|
||||
in the List.
|
||||
********************************************************/
|
||||
/* %%e */
|
||||
|
||||
#endif
|
||||
|
||||
|
628
Stripe_w/sgi_triang.c
Normal file
628
Stripe_w/sgi_triang.c
Normal 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
582
Stripe_w/sgi_triangex.c
Normal file
|
@ -0,0 +1,582 @@
|
|||
/********************************************************************/
|
||||
/* STRIPE: converting a polygonal model to triangle strips
|
||||
Francine Evans, 1996.
|
||||
SUNY @ Stony Brook
|
||||
Advisors: Steven Skiena and Amitabh Varshney
|
||||
*/
|
||||
/********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* STRIPE: 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
549
Stripe_w/struct.c
Normal file
|
@ -0,0 +1,549 @@
|
|||
/********************************************************************/
|
||||
/* STRIPE: converting a polygonal model to triangle strips
|
||||
Francine Evans, 1996.
|
||||
SUNY @ Stony Brook
|
||||
Advisors: Steven Skiena and Amitabh Varshney
|
||||
*/
|
||||
/********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* STRIPE: struct.c
|
||||
Contains routines that update structures, and micellaneous routines.
|
||||
*/
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "polverts.h"
|
||||
#include "ties.h"
|
||||
#include "output.h"
|
||||
#include "triangulate.h"
|
||||
#include "sturcts.h"
|
||||
#include "options.h"
|
||||
#include "common.h"
|
||||
#include "util.h"
|
||||
|
||||
int out1 = -1;
|
||||
int out2 = -1;
|
||||
|
||||
int Get_Edge(int *edge1,int *edge2,int *index,int face_id,
|
||||
int size, int id1, int id2)
|
||||
{
|
||||
/* Put the edge that is adjacent to face_id into edge1
|
||||
and edge2. For each edge see if it is adjacent to
|
||||
face_id. Id1 and id2 is the input edge, so see if
|
||||
the orientation is reversed, and save it in reversed.
|
||||
*/
|
||||
register int x;
|
||||
int reversed = -1;
|
||||
BOOL set = FALSE;
|
||||
|
||||
for (x=0; x< size; x++)
|
||||
{
|
||||
if (x == (size-1))
|
||||
{
|
||||
if ((*(index) == id1) && (*(index+size-1)==id2))
|
||||
{
|
||||
if (set)
|
||||
return 1;
|
||||
reversed = 1;
|
||||
}
|
||||
else if ((*(index) == id2) && (*(index+size-1)==id1))
|
||||
{
|
||||
if (set)
|
||||
return 0;
|
||||
reversed = 0;
|
||||
}
|
||||
|
||||
if (Look_Up(*(index),*(index+size-1),face_id))
|
||||
{
|
||||
if ( (out1 != -1) && ( (out1 == *(index)) || (out1 == *(index+size-1)) ) &&
|
||||
( (out2 == *(index)) || (out2 == *(index+size-1)) ))
|
||||
{
|
||||
set = TRUE;
|
||||
*edge1 = *(index);
|
||||
*edge2 = *(index+size-1);
|
||||
}
|
||||
else if (out1 == -1)
|
||||
{
|
||||
set = TRUE;
|
||||
*edge1 = *(index);
|
||||
*edge2 = *(index+size-1);
|
||||
}
|
||||
if ((reversed != -1) && (set))
|
||||
return reversed;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((*(index+x) == id1) && (*(index+x+1)==id2))
|
||||
{
|
||||
if (set)
|
||||
return 0;
|
||||
reversed = 0;
|
||||
}
|
||||
else if ((*(index+x) == id2) && (*(index+x+1)==id1))
|
||||
{
|
||||
if (set)
|
||||
return 1;
|
||||
reversed = 1;
|
||||
}
|
||||
|
||||
if (Look_Up(*(index+x),*(index+x+1),face_id))
|
||||
{
|
||||
if ( (out1 != -1) && ( (out1 == *(index+x)) || (out1 == *(index+x+1)) ) &&
|
||||
((out2 == *(index+x)) || (out2 == *(index+x+1))))
|
||||
{
|
||||
set = TRUE;
|
||||
*edge1 = *(index+x);
|
||||
*edge2 = *(index+x+1);
|
||||
}
|
||||
else if (out1 == -1)
|
||||
{
|
||||
set = TRUE;
|
||||
*edge1 = *(index+x);
|
||||
*edge2 = *(index+x + 1);
|
||||
}
|
||||
if ((reversed != -1) && (set))
|
||||
return reversed;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((x == size) && (reversed != -1))
|
||||
{
|
||||
/* Could not find the output edge */
|
||||
printf("Error in the Lookup %d %d %d %d %d %d %d %d\n",face_id,id1,id2,reversed,*edge1,*edge2,out1,out2);
|
||||
exit(0);
|
||||
}
|
||||
return reversed;
|
||||
}
|
||||
|
||||
|
||||
void Update_Face(int *next_bucket, int *min_face, int face_id, int *e1,
|
||||
int *e2,int temp1,int temp2,int *ties)
|
||||
{
|
||||
/* We have a face id that needs to be decremented.
|
||||
We have to determine where it is in the structure,
|
||||
so that we can decrement it.
|
||||
*/
|
||||
/* The number of adjacencies may have changed, so to locate
|
||||
it may be a little tricky. However we know that the number
|
||||
of adjacencies is less than or equal to the original number
|
||||
of adjacencies,
|
||||
*/
|
||||
int y,size;
|
||||
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
553
Stripe_w/structex.c
Normal file
|
@ -0,0 +1,553 @@
|
|||
/********************************************************************/
|
||||
/* STRIPE: converting a polygonal model to triangle strips
|
||||
Francine Evans, 1996.
|
||||
SUNY @ Stony Brook
|
||||
Advisors: Steven Skiena and Amitabh Varshney
|
||||
*/
|
||||
/********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* STRIPE: structex.c
|
||||
This file contains routines that are used for various functions in
|
||||
the local algorithm.
|
||||
*/
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "polverts.h"
|
||||
#include "ties.h"
|
||||
#include "outputex.h"
|
||||
#include "triangulatex.h"
|
||||
#include "sturctsex.h"
|
||||
#include "options.h"
|
||||
#include "common.h"
|
||||
#include "util.h"
|
||||
|
||||
int out1Ex = -1;
|
||||
int out2Ex = -1;
|
||||
|
||||
int Get_EdgeEx(int *edge1,int *edge2,int *index,int face_id,
|
||||
int size, int id1, int id2)
|
||||
{
|
||||
/* Put the edge that is adjacent to face_id into edge1
|
||||
and edge2. For each edge see if it is adjacent to
|
||||
face_id. Id1 and id2 is the input edge, so see if
|
||||
the orientation is reversed, and save it in reversed.
|
||||
*/
|
||||
int x;
|
||||
int reversed = -1;
|
||||
BOOL set = FALSE;
|
||||
|
||||
for (x=0; x< size; x++)
|
||||
{
|
||||
if (x == (size-1))
|
||||
{
|
||||
if ((*(index) == id1) && (*(index+size-1)==id2))
|
||||
{
|
||||
if (set)
|
||||
return 1;
|
||||
reversed = 1;
|
||||
}
|
||||
else if ((*(index) == id2) && (*(index+size-1)==id1))
|
||||
{
|
||||
if (set)
|
||||
return 0;
|
||||
reversed = 0;
|
||||
}
|
||||
|
||||
if (Look_Up(*(index),*(index+size-1),face_id))
|
||||
{
|
||||
if ( (out1Ex != -1) && ( (out1Ex == *(index)) || (out1Ex == *(index+size-1)) ) &&
|
||||
( (out2Ex == *(index)) || (out2Ex == *(index+size-1)) ))
|
||||
{
|
||||
set = TRUE;
|
||||
*edge1 = *(index);
|
||||
*edge2 = *(index+size-1);
|
||||
}
|
||||
else if (out1Ex == -1)
|
||||
{
|
||||
set = TRUE;
|
||||
*edge1 = *(index);
|
||||
*edge2 = *(index+size-1);
|
||||
}
|
||||
if ((reversed != -1) && (set))
|
||||
return reversed;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((*(index+x) == id1) && (*(index+x+1)==id2))
|
||||
{
|
||||
if (set)
|
||||
return 0;
|
||||
reversed = 0;
|
||||
}
|
||||
else if ((*(index+x) == id2) && (*(index+x+1)==id1))
|
||||
{
|
||||
if (set)
|
||||
return 1;
|
||||
reversed = 1;
|
||||
}
|
||||
|
||||
if (Look_Up(*(index+x),*(index+x+1),face_id))
|
||||
{
|
||||
if ( (out1Ex != -1) && ( (out1Ex == *(index+x)) || (out1Ex == *(index+x+1)) ) &&
|
||||
((out2Ex == *(index+x)) || (out2Ex == *(index+x+1))))
|
||||
{
|
||||
set = TRUE;
|
||||
*edge1 = *(index+x);
|
||||
*edge2 = *(index+x+1);
|
||||
}
|
||||
else if (out1Ex == -1)
|
||||
{
|
||||
set = TRUE;
|
||||
*edge1 = *(index+x);
|
||||
*edge2 = *(index+x + 1);
|
||||
}
|
||||
if ((reversed != -1) && (set))
|
||||
return reversed;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((x == size) && (reversed != -1))
|
||||
{
|
||||
/* Could not find the output edge */
|
||||
printf("Error in the Lookup %d %d %d %d %d %d %d %d\n",face_id,id1,id2,reversed,*edge1,*edge2,out1Ex,out2Ex);
|
||||
exit(0);
|
||||
}
|
||||
return reversed;
|
||||
}
|
||||
|
||||
|
||||
void Update_FaceEx(int *next_bucket, int *min_face, int face_id, int *e1,
|
||||
int *e2,int temp1,int temp2,int *ties)
|
||||
{
|
||||
/* We have a face id that needs to be decremented.
|
||||
We have to determine where it is in the structure,
|
||||
so that we can decrement it.
|
||||
*/
|
||||
/* The number of adjacencies may have changed, so to locate
|
||||
it may be a little tricky. However we know that the number
|
||||
of adjacencies is less than or equal to the original number
|
||||
of adjacencies,
|
||||
*/
|
||||
int y,size;
|
||||
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
36
Stripe_w/sturcts.h
Normal 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
33
Stripe_w/sturctsex.h
Normal 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
304
Stripe_w/ties.c
Normal file
|
@ -0,0 +1,304 @@
|
|||
/********************************************************************/
|
||||
/* STRIPE: converting a polygonal model to triangle strips
|
||||
Francine Evans, 1996.
|
||||
SUNY @ Stony Brook
|
||||
Advisors: Steven Skiena and Amitabh Varshney
|
||||
*/
|
||||
/********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* STRIPE: ties.c
|
||||
This file will contain all the routines used to determine the next face if there
|
||||
is a tie
|
||||
*/
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "polverts.h"
|
||||
#include "ties.h"
|
||||
#include "sturctsex.h"
|
||||
#include "triangulatex.h"
|
||||
#include "options.h"
|
||||
#include "common.h"
|
||||
#include "util.h"
|
||||
|
||||
#define MAX_TIE 60
|
||||
int ties_array[60];
|
||||
int last = 0;
|
||||
|
||||
void Clear_Ties()
|
||||
{
|
||||
/* Clear the buffer, because we do not have the tie
|
||||
any more that we had before */
|
||||
last = 0;
|
||||
}
|
||||
|
||||
void Add_Ties(int id)
|
||||
{
|
||||
/* We have a tie to add to the buffer */
|
||||
ties_array[last++] = id;
|
||||
}
|
||||
|
||||
int Alternate_Tie()
|
||||
{
|
||||
/* Alternate in what we choose to break the tie
|
||||
We are just alternating between the first and
|
||||
second thing that we found
|
||||
*/
|
||||
static int x = 0;
|
||||
register int t;
|
||||
|
||||
t = ties_array[x];
|
||||
x++;
|
||||
if (x == 2)
|
||||
x = 0;
|
||||
return t;
|
||||
}
|
||||
|
||||
int Random_Tie()
|
||||
{
|
||||
/* Randomly choose the next face with which
|
||||
to break the tie
|
||||
*/
|
||||
register int num;
|
||||
|
||||
num = rand();
|
||||
while (num >= last)
|
||||
num = num/20;
|
||||
return (ties_array[num]);
|
||||
}
|
||||
|
||||
int Look_Ahead(int id)
|
||||
{
|
||||
/* Look ahead at this face and save the minimum
|
||||
adjacency of all the faces that are adjacent to
|
||||
this face.
|
||||
*/
|
||||
return Min_Adj(id);
|
||||
}
|
||||
|
||||
int Random_Look(int id[],int count)
|
||||
{
|
||||
/* We had a tie within a tie in the lookahead,
|
||||
break it randomly
|
||||
*/
|
||||
register int num;
|
||||
|
||||
num = rand();
|
||||
while (num >= count)
|
||||
num = num/20;
|
||||
return (id[num]);
|
||||
}
|
||||
|
||||
|
||||
int Look_Ahead_Tie()
|
||||
{
|
||||
/* Look ahead and find the face to go to that
|
||||
will give the least number of adjacencies
|
||||
*/
|
||||
int id[60],t,x,f=0,min = 60;
|
||||
|
||||
for (x = 0; x < last; x++)
|
||||
{
|
||||
t = Look_Ahead(ties_array[x]);
|
||||
/* We have a tie */
|
||||
if (t == min)
|
||||
id[f++] = ties_array[x];
|
||||
if (t < min)
|
||||
{
|
||||
f = 0;
|
||||
min = t;
|
||||
id[f++] = ties_array[x];
|
||||
}
|
||||
}
|
||||
/* No tie within the tie */
|
||||
if ( f == 1)
|
||||
return id[0];
|
||||
/* Or ties, but we are at the end of strips */
|
||||
if (min == 0)
|
||||
return id[0];
|
||||
return (Random_Look(id,f));
|
||||
}
|
||||
|
||||
|
||||
int Sequential_Tri(int *index)
|
||||
{
|
||||
/* We have a triangle and need to break the ties at it.
|
||||
We will choose the edge that is sequential. There
|
||||
is definitely one since we know we have a triangle
|
||||
and that there is a tie and there are only 2 edges
|
||||
for the tie.
|
||||
*/
|
||||
int 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
15
Stripe_w/ties.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
/********************************************************************/
|
||||
/* STRIPE: converting a polygonal model to triangle strips
|
||||
Francine Evans, 1996.
|
||||
SUNY @ Stony Brook
|
||||
Advisors: Steven Skiena and Amitabh Varshney
|
||||
*/
|
||||
/********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* STRIPE: ties.h
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
void Clear_Ties();
|
||||
void Add_Ties(int id);
|
||||
int Get_Next_Face(int t, int face_id, int triangulate);
|
27
Stripe_w/triangulate.h
Normal file
27
Stripe_w/triangulate.h
Normal 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
28
Stripe_w/triangulatex.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/********************************************************************/
|
||||
/* STRIPE: converting a polygonal model to triangle strips
|
||||
Francine Evans, 1996.
|
||||
SUNY @ Stony Brook
|
||||
Advisors: Steven Skiena and Amitabh Varshney
|
||||
*/
|
||||
/********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* STRIPE: 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
272
Stripe_w/util.c
Normal file
|
@ -0,0 +1,272 @@
|
|||
/********************************************************************/
|
||||
/* STRIPE: converting a polygonal model to triangle strips
|
||||
Francine Evans, 1996.
|
||||
SUNY @ Stony Brook
|
||||
Advisors: Steven Skiena and Amitabh Varshney
|
||||
*/
|
||||
/********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* STRIPE: util.c
|
||||
This file contains routines that are used for various functions
|
||||
*/
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "polverts.h"
|
||||
|
||||
void switch_lower (int *x, int *y)
|
||||
{
|
||||
register int temp;
|
||||
|
||||
/* Put lower value in x */
|
||||
if (*y < *x)
|
||||
{
|
||||
temp = *x;
|
||||
*x = *y;
|
||||
*y = temp;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL member(int x , int id1, int id2, int id3)
|
||||
{
|
||||
/* Is x in the triangle specified by id1,id2,id3 */
|
||||
if ((x != id1) && (x != id2) && (x != id3))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
int Compare (P_ADJACENCIES node1, P_ADJACENCIES node2)
|
||||
{
|
||||
/* This will only return whether 2 adjacency nodes
|
||||
are equivalent.
|
||||
*/
|
||||
if (node1->face_id == node2->face_id)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
BOOL Exist(int face_id, int id1, int id2)
|
||||
{
|
||||
/* Does the edge specified by id1 and id2 exist in this
|
||||
face currently? Maybe we deleted in partial triangulation
|
||||
*/
|
||||
ListHead *pListHead;
|
||||
PF_FACES temp;
|
||||
register int x,size;
|
||||
BOOL a=FALSE,b =FALSE;
|
||||
|
||||
pListHead = PolFaces[face_id];
|
||||
temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 );
|
||||
size = temp->nPolSize;
|
||||
for (x=0; x<size; x++)
|
||||
{
|
||||
if (*(temp->pPolygon+x) == id1)
|
||||
a = TRUE;
|
||||
if (*(temp->pPolygon+x) == id2)
|
||||
b = TRUE;
|
||||
if (a && b)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int Get_Next_Id(int *index,int e3, int size)
|
||||
{
|
||||
/* Return the id following e3 in the list of vertices */
|
||||
|
||||
register int x;
|
||||
|
||||
for (x = 0; x< size; x++)
|
||||
{
|
||||
if ((*(index+x) == e3) && (x != (size-1)))
|
||||
return *(index+x+1);
|
||||
else if (*(index+x) == e3)
|
||||
return *(index);
|
||||
}
|
||||
printf("There is an error in the next id\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int Different (int id1,int id2,int id3,int id4,int id5, int id6, int *x, int *y)
|
||||
{
|
||||
/* Find the vertex in the first 3 numbers that does not exist in
|
||||
the last three numbers
|
||||
*/
|
||||
if ((id1 != id4) && (id1 != id5) && (id1 != id6))
|
||||
{
|
||||
*x = id2;
|
||||
*y = id3;
|
||||
return id1;
|
||||
}
|
||||
if ((id2 != id4) && (id2 != id5) && (id2 != id6))
|
||||
{
|
||||
*x = id1;
|
||||
*y = id3;
|
||||
return id2;
|
||||
}
|
||||
if ((id3 != id4) && (id3 != id5) && (id3 != id6))
|
||||
{
|
||||
*x = id1;
|
||||
*y = id2;
|
||||
return id3;
|
||||
}
|
||||
|
||||
/* Because there are degeneracies in the data, this might occur */
|
||||
*x = id5;
|
||||
*y = id6;
|
||||
return id4;
|
||||
}
|
||||
|
||||
int Return_Other(int *index,int e1,int e2)
|
||||
{
|
||||
/* We have a triangle and want to know the third vertex of it */
|
||||
register int x;
|
||||
|
||||
for (x=0;x<3;x++)
|
||||
{
|
||||
if ((*(index+x) != e1) && (*(index+x) != e2))
|
||||
return *(index+x);
|
||||
}
|
||||
/* If there is a degenerate triangle return arbitrary */
|
||||
return e1;
|
||||
}
|
||||
|
||||
int Get_Other_Vertex(int id1,int id2,int id3,int *index)
|
||||
{
|
||||
/* We have a list index of 4 numbers and we wish to
|
||||
return the number that is not id1,id2 or id3
|
||||
*/
|
||||
register int x;
|
||||
|
||||
for (x=0; x<4; x++)
|
||||
{
|
||||
if ((*(index+x) != id1) && (*(index+x) != id2) &&
|
||||
(*(index+x) != id3))
|
||||
return *(index+x);
|
||||
}
|
||||
/* If there is some sort of degeneracy this might occur,
|
||||
return arbitrary
|
||||
*/
|
||||
if (x==4)
|
||||
return id1;
|
||||
}
|
||||
|
||||
|
||||
PLISTINFO Done(int face_id, int size, int *bucket)
|
||||
{
|
||||
/* Check to see whether the polygon with face_id was used
|
||||
already, return NULL if it was, otherwise return a pointer to the face.
|
||||
*/
|
||||
P_ADJACENCIES pfNode;
|
||||
register int y;
|
||||
PLISTINFO lpListInfo;
|
||||
|
||||
pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) );
|
||||
if ( pfNode )
|
||||
pfNode->face_id = face_id;
|
||||
|
||||
for (y=size; ; y--)
|
||||
{
|
||||
lpListInfo = SearchList(array[y], pfNode,
|
||||
(int (*)(void *,void *)) (Compare));
|
||||
if (lpListInfo != NULL)
|
||||
{
|
||||
*bucket = y;
|
||||
return lpListInfo;
|
||||
}
|
||||
if (y == 0)
|
||||
/* This adjacent face was done already */
|
||||
return lpListInfo;
|
||||
}
|
||||
free (pfNode);
|
||||
}
|
||||
|
||||
void Output_Edge(int *index,int e2,int e3,int *output1,int *output2)
|
||||
{
|
||||
/* Given a quad and an input edge return the other 2 vertices of the
|
||||
quad.
|
||||
*/
|
||||
|
||||
*output1 = -1;
|
||||
*output2 = -1;
|
||||
|
||||
if ((*(index) != e2) && (*(index) != e3))
|
||||
*output1 = *(index);
|
||||
|
||||
if ((*(index+1) != e2) && (*(index+1) != e3))
|
||||
{
|
||||
if (*output1 == -1)
|
||||
*output1 = *(index+1);
|
||||
else
|
||||
{
|
||||
*output2 = *(index+1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((*(index+2) != e2) && (*(index+2) != e3))
|
||||
{
|
||||
if (*output1 == -1)
|
||||
*output1 = *(index+2);
|
||||
else
|
||||
{
|
||||
*output2 = *(index+2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
*output2 = *(index+3);
|
||||
}
|
||||
|
||||
|
||||
void First_Edge(int *id1,int *id2, int *id3)
|
||||
{
|
||||
/* Get the first triangle in the strip we just found, we will use this to
|
||||
try to extend backwards in the strip
|
||||
*/
|
||||
|
||||
ListHead *pListHead;
|
||||
register int num;
|
||||
P_STRIPS temp1,temp2,temp3;
|
||||
|
||||
pListHead = strips[0];
|
||||
num = NumOnList(pListHead);
|
||||
|
||||
/* Did not have a strip */
|
||||
if (num < 3)
|
||||
return;
|
||||
|
||||
temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 0);
|
||||
temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 1);
|
||||
temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 2);
|
||||
*id1 = temp1->face_id;
|
||||
*id2 = temp2->face_id;
|
||||
*id3 = temp3->face_id;
|
||||
|
||||
}
|
||||
|
||||
void Last_Edge(int *id1, int *id2, int *id3, BOOL save)
|
||||
{
|
||||
/* We need the last edge that we had */
|
||||
static int v1, v2, v3;
|
||||
|
||||
if (save)
|
||||
{
|
||||
v1 = *id1;
|
||||
v2 = *id2;
|
||||
v3 = *id3;
|
||||
}
|
||||
else
|
||||
{
|
||||
*id1 = v1;
|
||||
*id2 = v2;
|
||||
*id3 = v3;
|
||||
}
|
||||
}
|
||||
|
||||
|
24
Stripe_w/util.h
Normal file
24
Stripe_w/util.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/********************************************************************/
|
||||
/* STRIPE: converting a polygonal model to triangle strips
|
||||
Francine Evans, 1996.
|
||||
SUNY @ Stony Brook
|
||||
Advisors: Steven Skiena and Amitabh Varshney
|
||||
*/
|
||||
/********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* STRIPE: util.h
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
void switch_lower (int *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);
|
Loading…
Reference in a new issue