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

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

Added original make3d

File size: 18.0 KB
Line 
1// plymirror
2//
3// Given that we have matched a mirror object to the mesh,
4// Read the mirror .xf and .mir files to figure out which
5// points were seen through the mirror, and mirror 'em.
6// (It also puts the scene in roughly the right place, but
7// you really should do alignment, because this depends on
8// how accurately we match the angle of the mirror frame,
9// and how closely the mirror frame model matches the actual
10// mirror (which might have the mirror surface off by several
11// mm...)
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <math.h>
16#include <malloc.h>
17#include <ply.h>
18#include <string.h>
19
20#include "Linear.h"
21
22
23/* user's vertex and face definitions for a polygonal object */
24typedef struct Vertex {
25  float x,y,z;
26  void *other_props;       /* other properties */
27  bool valid;
28  int newindex;
29} Vertex;
30
31typedef struct Face {
32  unsigned char num_pts;
33  int *v;
34  int *origv;  // filled in if we overwrite v with new index numbers...
35  void *other_props;       /* other properties */
36  bool valid;
37} Face;
38
39char *elem_names[] = { /* list of the kinds of elements in the user's object */
40  "vertex", "face"
41};
42
43PlyProperty vert_props[] = { /* list of property information for a vertex */
44  {"x", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,x), 0, 0, 0, 0},
45  {"y", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,y), 0, 0, 0, 0},
46  {"z", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,z), 0, 0, 0, 0},
47};
48
49PlyProperty face_props[] = { /* list of property information for a face */
50  {"vertex_indices", PLY_INT, PLY_INT, offsetof(Face, v),
51   1, PLY_UCHAR, PLY_UCHAR, offsetof(Face,num_pts)},
52};
53
54
55/*** the PLY object ***/
56int nverts;
57Vertex **vlist;
58
59int nfaces;
60Face **flist;
61
62PlyOtherElems *other_elements = NULL;
63PlyOtherProp *vert_other;
64PlyOtherProp *face_other;
65int nelems;
66char **elist;
67int num_comments;
68char **comments;
69int num_obj_info;
70char **obj_info;
71int file_type;
72
73// Mirror info
74Vec3f mir[4];
75Matrix4f mirxf;
76
77// Flags
78bool mirAll = FALSE;
79bool xfNone = FALSE;
80
81// helper functions
82void usage(char *progName);
83
84void read_mir(FILE *mirFile);
85void read_xf(FILE *xfFile);
86void read_file(FILE *inFile);
87void mirror(FILE *outxfFile);
88void select_rest();
89void flipValidNorms();
90void renumberValidVertices();
91void write_file(FILE *outFile);
92
93
94int
95main(int argc, char *argv[])
96{
97  int i,j;
98  char *s;
99  FILE *outFile = stdout;
100  FILE *outxfFile = stderr;
101  FILE *restFile = NULL;  // Output for the "rest" (non-mirrored stuff)
102  char *progName = argv[0];
103
104  char *mirName = NULL;
105  char *xfName = NULL;
106  char *inName = NULL;
107  FILE *mirFile = NULL;
108  FILE *xfFile = NULL;
109  FILE *inFile = stdin;
110
111
112  /* Parse -flags */
113  while (--argc > 0) {
114    argv++;
115    if (!strcmp(*argv, "-h")) {
116      usage(progName);
117      exit(-1);
118    } else if (!strcmp(*argv, "-o")) {
119      // Redirect mirrored output to file
120      if (argc < 2) usage(progName);
121      argc--; argv++;
122      outFile = fopen(argv[0], "w");
123      if (outFile == NULL) {
124        fprintf(stderr, "Error: Couldn't open output file %s\n", argv[0]);
125        usage(progName);
126        exit(-1);
127      }
128      // Also open up a .xf file, if we can
129      int namelen = strlen(argv[0]);
130      if (namelen > 4 && !strcmp(&(argv[0][namelen-4]), ".ply")) {
131        // Write over .ply extension with .xf
132        sprintf(&(argv[0][namelen-4]), ".xf");
133        outxfFile = fopen(argv[0], "w");
134        if (outFile == NULL) {
135          fprintf(stderr, "Warning: Couldn't open output .xf file %s.\n",
136                  argv[0]);
137          outxfFile = stderr;
138        } else {
139          fprintf(stderr, "Writing xform to %s\n", argv[0]);
140        }
141      }
142
143    } else if (!strcmp(*argv, "-r")) {
144      // Redirect UNmirrored output to file
145      if (argc < 2) usage(progName);
146      argc--; argv++;
147      restFile = fopen(argv[0], "w");
148      if (outFile == NULL) {
149        fprintf(stderr, "Error: Couldn't open unmirrored output file %s\n",
150                argv[0]);
151        usage(progName);
152        exit(-1);
153      }
154    } else if (argv[0][0] != '-') {
155      // Handle mirName, xfName, inName files....
156      if (mirName == NULL) {
157        mirName = argv[0];
158      } else if (xfName == NULL) {
159        xfName = argv[0];
160      } else if (inName == NULL) {
161        inName = argv[0];
162      } else {
163        fprintf(stderr, "Error, Unhandled arg '%s'\n", argv[0]);
164        usage(progName);
165        exit(-1);
166      }
167    } else {
168      // Unhandled arg
169      fprintf(stderr, "Error, Unhandled arg '%s'\n", argv[0]);
170      usage(progName);
171      exit(-1);
172    }
173  }
174
175  // Open mir file...
176  if (mirName == NULL) {
177    fprintf(stderr, "Missing arg:  .mir file.\n");
178    usage(progName);
179    exit(-1);
180  } else if (!strcmp(mirName, "all")) {
181    mirAll = TRUE;
182  } else {
183    mirFile = fopen(mirName, "r");
184    if (mirFile == NULL) {
185      fprintf(stderr, "Error: Couldn't open .mir file %s\n", mirName);
186      usage(progName);
187      exit(-1);
188    }
189  }
190
191  // Open xf file...
192  if (xfName == NULL) {
193    fprintf(stderr, "Missing arg:  .xf file.\n");
194    usage(progName);
195    exit(-1);
196  } else if (!strcmp(xfName, "none")) {
197    xfNone = TRUE;
198  } else {
199    xfFile = fopen(xfName, "r");
200    if (xfFile == NULL) {
201      fprintf(stderr, "Error: Couldn't open .xf file %s\n", xfName);
202      usage(progName);
203      exit(-1);
204    }
205  }
206
207  // Open (optional) input file...
208  if (inName != NULL) {
209    inFile = fopen(inName, "r");
210    if (inFile == NULL) {
211      fprintf(stderr, "Error: Couldn't open input file %s\n", inName);
212      usage(progName);
213      exit(-1);
214    }
215  }
216
217 
218  read_mir(mirFile);
219  read_xf(xfFile);
220  read_file(inFile);
221
222  mirror(outxfFile);
223
224  write_file(outFile);
225  if (restFile != NULL) {
226    select_rest();
227    write_file(restFile);
228  }
229
230}
231
232
233/******************************************************************************
234Transform the PLY object.
235******************************************************************************/
236
237void
238select_rest() 
239{
240  int i;
241  Vertex *vert;
242  // Select all the vertices, etc OUTSIDE the mirror
243
244  // First, set every vert flag to valid.
245  for (i = 0; i < nverts; i++) {
246    vert = vlist[i];
247    vert->valid = TRUE;
248  }
249
250  // Now remove all the points that are behind or
251  // within epsilon of the mirror surface.
252  // (to get rid of the frame, any supporting
253  // structure, etc...)
254  Vec3f miraxes[2];
255  Vec3f mirnorm;
256  float mirD;    // Distance along normal to the mirror surface
257
258  miraxes[0] = mir[1] - mir[0];
259  miraxes[1] = mir[2] - mir[1];
260  mirnorm = miraxes[0].cross(miraxes[1]);
261  mirnorm.normalize();
262  mirD = mirnorm.dot(mir[0]);
263
264#define REST_EPSILON 0.06
265
266  Vec3f pos;
267  float d;
268
269  for (i = 0; i < nverts; i++) {
270    vert = vlist[i];
271    pos.setValue(vert->x, vert->y, vert->z);
272    d = mirnorm.dot(pos);
273    if (mirAll || d < (mirD + REST_EPSILON)) {
274      vlist[i]->valid = FALSE;
275    }
276  }
277
278  renumberValidVertices();
279}
280
281void
282mirror(FILE *outxfFile)
283{
284  Vec3f miraxes[2];
285  Vec3f mirnorm;
286  float mirD;    // Distance along normal to the mirror surface
287
288  miraxes[0] = mir[1] - mir[0];
289  miraxes[1] = mir[2] - mir[1];
290  mirnorm = miraxes[0].cross(miraxes[1]);
291  mirnorm.normalize();
292
293  // fprintf(stderr, "Mirror normal:  %f %f %f\n",
294  //      mirnorm[0], mirnorm[1], mirnorm[2]);
295
296  mirD = mirnorm.dot(mir[0]);
297  // First clip all the points to be farther than the mirror
298  // (plus an epsilon)
299
300#define EPSILON 0.03
301
302  int i;
303  Vertex *vert;
304  Vec3f pos;
305  float d;
306
307  for (i = 0; i < nverts; i++) {
308    vert = vlist[i];
309    pos.setValue(vert->x, vert->y, vert->z);
310    d = mirnorm.dot(pos);
311    if (!mirAll && d > (mirD - EPSILON)) {
312      vlist[i]->valid = FALSE;
313    }
314  }
315
316  // Now clip against the four sides of the mirror.
317  Vec3f *v1, *v2, sidenorm;
318  for (int side=0; side < 4; side++) {
319    v1 = &(mir[side]);
320    v2 = &(mir[(side+1)%4]);
321    // Sidenorm points outward from mirror boundary.
322    // This assumes that we're clipping outside the frustum
323    // emanating from the origin (0,0,0)
324    sidenorm = v1->cross(*v2);
325    for (i = 0; i < nverts; i++) {
326      vert = vlist[i];
327      pos.setValue(vert->x, vert->y, vert->z);
328      d = sidenorm.dot(pos);
329      if (!mirAll && d > 0) {
330        vlist[i]->valid = FALSE;
331      } 
332    }
333  }
334   
335  // Now, if the point is still valid, reflect it in the mirror.
336  Vec3f newpos, diff;
337  for (i = 0; i < nverts; i++) {
338    vert = vlist[i];
339    if (vert->valid) {
340      vert->x *= -1.0;
341    }
342  }
343
344  // Compute the new .xf for the mirrored points:
345  Matrix4f outxf;
346  outxf.makeIdentity();
347
348  // Basically, here, we put a vertex at the end of each of
349  // the basis vectors.  Then we reflect it through the mirror,
350  // subtract the origin, and we are left with the new basis
351  // vectors for the mirrored scan, which also form the rotation
352  // matrix for the .xf file.
353  Vec3f _000(0,0,0);
354  Vec3f _100(1,0,0);
355  Vec3f _010(0,1,0);
356  Vec3f _001(0,0,1);
357  float d000 = 2.0*(mirD - mirnorm.dot(_000));
358  float d100 = 2.0*(mirD - mirnorm.dot(_100));
359  float d010 = 2.0*(mirD - mirnorm.dot(_010));
360  float d001 = 2.0*(mirD - mirnorm.dot(_001));
361  // fprintf(stderr, "distances: %f %f %f %f\n", d000, d100, d010, d001);
362  Vec3f t000(mirnorm);
363  Vec3f t100(mirnorm);
364  Vec3f t010(mirnorm);
365  Vec3f t001(mirnorm);
366  t000 *= d000;
367  t100 *= d100;
368  t010 *= d010;
369  t001 *= d001;
370  _000 += t000;
371  _100 += t100;
372  _010 += t010;
373  _001 += t001;
374
375  _100 -= _000;
376  _010 -= _000;
377  _001 -= _000;
378
379  Matrix4f rot;
380  rot.makeIdentity();
381  rot.m[0][0] = -_100[0];
382  rot.m[0][1] = _100[1];
383  rot.m[0][2] = _100[2];
384  rot.m[1][0] = -_010[0];
385  rot.m[1][1] = _010[1];
386  rot.m[1][2] = _010[2];
387  rot.m[2][0] = -_001[0];
388  rot.m[2][1] = _001[1];
389  rot.m[2][2] = _001[2];
390
391  outxf.multLeft(rot);
392
393  // Set the translation of the .xf file equal to the translation
394  // of the origin through the mirror.
395  Vec3f trans(mirnorm);
396  trans *= (mirD * 2.0);
397  outxf.setTranslate(trans);
398
399  // Print out the new matrix for it to outxfFile
400  for (i=0; i<4; i++) {
401    for (int j=0; j<4; j++) {
402      fprintf(outxfFile, "%f ", outxf.m[i][j]);
403    }
404    fprintf(outxfFile, "\n");
405  }
406 
407
408  // Now we need to renumber all the valid vertices, so that
409  // they form a contiguous list
410  renumberValidVertices();
411  flipValidNorms();
412}
413
414void flipValidNorms()
415{
416  // Mirored triangles have backwards normals, so reset them...
417  int i;
418  for (i=0; i < nfaces; i++) {
419    Face *face = flist[i];
420    if (face->valid && face->origv != NULL) {
421      for (int j=0; j < face->num_pts; j++) {
422        face->v[j] = vlist[face->origv[face->num_pts-(j+1)]]->newindex;
423      }
424    }
425  }
426}
427
428void renumberValidVertices() 
429{
430  int i;
431  Vertex *vert;
432  // Go through all the vertices and reassign new index numbers
433  int num=0;
434  for (i=0; i < nverts; i++) {
435    if (vlist[i]->valid) {
436      vlist[i]->newindex = num++;
437    }
438  }
439
440  // Go through all the triangles -- if they touch invalid points,
441  // then invalidate the triangle...  If the point is valid, grab
442  // the new index number... :-)
443  for (i=0; i < nfaces; i++) {
444    Face *face = flist[i];
445    // Allocate an origv array, containing the old index numbers
446    if (face->origv == NULL) {
447      face->origv = (int *) malloc(sizeof(int) * face->num_pts);
448      for (int j=0; j < face->num_pts; j++) {
449        face->origv[j] = face->v[j];
450      }
451    }
452
453    // Set the face valid, and then invalidate if it touches any
454    // invalid points...
455    face->valid = TRUE;
456    for (int j=0; j < face->num_pts; j++) {
457      vert = vlist[face->v[j]];
458      if (vert->valid) {
459        // get the new index.
460        face->v[j] = vlist[face->origv[j]]->newindex;
461      } else {
462        face->valid = FALSE;
463      }
464    }
465  }
466}
467
468/******************************************************************************
469Read in the input files
470******************************************************************************/
471
472void read_mir(FILE *mirFile)
473{
474
475  // If we're mirroring everything, then just put the mirror
476  // down the Z axis, so that it only flips x coord.
477  if (mirAll) {
478    mir[0].x = 0; mir[0].y = -1; mir[0].z =  1;
479    mir[1].x = 0; mir[1].y = -1; mir[1].z = -1;
480    mir[2].x = 0; mir[2].y =  1; mir[2].z = -1;
481    mir[3].x = 0; mir[3].y =  1; mir[3].z =  1;
482    return;
483  }
484
485  // Read mirror file -- must have the coordinates of the 4
486  // vertices, one per line
487  for (int i=0; i < 4; i++) {
488    if (fscanf(mirFile, "%f %f %f\n", &(mir[i][0]), &(mir[i][1]),
489               &(mir[i][2])) != 3) {
490      fprintf(stderr, "Error: did not find 3-vector on line %d of mirror"
491              " file.\n", i+1);
492      exit(-1);
493    }
494  }
495}
496
497void read_xf(FILE *xfFile)
498{
499
500  // If we have no xform, then just load the identity matrix.
501  // No need to transform the mirror to new position, cuz it ain't
502  // movin.
503  if (xfNone) {
504    mirxf.makeIdentity();
505    return;
506  }
507
508  float mat[4][4];
509
510  // Read mirror file -- must have the coordinates of the 4
511  // vertices, one per line
512  int i;
513  for (i=0; i < 4; i++) {
514    if (fscanf(xfFile, "%f %f %f %f\n", &(mat[i][0]), &(mat[i][1]),
515               &(mat[i][2]), &(mat[i][3])) != 4) {
516      fprintf(stderr, "Error: did not find 4-vector on line %d of matrix"
517              " file.\n", i+1);
518      exit(-1);
519    }
520  }
521 
522  // Fill the mirror matrix
523  mirxf.setValue(mat);
524
525  // Transform the mirror to its new position...
526  Vec3f corner;
527  for (i=0; i < 4; i++) {
528    corner.setValue(mir[i]);
529    mirxf.multVec(corner, mir[i]);
530  }
531}
532
533void
534read_file(FILE *inFile)
535{
536  int i,j,k;
537  PlyFile *ply;
538  int nprops;
539  int num_elems;
540  char *elem_name;
541  float version;
542
543
544  /*** Read in the original PLY object ***/
545
546
547  ply  = ply_read (inFile, &nelems, &elist);
548  ply_get_info (ply, &version, &file_type);
549
550  for (i = 0; i < nelems; i++) {
551
552    /* get the description of the first element */
553    elem_name = elist[i];
554    ply_get_element_description (ply, elem_name, &num_elems, &nprops);
555
556    if (equal_strings ("vertex", elem_name)) {
557
558      /* create a vertex list to hold all the vertices */
559      vlist = (Vertex **) malloc (sizeof (Vertex *) * num_elems);
560      nverts = num_elems;
561
562      /* set up for getting vertex elements */
563
564      ply_get_property (ply, elem_name, &vert_props[0]);
565      ply_get_property (ply, elem_name, &vert_props[1]);
566      ply_get_property (ply, elem_name, &vert_props[2]);
567      vert_other = ply_get_other_properties (ply, elem_name,
568                     offsetof(Vertex,other_props));
569
570      /* grab all the vertex elements */
571      for (j = 0; j < num_elems; j++) {
572        vlist[j] = (Vertex *) malloc (sizeof (Vertex));
573        ply_get_element (ply, (void *) vlist[j]);
574        // all points are initially valid, until we crop to mirror
575        vlist[j]->valid = TRUE;
576      }
577    }
578
579    else if (equal_strings ("face", elem_name)) {
580
581      /* create a face list to hold all the vertices */
582      flist = (Face **) malloc (sizeof (Face *) * num_elems);
583      nfaces = num_elems;
584
585      /* set up for getting face elements */
586      ply_get_property (ply, elem_name, &face_props[0]);
587      face_other = ply_get_other_properties (ply, elem_name,
588                     offsetof(Face,other_props));
589
590      /* grab all the face elements */
591      for (j = 0; j < num_elems; j++) {
592        flist[j] = (Face *) malloc (sizeof (Face));
593        ply_get_element (ply, (void *) flist[j]);
594        // all faces are initially valid, until we crop to mirror
595        flist[j]->valid = TRUE;
596        flist[j]->origv = NULL;
597      }
598    }
599    else
600      other_elements = ply_get_other_element (ply, elem_name, num_elems);
601  }
602
603  comments = ply_get_comments (ply, &num_comments);
604  obj_info = ply_get_obj_info (ply, &num_obj_info);
605
606  ply_close (ply);
607}
608
609
610/******************************************************************************
611Write out the PLY file to output file.  Write only the valid points.
612(Valid points are the ones seen through the mirror.)
613******************************************************************************/
614
615void
616write_file(FILE *outFile)
617{
618  int i,j,k;
619  PlyFile *ply;
620  int num_elems;
621  char *elem_name;
622
623  ply = ply_write (outFile, nelems, elist, file_type);
624
625  // Compute number of valid vertices
626  int validverts = 0;
627  for (i=0; i < nverts; i++) {
628    if (vlist[i]->valid) validverts++;
629  }
630
631  // Compute number of valid faces
632  int validfaces = 0;
633  for (i=0; i < nfaces; i++) {
634    if (flist[i]->valid) validfaces++;
635  }
636
637  /* describe what properties go into the vertex and face elements */
638  ply_element_count (ply, "vertex", validverts);
639  ply_describe_property (ply, "vertex", &vert_props[0]);
640  ply_describe_property (ply, "vertex", &vert_props[1]);
641  ply_describe_property (ply, "vertex", &vert_props[2]);
642  ply_describe_other_properties(ply, vert_other, offsetof(Vertex,other_props));
643
644  ply_element_count (ply, "face", validfaces);
645  ply_describe_property (ply, "face", &face_props[0]);
646  ply_describe_other_properties(ply, face_other, offsetof(Face,other_props));
647
648  ply_describe_other_elements (ply, other_elements);
649
650  for (i = 0; i < num_comments; i++)
651    ply_put_comment (ply, comments[i]);
652
653  for (i = 0; i < num_obj_info; i++)
654    ply_put_obj_info (ply, obj_info[i]);
655
656  ply_header_complete (ply);
657
658  /* set up and write the vertex elements */
659  ply_put_element_setup (ply, "vertex");
660  for (i = 0; i < nverts; i++) {
661    if (vlist[i]->valid) {
662      ply_put_element (ply, (void *) vlist[i]);
663    }
664  }
665
666  /* set up and write the face elements */
667  ply_put_element_setup (ply, "face");
668  for (i = 0; i < nfaces; i++) {
669    if (flist[i]->valid) {
670      ply_put_element (ply, (void *) flist[i]);
671    }
672  }
673
674  ply_put_other_elements (ply);
675
676  ply_close (ply);
677}
678
679
680/******************************************************************************
681Print out usage information.
682******************************************************************************/
683
684void
685usage(char *progName)
686{
687  fprintf (stderr, 
688           "usage: %s in.mir in.xf [-o out.ply] [-r rest.ply] [in.ply]\n"
689           "   or: %s in.mir in.xf [-o out.ply] [-r rest.ply] < in.ply\n" 
690           "   or: %s all    none  [-o out.ply] [-r rest.ply] < in.ply\n", 
691           progName, progName, progName);
692  fprintf (stderr, 
693           "where:\n"
694           "     in.mir is mirror file, four lines of 3 coords, for each\n"
695           "              corner of the mirror glass.  (the keyword\n"
696           "              'all' mirrors the entire scan in x.)\n"
697           "     in.xf is the .xf file moving the mirror file to match\n"
698           "              the position of the mirror in the input file.\n"
699           "              ('none' loads the identity matrix.)\n"
700           "     out.ply is the output file for all points seen through\n"
701           "              the mirror.\n"
702           "     rest.ply is the output file for all points NOT seen\n"
703           "              through the mirror.\n"
704           "     in.ply   is the input ply file.\n"
705           "\n");
706  exit(-1);
707}
Note: See TracBrowser for help on using the repository browser.