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

810 lines
21 KiB
C

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