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

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

Added original make3d

File size: 21.0 KB
Line 
1/*
2
3Simplify a polygon model by collapsing multiple points together.  This
4is basically Jarek Rossignac's method of simplifying polygon models.
5
6This code borrows heavily from "plyshared".
7
8Greg Turk, August 1994
9
10*/
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <math.h>
15#include <strings.h>
16#include <ply.h>
17#include <sys/times.h>
18#include <limits.h>
19#include <time.h>
20
21
22/* user's vertex and face definitions for a polygonal object */
23 
24typedef struct Vertex {
25  float x,y,z;                  /* SUM of coordinates that contributed */
26  float nx,ny,nz;               /* SUM of normals that contributed */
27  uint diff_r, diff_g, diff_b;   /* SUM of diffuse colors that contributed */
28  int count;                    /* number of vertices that contributed */
29  int a,b,c;                    /* integer indices used in hash */
30  int index;
31  struct Vertex *shared;
32  struct Vertex *next;
33  void *other_props;       /* other properties */
34} Vertex;
35
36typedef struct Face {
37  unsigned char nverts;    /* number of vertex indices in list */
38  int *verts;              /* vertex index list */
39  void *other_props;       /* other properties */
40} Face;
41
42char *elem_names[] = { /* list of the kinds of elements in the user's object */
43  "vertex", "face"
44};
45
46
47#define MAX_VERT_PROPS 20
48
49static PlyProperty vert_prop_x = 
50   {"x", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
51static PlyProperty vert_prop_y = 
52  {"y", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
53static PlyProperty vert_prop_z = 
54  {"z", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
55
56static PlyProperty vert_prop_nx = 
57   {"nx", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
58static PlyProperty vert_prop_ny = 
59  {"ny", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
60static PlyProperty vert_prop_nz = 
61  {"nz", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
62
63static PlyProperty vert_prop_diff_r = 
64  {"diffuse_red", PLY_UCHAR, PLY_UINT, 0, 0, PLY_START_TYPE, 
65   PLY_START_TYPE, 0};
66static PlyProperty vert_prop_diff_g = 
67  {"diffuse_green", PLY_UCHAR, PLY_UINT, 0, 0, PLY_START_TYPE, 
68   PLY_START_TYPE, 0};
69static PlyProperty vert_prop_diff_b = 
70  {"diffuse_blue", PLY_UCHAR, PLY_UINT, 0, 0, PLY_START_TYPE, 
71   PLY_START_TYPE, 0};
72
73static int num_vert_props;
74static PlyProperty vert_props[MAX_VERT_PROPS];
75
76PlyProperty face_props[] = { /* list of property information for a vertex */
77  {"vertex_indices", PLY_INT, PLY_INT, offsetof(Face,verts),
78   1, PLY_UCHAR, PLY_UCHAR, offsetof(Face,nverts)},
79};
80
81
82/*** the PLY object ***/
83
84static int nverts,nfaces;
85static int n_final_verts, n_final_faces;
86static Vertex **vlist;
87static Face **flist;
88static PlyOtherElems *other_elements = NULL;
89static PlyOtherProp *vert_other,*face_other;
90static int nelems;
91static char **elist;
92static int num_comments;
93static char **comments;
94static int num_obj_info;
95static char **obj_info;
96static int file_type;
97
98static float tolerance = 0.0001;   /* what constitutes "near" */
99
100static int HAS_DIFFUSE_COLORS = 0;
101static int HAS_NORMALS = 0;
102
103
104/* hash table for near neighbor searches */
105/* A few randomly chosen prime numbers... */
106
107#define PR1  17
108#define PR2 101
109
110#define TABLE_SIZE1       5003
111#define TABLE_SIZE2      17011
112#define TABLE_SIZE3      53003
113#define TABLE_SIZE4     107021
114#define TABLE_SIZE5     233021
115#define TABLE_SIZE6     472019
116#define TABLE_SIZE7     600169
117#define TABLE_SIZE8    1111189
118#define TABLE_SIZE9    2222177
119#define TABLE_SIZE10   4444147
120#define TABLE_SIZE11   9374153
121#define TABLE_SIZE12  20123119
122#define TABLE_SIZE13  30123139
123#define TABLE_SIZE14  50123011
124#define TABLE_SIZE15  70123117
125#define TABLE_SIZE16 100123171
126#define TABLE_SIZE17 140123143
127#define TABLE_SIZE18 200123111
128#define TABLE_SIZE19 400123123
129#define TABLE_SIZE20 800123119
130
131typedef struct Hash_Table {     /* uniform spatial subdivision, with hash */
132  int npoints;                  /* number of points placed in table */
133  Vertex **verts;               /* array of hash cells */
134  int num_entries;              /* number of array elements in verts */
135  float scale;                  /* size of cell */
136} Hash_Table;
137
138
139Hash_Table *init_table(int, float);
140void add_to_hash (Vertex *, Hash_Table *, float);
141void usage(char *progname);
142void write_file();
143void read_file(FILE *inFile);
144void crunch_vertices();
145float compute_average_edge_length();
146
147
148clock_t tm;
149static void start_time();
150static void end_time();
151static float time_elapsed();
152
153
154/******************************************************************************
155Main program.
156******************************************************************************/
157
158int
159main(int argc, char *argv[])
160{
161  int i,j,got_tolerance;
162  char *s;
163  char *progname;
164  float avg_edge_length;
165  FILE *inFile = stdin;
166
167  progname = argv[0];
168
169  /* parse -flags */
170  got_tolerance = 0;
171  while (--argc > 0 && (*++argv)[0]=='-') {
172    for (s = argv[0]+1; *s; s++)
173      switch (*s) {
174        case 'd':
175          /* Make sure a second argument */
176          if (argc == 1) {
177            usage(progname);
178            exit(-1);
179          }
180          tolerance = atof (*++argv);
181          argc -= 1;
182          got_tolerance = 1;
183          break;
184        default:
185          usage (progname);
186          exit (-1);
187          break;
188      }
189  }
190
191   /* optional input file (if not, read stdin ) */
192   if (argc > 0 && *argv[0] != '-') {
193       inFile = fopen(argv[0], "r");
194       if (inFile == NULL) {
195           fprintf(stderr, "Error: Couldn't open input file %s\n", argv[0]);
196           usage(progname);
197           exit(-1);
198       }
199       argc --;
200       argv ++;
201   } 
202
203   /* Check no extra args */
204   if (argc > 0) {
205     fprintf(stderr, "Error: Unhandled arg: %s\n", argv[0]);
206     usage(progname);
207     exit(-1);
208   }
209
210
211
212  start_time();
213  read_file(inFile);
214  end_time();
215
216#ifdef VERBOSE
217  fprintf(stderr, 
218          "Input file has %d vertices and %d faces\n",
219          nverts, nfaces);
220  fprintf(stderr, "Took %f seconds to read file.\n", time_elapsed());
221#endif
222
223  if (!got_tolerance) {
224      start_time();
225      avg_edge_length = compute_average_edge_length();
226      tolerance = avg_edge_length*2;
227      end_time();
228#ifdef VERBOSE
229      fprintf(stderr, 
230              "Took %f seconds to compute average edge length.\n", 
231              time_elapsed());
232#endif
233  }
234
235  start_time();
236  crunch_vertices();
237  end_time();
238#ifdef VERBOSE
239  fprintf(stderr, "Took %f seconds to simplify mesh.\n", time_elapsed());
240#endif
241
242  start_time();
243  write_file();
244  end_time();
245#ifdef VERBOSE
246  fprintf(stderr, "Took %f seconds to write file.\n", time_elapsed());
247  fprintf(stderr, 
248          "Output file has %d vertices and %d faces\n",
249          n_final_verts, n_final_faces);
250#endif
251
252  exit(0);
253}
254
255
256/******************************************************************************
257Print out usage information.
258******************************************************************************/
259
260void
261usage(char *progname)
262{
263  fprintf (stderr, "usage: %s [flags] [in.ply] > out.ply\n", progname);
264  fprintf (stderr, "   or: %s [flags] < in.ply > out.ply\n", progname);
265  fprintf (stderr, "       -d distance (default = %g)\n", tolerance);
266}
267
268
269/******************************************************************************
270Figure out which vertices should be collapsed into one.
271******************************************************************************/
272
273void
274crunch_vertices()
275{
276  int i,j,k;
277  int jj;
278  Hash_Table *table;
279  float squared_dist;
280  Vertex *vert;
281  Face *face;
282  float recip, nrecip;
283
284  table = init_table (nverts, tolerance);
285
286  squared_dist = tolerance * tolerance;
287
288  /* place all vertices in the hash table, and in the process */
289  /* learn which ones should be collapsed */
290
291  for (i = 0; i < nverts; i++) {
292    vlist[i]->count = 1;
293    add_to_hash (vlist[i], table, squared_dist);
294  }
295
296  /* compute average of all coordinates that contributed to */
297  /* the vertices placed in the hash table */
298
299  for (i = 0; i < nverts; i++) {
300    vert = vlist[i];
301    if (vert->shared == vert) {
302      recip = 1.0 / vert->count;
303      vert->x *= recip;
304      vert->y *= recip;
305      vert->z *= recip;
306
307      if (HAS_NORMALS) {
308          squared_dist = 
309              vert->nx*vert->nx + vert->ny*vert->ny + vert->nz*vert->nz;
310          if (squared_dist == 0)
311              nrecip = 0;
312          else 
313              nrecip = 1/sqrt(squared_dist);
314          vert->nx *= nrecip;
315          vert->ny *= nrecip;
316          vert->nz *= nrecip;
317      }
318
319      if (HAS_DIFFUSE_COLORS) {
320          vert->diff_r = (int)(vert->diff_r*recip + 0.5);
321          vert->diff_g = (int)(vert->diff_g*recip + 0.5);
322          vert->diff_b = (int)(vert->diff_b*recip + 0.5);
323      }
324    }
325  }
326
327  /* fix up the faces to point to the collapsed vertices */
328
329  for (i = 0; i < nfaces; i++) {
330
331    face = flist[i];
332   
333    /* change all indices to pointers to the collapsed vertices */
334    for (j = 0; j < face->nverts; j++)
335      face->verts[j] = (int) (vlist[face->verts[j]]->shared);
336
337    /* collapse adjacent vertices in a face that are the same */
338    for (j = face->nverts-1; j >= 0; j--) {
339      jj = (j+1) % face->nverts;
340      if (face->verts[j] == face->verts[jj]) {
341        for (k = j+1; k < face->nverts - 1; k++)
342          face->verts[k] = face->verts[k+1];
343        face->nverts--;
344      }
345    }
346
347    /* remove any faces with less than three vertices by setting */
348    /* its vertex count to zero */
349
350    if (face->nverts < 3)
351      face->nverts = 0;
352
353  }
354}
355
356 
357/******************************************************************************
358Compute the average edge length.  Currently loops through faces and
359visits all shared edges twice, giving them double wieghting with respect
360to boundary edges.
361******************************************************************************/
362
363float 
364compute_average_edge_length()
365{
366  int i,j,k;
367  int jj;
368  Hash_Table *table;
369  float squared_dist;
370  Vertex *vert1, *vert2;
371  Face *face;
372  float total_length;
373  int num_edges;
374  float avg_edge_length;
375
376  total_length = 0;
377  num_edges = 0;
378
379  for (i = 0; i < nfaces; i++) {
380    face = flist[i];
381    for (j = 0; j < face->nverts-1; j++) {
382        vert1 = vlist[face->verts[j]];
383        vert2 = vlist[face->verts[j+1]];
384        total_length += sqrt((vert1->x - vert2->x)*(vert1->x - vert2->x) +
385                             (vert1->y - vert2->y)*(vert1->y - vert2->y) +
386                             (vert1->z - vert2->z)*(vert1->z - vert2->z));
387        num_edges++;
388    }
389    vert1 = vlist[face->verts[face->nverts-1]];
390    vert2 = vlist[face->verts[0]];
391    total_length += sqrt((vert1->x - vert2->x)*(vert1->x - vert2->x) +
392                         (vert1->y - vert2->y)*(vert1->y - vert2->y) +
393                         (vert1->z - vert2->z)*(vert1->z - vert2->z));
394    num_edges++;
395  }
396
397  avg_edge_length = total_length/num_edges;
398
399  return avg_edge_length;
400}
401
402
403/******************************************************************************
404Add a vertex to it's hash table.
405
406Entry:
407  vert    - vertex to add
408  table   - hash table to add to
409  sq_dist - squared value of distance tolerance
410******************************************************************************/
411
412void 
413add_to_hash(Vertex *vert, Hash_Table *table, float sq_dist)
414{
415  int index;
416  int a,b,c;
417  int aa,bb,cc;
418  float scale;
419  Vertex *ptr;
420  float dx,dy,dz;
421  float sq;
422  float min_dist;
423  Vertex *min_ptr;
424
425  /* determine which cell the position lies within */
426
427  scale = table->scale;
428  a = floor (vert->x * scale);
429  b = floor (vert->y * scale);
430  c = floor (vert->z * scale);
431  index = (a * PR1 + b * PR2 + c) % table->num_entries;
432  if (index < 0)
433    index += table->num_entries;
434
435  /* examine all points hashed to this cell, looking for */
436  /* a vertex to collapse with */
437
438  for (ptr = table->verts[index]; ptr != NULL; ptr = ptr->next)
439    if (a == ptr->a && b == ptr->b && c == ptr->c) {
440      /* add to sums of coordinates (that later will be averaged) */
441      ptr->x += vert->x;
442      ptr->y += vert->y;
443      ptr->z += vert->z;
444
445      if (HAS_NORMALS) {
446          ptr->nx += vert->nx;
447          ptr->ny += vert->ny;
448          ptr->nz += vert->nz;
449      }
450
451      if (HAS_DIFFUSE_COLORS) {
452          ptr->diff_r += vert->diff_r;
453          ptr->diff_g += vert->diff_g;
454          ptr->diff_b += vert->diff_b;
455      }
456
457      ptr->count++;
458      vert->shared = ptr;
459      return;
460    }
461
462  /* no match if we get here, so add new hash table entry */
463
464  vert->next = table->verts[index];
465  table->verts[index] = vert;
466  vert->shared = vert;  /* self-reference as close match */
467  vert->a = a;
468  vert->b = b;
469  vert->c = c;
470}
471
472
473/******************************************************************************
474Initialize a uniform spatial subdivision table.  This structure divides
4753-space into cubical cells and deposits points into their appropriate
476cells.  It uses hashing to make the table a one-dimensional array.
477
478Entry:
479  nverts - number of vertices that will be placed in the table
480  size   - size of a cell
481
482Exit:
483  returns pointer to hash table
484******************************************************************************/
485
486Hash_Table *
487init_table(int nverts, float size)
488{
489  int i;
490  int index;
491  int a,b,c;
492  Hash_Table *table;
493  float scale;
494
495  /* allocate new hash table */
496
497  table = (Hash_Table *) malloc (sizeof (Hash_Table));
498
499  if (nverts < TABLE_SIZE1)
500    table->num_entries = TABLE_SIZE1;
501  else if (nverts < TABLE_SIZE2)
502    table->num_entries = TABLE_SIZE2;
503  else if (nverts < TABLE_SIZE3)
504    table->num_entries = TABLE_SIZE3;
505  else if (nverts < TABLE_SIZE4)
506    table->num_entries = TABLE_SIZE4;
507  else if (nverts < TABLE_SIZE5)
508    table->num_entries = TABLE_SIZE5;
509  else if (nverts < TABLE_SIZE6)
510    table->num_entries = TABLE_SIZE6;
511  else if (nverts < TABLE_SIZE7)
512    table->num_entries = TABLE_SIZE7;
513  else if (nverts < TABLE_SIZE8)
514    table->num_entries = TABLE_SIZE8;
515  else if (nverts < TABLE_SIZE9)
516    table->num_entries = TABLE_SIZE9;
517  else if (nverts < TABLE_SIZE10)
518    table->num_entries = TABLE_SIZE10;
519  else if (nverts < TABLE_SIZE11)
520    table->num_entries = TABLE_SIZE11;
521  else if (nverts < TABLE_SIZE12)
522    table->num_entries = TABLE_SIZE12;
523  else if (nverts < TABLE_SIZE13)
524    table->num_entries = TABLE_SIZE13;
525  else if (nverts < TABLE_SIZE14)
526    table->num_entries = TABLE_SIZE14;
527  else if (nverts < TABLE_SIZE15)
528    table->num_entries = TABLE_SIZE15;
529  else if (nverts < TABLE_SIZE16)
530    table->num_entries = TABLE_SIZE16;
531  else if (nverts < TABLE_SIZE17)
532    table->num_entries = TABLE_SIZE17;
533  else if (nverts < TABLE_SIZE18)
534    table->num_entries = TABLE_SIZE18;
535  else if (nverts < TABLE_SIZE19)
536    table->num_entries = TABLE_SIZE19;
537  else
538    table->num_entries = TABLE_SIZE20;
539
540  table->verts = (Vertex **) malloc (sizeof (Vertex *) * table->num_entries);
541
542  /* set all table elements to NULL */
543  for (i = 0; i < table->num_entries; i++)
544    table->verts[i] = NULL;
545
546  /* place each point in table */
547
548  scale = 1 / size;
549  table->scale = scale;
550
551  return (table);
552}
553
554
555/******************************************************************************
556Read in the PLY file from standard in.
557******************************************************************************/
558
559void
560read_file(FILE *inFile)
561{
562  int i,j,k;
563  PlyFile *ply;
564  int nprops;
565  int num_elems;
566  PlyProperty **plist;
567  char *elem_name;
568  float version;
569  int nvp;
570
571
572  /*** Read in the original PLY object ***/
573
574
575  ply  = ply_read (inFile, &nelems, &elist);
576  ply_get_info (ply, &version, &file_type);
577
578  nvp = 0;
579
580  HAS_DIFFUSE_COLORS = 0;
581  HAS_NORMALS = 0;
582
583  if (ply_is_valid_property(ply, "vertex", vert_prop_x.name) &&
584      ply_is_valid_property(ply, "vertex", vert_prop_y.name) &&
585      ply_is_valid_property(ply, "vertex", vert_prop_z.name)) {
586
587      vert_props[nvp] = vert_prop_x;
588      vert_props[nvp].offset = offsetof(Vertex,x); nvp++;
589      vert_props[nvp] = vert_prop_y;
590      vert_props[nvp].offset = offsetof(Vertex,y); nvp++;
591      vert_props[nvp] = vert_prop_z;
592      vert_props[nvp].offset = offsetof(Vertex,z); nvp++;
593  }
594 
595  if (ply_is_valid_property(ply, "vertex", vert_prop_nx.name) &&
596      ply_is_valid_property(ply, "vertex", vert_prop_ny.name) &&
597      ply_is_valid_property(ply, "vertex", vert_prop_nz.name) ) {
598
599      HAS_NORMALS = 1;
600      vert_props[nvp] = vert_prop_nx;
601      vert_props[nvp].offset = offsetof(Vertex,nx); nvp++;
602      vert_props[nvp] = vert_prop_ny;
603      vert_props[nvp].offset = offsetof(Vertex,ny); nvp++;
604      vert_props[nvp] = vert_prop_nz;
605      vert_props[nvp].offset = offsetof(Vertex,nz); nvp++;
606  }
607 
608  if (ply_is_valid_property(ply, "vertex", "diffuse_red") &&
609      ply_is_valid_property(ply, "vertex", "diffuse_green") &&
610      ply_is_valid_property(ply, "vertex", "diffuse_blue")) {
611
612      HAS_DIFFUSE_COLORS = 1;
613      vert_props[nvp] = vert_prop_diff_r;
614      vert_props[nvp].offset = offsetof(Vertex,diff_r); nvp++;
615      vert_props[nvp] = vert_prop_diff_g;
616      vert_props[nvp].offset = offsetof(Vertex,diff_g); nvp++;
617      vert_props[nvp] = vert_prop_diff_b;
618      vert_props[nvp].offset = offsetof(Vertex,diff_b); nvp++;
619    }
620
621  num_vert_props = nvp;
622
623  for (i = 0; i < nelems; i++) {
624
625    /* get the description of the first element */
626    elem_name = elist[i];
627    plist = ply_get_element_description (ply, elem_name, &num_elems, &nprops);
628
629    if (equal_strings ("vertex", elem_name)) {
630
631      /* create a vertex list to hold all the vertices */
632      vlist = (Vertex **) malloc (sizeof (Vertex *) * num_elems);
633      nverts = num_elems;
634
635      /* set up for getting vertex elements */
636
637      /* set up for getting vertex elements */
638      for (j = 0; j < num_vert_props; j++) {
639          ply_get_property (ply, elem_name, &vert_props[j]);
640      }
641/*
642      ply_get_element_setup (ply, elem_name, num_vert_props, vert_props);
643      */
644/*
645      ply_get_property (ply, elem_name, &vert_props[0]);
646      ply_get_property (ply, elem_name, &vert_props[1]);
647      ply_get_property (ply, elem_name, &vert_props[2]);
648      */
649      vert_other = ply_get_other_properties (ply, elem_name,
650                     offsetof(Vertex,other_props));
651
652      /* grab all the vertex elements */
653      for (j = 0; j < num_elems; j++) {
654        vlist[j] = (Vertex *) malloc (sizeof (Vertex));
655        ply_get_element (ply, (void *) vlist[j]);
656      }
657    }
658    else if (equal_strings ("face", elem_name)) {
659
660      /* create a list to hold all the face elements */
661      flist = (Face **) malloc (sizeof (Face *) * num_elems);
662      nfaces = num_elems;
663
664      /* set up for getting face elements */
665
666      ply_get_property (ply, elem_name, &face_props[0]);
667      face_other = ply_get_other_properties (ply, elem_name,
668                     offsetof(Face,other_props));
669
670      /* grab all the face elements */
671      for (j = 0; j < num_elems; j++) {
672        flist[j] = (Face *) malloc (sizeof (Face));
673        ply_get_element (ply, (void *) flist[j]);
674      }
675    }
676    else
677      other_elements = ply_get_other_element (ply, elem_name, num_elems);
678  }
679
680  comments = ply_get_comments (ply, &num_comments);
681  obj_info = ply_get_obj_info (ply, &num_obj_info);
682
683  ply_close (ply);
684}
685
686
687/******************************************************************************
688Write out the PLY file to standard out.
689******************************************************************************/
690
691void
692write_file()
693{
694  int i,j,k;
695  PlyFile *ply;
696  int num_elems;
697  char *elem_name;
698  int vert_count;
699  int face_count;
700
701  /*** Write out the final PLY object ***/
702
703
704  ply = ply_write (stdout, nelems, elist, file_type);
705
706  /* count the vertices that are in the hash table */
707
708  vert_count = 0;
709  for (i = 0; i < nverts; i++)
710    if (vlist[i]->shared == vlist[i]) {
711      vlist[i]->index = vert_count;
712      vert_count++;
713    }
714  n_final_verts = vert_count;
715
716
717  /* count the faces that have not been collapsed */
718
719  face_count = 0;
720  for (i = 0; i < nfaces; i++)
721    if (flist[i]->nverts != 0)
722      face_count++;
723
724  n_final_faces = face_count;
725
726  /* describe what properties go into the vertex and face elements */
727
728  ply_element_count (ply, "vertex", vert_count);
729  for (j = 0; j < num_vert_props; j++) {
730      ply_describe_property (ply, "vertex", &vert_props[j]);
731  }
732/*
733  ply_describe_property (ply, "vertex", &vert_props[0]);
734  ply_describe_property (ply, "vertex", &vert_props[1]);
735  ply_describe_property (ply, "vertex", &vert_props[2]);
736  */
737  ply_describe_other_properties (ply, vert_other, offsetof(Vertex,other_props));
738
739  ply_element_count (ply, "face", face_count);
740  ply_describe_property (ply, "face", &face_props[0]);
741  ply_describe_other_properties (ply, face_other, offsetof(Face,other_props));
742
743  ply_describe_other_elements (ply, other_elements);
744
745  for (i = 0; i < num_comments; i++)
746    ply_put_comment (ply, comments[i]);
747
748  for (i = 0; i < num_obj_info; i++)
749    ply_put_obj_info (ply, obj_info[i]);
750
751  ply_header_complete (ply);
752
753  /* set up and write the vertex elements */
754
755  ply_put_element_setup (ply, "vertex");
756
757  for (i = 0; i < nverts; i++)
758    if (vlist[i]->shared == vlist[i])
759      ply_put_element (ply, (void *) vlist[i]);
760
761  /* set up and write the face elements */
762
763  ply_put_element_setup (ply, "face");
764
765  for (i = 0; i < nfaces; i++) {
766    if (flist[i]->nverts == 0)
767      continue;
768    for (j = 0; j < flist[i]->nverts; j++)
769      flist[i]->verts[j] = ((Vertex *) flist[i]->verts[j])->index;
770    ply_put_element (ply, (void *) flist[i]);
771  }
772
773  ply_put_other_elements (ply);
774
775  /* close the PLY file */
776  ply_close (ply);
777}
778
779
780static void
781start_time()
782{
783  struct tms buffer;
784  times(&buffer);
785  tm = buffer.tms_utime;
786}
787
788static void
789end_time()
790{
791  struct tms buffer;
792  times(&buffer);
793  tm = buffer.tms_utime - tm;
794}
795
796static float
797time_elapsed()
798{
799    return (double) tm / (double) CLOCKS_PER_SEC;
800}
Note: See TracBrowser for help on using the repository browser.