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