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

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

Added original make3d

File size: 15.0 KB
Line 
1/*
2
3plysubdiv:
4Subdivide triangles in the mesh to create a new file with even more
5triangles.  As a general operator, it will create a new vertex in
6the middle of a triangle, and re-tesselate it with 3 triangles instead
7of 1.
8
9Lucas Pereira, Jan, 2000.
10
11*/
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <math.h>
16#include <strings.h>
17#include <ply.h>
18#include <iostream>
19#include <assert.h>
20
21/* user's vertex and face definitions for a polygonal object */
22
23typedef struct Vertex {
24  float x,y,z;
25  int index;
26  void *other_props;       /* other properties */
27} Vertex;
28
29typedef struct Face {
30  unsigned char nverts;    /* number of vertex indices in list */
31  int *verts;              /* vertex index list */
32  void *other_props;       /* other properties */
33} Face;
34
35char *elem_names[] = { /* list of the kinds of elements in the user's object */
36  "vertex", "face"
37};
38
39PlyProperty vert_props[] = { /* list of property information for a vertex */
40  {"x", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,x), 0, 0, 0, 0},
41  {"y", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,y), 0, 0, 0, 0},
42  {"z", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,z), 0, 0, 0, 0},
43};
44
45PlyProperty face_props[] = { /* list of property information for a vertex */
46  {"vertex_indices", PLY_INT, PLY_INT, offsetof(Face,verts),
47   1, PLY_UCHAR, PLY_UCHAR, offsetof(Face,nverts)},
48};
49
50
51/*** the PLY object ***/
52
53#define MAXTRISPERVERT 20
54
55class Midpoints {
56
57public:
58  Midpoints() {
59    npoints = 0;
60  }
61
62  int GetMidpoint(int ptB) {
63    for (int i=0; i < npoints; i++) {
64      if (otherpoint[i] == ptB) {
65        return(midpoint[i]);
66      }
67
68    }
69    // if we get to here, didn't find it
70    return(-1);
71  }
72
73  int SetMidpoint(int ptB, int mid) {
74    if (npoints+1 >= MAXTRISPERVERT) {
75      fprintf(stderr, "Error adding edge to vertex %d -> too many tris!\n", 
76              ptB);
77      exit(-1);
78    }
79    otherpoint[npoints] = ptB;
80    midpoint[npoints] = mid;
81    npoints++;
82    return mid;
83  }
84
85  int npoints;
86  int otherpoint[MAXTRISPERVERT];
87  int midpoint[MAXTRISPERVERT];
88
89};
90
91// The midpointtable class looks up the numbers of the midpoints,
92// and assigns them as needed...
93class MidpointTable {
94public:
95  MidpointTable(int numverts) {
96    nverts = numverts;
97    mps = new Midpoints[nverts];
98  }
99  int GetMidpoint(int ptA, int ptB) {
100    // cerr << "GMP: " << ptA << " " << ptB << endl;
101    // make sure ptA is the lower index.
102    if (ptA > ptB) {
103      int t = ptA;
104      ptA = ptB;
105      ptB = t;
106    }
107    return(mps[ptA].GetMidpoint(ptB));
108  }
109
110  int SetMidpoint(int ptA, int ptB, int mid) {
111    // make sure ptA is the lower index.
112    if (ptA > ptB) {
113      int t = ptA;
114      ptA = ptB;
115      ptB = t;
116    }
117    return(mps[ptA].SetMidpoint(ptB, mid));
118  }
119   
120  int nverts;
121  Midpoints *mps;
122};
123 
124
125
126class PlyObject {
127
128public:
129  void read_file(FILE *inFile);
130  void write_file();
131  void subdivide(PlyObject *inply);
132
133  int nverts,nfaces;
134  int nvertsallocated, nfacesallocated;
135  Vertex **vlist;
136  Face **flist;
137  PlyOtherElems *other_elements;
138  PlyOtherProp *vert_other, *face_other;
139  int nelems;
140  char **elist;
141  int num_comments;
142  char **comments;
143  int num_obj_info;
144  char **obj_info;
145  int file_type;
146  MidpointTable *mpt;
147};
148
149void usage(char *progname);
150
151
152/******************************************************************************
153Main program.
154******************************************************************************/
155
156int
157main(int argc, char *argv[])
158{
159  int i,j;
160  char *s;
161  char *progname;
162  FILE *inFile = stdin;
163  PlyObject *inply, *outply;
164
165  inply = new PlyObject();
166  outply = new PlyObject();
167
168  progname = argv[0];
169
170  /* Parse -flags */
171  while (--argc > 0 && (*++argv)[0]=='-') {
172    for (s = argv[0]+1; *s; s++)
173      switch (*s) {
174        case 'h':
175          usage (progname);
176          exit(0);
177          break;
178        default:
179          usage (progname);
180          exit (-1);
181          break;
182      }
183  }
184
185  /* optional input file (if not, read stdin ) */
186  if (argc > 0 && *argv[0] != '-') {
187    inFile = fopen(argv[0], "r");
188    if (inFile == NULL) {
189      fprintf(stderr, "Error: Couldn't open input file %s\n", argv[0]);
190      usage(progname);
191      exit(-1);
192    }
193    argc --;
194    argv ++;
195  } 
196
197   /* Check no extra args */
198   if (argc > 0) {
199     fprintf(stderr, "Error: Unhandled arg: %s\n", argv[0]);
200     usage(progname);
201     exit(-1);
202   }
203
204   // Read in the file
205   inply->read_file(inFile);
206
207   // Generate outply from inply
208   outply->subdivide(inply);
209   
210  // Write back out
211  outply->write_file();
212}
213
214
215/******************************************************************************
216Print out usage information.
217******************************************************************************/
218
219void
220usage(char *progname)
221{
222  fprintf (stderr, "usage: %s [flags] [in.ply] > out.ply\n", progname);
223  fprintf (stderr, "   or: %s [flags] < in.ply > out.ply\n", progname);
224  fprintf (stderr, "\n");
225  fprintf (stderr, "   This program will subdivide triangles in the mesh\n");
226  fprintf (stderr, "   to create a new file with even more triangles. \n");
227  fprintf (stderr, "   As a general operator, it will create a new vertex\n");
228  fprintf (stderr, "   at the midpoint of each triangle edge, and then\n");
229  fprintf (stderr, "   re-tesselate it with 4 triangles instead of 1.\n");
230  fprintf (stderr, "   E.g.:\n");
231  fprintf (stderr, "                                                     \n");
232  fprintf (stderr, "        o                      o                     \n");
233  fprintf (stderr, "       / `                    / `                    \n");
234  fprintf (stderr, "      /   `     ------>      o---o                   \n");
235  fprintf (stderr, "     /     `                / ` / `                  \n");
236  fprintf (stderr, "    o-------o              o---o---o                 \n");
237  fprintf (stderr, "\n");
238  fprintf (stderr, "   It does nothing intelligent with other properties\n");
239  fprintf (stderr, "   (such as confidence or normals).  Faces copy the\n");
240  fprintf (stderr, "   original face's properties, and new vertices copy\n");
241  fprintf (stderr, "   the attributes of original vertices.\n");
242  fprintf (stderr, "\n");
243  fprintf (stderr, "Known bugs:\n");
244  fprintf (stderr, "   - It allocates a little more memory than it needs,\n");
245  fprintf (stderr, "     and doesn't check array limits well.\n");
246  fprintf (stderr, "   - It only works for triangles, not 4+ sided faces.\n");
247  fprintf (stderr, "\n");
248  exit(-1);
249}
250
251
252
253/******************************************************************************
254Generate a new plyobject by subdividing tris in old
255******************************************************************************/
256
257void
258PlyObject::subdivide(PlyObject *inply)
259{
260  // First, set all the random junk to be equal
261  *this = *inply;
262
263  // compute number of vertices, triangles to allocate
264  // These computations require only triangles (not squares, etc...)
265  nfacesallocated = 4 * nfaces;
266  nvertsallocated = nverts + 3 * nfaces;
267  flist = (Face **) malloc (sizeof (Face *) * nfacesallocated);
268  vlist = (Vertex **) malloc (sizeof (Vertex *) * nvertsallocated);
269  mpt = new MidpointTable(nverts);
270
271  nfaces = 0;
272  nverts = 0;
273 
274  // First, copy all existing vertices into vlist...
275  for (nverts = 0; nverts < inply->nverts; nverts++) {
276    vlist[nverts] = inply->vlist[nverts];
277    // cerr << "Copying vertex " << nverts << endl;
278  }
279
280  // Allocate space to store new faces  (memory leak, but this is a
281  // really short program...)
282  Face *newfaces = (Face *) malloc (sizeof(Face) * nfacesallocated);
283  Vertex *newverts = (Vertex *) malloc (sizeof(Vertex) * nvertsallocated);
284  int newfacei = 0;
285  int newverti = 0;
286
287  // Assign numbers to all the new midpoints...
288  // (iterate over every input vertex....)
289  for (int facei = 0; facei < inply->nfaces; facei++) {
290    Face *inface = inply->flist[facei];
291    assert(inface->nverts == 3);
292    int v1n = inface->verts[0];
293    int v2n = inface->verts[1];
294    int v3n = inface->verts[2];
295    Vertex *v1 = inply->vlist[v1n];
296    Vertex *v2 = inply->vlist[v2n];
297    Vertex *v3 = inply->vlist[v3n];
298
299    //
300    //          3
301    //         * *
302    //        *   *
303    //       13***23
304    //      * *   * *
305    //     *   * *   *
306    //    1*****12****2
307    //
308    // First edge...
309    int v12n = mpt->GetMidpoint(v1n, v2n);
310    if (v12n == -1) { 
311      v12n = mpt->SetMidpoint(v1n, v2n, nverts);
312      // cerr << "MidVert#: " << v12n << endl;
313      Vertex *newv = &(newverts[newverti++] = *v1);
314      newv->x = (v1->x + v2->x) / 2;
315      newv->y = (v1->y + v2->y) / 2;
316      newv->z = (v1->z + v2->z) / 2;
317      newv->index = v12n;
318      vlist[nverts++] = newv;
319    }
320    // Second edge...
321    int v23n = mpt->GetMidpoint(v2n, v3n);
322    if (v23n == -1) { 
323      v23n = mpt->SetMidpoint(v2n, v3n, nverts);
324      // cerr << "MidVert#: " << v23n << endl;
325      Vertex *newv = &(newverts[newverti++] = *v2);
326      newv->x = (v2->x + v3->x) / 2;
327      newv->y = (v2->y + v3->y) / 2;
328      newv->z = (v2->z + v3->z) / 2;
329      newv->index = v23n;
330      vlist[nverts++] = newv;
331    }
332    // Third edge...
333    int v31n = mpt->GetMidpoint(v3n, v1n);
334    if (v31n == -1) { 
335      v31n = mpt->SetMidpoint(v3n, v1n, nverts);
336      // cerr << "MidVert#: " << v31n << endl;
337      Vertex *newv = &(newverts[newverti++] = *v3);
338      newv->x = (v3->x + v1->x) / 2;
339      newv->y = (v3->y + v1->y) / 2;
340      newv->z = (v3->z + v1->z) / 2;
341      newv->index = v31n;
342      vlist[nverts++] = newv;
343    }
344 
345    // Generate 4 faces...
346    // just copies "other properties" from inface...
347    Face *newf;
348    // 1, 12, 31
349    newf = &(newfaces[newfacei++] = *inface);
350    newf->verts = (int *) new int[3];
351    newf-> verts[0] = v1n;
352    newf-> verts[1] = v12n;
353    newf-> verts[2] = v31n;
354    flist[nfaces++] = newf;
355    // 12, 23, 31
356    newf = &(newfaces[newfacei++] = *inface);
357    newf->verts = (int *) new int[3];
358    newf-> verts[0] = v12n;
359    newf-> verts[1] = v23n;
360    newf-> verts[2] = v31n;
361    flist[nfaces++] = newf;
362    // 2, 23, 12
363    newf = &(newfaces[newfacei++] = *inface);
364    newf->verts = (int *) new int[3];
365    newf-> verts[0] = v2n;
366    newf-> verts[1] = v23n;
367    newf-> verts[2] = v12n;
368    flist[nfaces++] = newf;
369    // 3, 31, 23
370    newf = &(newfaces[newfacei++] = *inface);
371    newf->verts = (int *) new int[3];
372    newf-> verts[0] = v3n;
373    newf-> verts[1] = v31n;
374    newf-> verts[2] = v23n;
375    flist[nfaces++] = newf;
376  }
377 
378}
379
380/******************************************************************************
381Read in the PLY file from standard in.
382******************************************************************************/
383
384void
385PlyObject::read_file(FILE *inFile)
386{
387  int i,j,k;
388  PlyFile *ply;
389  int nprops;
390  int num_elems;
391  PlyProperty **plist;
392  char *elem_name;
393  float version;
394
395
396  /*** Read in the original PLY object ***/
397
398
399  ply  = ply_read (inFile, &nelems, &elist);
400  ply_get_info (ply, &version, &file_type);
401
402  for (i = 0; i < nelems; i++) {
403
404    /* get the description of the first element */
405    elem_name = elist[i];
406    plist = ply_get_element_description (ply, elem_name, &num_elems, &nprops);
407 
408
409    if (equal_strings ("vertex", elem_name)) {
410
411      /* create a vertex list to hold all the vertices */
412      vlist = (Vertex **) malloc (sizeof (Vertex *) * num_elems);
413      nverts = num_elems;
414     
415      /* set up for getting vertex elements */
416      ply_get_property (ply, elem_name, &vert_props[0]);
417      ply_get_property (ply, elem_name, &vert_props[1]);
418      ply_get_property (ply, elem_name, &vert_props[2]);
419      vert_other = ply_get_other_properties (ply, elem_name,
420                     offsetof(Vertex,other_props));
421
422      /* grab all the vertex elements */
423      for (j = 0; j < num_elems; j++) {
424        vlist[j] = (Vertex *) malloc (sizeof (Vertex));
425        ply_get_element (ply, (void *) vlist[j]);
426      }
427    }
428    else if (equal_strings ("face", elem_name)) {
429
430      /* create a list to hold all the face elements */
431      flist = (Face **) malloc (sizeof (Face *) * num_elems);
432      nfaces = num_elems;
433
434      /* set up for getting face elements */
435
436      ply_get_property (ply, elem_name, &face_props[0]);
437      face_other = ply_get_other_properties (ply, elem_name,
438                     offsetof(Face,other_props));
439
440      /* grab all the face elements */
441      for (j = 0; j < num_elems; j++) {
442        flist[j] = (Face *) malloc (sizeof (Face));
443        ply_get_element (ply, (void *) flist[j]);
444
445      }
446    }
447    else
448      other_elements = ply_get_other_element (ply, elem_name, num_elems);
449  }
450
451  comments = ply_get_comments (ply, &num_comments);
452  obj_info = ply_get_obj_info (ply, &num_obj_info);
453
454  ply_close (ply);
455}
456
457
458/******************************************************************************
459Write out the PLY file to standard out.
460Ignore all the points (and corresponding faces) that have confidence
461below the specified threshold....
462******************************************************************************/
463
464void
465PlyObject::write_file()
466{
467  int i,j,k;
468  PlyFile *ply;
469  int num_elems;
470  char *elem_name;
471  int vert_count;
472  int face_count;
473
474  /*** Write out the final PLY object ***/
475
476
477  ply = ply_write (stdout, nelems, elist, file_type);
478
479  // count the vertices that have valid confidence
480  vert_count = 0;
481  for (i = 0; i < nverts; i++) {
482    // Set the index to either the index number, or -1...
483    if (1) {
484      vlist[i]->index = vert_count;
485      vert_count++;
486    } else {
487      vlist[i]->index = -1;
488    }
489  }
490
491  // count the faces that are still valid
492  face_count = 0;
493  for (i = 0; i < nfaces; i++) {
494    bool valid = (flist[i]->nverts > 0);
495    for (j = 0; j < flist[i]->nverts; j++) {
496      if (vlist[flist[i]->verts[j]]->index == -1) {
497        valid = false;
498        break;
499      }
500    }
501   
502    // If face not valid, set nverts to 0, so it won't
503    // get written out later.
504    if (valid) {
505      face_count++;
506    } else {
507      flist[i]->nverts = 0;
508    }
509  }
510
511  /* describe what properties go into the vertex and face elements */
512
513  ply_element_count (ply, "vertex", vert_count);
514  ply_describe_property (ply, "vertex", &vert_props[0]);
515  ply_describe_property (ply, "vertex", &vert_props[1]);
516  ply_describe_property (ply, "vertex", &vert_props[2]);
517  ply_describe_other_properties (ply, vert_other, offsetof(Vertex,other_props));
518
519  ply_element_count (ply, "face", face_count);
520  ply_describe_property (ply, "face", &face_props[0]);
521  ply_describe_other_properties (ply, face_other, offsetof(Face,other_props));
522
523  ply_describe_other_elements (ply, other_elements);
524
525  for (i = 0; i < num_comments; i++)
526    ply_put_comment (ply, comments[i]);
527
528  for (i = 0; i < num_obj_info; i++)
529    ply_put_obj_info (ply, obj_info[i]);
530
531  ply_header_complete (ply);
532
533  /* set up and write the vertex elements */
534
535  ply_put_element_setup (ply, "vertex");
536
537  for (i = 0; i < nverts; i++)
538    if (vlist[i]->index > -1)
539      ply_put_element (ply, (void *) vlist[i]);
540
541  /* set up and write the face elements */
542  ply_put_element_setup (ply, "face");
543
544  for (i = 0; i < nfaces; i++) {
545    if (flist[i]->nverts == 0)
546      continue;
547    for (j = 0; j < flist[i]->nverts; j++)
548      flist[i]->verts[j] = (vlist[flist[i]->verts[j]])->index;
549    ply_put_element (ply, (void *) flist[i]);
550  }
551
552  ply_put_other_elements (ply);
553
554  /* close the PLY file */
555  ply_close (ply);
556}
Note: See TracBrowser for help on using the repository browser.