pkh@vap.vi.ri.cmu.edu (Ping Kang Hsiung) (12/14/88)
I am posting the source code since among the people who requested for the source code, two of them are not reach-able from my system. Fortunately it's not a big program. Sorry for the inconvenience. *** /* * program: nfff.c * * a filter for NFF (Neutral File Format) * nfff [infile] * input: infile.nff or stdin * output: stdout * * input items other than polygons are copied to output directly. * for polygons that have 2 or more identical vertices, the redundant * vertices are filtered out and the "p <vert_count>" lines of * the polygons are adjusted properly. * * the vertices degeneration cases occur in data produced by some * automatic nff generation program when the resolution/prec. of * generation exceeds that of the floating point format. * * definition of NFF: see nff.def * bugs: * (1) handles polygons only. break if there are other obj. types * (2) MAX_VERT may cause trouble * * Fri Dec 2 16:41:27 EST 1988 * pkh@vap * * bugs fixed: * */ #include <stdio.h> #include <math.h> /* #include "/usr/pkh/include/all.h" */ /* #include "/usr/pkh/include/def3d.h" */ /* from "def3d.h" */ typedef struct pt3d_struct { float x, y, z; } pt3d, *pt3d_t; #define FPRINT3d(fp, pt, newline) do { \ if (newline) \ fprintf(fp, "%g %g %g\n", pt.x, pt.y, pt.z); \ else \ fprintf(fp, "%g %g %g", pt.x, pt.y, pt.z); \ } while (0) #define FSCAN3d(fp, pt) do { \ fscanf(fp,"%f %f %f", &(pt.x), &(pt.y), &(pt.z)); \ } while(0) #define ASSIGN3d(p0, p1) do {p0.x=p1.x; p0.y=p1.y; p0.z=p1.z;} while(0) #define EQ3d(p0, p1) ((p0.x==p1.x)&&(p0.y==p1.y)&& (p0.z==p1.z)) /* from "all.h" */ int debug; #define POW2(y) (1<<y) #define ERROR_MSG_LENGTH (200) #define DEBUG(arg) \ do { \ char msg[ERROR_MSG_LENGTH]; \ if (debug) { \ sprintf arg; \ fprintf(stderr, "%s", msg); \ } \ } while (0) #define ERROR(arg) \ do { \ char msg[ERROR_MSG_LENGTH]; \ sprintf arg; \ fprintf(stderr, "%s", msg); \ exit(0); \ } while (0) #define MAX_VERT POW2(12) /* 4k verts per poly */ pt3d *v; /* array of dim MAX_VERT */ FILE *nfffile; char infile[25]; /* * for statistics */ int total_byte; /* total byte allocated */ int poly_id; /* * copy to end of line */ copy_line(ifp, ofp) FILE *ifp, *ofp; { char c; do { putc((c=getc(ifp)), ofp); } while (c!='\n'); } int read_poly(fp) FILE *fp; { int tv; int i; fscanf(fp, "%d", &tv); for (i = 0; i < tv; i++) { FSCAN3d(fp,(v[i])); } return (tv); } /* * filter out degenerated (redundant) vertices * and return the true vert count. * complain when polygon has less than 3 vert */ int vert_filter(in_vert) int in_vert; { int head, tail; int tv, skip; /* * filter out degenerated vertices. head points to the verified vert, * tail scans down the vert list for new vert. */ head = 0; /* points to v[0] */ tail = head + 1; /* points to v[1] */ tv = 1; /* count one vert already (v[0]) */ skip = 0; /* "skip occured" flag */ do { while (EQ3d((v[head]), (v[tail]))) { tail++; if (tail == in_vert) goto last_vert; skip = 1; } if (skip) { ASSIGN3d((v[head + 1]), (v[tail])); } head++; tail++; } while (tail < in_vert); /* head now points to the last valid vert. compare last and first */ last_vert:if (EQ3d((v[0]), v[head])) tv = head; else tv = head + 1; if (tv < 3) { ERROR((msg, "poly %d has less than 3 vert\n", poly_id)); write_polygon(stderr, tv); /* write vert */ } if (debug) { write_polygon(stderr, tv); /* write vert */ } return (tv); } /* * write out the cleaned-up polygons in nff format * also print out the poly id */ write_polygon(fp, ply_vert) FILE *fp; int ply_vert; { int j; fprintf(fp, "# p%d\np %d\n", poly_id, ply_vert); for (j = 0; j < ply_vert; j++) { FPRINT3d(fp, (v[j]), 0); fprintf(fp, "\n"); } } /* * for polygons: read-filter-write * for the rest: read-write */ read_write(ifp, ofp) FILE *ifp, *ofp; { char key[20]; int in_vert, out_vert; /* read "key" */ while (fscanf(ifp, "%s", key) != EOF) { DEBUG((msg, "get key %s\n", key)); if (strcmp(key, "p") == 0) { in_vert = read_poly(ifp); out_vert = vert_filter(in_vert); write_polygon(ofp, out_vert); poly_id++; } else { fprintf(ofp, "%s ", key); copy_line(ifp, ofp); } }; } init() { int new_byte; new_byte = sizeof(pt3d) * MAX_VERT; total_byte += new_byte; v = (pt3d_t) malloc(new_byte); DEBUG((msg, "v alloc %3dB; total %5dB\n", new_byte, total_byte)); if (v == NULL) ERROR((msg, "v array alloc err\n")); poly_id = 0; } main(argc, argv) int argc; char *argv[]; { if (argc == 1) { nfffile= stdin; } else if (argc == 2) { /* append .nff suffix */ sprintf(infile, "%s.nff", argv[1]); if ((nfffile= fopen(infile, "r")) == NULL) { ERROR((msg, "input file %s not found\n", infile)); exit(1); } } else { ERROR((msg, "Usage: %s [file].nff\n", argv[0])); exit(1); } debug = 0; init(); fprintf(stdout, "#\n# polygons filtered by nfffilter program\n"); fprintf(stdout, "# date:\n#\n"); read_write(nfffile, stdout); } --