1
0
Fork 0
flightgear/Stripe_w/bands.c

561 lines
15 KiB
C
Raw Normal View History

1998-07-31 18:27:36 +00:00
/********************************************************************/
/* STRIPE: converting a polygonal model to triangle strips
Francine Evans, 1996.
SUNY @ Stony Brook
Advisors: Steven Skiena and Amitabh Varshney
*/
/********************************************************************/
/*---------------------------------------------------------------------*/
/* STRIPE: bands.c
This file contains the main procedure code that will read in the
object and then call the routines that produce the triangle strips.
*/
/*---------------------------------------------------------------------*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "global.h"
#include "polverts.h"
#include "triangulate.h"
#include "ties.h"
#include "outputex.h"
#include "options.h"
#include "local.h"
#include "init.h"
#include "free.h"
#include "add.h"
/* TIMING for Windows */
#ifdef WIN32
#include <sys/timeb.h>
#include <time.h>
/* TIMING for UNIX */
#else
#include <sys/types.h>
#include <sys/param.h>
#include <sys/times.h>
extern long times( );
long elapsed()
{
static long total = 0;
long cpu_time, dummy;
struct tms buffer;
times(&buffer);
dummy = buffer.tms_utime + buffer.tms_stime +
buffer.tms_cutime + buffer.tms_cstime;
cpu_time = ((dummy - total) * 1000) / HZ;
total = dummy;
return(cpu_time);
}
#endif
int norms[STRIP_MAX];
int *vert_norms;
int *vert_texture;
void get_time()
{
/* For timing */
#ifdef WIN32
struct timeb timebuffer;
char *timeline;
#else
long timer;
#endif
#ifdef WIN32
ftime( &timebuffer );
timeline = ctime( & ( timebuffer.time ) );
printf( "The time is %.19s.%hu %s", timeline, timebuffer.millitm, &timeline[20] );
#else
timer = elapsed();
printf("The time is %ld\n",timer);
#endif
}
/*
**
Here the main program begins. It will start by loading in a .obj file
then it will convert the polygonal model into triangle strips.
**
*/
int main (int argc,char *argv[])
{
char *fname,*all,buff[255], *ptr, *ptr2;
FILE *file, *bands;
int face_id=0;
int vert_count=0;
int loop=0;
int num=0;
int num2=0;
float center[3];
int temp[STRIP_MAX],vertex,strips, swaps,tempi,cost,triangles;
int f,t,tr,g;
char *file_open;
int num_vert = 0,
num_faces = 0,
num_nvert = 0,
num_edges = 0,
num_texture = 0,
num_tris = 0;
double fra = 0.0;
BOOL texture, normal, normal_and_texture,quads = FALSE;
/* Options variables */
double norm_difference;
/* Structures for the object */
struct vert_struct *vertices = NULL,
*nvertices = NULL,
*pvertices = NULL,
*pnvertices = NULL;
get_time();
/* File that will contain the triangle strip data */
bands = fopen("stripe.objf","w");
/*
Scan the file once to find out the number of vertices,
vertice normals, and faces so we can set up some memory
structures
*/
/* Interpret the options specified */
norm_difference = get_options(argc,argv,&f,&t,&tr,&g);
if (f == BINARY)
file_open = "rb";
else
file_open = "r";
fname = argv[argc-1];
printf ("File: %s\n",fname);
printf ("Scanning...%s ",file_open);
/* File can be in binary for faster reading */
if (file = fopen (fname,file_open))
{
while (!feof (file))
{
/* Read a line */
if (f == BINARY)
fread (buff,sizeof(char) * 255,1, file);
else
fgets (buff, sizeof(char) * 255, file);
num++;
printf("%d\r",num);
/* At a vertex */
if (*buff == 'v')
{
/* At a normal */
if (*(buff+1)=='n')
num_nvert++;
else if (*(buff+1)=='t')
num_texture++;
/* At a regular vertex */
else
num_vert++;
}
/* At a face */
else if (*buff == 'f')
{
num_faces++;
strtok(buff, " ");
tempi = 0;
while (strtok(NULL, " ") != NULL) tempi++;
num_tris += tempi - 2;
}
}
fclose (file);
}
else
{
printf("Error in the file name\n");
exit(1);
}
printf("%s pass 1\n",fname);
/* Allocate structures for the information */
Start_Face_Struct(num_faces);
vertices = (struct vert_struct *)
malloc (sizeof (struct vert_struct) * num_vert);
if (num_nvert > 0) {
nvertices = (struct vert_struct *)
malloc (sizeof (struct vert_struct) * num_nvert);
vert_norms = (int *) malloc (sizeof (int) * num_vert);
/*
Initialize entries to zero, in case there are 2 hits
to the same vertex we will know it - used for determining
the normal difference
*/
init_vert_norms(num_vert);
} else {
nvertices = NULL;
}
if (num_texture > 0) {
vert_texture = (int *) malloc (sizeof(int) * num_vert);
init_vert_texture(num_vert);
}
/*
Set up the temporary 'p' pointers
*/
pvertices = vertices;
pnvertices = nvertices;
/* Load the object into memory */
/*printf (" Loading...");*/
fprintf(bands,"#%s: a triangle strip representation created by STRIPE.\n#This is a .objf file\n#by Francine Evans\n",fname);
/* File will be put in a list for faster execution if file is in binary */
if (file = fopen(fname,file_open)) {
if (f == BINARY) {
all = (char *) malloc (sizeof(char) * 255 * num);
fread(all,sizeof(char) * 255 * num, 1, file);
ptr = all;
} else {
ptr = (char *) malloc (sizeof(char) * 255 * num);
}
}
while (num > 0) {
num--;
printf("%d\r",num);
if (f == ASCII) {
fgets (ptr, sizeof(char) * 255, file);
} else {
ptr = ptr + 255;
}
/* Load in vertices/normals */
if (*ptr == 'v') {
if (*(ptr+1)=='n') {
sscanf (ptr+3,"%lf%lf%lf",
&(pnvertices->x),
&(pnvertices->y),
&(pnvertices->z));
fprintf(bands,"vn %f %f %f\n",
pnvertices->x,pnvertices->y,pnvertices->z);
++pnvertices;
} else if (*(ptr+1)=='t') {
sscanf (ptr+3,"%f%f%f",&center[0],&center[1],&center[2]);
fprintf(bands,"vt %f %f %f\n",center[0],center[1],center[2]);
} else {
sscanf (ptr+2,"%lf%lf%lf",
&(pvertices->x),
&(pvertices->y),
&(pvertices->z));
fprintf(bands,"v %f %f %f\n",
pvertices->x,pvertices->y,pvertices->z);
++pvertices;
}
} else if (*ptr == 'f') {
/* Read in faces */
num2 = 0;
face_id++;
ptr2 = ptr+1;
normal = FALSE; texture = FALSE, normal_and_texture = FALSE;
while (*ptr2) {
if (*ptr2 >='0' && *ptr2 <='9') {
num2++;
++ptr2;
while (*ptr2 && (*ptr2!=' ' && *ptr2!='/')) {
ptr2++;
}
/* There are normals in this line */
if (*ptr2 == '/') {
if (*(ptr2+1) == '/') {
normal = TRUE;
} else {
texture = TRUE;
}
} else if (*ptr2 == ' ') {
if ((num2 == 3) && (texture)) {
normal_and_texture = TRUE;
}
}
} else {
++ptr2;
}
}
ptr2 = ptr+1;
/*
loop on the number of numbers in this line of face data
*/
vert_count = 0;
for (loop=0;loop<num2;loop++) {
/* skip the whitespace */
while (*ptr2<'0' || *ptr2>'9') {
if (*ptr2 == '-') {
break;
}
ptr2++;
}
vertex = atoi(ptr2)-1;
if (vertex < 0) {
vertex = num_vert + vertex;
*ptr2 = ' ';
ptr2++;
}
/*
If there are either normals or textures with the vertices
in this file, the data alternates so we must read it this way
*/
if ( (normal) && (!normal_and_texture)) {
if (loop%2) {
add_norm_id(vertex,vert_count);
/*
Test here to see if we added a new vertex, since the
vertex has more than one normal and the 2 normals are greater
than the threshold specified
*/
if (norm_array(vertex,0,norm_difference,nvertices,num_vert)) {
/*
Add a new vertex and change the
id of the vertex that we just read to the id of the new
vertex that we just added
*/
/*
Put it in the output file, note the added vertices will
be after the normals and separated from the rest of the
vertices. Will not affect our viewer
*/
fprintf(bands,"v %f %f %f\n",
(vertices + temp[vert_count - 1])->x,
(vertices + temp[vert_count - 1])->y,
(vertices + temp[vert_count - 1])->z);
num_vert++;
temp[vert_count - 1] = num_vert - 1;
if (!(add_vert_id(num_vert - 1,vert_count))) {
vert_count--;
}
}
} else {
/* the vertex */
temp[vert_count] = vertex ;
vert_count++;
if (!(add_vert_id(vertex,vert_count))) {
vert_count--;
}
norm_array(vertex,1,norm_difference,nvertices,num_vert);
}
} else if (normal_and_texture) {
/* Else there are vertices and textures with the data */
if( !((loop+1)%3)) {
add_norm_id(vertex,vert_count);
/*
Test here to see if we added a new vertex, since the
vertex has more than one normal and the 2 normals are greater
than the threshold specified
*/
if (norm_array(vertex,0,norm_difference,nvertices,num_vert)) {
/*
Add a new vertex and change the
id of the vertex that we just read to the id of the new
vertex that we just added
*/
/*
Put it in the output file, note the added vertices will
be after the normals and separated from the rest of the
vertices. Will not affect our viewer
*/
fprintf(bands,"v %f %f %f\n",
(vertices + temp[vert_count - 1])->x,
(vertices + temp[vert_count - 1])->y,
(vertices + temp[vert_count - 1])->z);
num_vert++;
temp[vert_count - 1] = num_vert - 1;
if (!(add_vert_id(num_vert - 1,vert_count))) {
vert_count--;
}
}
} else if ((loop == 0) || (*(ptr2-1) == ' ')) {
/* the vertex */
temp[vert_count] = vertex ;
vert_count++;
if (vert_count == 4) {
quads = TRUE;
}
if (!(add_vert_id(vertex,vert_count))) {
vert_count--;
}
add_texture(vertex,TRUE);
norm_array(vertex,1,norm_difference,nvertices,num_vert);
} else {
/* The texture */
add_texture(vertex,FALSE);
}
} else if ( texture ) {
/* the vertex */
if (!(loop%2)) {
temp[vert_count] = vertex ;
vert_count++;
if (vert_count == 4)
quads = TRUE;
add_texture(vertex,TRUE);
if (!(add_vert_id(vertex,vert_count)))
vert_count--;
norm_array(vertex,1,norm_difference,nvertices,num_vert);
} else {
/* texture */
add_texture(vertex,FALSE);
}
} else {
/*** no nvertices ***/
temp[vert_count] = vertex ;
vert_count++;
if (vert_count == 4)
quads = TRUE;
if (!(add_vert_id(vertex,vert_count)))
vert_count--;
}
while (*ptr2>='0' && *ptr2<='9')
ptr2++;
}
/* Done with the polygon */
num_edges += vert_count;
/* add it to face structure */
if (vert_count >= 3)
AddNewFace(ids,vert_count,face_id,norms);
else
face_id--;
if (vert_count == 4)
quads = TRUE;
}
else if ((g == TRUE) && (face_id > 0)
&& ((*ptr == 'g') || (*ptr == 's') || (*ptr == 'm') || (*ptr == 'o')))
{
/*
The user specified that the strips will be contained in each group
from the data file, so we just finished a group and will find the
triangle strips in it.
*/
Start_Edge_Struct(num_vert);
Find_Adjacencies(face_id);
if (quads)
{
Init_Table_SGI();
Build_SGI_Table(num_vert,face_id);
/* Code for lengths of walks in each direction */
/* Save_Walks(face_id,TRUE); */
Save_Walks(face_id);
/* Code for finding the bands */
Find_Bands(face_id,bands,&swaps,&strips,&cost,&triangles,num_nvert,vert_norms,num_texture,vert_texture);
/*
Remove the faces that we did so that we can
run the strip code on the rest of the faces that are left
*/
if (cost != 0)
{
printf("Total %d triangles with %d cost\n",triangles,cost);
Save_Rest(&face_id);
printf("We saved %d .... now doing the local algorithm\n",face_id);
fprintf(bands,"\n#local\n");
End_Edge_Struct(num_vert);
Start_Edge_Struct(num_vert);
Find_Adjacencies(face_id);
}
}
SGI_Strip(num_vert,face_id,bands,t,tr);
/* Get the total cost */
Output_TriEx(-1,-2,-3,NULL,-1,-20,cost);
End_Face_Struct(num_faces);
End_Edge_Struct(num_vert);
cost = 0;
face_id = 0;
quads = FALSE;
Start_Face_Struct(num_faces-face_id);
num_faces = num_faces - face_id;
Free_Strips();
}
}
/* Done reading in all the information into data structures */
num_faces = face_id;
fclose (file);
printf("Input Done.\n\n");
free(vertices);
free(nvertices);
printf ("Vertices: %d\nNormals: %d\nFaces: %d\n",num_vert,num_nvert,num_faces);
Start_Edge_Struct(num_vert);
Find_Adjacencies(num_faces);
/* Initialize it */
Init_Table_SGI();
/* Build it */
Build_SGI_Table(num_vert,num_faces);
InitStripTable();
if (quads) {
/* Code for lengths of walks in each direction */
/* Save_Walks(num_faces,TRUE); */
Save_Walks(num_faces);
/* Code for finding the bands */
Find_Bands(num_faces,bands,&swaps,&strips,&cost,&triangles,num_nvert,vert_norms,num_texture,vert_texture);
/*printf("Total %d triangles with %d cost\n",triangles,cost);*/
/*
Remove the faces that we did so that we can
run the strip code on the rest of the faces that are left
*/
Save_Rest(&num_faces);
/*printf("We saved %d .... now doing the local algorithm\n",num_faces);*/
fprintf(bands,"\n#local\n");
End_Edge_Struct(num_vert);
Start_Edge_Struct(num_vert);
Find_Adjacencies(num_faces);
}
SGI_Strip(num_vert,num_faces,bands,t,tr);
/* Get the total cost */
Output_TriEx(-1,-2,-3,NULL,-1,-20,cost);
End_Face_Struct(num_faces);
End_Edge_Struct(num_vert);
fclose(bands);
get_time();
return(0);
}