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

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

Added original make3d

File size: 17.2 KB
Line 
1//
2// iv2ply.cc
3// Written by Sean Anderson.
4// February 1999.
5//
6// Brian Curless' original code at the bottom, ifdef out.
7// Brian's code was not general enough; it didn't work on nearly all
8// Inventor files, but this code should.
9//
10
11#include <assert.h>
12#include <stdio.h>
13
14#include <Inventor/SoDB.h>
15#include <Inventor/nodes/SoSeparator.h>
16#include <Inventor/SoPrimitiveVertex.h>
17#include <Inventor/details/SoFaceDetail.h>
18#include <Inventor/details/SoPointDetail.h>
19#include <Inventor/actions/SoCallbackAction.h>
20
21#include <vector.h> // STL
22
23
24struct TriangleFace
25{
26   TriangleFace()
27   {
28      data[0] = 3; // 3 indices follow, since we have a triangle
29   }
30   
31   void set(const int v, const int coordindex)
32   {
33      memcpy(data + 1 + v * sizeof(int), &coordindex, sizeof(int));
34   }
35   
36   int get(const int v) const
37   {
38      int coordindex;
39      memcpy(&coordindex, data + 1 + v * sizeof(int), sizeof(int));
40      return coordindex;
41   }
42   
43   // uchar int int int
44   unsigned char data[sizeof(unsigned char) + 3 * sizeof(int)];
45};
46
47
48// When we do a traversal of the scene graph, we put the newly
49// found vertices and triangles into an instance of CallbackInfo,
50// so that successive calls of the callback function can return
51// what they find and see what has been found so far.
52class CallbackInfo
53{
54public:
55   CallbackInfo()
56   {
57      currentCoord3 = NULL; 
58      binary = true;
59   
60      cba.addTriangleCallback(SoNode::getClassTypeId(), 
61                              &CallbackInfo::triangleCallback, 
62                              this);
63   }
64   
65   ~CallbackInfo()
66   {
67   }
68   
69   
70   bool apply(SoNode * node)
71   {
72      if (node == NULL)
73      {
74         return true;
75      }
76     
77      cba.apply(node);
78      return false;
79   }
80   
81   bool write(FILE * out)
82   {
83      fprintf(out, 
84              "ply\n"
85              "format %s 1.0\n"
86              "element vertex %d\n"
87              "property float x\n"
88              "property float y\n"
89              "property float z\n"
90              "element face %d\n"
91              "property list uchar int vertex_indices\n"
92              "end_header\n",
93              binary ? "binary_big_endian" : "ascii",
94              coords.size(),
95              indices.size());
96     
97      if (binary)
98      {
99         int numWritten;
100         numWritten = fwrite(coords.begin(), 
101                             sizeof(*coords.begin()), coords.size(), 
102                             out);
103         if (numWritten != coords.size())
104         {
105            fprintf(stderr, "error writing ply file\n");
106            return true;
107         }
108         
109         numWritten = fwrite(indices.begin(), 
110                             sizeof(*indices.begin()), indices.size(), 
111                             out);
112         if (numWritten != indices.size())
113         {
114            fprintf(stderr, "error writing ply file\n");
115            return true;
116         }
117      }
118      else // ascii
119      {
120         for (vector<SbVec3f>::iterator i = coords.begin();
121              i != coords.end();
122              i++)
123         {
124            if (0 > fprintf(out, "%g %g %g\n", (*i)[0], (*i)[1], (*i)[2]))
125            {
126               fprintf(stderr, "error writing ply file\n");
127               return true;
128            }
129         }
130         
131         for (vector<TriangleFace>::iterator j = indices.begin();
132              j != indices.end();
133              j++)
134         {
135            if (0 > fprintf(out, "3 %d %d %d\n", 
136                            (*j).get(0), (*j).get(1), (*j).get(2)))
137            {
138               fprintf(stderr, "error writing ply file\n");
139               return true;
140            }
141         }
142         
143      }
144     
145      return false;
146   }
147   
148   static void triangleCallback(void * userData,
149                                SoCallbackAction * action,
150                                const SoPrimitiveVertex * v1,
151                                const SoPrimitiveVertex * v2,
152                                const SoPrimitiveVertex * v3)
153
154   {
155      assert(userData);
156      ((CallbackInfo *) userData)->triangleCallback(action, v1, v2, v3);
157   }
158
159   void triangleCallback(SoCallbackAction * action,
160                         const SoPrimitiveVertex * v1,
161                         const SoPrimitiveVertex * v2,
162                         const SoPrimitiveVertex * v3);
163   
164   SoCallbackAction cba; 
165   
166   bool binary;
167   
168   vector<SbVec3f> coords;
169   vector<TriangleFace> indices;
170   const SbVec3f * currentCoord3;
171     
172};
173
174void
175CallbackInfo::triangleCallback(SoCallbackAction * action,
176                               const SoPrimitiveVertex * v1,
177                               const SoPrimitiveVertex * v2,
178                               const SoPrimitiveVertex * v3)
179{
180   const SbVec3f * newCurrentCoord3 = (action->getNumCoordinates() > 0) ? 
181      &action->getCoordinate3(0) : NULL;   
182   
183   if (newCurrentCoord3 != currentCoord3)
184   {
185      currentCoord3 = newCurrentCoord3;
186      if (currentCoord3)
187      {
188         SbMatrix m = action->getModelMatrix();
189         SbVec3f p;
190           
191         const int n = action->getNumCoordinates();
192         for (int i = 0; i < n; i++)
193         {         
194            m.multVecMatrix(currentCoord3[i], p);
195            coords.push_back(p);
196         }         
197      }
198   }
199   
200
201   const SoFaceDetail * facedetail = 
202      dynamic_cast<const SoFaceDetail *>(v1->getDetail());
203   
204   TriangleFace f;
205   
206   if (currentCoord3 && facedetail)
207   {
208      for (int i = 0; i < 3; i++) 
209      {
210         const SoPointDetail * pointdetail = facedetail->getPoint(i);
211         assert(pointdetail);
212         
213         int index = pointdetail->getCoordinateIndex();
214     
215         int k;
216         if (currentCoord3[index] == v1->getPoint())
217         {
218            k = 0;
219         }
220         else if (currentCoord3[index] == v2->getPoint())
221         {
222            k = 1;
223         }
224         else 
225         {
226            assert(currentCoord3[index] == v3->getPoint());
227            k = 2;
228         }
229         f.set(k, index + coords.size() - action->getNumCoordinates());
230      }
231   }
232   else
233   {
234      SbMatrix m = action->getModelMatrix();
235      SbVec3f p;
236     
237      f.set(0, coords.size());           
238      m.multVecMatrix(v1->getPoint(), p);
239      coords.push_back(p);
240     
241      f.set(1, coords.size());           
242      m.multVecMatrix(v2->getPoint(), p);
243      coords.push_back(p);
244
245      f.set(2, coords.size());           
246      m.multVecMatrix(v3->getPoint(), p);
247      coords.push_back(p);
248   } 
249   
250   indices.push_back(f);
251}
252
253
254// Returns false on success.
255bool
256iv2ply(SoNode * node, FILE * plyoutput, bool binary)
257{
258   CallbackInfo cbi;
259
260   cbi.binary = binary;
261   
262   return cbi.apply(node) || cbi.write(plyoutput);
263}
264
265
266#if 0
267// We could paste the following into a header called iv2ply.h and
268// change the above 0 to a 1 to use iv2ply as a function in a larger program.
269
270
271// -- start of iv2ply.h
272#ifndef iv2ply_h
273#define iv2ply_h
274
275#include <stdio.h>
276#include <Inventor/nodes/SoGroup.h>
277
278bool iv2ply(SoNode * node, FILE * plyoutput, bool binary = true);
279
280#endif
281// -- end of iv2ply.h
282
283
284#else // use as stand alone program.
285
286void
287printUsage(const char * name)
288{
289   fprintf(stderr, 
290           "Usage:\n%s -h | [-a] [(- | infile.iv) [outfile.ply]]\n"
291           "Where:\n"
292           "  -a           write ascii ply file instead of binary\n"
293           "  -            read Inventor scene graph from standard input\n"
294           "  infile.iv    is the name of the Inventor input file\n"
295           "  outfile.ply  is the name of the plyfile output\n"
296           "               (use standard out otherwise).\n", name);
297}
298
299int
300main(int argc, char * argv[])
301{
302   bool binary = true;
303   char * inputname = NULL;
304   char * outputname = NULL;
305   
306   for (int c = 1; c < argc; c++)
307   {
308      if (!strcmp(argv[c], "-h"))
309      {
310         printUsage(argv[0]);
311         return 1;
312      }
313      else if (!strcmp(argv[c], "-a"))
314      {
315         binary = false;
316      }
317      else if (!inputname)
318      {
319         inputname = argv[c];
320      }
321      else if (!outputname)
322      {
323         outputname = argv[c];
324      }
325   }
326   
327   SoDB::init();
328   
329   SoInput in;
330   if (inputname && strcmp(inputname, "-"))
331   {
332      if (!in.openFile(inputname))
333      {
334         printUsage(argv[0]);
335         return 1;
336      }
337   }
338   SoSeparator * root = SoDB::readAll(&in);
339   if (root == NULL)
340   {
341      fprintf(stderr, "Error reading inventor file\n");
342      printUsage(argv[0]);
343      return 1;
344   }
345   
346   root->ref();
347   
348   FILE * out = stdout;
349   if (outputname)
350   {
351      out = fopen(outputname, "w");
352      if (!out)
353      {
354         fprintf(stderr, "Error opening ply file '%s' for writing.\n", 
355                 outputname);
356         printUsage(argv[0]);
357         return 1;       
358      }
359   }
360   
361   bool r = iv2ply(root, out, binary);
362   
363   root->unref();
364   
365   return r;
366}
367
368#endif
369
370
371
372
373
374#if 0
375
376//
377// Brian L. Curless
378// Stanford University
379// August 1997
380//
381
382
383//  This program is a quick fix for doing some Inventor to ply conversions.
384//  Known problems include: the shapes must be under a single group node,
385//  and normals are not handled carefully.
386//  This program should be generalized to use scene graph traversal.
387
388#include <stdio.h>
389#include <Inventor/So.h>
390#include <ply.h>
391#include <stdlib.h>
392#include <strings.h>
393#include <iostream.h>
394
395#define MAX_VERT_PROPS 20
396
397typedef unsigned char uchar;
398typedef float Normal[3];
399
400struct Vertex {
401    float x, y, z;
402    float nx, ny, nz;
403    uchar diff_r, diff_g, diff_b;
404    float intensity;
405    float std_dev;
406};
407
408struct Face {
409    uchar nverts;
410    int *verts;
411};
412
413struct FaceNorms {
414    uchar nnorms;
415    int *norms;
416};
417
418
419
420static PlyProperty vert_prop_x = 
421   {"x", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
422static PlyProperty vert_prop_y = 
423  {"y", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
424static PlyProperty vert_prop_z = 
425  {"z", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
426static PlyProperty vert_prop_nx = 
427   {"nx", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
428static PlyProperty vert_prop_ny = 
429  {"ny", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
430static PlyProperty vert_prop_nz = 
431  {"nz", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
432static PlyProperty vert_prop_intens = 
433  {"intensity", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
434static PlyProperty vert_prop_std_dev = 
435  {"std_dev", PLY_FLOAT, PLY_FLOAT, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
436static PlyProperty vert_prop_diff_r = 
437  {"diffuse_red", PLY_UCHAR, PLY_UCHAR, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
438static PlyProperty vert_prop_diff_g = 
439  {"diffuse_green", PLY_UCHAR, PLY_UCHAR, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
440static PlyProperty vert_prop_diff_b = 
441  {"diffuse_blue", PLY_UCHAR, PLY_UCHAR, 0, 0, PLY_START_TYPE, PLY_START_TYPE, 0};
442
443static PlyProperty vert_props[MAX_VERT_PROPS];
444
445
446static PlyProperty face_props[] = {
447  {"vertex_indices", PLY_INT, PLY_INT, 0, 1, PLY_UCHAR, PLY_UCHAR, 0},
448};
449
450
451/* dummy variables and associated macros for computing field offsets */
452
453Vertex *vert_dummy;
454#define voffset(field) ((char *) (&vert_dummy->field) - (char *) vert_dummy)
455Face *face_dummy;
456#define foffset(field) ((char *) (&face_dummy->field) - (char *) face_dummy)
457
458
459static int DIFFUSE_COLORS;
460static int INTENSITIES;
461static int FOUND_NORMALS;
462
463// Function definitions
464int readInventorFile(FILE *inFile, Vertex **pVerts, Face **pFaces,
465                     int *pNumVerts, int *pNumFaces);
466int writePlyFile(FILE *outFile, Vertex *verts, Face *faces,
467                 int numVerts, int numFaces);
468void printUsage();
469
470
471void
472main(int argc, char**argv)
473{   
474    Vertex *verts = NULL;
475    Face *faces = NULL;
476    int numVerts, numFaces, i;
477
478    char *ivName = NULL;
479    FILE *ivIn = NULL;
480
481
482    // Process input parameters
483    if (argc == 1) {
484      // No args, use stdin
485      ivIn = stdin;
486    } else if (argc == 2 && argv[1][0] != '-') {
487      // 1 arg, doesn't begin with "-", use as input iv file
488      ivName = argv[1];
489      ivIn = fopen(ivName, "r");
490      if (ivIn == NULL) {
491        fprintf(stderr, "Error: Cannot open input Inventor file %s\n", ivName);
492        printUsage();
493        exit(-1);
494      }
495    } else {
496      printUsage();
497      exit(-1);
498    }
499                       
500    readInventorFile(ivIn, &verts, &faces, &numVerts, &numFaces);
501
502    if (verts == NULL) {
503        fprintf(stderr, "Obtained no vertices.\n");
504        exit(1);
505    }
506
507    writePlyFile(stdout, verts, faces, numVerts, numFaces);
508
509    exit(0);
510}
511
512
513int
514readInventorFile(FILE *inFile, Vertex **pVerts, Face **pFaces,
515                 int *pNumVerts, int *pNumFaces)
516{
517   int i, j, k;
518
519    // Initialize Inventor
520    SoDB::init();
521
522    SoInput in;
523   
524    // Set input file to read from
525    in.setFilePointer(inFile);
526
527    SoNode *node;
528    SbBool ok;
529    ok = SoDB::read(&in, node);
530    if (!ok || node == NULL)
531       return 0;
532
533    Vertex *verts = NULL;
534    Normal *norms = NULL;
535    Face *faces = NULL;
536    FaceNorms *faceNorms = NULL;
537    int numFaceNorms;
538    SoSFEnum binding;
539
540    SoGroup *group = (SoGroup *)node;
541    for (i = 0; i < group->getNumChildren(); i++) {       
542       if (group->getChild(i)->
543           isOfType(SoIndexedFaceSet::getClassTypeId())) {
544
545          SoMFInt32 &coordIndices =
546             ((SoIndexedFaceSet *)group->getChild(i))->coordIndex;
547          int numIndices = coordIndices.getNum();
548          *pNumFaces = 0;
549          for (j = 0; j < numIndices; j++) {
550             if (coordIndices[j] == -1)
551                *pNumFaces = *pNumFaces + 1;
552          }
553          faces = *pFaces = new Face[*pNumFaces];
554          int curFaceIndex = 0;
555          uchar curVerts = 0;
556          for (j = 0; j < numIndices; j++) {
557             if (coordIndices[j] == -1) {
558                faces[curFaceIndex].nverts = curVerts;
559                faces[curFaceIndex].verts = new int[curVerts];
560                for (k = 0; k < curVerts; k++) {
561                   faces[curFaceIndex].verts[k] = coordIndices[k+j-curVerts];
562                }
563                curFaceIndex++;
564                curVerts = 0;
565             } else {
566                curVerts++;
567             }
568          }
569
570          SoMFInt32 &normIndices =
571             ((SoIndexedFaceSet *)group->getChild(i))->normalIndex;       
572          numIndices = normIndices.getNum();
573          if (numIndices == 1 && normIndices[0] == -1) {
574             continue;
575          }
576          numFaceNorms = 0;
577          for (j = 0; j < numIndices; j++) {
578             if (normIndices[j] == -1)
579                numFaceNorms++;
580          }
581          faceNorms = new FaceNorms[numFaceNorms];
582          curFaceIndex = 0;
583          curVerts = 0;
584          for (j = 0; j < numIndices; j++) {
585             if (normIndices[j] == -1) {
586                faceNorms[curFaceIndex].nnorms = curVerts;
587                faceNorms[curFaceIndex].norms = new int[curVerts];
588                for (k = 0; k < curVerts; k++) {
589                   faceNorms[curFaceIndex].norms[k] =
590                      normIndices[k+j-curVerts];
591                }
592                curFaceIndex++;
593                curVerts = 0;
594             } else {
595                curVerts++;
596             }
597          }
598
599       }
600       else if (group->getChild(i)->
601               isOfType(SoCoordinate3::getClassTypeId())) {
602          SoMFVec3f &points = ((SoCoordinate3 *)group->getChild(i))->point;
603          if (verts == NULL) {
604             *pNumVerts = points.getNum();
605             verts = *pVerts = new Vertex[*pNumVerts];
606          }
607          for (j = 0; j < *pNumVerts; j++) {
608             const float *vec = points[j].getValue();
609             verts[j].x = vec[0];
610             verts[j].y = vec[1];
611             verts[j].z = vec[2];
612          }
613       }
614
615       else if (group->getChild(i)->
616               isOfType(SoNormal::getClassTypeId())) {
617          SoMFVec3f &normals = ((SoNormal *)group->getChild(i))->vector;
618          FOUND_NORMALS = TRUE;
619          int numNorms = normals.getNum();
620          norms = new Normal[numNorms];
621          for (j = 0; j < numNorms; j++) {
622             const float *vec = normals[j].getValue();
623             norms[j][0] = vec[0];
624             norms[j][1] = vec[1];
625             norms[j][2] = vec[2];
626          }
627       }
628       else if (group->getChild(i)->
629               isOfType(SoNormalBinding::getClassTypeId())) {
630          binding = ((SoNormalBinding *)group->getChild(i))->value;
631       }
632    }
633
634    if (FOUND_NORMALS && (binding.getValue() == SoNormalBinding::PER_VERTEX_INDEXED)) {
635       if (faceNorms == NULL) {
636          for (j = 0; j < *pNumVerts; j++) {
637             verts[j].nx = norms[j][0];
638             verts[j].ny = norms[j][1];
639             verts[j].nz = norms[j][2];
640          }
641       }
642       else {
643          for (j = 0; j < numFaceNorms; j++) {
644             for (k = 0; k < faceNorms[j].nnorms; k++) {
645                verts[faces[j].verts[k]].nx = norms[faceNorms[j].norms[k]][0];
646                verts[faces[j].verts[k]].ny = norms[faceNorms[j].norms[k]][1];
647                verts[faces[j].verts[k]].nz = norms[faceNorms[j].norms[k]][2];
648             }
649          }
650       }
651    }
652    else {
653       FOUND_NORMALS = FALSE;
654    }
655
656    return 1;
657}
658
659
660int
661writePlyFile(FILE *outFile, Vertex *verts, Face *faces,
662                 int numVerts, int numFaces)
663{
664    int i, j;
665    int nelems;
666    char **elist;
667    int file_type;
668    float version;
669    char *elem_name;
670    int nprops, num_vert_props;
671    int num_elems;
672    PlyProperty **plist;
673    int nvp;
674    char *elem_names[] = {"vertex", "face"};
675
676    PlyFile *ply = ply_write (stdout, 2, elem_names, PLY_BINARY_BE);
677
678    if (ply == NULL) {
679      fprintf(stderr, "Error, couldn't write output.\n");
680      exit(-1);
681    }
682
683    nvp = 0;
684
685    vert_props[nvp] = vert_prop_x;
686    vert_props[nvp].offset = offsetof(Vertex,x); nvp++;
687    vert_props[nvp] = vert_prop_y;
688    vert_props[nvp].offset = offsetof(Vertex,y); nvp++;
689    vert_props[nvp] = vert_prop_z;
690    vert_props[nvp].offset = offsetof(Vertex,z); nvp++;
691
692    if (FOUND_NORMALS) {
693       vert_props[nvp] = vert_prop_nx;
694       vert_props[nvp].offset = offsetof(Vertex,nx); nvp++;
695       vert_props[nvp] = vert_prop_ny;
696       vert_props[nvp].offset = offsetof(Vertex,ny); nvp++;
697       vert_props[nvp] = vert_prop_nz;
698       vert_props[nvp].offset = offsetof(Vertex,nz); nvp++;       
699    }
700
701    num_vert_props = nvp;
702
703    face_props[0].offset = offsetof(Face, verts);
704    face_props[0].count_offset = offsetof(Face, nverts);  /* count offset */
705   
706    ply_describe_element (ply, "vertex", numVerts,
707                          num_vert_props, vert_props);
708
709    ply_describe_element (ply, "face", numFaces, 1, face_props);
710
711    ply_header_complete (ply);
712   
713    /* set up and write the vertex elements */
714
715    ply_put_element_setup (ply, "vertex");
716
717    for (i = 0; i < numVerts; i++) {
718        ply_put_element (ply, (void *) &verts[i]);
719    }
720
721    int vertIndices[3];
722
723    ply_put_element_setup (ply, "face");
724
725    for (i = 0; i < numFaces; i++) {
726        ply_put_element (ply, (void *) &faces[i]);
727    }
728   
729    return 1;
730}
731
732
733void
734printUsage()
735{
736    printf("\n");
737    printf("Usage: iv2ply [in.ply] > out.ply\n");
738    printf("   or: iv2ply < in.ply > out.ply\n");
739    printf("\n");
740    printf("  Iv2ply converts an Inventor file containing a Group node\n");
741    printf("  above a Coordinate3 and IndexedFaceSet node into a ply file.\n");
742    printf("  Normals are preserved, but not color, etc.\n");
743    printf("\n");
744    exit(-1);
745}
746
747#endif
Note: See TracBrowser for help on using the repository browser.