[37] | 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 */ |
---|
| 24 | typedef struct Vertex { |
---|
| 25 | float x,y,z; |
---|
| 26 | void *other_props; /* other properties */ |
---|
| 27 | bool valid; |
---|
| 28 | int newindex; |
---|
| 29 | } Vertex; |
---|
| 30 | |
---|
| 31 | typedef 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 | |
---|
| 39 | char *elem_names[] = { /* list of the kinds of elements in the user's object */ |
---|
| 40 | "vertex", "face" |
---|
| 41 | }; |
---|
| 42 | |
---|
| 43 | PlyProperty 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 | |
---|
| 49 | PlyProperty 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 ***/ |
---|
| 56 | int nverts; |
---|
| 57 | Vertex **vlist; |
---|
| 58 | |
---|
| 59 | int nfaces; |
---|
| 60 | Face **flist; |
---|
| 61 | |
---|
| 62 | PlyOtherElems *other_elements = NULL; |
---|
| 63 | PlyOtherProp *vert_other; |
---|
| 64 | PlyOtherProp *face_other; |
---|
| 65 | int nelems; |
---|
| 66 | char **elist; |
---|
| 67 | int num_comments; |
---|
| 68 | char **comments; |
---|
| 69 | int num_obj_info; |
---|
| 70 | char **obj_info; |
---|
| 71 | int file_type; |
---|
| 72 | |
---|
| 73 | // Mirror info |
---|
| 74 | Vec3f mir[4]; |
---|
| 75 | Matrix4f mirxf; |
---|
| 76 | |
---|
| 77 | // Flags |
---|
| 78 | bool mirAll = FALSE; |
---|
| 79 | bool xfNone = FALSE; |
---|
| 80 | |
---|
| 81 | // helper functions |
---|
| 82 | void usage(char *progName); |
---|
| 83 | |
---|
| 84 | void read_mir(FILE *mirFile); |
---|
| 85 | void read_xf(FILE *xfFile); |
---|
| 86 | void read_file(FILE *inFile); |
---|
| 87 | void mirror(FILE *outxfFile); |
---|
| 88 | void select_rest(); |
---|
| 89 | void flipValidNorms(); |
---|
| 90 | void renumberValidVertices(); |
---|
| 91 | void write_file(FILE *outFile); |
---|
| 92 | |
---|
| 93 | |
---|
| 94 | int |
---|
| 95 | main(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 | /****************************************************************************** |
---|
| 234 | Transform the PLY object. |
---|
| 235 | ******************************************************************************/ |
---|
| 236 | |
---|
| 237 | void |
---|
| 238 | select_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 | |
---|
| 281 | void |
---|
| 282 | mirror(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 | |
---|
| 414 | void 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 | |
---|
| 428 | void 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 | /****************************************************************************** |
---|
| 469 | Read in the input files |
---|
| 470 | ******************************************************************************/ |
---|
| 471 | |
---|
| 472 | void 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 | |
---|
| 497 | void 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 | |
---|
| 533 | void |
---|
| 534 | read_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 | /****************************************************************************** |
---|
| 611 | Write out the PLY file to output file. Write only the valid points. |
---|
| 612 | (Valid points are the ones seen through the mirror.) |
---|
| 613 | ******************************************************************************/ |
---|
| 614 | |
---|
| 615 | void |
---|
| 616 | write_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 | /****************************************************************************** |
---|
| 681 | Print out usage information. |
---|
| 682 | ******************************************************************************/ |
---|
| 683 | |
---|
| 684 | void |
---|
| 685 | usage(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 | } |
---|