Xref: utzoo comp.graphics:7500 alt.sources:1034 Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!uwm.edu!uakari.primate.wisc.edu!aplcen!ginosko!uunet!mcsun!inria!irisa!badouel From: badouel@irisa.irisa.fr (Didier Badouel) Newsgroups: comp.graphics,alt.sources Subject: NFF filter Keywords: NFF,patches Message-ID: <1481@irisa.irisa.fr> Date: 15 Sep 89 13:39:20 GMT Organization: IRISA, Rennes (Fr) Lines: 358 This is a new filter program for NFF databases, it converts polygons (p) into patches (pp) computing normal vector for vertices. ________________________________________________________________ Didier BADOUEL badouel@irisa.fr INRIA / IRISA Phone : +33 99 36 20 00 Campus Universitaire de Beaulieu Fax : 99 38 38 32 35042 RENNES CEDEX - FRANCE Telex : UNIRISA 950 473F ________________________________________________________________ ++++++++++++++++++++++++++cut here+++++++++++++++++++++++++++++++++++++++++++++ /*__________________________________________________________________________ Fichier : ptopp.c Auteur : Didier BADOUEL (badouel@irisa.fr) ___________________________________________________________________________ ptopp [infile] input: infile.nff or stdin output: stdout 1) convert polygons to patches computing normal vector for vertices. hacked from nfff.c (author: pkh@vap): 2) redundant vertices are filtered out and the "p " lines of the polygons are adjusted properly. Degenerated polygons are rejected. ___________________________________________________________________________*/ #include #include #define MAXPOLY 100000 #define MAXVERTEX 350000 #define MAXPOINT 4 #define EPSIcmp 1e-05 #define MAXfloat ((float) 1.701411733192644299e+38) #define MINfloat ((float)-1.701411733192644299e+38) #define PROD_SCAL(A,B) ((A)->x*(B)->x+(A)->y*(B)->y+(A)->z*(B)->z) #define PROD_VEC(A,B,C) {\ (C)->x=(A)->y*(B)->z-(A)->z*(B)->y;\ (C)->y=(A)->z*(B)->x-(A)->x*(B)->z;\ (C)->z=(A)->x*(B)->y-(A)->y*(B)->x;\ } #define SIZE_VEC(A) (sqrt((double)PROD_SCAL(A,A))) #define NORM_VEC(A) {\ double _len = SIZE_VEC(A);\ (A)->x /= _len;\ (A)->y /= _len;\ (A)->z /= _len;\ } #define VECTOR(A,B,C) {\ (C)->x = (B)->x - (A)->x;\ (C)->y = (B)->y - (A)->y;\ (C)->z = (B)->z - (A)->z;\ } #define ADD_VEC(A,B,C) {\ (C)->x = (A)->x + (B)->x;\ (C)->y = (A)->y + (B)->y;\ (C)->z = (A)->z + (B)->z;\ } typedef struct { float x; float y; float z; } Vec; typedef struct { int n; int s[MAXPOINT]; } Poly; /* Space for points */ Vec vertex_space[MAXVERTEX]; /* Space for normal vectors */ Vec normal_space[MAXVERTEX]; /* Space for polygons */ Poly poly_space[MAXPOLY]; int *s; long ns, np; Vec vector, point; float x_min, x_max, y_min, y_max, z_min, z_max; float X_min, X_max, Y_min, Y_max, Z_min, Z_max; char infile[25]; FILE *ifp, *ofp; main(argc, argv) int argc; char *argv[]; { if (argc == 1) { ifp= stdin; } else if (argc == 2) { /* append .nff suffix */ sprintf(infile, "%s.nff", argv[1]); if ((ifp= fopen(infile, "r")) == NULL) { fprintf(stderr, "input file %s not found\n", infile); exit(1); } } else { fprintf(stderr, "Usage: %s [file].nff\n", argv[0]); exit(1); } ofp = stdout; ReadWrite(); exit(0); } /* * for polygons: read-filter-write * for the rest: read-write */ ReadWrite() { char key[20]; /* read "key" */ X_min = Y_min = Z_min = MAXfloat; X_max = Y_max = Z_max = MINfloat; x_min = y_min = z_min = MAXfloat; x_max = y_max = z_max = MINfloat; while (fscanf(ifp, "%s", key) != EOF) { if (strcmp(key, "p") == 0) { ReadPoly(); } else if (strcmp(key, "pp") == 0) { ReadPatch(); } else { /* * anything different than a polygon is used * as a separator of object. */ if (np != 0) WriteObject(); fprintf(ofp, "%s ", key); CopyLine(); } } if (np != 0) WriteObject(); fprintf(stderr,"scene bound: x %f, %f y %f, %f z %f, %f\n", X_min,X_max,Y_min,Y_max,Z_min,Z_max); } /* * copy to end of line */ CopyLine() { char c; do { putc((c=getc(ifp)), ofp); } while (c!='\n'); } StorePoint () { int i; for (i=ns-1; i>=0; i--) { if ((vertex_space[i].x == point.x)&& (vertex_space[i].y == point.y)&& (vertex_space[i].z == point.z)) { return(i); } } if (point.x < x_min) x_min = point.x; if (point.x > x_max) x_max = point.x; if (point.y < y_min) y_min = point.y; if (point.y > y_max) y_max = point.y; if (point.z < z_min) z_min = point.z; if (point.z > z_max) z_max = point.z; if (ns>=MAXVERTEX) { fprintf(stderr,"Too much vertices (MAXVERTEX = %d)\n",MAXVERTEX); exit(-1); } vertex_space[ns].x = point.x; vertex_space[ns].y = point.y; vertex_space[ns].z = point.z; normal_space[ns].x = 0.0; normal_space[ns].y = 0.0; normal_space[ns].z = 0.0; return(ns++); } /* * filter out degenerated (redundant) vertices * and return the true vert count. * complain when polygon has less than 3 vert */ VertFilter() { int head, tail; int tv, skip,in_vert; /* * filter out degenerated vertices. head points to the verified vert, * tail scans down the vert list for new vert. */ in_vert = poly_space[np].n; head = 0; /* points to s[0] */ tail = head + 1; /* points to s[1] */ tv = 1; /* count one vert already (s[0]) */ skip = 0; /* "skip occured" flag */ do { while (s[head] == s[tail]) { tail++; if (tail == in_vert) goto last_vert; skip = 1; } if (skip) { s[head + 1] = s[tail]; } head++; tail++; } while (tail < in_vert); /* head now points to the last valid vert. compare last and first */ last_vert:if (s[0] == s[head]) poly_space[np].n = head; else poly_space[np].n = head + 1; } ReadPoly() { int n; int i; fscanf(ifp, "%d", &n); if (np>=MAXPOLY) { fprintf(stderr,"Too much polygons (MAXPOLY = %d)\n",MAXPOLY); exit(-1); } poly_space[np].n = n; s = poly_space[np].s; for (i = 0; i < n; i++) { fscanf(ifp,"%f %f %f", &(point.x), &(point.y), &(point.z)); s[i] = StorePoint (); } VertFilter (); VecPlane(); n = poly_space[np].n; if (n<3) { fprintf(stderr,"degenerated polygon: reject\n"); return; } for (i = 0; i < n; i++) { ADD_VEC(&(normal_space[s[i]]), &(vector), &(normal_space[s[i]])); } np++; } ReadPatch() { int n; int i; fscanf(ifp, "%d", &n); if (np>=MAXPOLY) { fprintf(stderr,"Too much polygons (MAXPOLY = %d)\n",MAXPOLY); exit(-1); } poly_space[np].n = n; s = poly_space[np].s; for (i = 0; i < n; i++) { fscanf(ifp,"%f %f %f", &(point.x), &(point.y), &(point.z)); s[i] = StorePoint (); fscanf(ifp,"%f %f %f", &(normal_space[s[i]].x), &(normal_space[s[i]].y), &(normal_space[s[i]].z)); } VertFilter (); n = poly_space[np].n; if (n<3) { fprintf(stderr,"degenerated polygon: reject\n"); return; } np++; } WriteObject() { int i,j; Vec *v; /* * compute normal vectors. */ for (i=0; ix,v->y,v->z); fprintf(ofp, "\n"); } } else { /* * write patches. */ fprintf(stderr,"object: %d polygons\n",np); for (i=0; ix,v->y,v->z); v = &(normal_space[s[j]]); fprintf(ofp,"%g %g %g",v->x,v->y,v->z); fprintf(ofp, "\n"); } } } fprintf(stderr,"bound: x %f, %f y %f, %f z %f, %f\n\n", x_min,x_max,y_min,y_max,z_min,z_max); if (x_min < X_min) X_min = x_min; if (x_max > X_max) X_max = x_max; if (y_min < Y_min) Y_min = y_min; if (y_max > Y_max) Y_max = y_max; if (z_min < Z_min) Z_min = z_min; if (z_max > Z_max) Z_max = z_max; x_min = y_min = z_min = MAXfloat; x_max = y_max = z_max = MINfloat; np = 0; ns = 0; } VecPlane () { Vec u, v; /* * Compute normal vector */ VECTOR (&(vertex_space[s[0]]),&(vertex_space[s[1]]),&u); VECTOR (&(vertex_space[s[0]]),&(vertex_space[s[2]]),&v); PROD_VEC(&u,&v,&vector); NORM_VEC(&vector); }