source: proiecte/pmake3d/make3d_original/Make3dSingleImageStanford_version0.1/third_party/vrippack-0.31/src/plytools/plynormals.c @ 37

Last change on this file since 37 was 37, checked in by (none), 14 years ago

Added original make3d

File size: 10.0 KB
Line 
1/*
2
3Compute vertex normals.
4
5Greg Turk, August 1994
6
7*/
8
9#include <stdlib.h>
10#include <stdio.h>
11#include <math.h>
12#include <malloc.h>
13#include <strings.h>
14#include <ply.h>
15
16
17/* user's vertex and face definitions for a polygonal object */
18
19typedef struct Vertex {
20  float x,y,z;
21  float nx,ny,nz;
22  void *other_props;       /* other properties */
23} Vertex;
24
25typedef struct Face {
26  unsigned char nverts;    /* number of vertex indices in list */
27  int *verts;              /* vertex index list */
28  void *other_props;       /* other properties */
29} Face;
30
31char *elem_names[] = { /* list of the kinds of elements in the user's object */
32  "vertex", "face"
33};
34
35PlyProperty vert_props[] = { /* list of property information for a vertex */
36  {"x", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,x), 0, 0, 0, 0},
37  {"y", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,y), 0, 0, 0, 0},
38  {"z", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,z), 0, 0, 0, 0},
39  {"nx", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,nx), 0, 0, 0, 0},
40  {"ny", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,ny), 0, 0, 0, 0},
41  {"nz", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,nz), 0, 0, 0, 0},
42};
43
44PlyProperty face_props[] = { /* list of property information for a vertex */
45  {"vertex_indices", PLY_INT, PLY_INT, offsetof(Face,verts),
46   1, PLY_UCHAR, PLY_UCHAR, offsetof(Face,nverts)},
47};
48
49
50/*** the PLY object ***/
51
52static int nverts,nfaces;
53static Vertex **vlist;
54static Face **flist;
55static PlyOtherElems *other_elements = NULL;
56static PlyOtherProp *vert_other,*face_other;
57static int nelems;
58static char **elist;
59static int num_comments;
60static char **comments;
61static int num_obj_info;
62static char **obj_info;
63static int file_type;
64
65static int flip_sign = 0;       /* flip the sign of the normals? */
66static int area_weight = 0;     /* use area weighted average */
67
68void usage(char *progname);
69void write_file();
70void read_file(FILE *inFile);
71void compute_normals();
72
73/******************************************************************************
74Main program.
75******************************************************************************/
76
77int
78main(int argc, char *argv[])
79{
80  int i,j;
81  char *s;
82  char *progname;
83  FILE *inFile = stdin;
84
85  progname = argv[0];
86
87  while (--argc > 0 && (*++argv)[0]=='-') {
88    for (s = argv[0]+1; *s; s++)
89      switch (*s) {
90        case 'f':
91          flip_sign = 1;
92          break;
93        case 'a':
94          area_weight = 1;
95          break;
96        default:
97          usage (progname);
98          exit (-1);
99          break;
100      }
101  }
102
103
104   /* optional input file (if not, read stdin ) */
105   if (argc > 0 && *argv[0] != '-') {
106       inFile = fopen(argv[0], "r");
107       if (inFile == NULL) {
108           fprintf(stderr, "Error: Couldn't open input file %s\n", argv[0]);
109           usage(progname);
110           exit(-1);
111       }
112       argc --;
113       argv ++;
114   } 
115
116   /* Check no extra args */
117   if (argc > 0) {
118     fprintf(stderr, "Error: Unhandled arg: %s\n", argv[0]);
119     usage(progname);
120     exit(-1);
121   }
122
123  read_file(inFile);
124
125  compute_normals();
126
127  write_file();
128}
129
130
131/******************************************************************************
132Print out usage information.
133******************************************************************************/
134
135void
136usage(char *progname)
137{
138  fprintf (stderr, "usage: %s [flags] [in.ply] > out.ply\n", progname);
139  fprintf (stderr, "   or: %s [flags] < in.ply > out.ply\n", progname);
140  fprintf (stderr, "       -f (flip sign of normals)\n");
141  fprintf (stderr, "       -a (use area weighted average)\n");
142}
143
144
145/******************************************************************************
146Compute normals at the vertices.
147******************************************************************************/
148
149void
150compute_normals()
151{
152  int i,j;
153  Face *face;
154  Vertex *vert;
155  int *verts;
156  float x,y,z;
157  float x0,y0,z0;
158  float x1,y1,z1;
159  float len;
160  float recip;
161
162  /* zero out all normal information at vertices */
163
164  for (i = 0; i < nverts; i++) {
165    vlist[i]->nx = 0;
166    vlist[i]->ny = 0;
167    vlist[i]->nz = 0;
168  }
169
170  /* find normal of each face and add it to each vertex adjacent to the face */
171
172  for (i = 0; i < nfaces; i++) {
173
174    face = flist[i];
175    verts = face->verts;
176
177    /* determine vectors parallel to two edges of face */
178
179    x0 = vlist[verts[face->nverts-1]]->x - vlist[verts[0]]->x;
180    y0 = vlist[verts[face->nverts-1]]->y - vlist[verts[0]]->y;
181    z0 = vlist[verts[face->nverts-1]]->z - vlist[verts[0]]->z;
182
183    x1 = vlist[verts[1]]->x - vlist[verts[0]]->x;
184    y1 = vlist[verts[1]]->y - vlist[verts[0]]->y;
185    z1 = vlist[verts[1]]->z - vlist[verts[0]]->z;
186
187    /* find cross-product between these vectors */
188    x = y0 * z1 - z0 * y1;
189    y = z0 * x1 - x0 * z1;
190    z = x0 * y1 - y0 * x1;
191
192    /* normalize this vector */
193    len = x*x + y*y + z*z;
194    if (len == 0) {
195      x = y = z = 0;
196    }
197    else {
198      if (area_weight)
199          recip = 1;
200      else
201          recip = 1 / sqrt (len);
202      x *= recip;
203      y *= recip;
204      z *= recip;
205    }
206
207    /* add this normal to each vertex that is adjacent to face */
208    for (j = 0; j < face->nverts; j++) {
209      vlist[verts[j]]->nx += x;
210      vlist[verts[j]]->ny += y;
211      vlist[verts[j]]->nz += z;
212    }
213  }
214
215  /* normalize all the normals at the vertices */
216
217  for (i = 0; i < nverts; i++) {
218    vert = vlist[i];
219    len = vert->nx * vert->nx + vert->ny * vert->ny + vert->nz * vert->nz;
220    if (len == 0) {
221      vert->nx = 0;
222      vert->ny = 0;
223      vert->nz = 0;
224    }
225    else {
226      if (flip_sign)
227        recip = -1 / sqrt (len);
228      else
229        recip = 1 / sqrt (len);
230      vert->nx *= recip;
231      vert->ny *= recip;
232      vert->nz *= recip;
233    }
234  }
235}
236
237
238/******************************************************************************
239Read in the PLY file from standard in.
240******************************************************************************/
241
242void
243read_file(FILE *inFile)
244{
245  int i,j,k;
246  PlyFile *ply;
247  int nprops;
248  int num_elems;
249  PlyProperty **plist;
250  char *elem_name;
251  float version;
252  int get_nx,get_ny,get_nz;
253
254  /*** Read in the original PLY object ***/
255
256
257  ply  = ply_read (inFile, &nelems, &elist);
258  ply_get_info (ply, &version, &file_type);
259
260  for (i = 0; i < nelems; i++) {
261
262    /* get the description of the first element */
263    elem_name = elist[i];
264    plist = ply_get_element_description (ply, elem_name, &num_elems, &nprops);
265
266    if (equal_strings ("vertex", elem_name)) {
267
268      /* see if vertex holds any normal information */
269      get_nx = get_ny = get_nz = 0;
270      for (j = 0; j < nprops; j++) {
271        if (equal_strings ("nx", plist[j]->name)) get_nx = 1;
272        if (equal_strings ("ny", plist[j]->name)) get_ny = 1;
273        if (equal_strings ("nz", plist[j]->name)) get_nz = 1;
274      }
275
276      /* create a vertex list to hold all the vertices */
277      vlist = (Vertex **) malloc (sizeof (Vertex *) * num_elems);
278      nverts = num_elems;
279
280      /* set up for getting vertex elements */
281
282      ply_get_property (ply, elem_name, &vert_props[0]);
283      ply_get_property (ply, elem_name, &vert_props[1]);
284      ply_get_property (ply, elem_name, &vert_props[2]);
285      if (get_nx) ply_get_property (ply, elem_name, &vert_props[3]);
286      if (get_ny) ply_get_property (ply, elem_name, &vert_props[4]);
287      if (get_nz) ply_get_property (ply, elem_name, &vert_props[5]);
288      vert_other = ply_get_other_properties (ply, elem_name,
289                     offsetof(Vertex,other_props));
290
291      /* grab all the vertex elements */
292      for (j = 0; j < num_elems; j++) {
293        vlist[j] = (Vertex *) malloc (sizeof (Vertex));
294        ply_get_element (ply, (void *) vlist[j]);
295      }
296    }
297    else if (equal_strings ("face", elem_name)) {
298
299      /* create a list to hold all the face elements */
300      flist = (Face **) malloc (sizeof (Face *) * num_elems);
301      nfaces = num_elems;
302
303      /* set up for getting face elements */
304
305      ply_get_property (ply, elem_name, &face_props[0]);
306      face_other = ply_get_other_properties (ply, elem_name,
307                     offsetof(Face,other_props));
308
309      /* grab all the face elements */
310      for (j = 0; j < num_elems; j++) {
311        flist[j] = (Face *) malloc (sizeof (Face));
312        ply_get_element (ply, (void *) flist[j]);
313      }
314    }
315    else
316      other_elements = ply_get_other_element (ply, elem_name, num_elems);
317  }
318
319  comments = ply_get_comments (ply, &num_comments);
320  obj_info = ply_get_obj_info (ply, &num_obj_info);
321
322  ply_close (ply);
323}
324
325
326/******************************************************************************
327Write out the PLY file to standard out.
328******************************************************************************/
329
330void
331write_file()
332{
333  int i,j,k;
334  PlyFile *ply;
335  int num_elems;
336  char *elem_name;
337
338  /*** Write out the final PLY object ***/
339
340
341  ply = ply_write (stdout, nelems, elist, file_type);
342
343
344  /* describe what properties go into the vertex and face elements */
345
346  ply_element_count (ply, "vertex", nverts);
347  ply_describe_property (ply, "vertex", &vert_props[0]);
348  ply_describe_property (ply, "vertex", &vert_props[1]);
349  ply_describe_property (ply, "vertex", &vert_props[2]);
350  ply_describe_property (ply, "vertex", &vert_props[3]);
351  ply_describe_property (ply, "vertex", &vert_props[4]);
352  ply_describe_property (ply, "vertex", &vert_props[5]);
353  ply_describe_other_properties (ply, vert_other, offsetof(Vertex,other_props));
354
355  ply_element_count (ply, "face", nfaces);
356  ply_describe_property (ply, "face", &face_props[0]);
357  ply_describe_other_properties (ply, face_other, offsetof(Face,other_props));
358
359  ply_describe_other_elements (ply, other_elements);
360
361  for (i = 0; i < num_comments; i++)
362    ply_put_comment (ply, comments[i]);
363
364  for (i = 0; i < num_obj_info; i++)
365    ply_put_obj_info (ply, obj_info[i]);
366
367  ply_header_complete (ply);
368
369  /* set up and write the vertex elements */
370  ply_put_element_setup (ply, "vertex");
371  for (i = 0; i < nverts; i++)
372    ply_put_element (ply, (void *) vlist[i]);
373
374  /* set up and write the face elements */
375  ply_put_element_setup (ply, "face");
376  for (i = 0; i < nfaces; i++)
377    ply_put_element (ply, (void *) flist[i]);
378
379  ply_put_other_elements (ply);
380
381  /* close the PLY file */
382  ply_close (ply);
383}
384
Note: See TracBrowser for help on using the repository browser.