NFF filter

Didier Badouel badouel at irisa.irisa.fr
Fri Sep 15 23:39:20 AEST 1989


This is a new filter program for NFF databases, it  converts polygons (p)
into patches (pp) computing normal vector for vertices. 

________________________________________________________________
  Didier  BADOUEL   		        badouel at 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 at 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 at vap):
  2) redundant vertices are filtered out and the "p <vert_count>" lines of
     the polygons are adjusted properly. Degenerated polygons are 
     rejected.
 
  ___________________________________________________________________________*/

#include <stdio.h>
#include <math.h>

#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; i<ns; i++) {
    NORM_VEC(&(normal_space[i]));
  }
  fprintf(ofp,"#number %d\n",np);
  fprintf(ofp,"#bound\n#%g %g %g %g %g %g\n",
	  x_min,x_max,y_min,y_max,z_min,z_max);
  if (np == 1) {
    /*
     * write one polygon.
     */
    int n = poly_space[i].n;

    fprintf(stderr,"object: 1 polygon\n");
    fprintf(ofp, "p %d\n", n);
    s = poly_space[i].s;
    for (j=0; j<n; j++) {
      v = &(vertex_space[s[j]]);
      fprintf(ofp,"%g %g %g ",v->x,v->y,v->z);
      fprintf(ofp, "\n");
    }
  } else {
  /*
   * write patches.
   */
    fprintf(stderr,"object: %d polygons\n",np);
    for (i=0; i<np; i++) {
      int n = poly_space[i].n;
      fprintf(ofp, "pp %d\n", n);
      s = poly_space[i].s;
      for (j=0; j<n; j++) {
	v = &(vertex_space[s[j]]);
	fprintf(ofp,"%g %g %g ",v->x,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);
}



More information about the Alt.sources mailing list