1
0
Fork 0
flightgear/Tools/Stripe_u/partial.c
2009-09-14 13:43:55 +02:00

665 lines
23 KiB
C

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