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

304 lines
7.9 KiB
C

/********************************************************************/
/* 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 reversed, 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 */
reversed = Get_EdgeEx(&output1,&output2,index,ties_array[0],3,0,0);
reversed = 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 reversed,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++)
{
reversed = 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,reversed,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++)
{
reversed = 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]);
}