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

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

Added original make3d

File size: 16.5 KB
Line 
1//
2// Brian L. Curless
3// Stanford University
4// May 1994
5//
6
7#include <stdio.h>
8#include <Inventor/So.h>
9#include <ply.h>
10#include <stdlib.h>
11#include <strings.h>
12#include <iostream.h>
13
14#define MAX_VERT_PROPS 20
15
16typedef unsigned char uchar;
17typedef float Normal[3];
18
19struct Vertex {
20    float x, y, z;
21    float nx, ny, nz;
22    uchar diff_r, diff_g, diff_b;
23    float intensity;
24    float std_dev;
25};
26
27struct Face {
28    uchar nverts;
29    int *verts;
30};
31
32
33
34static PlyProperty vert_prop_x = 
35   {"x", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
36static PlyProperty vert_prop_y = 
37  {"y", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
38static PlyProperty vert_prop_z = 
39  {"z", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
40static PlyProperty vert_prop_nx = 
41   {"nx", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
42static PlyProperty vert_prop_ny = 
43  {"ny", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
44static PlyProperty vert_prop_nz = 
45  {"nz", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
46static PlyProperty vert_prop_intens = 
47  {"intensity", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
48static PlyProperty vert_prop_std_dev = 
49  {"std_dev", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
50static PlyProperty vert_prop_diff_r = 
51  {"diffuse_red", PLY_UCHAR, PLY_UCHAR, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
52static PlyProperty vert_prop_diff_g = 
53  {"diffuse_green", PLY_UCHAR, PLY_UCHAR, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
54static PlyProperty vert_prop_diff_b = 
55  {"diffuse_blue", PLY_UCHAR, PLY_UCHAR, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
56
57static PlyProperty vert_props[MAX_VERT_PROPS];
58
59
60static PlyProperty face_props[] = { 
61  {"vertex_indices", PLY_INT, PLY_INT, 0, 1, PLY_UCHAR, PLY_UCHAR, 0},
62};
63
64
65/* dummy variables and associated macros for computing field offsets */
66
67Vertex *vert_dummy;
68#define voffset(field) ((char *) (&vert_dummy->field) - (char *) vert_dummy)
69Face *face_dummy;
70#define foffset(field) ((char *) (&face_dummy->field) - (char *) face_dummy)
71
72
73static int DIFFUSE_COLORS;
74static int INTENSITIES;
75static int FOUND_NORMALS;
76
77// Function defintions
78PlyFile *readPlyFile(FILE *inFile, Vertex **pVerts, Face **pFaces, 
79                     int *pNumVerts, int *pNumFaces);
80SoIndexedFaceSet *buildFaceSet(Face *faces, int numFaces, int flipNormals);
81SoIndexedTriangleStripSet *buildTMesh(Face *faces, int numFaces);
82int isTriangleMesh(Face *faces, int numFaces);
83void printUsage();
84Normal *createNormals(Vertex *verts, Face *faces, int numVerts, int numFaces);
85void getAreaAndNormal(Face *tri, Vertex *verts, float *area, Normal normal);
86
87
88void
89main(int argc, char**argv)
90{   
91    Vertex *verts;
92    Face *faces;
93    int numVerts, numFaces, i;
94    SoMaterialBinding *mtlBndg;
95
96    int useIntensities = FALSE;
97    int flipNormals = FALSE;
98    int computeNormals = FALSE;
99
100    char *plyName = NULL;
101    FILE *inFile;
102
103    // Process input parameters
104
105    for (i = 1; i < argc; i++) {
106        if (!strcmp(argv[i], "-n")) {
107            computeNormals = TRUE;
108        } else if (!strcmp(argv[i], "-intens")) {
109            useIntensities = TRUE;
110        } else if (!strcmp(argv[i], "-flipn")) {
111            flipNormals = TRUE;
112        } else if (!strcmp(argv[i], "-h")) {
113            printUsage();
114            exit(0);
115        } else if (argv[i][0] != '-' && plyName == NULL) {
116          // First non-'-flag' arg, assume input ply file
117          plyName = argv[i];
118        } else {
119          // Unhandled arg -- print usage
120          printUsage();
121          exit(-1);
122        }
123    }
124
125    // open input file
126    if (plyName == NULL) {
127      inFile = stdin;
128    } else {
129      inFile = fopen(plyName, "r");
130      if (inFile == NULL) {
131        fprintf(stderr, "Error: Couldn't open input ply file %s.\n", plyName);
132        printUsage();
133        exit(-1);
134      }
135    }
136    readPlyFile(inFile, &verts, &faces, &numVerts, &numFaces);
137
138    if (verts == NULL) {
139        fprintf(stderr, "Obtained no vertices.\n");
140        exit(1);
141    }
142
143    if (faces == NULL) 
144        computeNormals = FALSE;
145
146    // Initialize Inventor
147    SoDB::init();
148
149
150    // Build scene graph
151
152    SoSeparator *root = new SoSeparator;
153    root->ref();
154
155    /*  Used to have to insert scale node 10x and then scale the
156        vertices by 0.1x .  I believe this bug has been fixed.
157
158    float scale = 10;
159    SoScale *sc = new SoScale;
160    root->addChild(sc);
161    sc->scaleFactor.setValue(1/scale, 1/scale, 1/scale);
162    */
163
164
165    Normal *normals;
166    SoNormalBinding *normalBinding;
167    if (FOUND_NORMALS && !computeNormals) {
168        SoNormal *normal = new SoNormal;
169        root->addChild(normal);
170        normal->vector.insertSpace(0, numVerts);
171        for (i = 0; i < numVerts; i++) {
172            if (!flipNormals) {
173                normal->vector.set1Value(i, verts[i].nx, 
174                                         verts[i].ny, verts[i].nz);
175            }
176            else {
177                normal->vector.set1Value(i, -verts[i].nx, 
178                                         -verts[i].ny, -verts[i].nz);
179            }
180        }
181        normalBinding = new SoNormalBinding;
182        root->addChild(normalBinding); 
183    }
184    else if (computeNormals) {
185        normals = createNormals(verts, faces, numVerts, numFaces);
186
187        if (normals != NULL) {
188            if (flipNormals) {
189                for (i = 0; i < numVerts; i++) {
190                    normals[i][0] = -normals[i][0];
191                    normals[i][1] = -normals[i][1];
192                    normals[i][2] = -normals[i][2];
193                }
194            }
195            SoNormal *normal = new SoNormal;
196            root->addChild(normal);
197            normal->vector.insertSpace(0, numVerts);
198            normal->vector.setValues(0, numVerts, normals);
199            normalBinding = new SoNormalBinding;
200            root->addChild(normalBinding);
201        } else {
202            computeNormals = FALSE;
203            // Assume smooth shading
204            SoShapeHints *shints = new SoShapeHints;
205            shints->creaseAngle.setValue(M_PI*0.999);
206            root->addChild(shints);
207        }
208    } else {
209        // Assume smooth shading
210        SoShapeHints *shints = new SoShapeHints;
211        shints->creaseAngle.setValue(M_PI*0.999);
212        root->addChild(shints);
213    }
214
215    // Insert the coordinates
216    SoCoordinate3 *coord = new SoCoordinate3;
217    root->addChild(coord);
218
219    coord->point.insertSpace(0, numVerts-1);
220    for (i = 0; i < numVerts; i++) {
221        coord->point.set1Value(i, verts[i].x, verts[i].y, verts[i].z);
222    }
223
224    SoMaterial *mtl = new SoMaterial;
225    root->addChild(mtl);
226    mtl->ambientColor.setValue(0,0,0);
227    mtl->diffuseColor.setValue(1.0,1.0,1.0);
228
229    // Build materials if necessary
230    if (DIFFUSE_COLORS || (useIntensities&&INTENSITIES)) {
231        mtl->diffuseColor.insertSpace(0, numVerts);
232        for (i = 0; i < numVerts; i++) {
233          if (useIntensities&&INTENSITIES)
234            mtl->diffuseColor.set1Value(i, verts[i].intensity, 
235                                        verts[i].intensity, 
236                                        verts[i].intensity);
237          else
238            mtl->diffuseColor.set1Value(i, 
239                                        verts[i].diff_r/255.0, 
240                                        verts[i].diff_g/255.0, 
241                                        verts[i].diff_b/255.0);
242        }
243        mtlBndg = new SoMaterialBinding;
244        root->addChild(mtlBndg);
245    } else {
246        mtl->diffuseColor.setValue(0.5,0.5,0.5);
247        mtl->specularColor.setValue(0.4,0.4,0.4);
248        mtl->shininess.setValue(0.1);
249    }
250   
251    if (faces == NULL) {
252        if (DIFFUSE_COLORS || (useIntensities&&INTENSITIES))
253            mtlBndg->value.setValue(SoMaterialBinding::PER_VERTEX_INDEXED);
254        SoPointSet *ptSet = new SoPointSet;
255        root->addChild(ptSet);   
256    } else {
257        if (DIFFUSE_COLORS || (useIntensities&&INTENSITIES))
258            mtlBndg->value.setValue(SoMaterialBinding::PER_VERTEX_INDEXED);
259
260        if (computeNormals || FOUND_NORMALS)
261            normalBinding->value.setValue
262                (SoNormalBinding::PER_VERTEX_INDEXED); 
263        SoIndexedFaceSet *faceSet = 
264            buildFaceSet(faces, numFaces, flipNormals);
265        faceSet->normalIndex.setValue(-1);
266        root->addChild(faceSet);   
267    }
268
269
270    // Write the Inventor file
271
272    SoWriteAction wa;
273    wa.getOutput()->setFilePointer(stdout);
274    wa.getOutput()->setBinary(TRUE);
275    wa.apply(root);   
276
277    exit(0);
278}
279
280
281
282//
283// Read in data from the ply file
284//
285
286PlyFile *
287readPlyFile(FILE *inFile, Vertex **pVerts, Face **pFaces, int *pNumVerts, 
288            int *pNumFaces)
289{
290    int j;
291    int nelems;
292    char **elist;
293    char *elem_name;
294    int nprops, num_vert_props;
295    int num_elems;
296
297    vert_props[0].offset = voffset(x);
298    vert_props[1].offset = voffset(y);
299    vert_props[2].offset = voffset(z);
300    vert_props[3].offset = voffset(diff_r);
301    vert_props[4].offset = voffset(diff_g);
302    vert_props[5].offset = voffset(diff_b);
303   
304    face_props[0].offset = foffset(verts);
305    face_props[0].count_offset = foffset(nverts);  /* count offset */
306   
307    PlyFile *ply  = ply_read (inFile, &nelems, &elist);
308
309    if (!ply)
310        exit(1);
311
312    int nvp = 0;
313
314    INTENSITIES = FALSE;
315    DIFFUSE_COLORS = FALSE;
316    FOUND_NORMALS = FALSE;
317
318    if (ply_is_valid_property(ply, "vertex", vert_prop_x.name)) {
319        vert_props[nvp] = vert_prop_x;
320        vert_props[nvp].offset = voffset(x); nvp++;
321    }
322   
323    if (ply_is_valid_property(ply, "vertex", vert_prop_y.name)) {
324        vert_props[nvp] = vert_prop_y;
325        vert_props[nvp].offset = voffset(y); nvp++;
326    }
327   
328    if (ply_is_valid_property(ply, "vertex", vert_prop_z.name)) {
329        vert_props[nvp] = vert_prop_z;
330        vert_props[nvp].offset = voffset(z); nvp++;
331    }
332   
333    if (ply_is_valid_property(ply, "vertex", vert_prop_nx.name)) {
334        FOUND_NORMALS = TRUE;
335        vert_props[nvp] = vert_prop_nx;
336        vert_props[nvp].offset = voffset(nx); nvp++;
337    }
338   
339    if (ply_is_valid_property(ply, "vertex", vert_prop_ny.name)) {
340        vert_props[nvp] = vert_prop_ny;
341        vert_props[nvp].offset = voffset(ny); nvp++;
342    }
343   
344    if (ply_is_valid_property(ply, "vertex", vert_prop_nz.name)) {
345        vert_props[nvp] = vert_prop_nz;
346        vert_props[nvp].offset = voffset(nz); nvp++;
347    }
348   
349    if (ply_is_valid_property(ply, "vertex", vert_prop_intens.name)) {
350        INTENSITIES = TRUE;
351        vert_props[nvp] = vert_prop_intens;
352        vert_props[nvp].offset = voffset(intensity); nvp++;
353    }
354   
355    if (ply_is_valid_property(ply, "vertex", vert_prop_std_dev.name)) {
356        vert_props[nvp] = vert_prop_std_dev;
357        vert_props[nvp].offset = voffset(std_dev); nvp++;
358    }
359   
360    if (ply_is_valid_property(ply, "vertex", "diffuse_red") &&
361        ply_is_valid_property(ply, "vertex", "diffuse_green") &&
362        ply_is_valid_property(ply, "vertex", "diffuse_blue")) 
363    {
364        DIFFUSE_COLORS = TRUE;
365        vert_props[nvp] = vert_prop_diff_r;
366        vert_props[nvp].offset = voffset(diff_r); nvp++;
367        vert_props[nvp] = vert_prop_diff_g;
368        vert_props[nvp].offset = voffset(diff_g); nvp++;
369        vert_props[nvp] = vert_prop_diff_b;
370        vert_props[nvp].offset = voffset(diff_b); nvp++;
371    }
372   
373    num_vert_props = nvp;
374
375    Vertex *verts = NULL;
376    Face *faces = NULL;
377
378    for (int i = 0; i < nelems; i++) {
379
380        /* get the description of the first element */
381        elem_name = elist[i];
382        ply_get_element_description
383            (ply, elem_name, &num_elems, &nprops);
384       
385        /* if we're on vertex elements, read them in */
386        if (equal_strings ("vertex", elem_name)) {
387           
388            int numVerts = *pNumVerts = num_elems;
389            verts = new Vertex[numVerts];
390           
391            /* set up for getting vertex elements */
392            ply_get_element_setup (ply, elem_name, num_vert_props, vert_props);
393           
394            /* grab all the vertex elements */
395            for (j = 0; j < numVerts; j++)
396                ply_get_element (ply, (void *) &verts[j]);
397        }
398
399        if (equal_strings ("face", elem_name)) {
400
401            ply_get_element_setup (ply, elem_name, 1, face_props);
402
403            int numFaces = *pNumFaces = num_elems;
404
405            if (numFaces == 0)
406                continue;
407
408            faces = new Face[numFaces];
409
410            for (j = 0; j < numFaces; j++)             
411                ply_get_element (ply, (void *) &faces[j]);
412        }
413    }
414
415    *pVerts = verts;
416    *pFaces = faces;
417
418    return ply;
419}
420
421
422
423//
424// Build Inventor face set from faces
425//
426
427SoIndexedFaceSet *
428buildFaceSet(Face *faces, int numFaces, int flipNormals)
429{
430    SoIndexedFaceSet *faceSet = new SoIndexedFaceSet;
431
432    int total = 0;
433    for (int i = 0; i < numFaces; i++) {
434        total += int(faces[i].nverts + 1);
435    }
436
437    faceSet->coordIndex.insertSpace(0, total-1);
438
439    int counter = 0;
440    for (i = 0; i < numFaces; i++) {
441        if (!flipNormals) {
442            for (int j = 0; j < faces[i].nverts; j++) {
443                faceSet->coordIndex.set1Value(counter, faces[i].verts[j]);
444                counter++;
445            }
446        } else {
447            for (int j = faces[i].nverts-1; j >= 0 ; j--) {
448                faceSet->coordIndex.set1Value(counter, faces[i].verts[j]);
449                counter++;
450            }
451        }
452        faceSet->coordIndex.set1Value(counter, SO_END_FACE_INDEX);     
453        counter++;
454    }
455
456    return faceSet;
457}
458
459
460
461//
462// Build Inventor triangle mesh from faces.
463//
464
465SoIndexedTriangleStripSet *
466buildTMesh(Face *faces, int numFaces)
467{
468    SoIndexedTriangleStripSet *tmesh = new SoIndexedTriangleStripSet;
469
470    tmesh->coordIndex.insertSpace(0, 4*numFaces);
471
472
473    // Make sure all the faces are triangles
474    if (!isTriangleMesh(faces, numFaces)) {
475        cerr << "Not a triangle mesh.\n";
476        return NULL;
477    }
478
479    int index = 0;
480
481    tmesh->coordIndex.set1Value(index, faces[0].verts[0] );     
482    index++;
483    tmesh->coordIndex.set1Value(index, faces[0].verts[1] );
484    index++;
485    tmesh->coordIndex.set1Value(index, faces[0].verts[2] );
486    index++;
487
488    int newStrip = TRUE;
489    for (int i = 1; i < numFaces; i++) {
490        if (faces[i-1].verts[1] == faces[i].verts[1] 
491            && faces[i-1].verts[2] == faces[i].verts[0]) {
492            tmesh->coordIndex.set1Value(index, faces[i].verts[2] );     
493            index++;
494            newStrip = FALSE;
495        }
496        else if (newStrip
497                 && faces[i-1].verts[1] == faces[i].verts[0] 
498                 && faces[i-1].verts[2] == faces[i].verts[1]) {
499
500// Can't swap???  Broken!!!
501//          tmesh->coordIndex.set1Value(index, SO_SWAP_MESH_INDEX);     
502
503
504            index++;
505            tmesh->coordIndex.set1Value(index, faces[i].verts[2] );     
506            index++;
507            newStrip = FALSE;
508        }
509        else {
510            tmesh->coordIndex.set1Value(index, SO_END_STRIP_INDEX);     
511            index++;
512            tmesh->coordIndex.set1Value(index, faces[i].verts[0] );
513            index++;
514            tmesh->coordIndex.set1Value(index, faces[i].verts[1] );     
515            index++;
516            tmesh->coordIndex.set1Value(index, faces[i].verts[2] );     
517            index++;
518            newStrip = TRUE;
519        }
520    }
521
522    tmesh->coordIndex.deleteValues(index, -1);
523
524    return tmesh;
525}
526
527
528
529//
530// Check to see that all faces are triangles.
531//
532
533int
534isTriangleMesh(Face *faces, int numFaces)
535{
536    for (int i = 0; i < numFaces; i++) {
537        if (faces[i].nverts != 3)
538            return FALSE;
539    }
540
541    return TRUE;
542}
543
544
545Normal *
546createNormals(Vertex *verts, Face *tris, int numVerts, int numTris)
547{
548    int i, j, index;
549
550    if (!isTriangleMesh(tris, numTris)) {
551        return NULL;
552    }
553
554    Normal *normals = new Normal[numVerts];
555
556    for (i = 0; i < numVerts; i++) {
557        normals[i][0] = normals[i][1] = normals[i][2] = 0;
558    }
559
560    float triArea, mag;
561    Normal triNormal;
562
563    for (i = 0; i < numTris; i++) {
564        getAreaAndNormal(&tris[i], verts, &triArea, triNormal);
565        for (j = 0; j < tris[i].nverts; j++) {
566            index = tris[i].verts[j];
567            // I'm doing straight averaging of normals here!
568            // What's the best answer???
569#if 0
570            normals[index][0] += triArea*triNormal[0];
571            normals[index][1] += triArea*triNormal[1];
572            normals[index][2] += triArea*triNormal[2];
573#else
574            normals[index][0] += triNormal[0];
575            normals[index][1] += triNormal[1];
576            normals[index][2] += triNormal[2];
577#endif
578        }
579    }
580
581    for (i = 0; i < numVerts; i++) {
582        mag = sqrt(normals[i][0] * normals[i][0] +
583                   normals[i][1] * normals[i][1] +
584                   normals[i][2] * normals[i][2]);
585        if (mag != 0) {
586            normals[i][0] /= mag;
587            normals[i][1] /= mag;
588            normals[i][2] /= mag;
589        }
590    }
591
592    return normals;
593}
594
595
596
597void
598getAreaAndNormal(Face *tri, Vertex *verts, float *area, Normal normal)
599{
600    Vertex *vert0 = &verts[tri->verts[0]];
601    Vertex *vert1 = &verts[tri->verts[1]];
602    Vertex *vert2 = &verts[tri->verts[2]];
603
604    float v0[3], v1[3], norm[3];
605
606    v0[0] = vert2->x - vert1->x;
607    v0[1] = vert2->y - vert1->y;
608    v0[2] = vert2->z - vert1->z;
609
610    v1[0] = vert0->x - vert1->x;
611    v1[1] = vert0->y - vert1->y;
612    v1[2] = vert0->z - vert1->z;
613
614    norm[0] = v0[1]*v1[2] - v0[2]*v1[1];
615    norm[1] = -v0[0]*v1[2] + v0[2]*v1[0];
616    norm[2] = v0[0]*v1[1] - v0[1]*v1[0];
617
618    float length = sqrt(norm[0]*norm[0] + norm[1]*norm[1] + norm[2]*norm[2]);
619
620    *area = length/2;
621
622    if (length != 0) {
623        normal[0] = norm[0]/length;
624        normal[1] = norm[1]/length;
625        normal[2] = norm[2]/length;
626    }
627    else {
628        normal[0] = 0;
629        normal[1] = 0;
630        normal[2] = 0;
631    }
632}
633
634
635void
636printUsage()
637{
638    printf("\n");
639    printf("Usage: ply2iv [-p -pf -intens -n -flipn -h] [in.ply] > out.iv\n");
640    printf("   or: ply2iv [-p -pf -intens -n -flipn -h] < in.ply > out.iv\n");
641    printf("\n");
642    printf("  Plytoiv converts a Ply file containing vertices and faces into an\n");
643    printf("  Inventor file containing a point set and/or a face set.  The default\n");
644    printf("  behavior is to generate a face set.  Options:\n");
645    printf("\n");
646    printf("  -h      Print this help message.\n");
647    printf("  -p      Generate a point set (no faces).\n");
648    printf("  -pf     Generate both a point set and a face set.\n");
649    printf("  -ic     Map 'intensity' to color.\n");
650    printf("  -n      Generate and store normals.\n");
651    printf("  -flipn  Flip normals.\n");
652    printf("\n");
653}
654
Note: See TracBrowser for help on using the repository browser.