]> git.mxchange.org Git - flightgear.git/blobdiff - FixObj/obj.c
Output more digits after the decimal place.
[flightgear.git] / FixObj / obj.c
index 55201f0fd8e85ee8b181c981d7abbe049797e746..cf7648604190550a82b940e8d44f05bd26e7b7d8 100644 (file)
 
 #include "obj.h"
 
-#include "../../Src/Math/mat3.h"
+#include <Math/mat3.h>
 
 
 /* what do ya' know, here's some global variables */
-float nodes[MAXNODES][3];
-float normals[MAXNODES][3];
+static double nodes[MAXNODES][3];
+static double normals[MAXNODES][3];
+static int faces[MAXNODES][3];
+int ncount, vncount, fcount;
 
-int ccw_list[MAXNODES];
+static int ccw_list[MAXNODES];
 int ccw_list_ptr;
 
-int cw_list[MAXNODES];
+static int cw_list[MAXNODES];
 int cw_list_ptr;
 
 FILE *in, *out;
 
+double refx, refy, refz;
+
 
 /* some simple list routines */
 
@@ -63,7 +67,135 @@ void list_add(int *list, int *list_ptr, int node) {
     list[*list_ptr] = node;
     *list_ptr += 1;
 
-    printf("list pointer = %d  adding %d\n", *list_ptr, node); 
+    /* printf("list pointer = %d  adding %d\n", *list_ptr, node); */
+}
+
+
+/* fix the cw list and append to ccw_list */
+void fix_cw_list(int *list, int list_ptr) {
+    int i, j, len;
+
+    if ( list_ptr < 3 ) {
+       printf("List is empty ... skipping\n");
+       return;
+    }
+
+    printf("Fixing cw list, size = %d\n", list_ptr);
+
+    i = 0;
+    while ( i < list_ptr ) { 
+       /* do next strip */
+
+       /* find length */
+       len = 0;
+       /* scan rest of strip (until -1) */
+       while ( ((i+len) < list_ptr) && (list[i+len] != -1) ) { 
+           // printf("len = %d item = %d\n", len, list[i+len] );
+           len++;
+       }
+       // printf("          Final length = %d\n", len);
+
+       if ( (len % 2) != 0 ) {
+           /* if length is odd, just reverse order of nodes to reverse
+              winding */
+           if ( ccw_list_ptr ) {
+               list_add(ccw_list, &ccw_list_ptr, -1);
+           }
+           for ( j = i + len - 1; j >= i; j-- ) {
+               // printf(" odd -> item = %d\n", list[j] );
+               list_add(ccw_list, &ccw_list_ptr, list[j]);
+           }
+       } else {
+           /* if length is even, reverse order of (n-1) nodes to
+              reverse winding, and create an orphan triangle for the
+              last "nth" node */
+           if ( ccw_list_ptr ) {
+               list_add(ccw_list, &ccw_list_ptr, -1);
+           }
+           for ( j = i + len - 2; j >= i; j-- ) {
+               // printf(" even -> item = %d\n", list[j] );
+               list_add(ccw_list, &ccw_list_ptr, list[j]);
+           }
+
+           // printf(" even bonus -> item = %d\n", list[i + len - 1] );
+           // printf(" even bonus -> item = %d\n", list[i + len - 2] );
+           // printf(" even bonus -> item = %d\n", list[i + len - 3] );
+           list_add(ccw_list, &ccw_list_ptr, -1);
+           list_add(ccw_list, &ccw_list_ptr, list[i + len - 3]);
+           list_add(ccw_list, &ccw_list_ptr, list[i + len - 2]);
+           list_add(ccw_list, &ccw_list_ptr, list[i + len - 1]);
+       }
+
+       i += len + 1;
+    }
+}
+
+
+// Calculate distance between (0,0,0) and the specified point
+static double calc_dist(double x, double y, double z) {
+    return ( sqrt(x*x + y*y + z*z) );
+}
+
+
+void dump_global_bounds( void ) {
+    double dist, radius;
+    int i;
+
+    radius = 0.0;
+
+    fprintf(out, "\n");
+
+    for ( i = 1; i < ncount; i++ ) {
+
+       dist = calc_dist(nodes[i][0] - refx, nodes[i][1] - refy, 
+                        nodes[i][2] - refz);
+       // printf("node = %.2f %.2f %.2f dist = %.2f\n", 
+        //        nodes[i][0], nodes[i][1], nodes[i][2],
+       //        dist);
+
+       if ( dist > radius ) {
+           radius = dist;
+       }
+
+    }
+
+    fprintf(out, "gb %.5f %.5f %.5f %.2f\n", refx, refy, refz, radius);
+}
+
+
+/* dump nodes */
+void dump_nodes( void ) {
+    int i;
+
+    fprintf(out, "\n");
+    for ( i = 1; i < ncount; i++ ) {
+       fprintf(out, "v %.5f %.5f %.5f\n",
+               nodes[i][0] - refx, nodes[i][1] - refy, nodes[i][2] - refz);
+    }
+}
+
+
+/* dump normals */
+void dump_normals( void ) {
+    int i;
+
+    fprintf(out, "\n");
+    for ( i = 1; i < vncount; i++ ) {
+       fprintf(out, "vn %.5f %.5f %.5f\n", 
+               normals[i][0], normals[i][1], normals[i][2]);
+    }
+}
+
+
+/* dump faces */
+void dump_faces( void ) {
+    int i;
+
+    fprintf(out, "\n");
+    for ( i = 1; i < fcount; i++ ) {
+       fprintf(out, "f %d %d %d\n", 
+               faces[i][0], faces[i][1], faces[i][2]);
+    }
 }
 
 
@@ -82,9 +214,15 @@ void dump_list(int *list, int list_ptr) {
     while ( i < list_ptr ) { 
        /* do next strip */
 
+       if ( (i % 2) == 0 ) {
+           fprintf(out, "\nusemtl desert1\n");
+       } else {
+           fprintf(out, "\nusemtl desert2\n");
+       }
+
        /* dump header */
        fprintf(out, "t %d %d %d\n", list[i], list[i+1], list[i+2]);
-       printf("t %d %d %d\n", list[i], list[i+1], list[i+2]);
+       /* printf("t %d %d %d\n", list[i], list[i+1], list[i+2]); */
        i += 3;
 
        /* dump rest of strip (until -1) */
@@ -139,53 +277,71 @@ double check_cur_face(int n1, int n2, int n3) {
 
 
 /* Load a .obj file */
-void obj_fix(char *basename) {
+void obj_fix(char *infile, char *outfile) {
     char line[256];
-    char inpath[256], outpath[256];
     double dot_prod;
-    int first, ncount, vncount, n1, n2, n3, n4;
+    int first, n1, n2, n3, n4;
+    double x, y, z, xmax, xmin, ymax, ymin, zmax, zmin;
     int is_ccw;
 
-    strcpy(inpath, basename);
-    strcat(inpath, ".obj");
-
-    strcpy(outpath, basename);
-    strcat(outpath, ".1.obj");
-
-    if ( (in = fopen(inpath, "r")) == NULL ) {
-       printf("Cannot open file: %s\n", inpath);
+    if ( (in = fopen(infile, "r")) == NULL ) {
+       printf("Cannot open file: %s\n", infile);
        exit(-1);
     }
 
-    if ( (out = fopen(outpath, "w")) == NULL ) {
-       printf("Cannot open file: %s\n", outpath);
+    if ( (out = fopen(outfile, "w")) == NULL ) {
+       printf("Cannot open file: %s\n", outfile);
        exit(-1);
     }
 
     list_init(&ccw_list_ptr);
     list_init(&cw_list_ptr);
 
+    /* I start counting at one because that is how the triangle
+       program refers to nodes and normals */
     first = 1;
     ncount = 1;
     vncount = 1;
+    fcount = 1;
 
-    printf("Reading file:  %s\n", inpath);
+    printf("Reading file:  %s\n", infile);
 
     while ( fgets(line, 250, in) != NULL ) {
        if ( line[0] == '#' ) {
            /* pass along the comments verbatim */
            fprintf(out, "%s", line);
        } else if ( strlen(line) <= 1 ) {
-           /* pass along empty lines */
-           fprintf(out, "%s", line);
+           /* don't pass along empty lines */
+           // fprintf(out, "%s", line);
        } else if ( strncmp(line, "v ", 2) == 0 ) {
            /* save vertex to memory and output to file */
             if ( ncount < MAXNODES ) {
                 /* printf("vertex = %s", line); */
-                sscanf(line, "v %f %f %f\n", 
-                       &nodes[ncount][0], &nodes[ncount][1], &nodes[ncount][2]);
-               fprintf(out, "v %.2f %.2f %.2f\n", 
-                      nodes[ncount][0], nodes[ncount][1], nodes[ncount][2]);
+                sscanf(line, "v %lf %lf %lf\n", &x, &y, &z);
+               nodes[ncount][0] = x;
+               nodes[ncount][1] = y;
+               nodes[ncount][2] = z;
+
+               /* first time through set min's and max'es */
+               if ( ncount == 1 ) {
+                   xmin = x;
+                   xmax = x;
+                   ymin = y;
+                   ymax = y;
+                   zmin = z;
+                   zmax = z;
+               }
+    
+               /* keep track of min/max vertex values */
+               if ( x < xmin ) xmin = x;
+               if ( x > xmax ) xmax = x;
+               if ( y < ymin ) ymin = y;
+               if ( y > ymax ) ymax = y;
+               if ( z < zmin ) zmin = z;
+               if ( z > zmax ) zmax = z;               
+
+               // fprintf(out, "v %.2f %.2f %.2f\n", 
+               //       nodes[ncount][0], nodes[ncount][1], nodes[ncount][2]);
                ncount++;
             } else {
                 printf("Read too many nodes ... dying :-(\n");
@@ -195,11 +351,11 @@ void obj_fix(char *basename) {
            /* save vertex normals to memory and output to file */
             if ( vncount < MAXNODES ) {
                 /* printf("vertex normal = %s", line); */
-                sscanf(line, "vn %f %f %f\n", 
+                sscanf(line, "vn %lf %lf %lf\n", 
                        &normals[vncount][0], &normals[vncount][1], 
                        &normals[vncount][2]);
-               fprintf(out, "vn %.4f %.4f %.4f\n", normals[vncount][0], 
-                       normals[vncount][1], normals[vncount][2]);
+               // fprintf(out, "vn %.4f %.4f %.4f\n", normals[vncount][0], 
+               //      normals[vncount][1], normals[vncount][2]);
                 vncount++;
             } else {
                 printf("Read too many vertex normals ... dying :-(\n");
@@ -215,8 +371,16 @@ void obj_fix(char *basename) {
            printf("new tri strip = %s", line);
            sscanf(line, "t %d %d %d %d\n", &n1, &n2, &n3, &n4);
 
+           /* special cases to handle bugs in our beloved tri striper */
+           if ( (n1 == 4) && (n2 == 2) && (n3 == 2) && (n4 == 1) ) {
+               n2 = 3;
+           }
+           if ( (n1 == 3) && (n2 == 1) && (n3 == 1) && (n4 == 0) ) {
+               n3 = 4;
+           }
+
            dot_prod = check_cur_face(n1, n2, n3);
-           if ( dot_prod < -0.5 ) {
+           if ( dot_prod < 0.0 ) {
                /* this stripe is backwards (CW) */
                is_ccw = 0;
                printf(" -> Starting a backwards stripe\n");
@@ -251,8 +415,20 @@ void obj_fix(char *basename) {
                }
            }
        } else if ( line[0] == 'f' ) {
-           /* pass along the unoptimized faces verbatim */
-           fprintf(out, "%s", line);
+           if ( fcount < MAXNODES ) {
+               /* pass along the unoptimized faces verbatim */
+               sscanf(line, "f %d %d %d\n", &n1, &n2, &n3);
+               faces[fcount][0] = n1;
+               faces[fcount][1] = n2;
+               faces[fcount][2] = n3;
+
+               fcount++;
+           } else {
+               printf("Read too many unoptimized faces ... dying :-(\n");
+                exit(-1);
+           }
+           // fprintf(out, "%s", line);
        } else if ( line[0] == 'q' ) {
            /* continue a triangle strip */
            n1 = n2 = 0;
@@ -274,15 +450,26 @@ void obj_fix(char *basename) {
                }
            }
        } else {
-           printf("Unknown line in %s = %s\n", inpath, line);
+           printf("Unknown line in %s = %s\n", infile, line);
        }
     }
 
-    fprintf(out, "winding ccw\n");
-    dump_list(ccw_list, ccw_list_ptr);
+    /* reference point is the "center" */
+    refx = (xmin + xmax) / 2.0;
+    refy = (ymin + ymax) / 2.0;
+    refz = (zmin + zmax) / 2.0;
 
-    fprintf(out, "winding cw\n");
-    dump_list(cw_list, cw_list_ptr);
+    /* convert the cw_list to ccw add append to ccw_list */
+    fix_cw_list(cw_list, cw_list_ptr);
+
+    dump_global_bounds();
+    dump_nodes();
+    dump_normals();
+    if ( fcount > 1 ) {
+       dump_faces();
+    }
+
+    dump_list(ccw_list, ccw_list_ptr);
 
     fclose(in);
     fclose(out);
@@ -290,7 +477,49 @@ void obj_fix(char *basename) {
 
 
 /* $Log$
-/* Revision 1.1  1997/12/08 19:28:54  curt
-/* Initial revision.
+/* Revision 1.14  1998/05/23 15:19:49  curt
+/* Output more digits after the decimal place.
 /*
+ * Revision 1.13  1998/05/20 20:55:19  curt
+ * Fixed arbitrary polygon winding problem here so all tristrips are passed
+ * to runtime simulator with a consistant counter clockwise winding.
+ *
+ * Revision 1.12  1998/05/16 13:11:26  curt
+ * Fixed an off by one error in node, normal, and face counters.
+ *
+ * Revision 1.11  1998/04/27 15:59:24  curt
+ * Fixed an off by one error.
+ *
+ * Revision 1.10  1998/04/27 03:33:11  curt
+ * Code now calculates a center reference points and outputs everything
+ * relative to that.  This is useful in the rendering engine to keep everything
+ * close to (0, 0, 0) where we can avoid many GLfloat precision problems.
+ *
+ * Revision 1.9  1998/04/18 04:01:03  curt
+ * Now use libMath rather than having local copies of math routines.
+ *
+ * Revision 1.8  1998/04/08 23:19:37  curt
+ * Adopted Gnu automake/autoconf system.
+ *
+ * Revision 1.7  1998/03/19 02:51:41  curt
+ * Added special case handling to compensate for bugs in our beloved tri striper
+ *
+ * Revision 1.6  1998/03/03 15:36:12  curt
+ * Tweaks for compiling with g++
+ *
+ * Revision 1.5  1998/03/03 03:37:03  curt
+ * Cumulative tweaks.
+ *
+ * Revision 1.4  1998/01/31 00:41:25  curt
+ * Made a few changes converting floats to doubles.
+ *
+ * Revision 1.3  1998/01/19 19:51:07  curt
+ * A couple final pre-release tweaks.
+ *
+ * Revision 1.2  1998/01/09 23:03:12  curt
+ * Restructured to split 1deg x 1deg dem's into 64 subsections.
+ *
+ * Revision 1.1  1997/12/08 19:28:54  curt
+ * Initial revision.
+ *
  */