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

384 lines
9.7 KiB
C

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