1
0
Fork 0
flightgear/Stripe_w/struct.c
1998-07-31 18:27:36 +00:00

549 lines
14 KiB
C

/********************************************************************/
/* 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);
}