Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

iv2sm.C

Go to the documentation of this file.
00001 /*
00002  * Portions of this file:
00003  * Copyright 1991-1995, Silicon Graphics, Inc.
00004  * ALL RIGHTS RESERVED
00005  *
00006  * UNPUBLISHED -- Rights reserved under the copyright laws of the United
00007  * States.   Use of a copyright notice is precautionary only and does not
00008  * imply publication or disclosure.
00009  *
00010  * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND:
00011  * Use, duplication or disclosure by the Government is subject to restrictions
00012  * as set forth in FAR 52.227.19(c)(2) or subparagraph (c)(1)(ii) of the Rights
00013  * in Technical Data and Computer Software clause at DFARS 252.227-7013 and/or
00014  * in similar or successor clauses in the FAR, or the DOD or NASA FAR
00015  * Supplement.  Contractor/manufacturer is Silicon Graphics, Inc.,
00016  * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311.
00017  *
00018  * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY
00019  * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION,
00020  * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY
00021  * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON
00022  * GRAPHICS, INC.
00023  */
00024 /*-----------------------------------------------------------
00025  *  This is an example from The Inventor Mentor,
00026  *  chapter 9, example 5.
00027  *
00028  *  Using a callback for generated primitives.
00029  *  A simple scene with a sphere is created.
00030  *  A callback is used to write out the triangles that
00031  *  form the sphere in the scene.
00032  *----------------------------------------------------------*/
00033 #define ROOM_STANDALONE
00034 #include <Inventor/SoDB.h>
00035 #include <Inventor/SoPrimitiveVertex.h>
00036 #include <Inventor/actions/SoCallbackAction.h>
00037 #include <Inventor/actions/SoWriteAction.h>
00038 #include <Inventor/details/SoDetail.h>
00039 #include <Inventor/nodes/SoDirectionalLight.h>
00040 #include <Inventor/nodes/SoIndexedFaceSet.h>
00041 #include <Inventor/nodes/SoIndexedTriangleStripSet.h>
00042 #include <Inventor/nodes/SoMaterial.h>
00043 #include <Inventor/nodes/SoPerspectiveCamera.h>
00044 #include <Inventor/nodes/SoSeparator.h>
00045 #include <Inventor/nodes/SoSphere.h>
00046 #include <stdlib.h>
00047 
00048 #include "std/support.H"
00049 #include "std/stop_watch.H"
00050 #include "mesh/bmesh.H"
00051 #include "mesh/patch.H" //add patches -sginsber
00052 #include "dev/dev.H"
00053 #include "dev/devpoll.H"
00054 #include "mesh/gtexture.H"
00055 
00056 // Reference dev symbols
00057 DEVice_2d *DEVice_2d::last = 0;
00058 ARRAY<DEVpoll *> DEVpoll::_pollable;
00059 
00060 // Hack to make sure BOOTH symbols are linked in
00061 inline Wpt      RET_Wpt(CBOOTHpt &p)   { return Wpt     (p[0], p[1], p[2]); }
00062 inline Wvec     RET_Wvec(CBOOTHvec &v) { return Wvec    (v[0], v[1], v[2]); }
00063 inline BOOTHpt  RET_BOOTHpt(CWpt &p)   { return BOOTHpt (p[0], p[1], p[2]); }
00064 inline BOOTHvec RET_BOOTHvec(CWvec &v) { return BOOTHvec(v[0], v[1], v[2]); }
00065 Wpt     (*BOOTHpttoWpt)(CBOOTHpt &)    = RET_Wpt;
00066 Wvec    (*BOOTHvectoWvec)(CBOOTHvec &) = RET_Wvec;
00067 BOOTHpt (*WpttoBOOTHpt)(CWpt &)        = RET_BOOTHpt;
00068 BOOTHvec(*WvectoBOOTHvec)(CWvec &)     = RET_BOOTHvec;
00069 
00070 // #include "/u/lsh/space/piggy/debug.H"
00071 void outputMesh(ostream &os);
00072 
00073 int correct = 0;
00074 int separate_files = 0;
00075 int obj_num = 0;
00076 
00077 #include <iostream.h>
00078 class Triangle {
00079     private:
00080        int _verts[3];
00081     public:
00082        Triangle() {_verts[0]=_verts[1]=_verts[2]=-1;}
00083        Triangle(int x, int y, int z) { _verts[0]=x; _verts[1]=y;_verts[2]=z; }
00084       void set (int x, int y, int z) { _verts[0]=x; _verts[1]=y;_verts[2]=z; }
00085        const int *data() const {return _verts;}
00086              int operator[](int x)       {return _verts[x];}
00087              int operator[](int x) const {return _verts[x];}
00088        int operator ==(const Triangle &tri) {
00089           return tri._verts[0] == _verts[0] &&
00090                  tri._verts[1] == _verts[1] &&
00091                  tri._verts[2] == _verts[2];
00092        }
00093 };
00094 
00095 ostream &operator<<(ostream &os, const Triangle &tri) {
00096    return os << tri[0] << " " << tri[1] << " " << tri[2];
00097 }
00098 
00099 ARRAY<SbVec3f>  points(1024);
00100 ARRAY<Triangle> tris(1024);
00101 ARRAY<SbVec2f>  texcoords(1024);
00102 
00103 //array for textures
00104 //array for colors? no, only a vector
00105 
00106 //CCOLOR objColor;
00107 SbVec3f objColor;
00108 
00109 int badtris = 0;
00110 int reppts  = 0;
00111 int duptris = 0;
00112 ostream *output_stream = 0;
00113 
00114 void
00115 initialize_mesh()
00116 {
00117    points.clear();
00118    texcoords.clear();
00119    tris.clear();   
00120    badtris = 0;
00121    reppts  = 0;
00122    duptris = 0;
00123 }
00124 
00125 // Function prototypes
00126 void scenegraph_to_tris(SoNode *);
00127 SoCallbackAction::Response shapeCallback(void *, 
00128    SoCallbackAction *, const SoNode *);
00129 
00130 SoCallbackAction::Response materialCallback(void *,
00131    SoCallbackAction *, const SoNode *);
00132 
00133 void printTriangleCallback(void *, SoCallbackAction *,
00134    const SoPrimitiveVertex *, const SoPrimitiveVertex *,
00135    const SoPrimitiveVertex *);
00136 int printVertex(const SoPrimitiveVertex *, const SbMatrix &mat);
00137 
00138 //////////////////////////////////////////////////////////////
00139 // CODE FOR The Inventor Mentor STARTS HERE
00140 
00141 
00142 void
00143 scenegraph_to_tris(SoNode *root)
00144 {
00145   //create a callbackaction that will send a callback
00146   //every time a given type of node is encountered while
00147   //traversing the scenegraph -sginsber
00148   SoCallbackAction myAction;
00149   //add a callback for a color block -sginsber
00150   myAction.addPreCallback(SoMaterial::getClassTypeId(),
00151            materialCallback, NULL);
00152   
00153   //specify that a shapeCallback should be executed 
00154   //every time a shapenode is encountered -sginsber
00155   myAction.addPreCallback(SoShape::getClassTypeId(), 
00156            shapeCallback, NULL);
00157 
00158   
00159      
00160   //now, call a printTriangleCallback whenever a triangle
00161   //node is encountered -sginsber
00162   myAction.addTriangleCallback(SoShape::getClassTypeId(), 
00163                 printTriangleCallback, NULL);
00164   
00165   myAction.apply(root);
00166 }
00167 
00168 
00169 void
00170 add_state_coords(SoCallbackAction *cb)
00171 {
00172   // cerr << "adding state coords" << endl; //-sginsber
00173    if (!points.empty()) {
00174       cerr << "add_state_coords - warning: removing unused points" << endl;
00175    }
00176    points.clear();
00177    const SbMatrix &mat = cb->getModelMatrix();
00178    int i;
00179 
00180    // Add coords
00181    int32_t num_coords = cb->getNumCoordinates();
00182    // cerr << "state coords: " << num_coords << endl;
00183    for (i = 0; i < num_coords; i++) {
00184       SbVec3f point;
00185       mat.multVecMatrix(cb->getCoordinate3(i), point);
00186       points += point;
00187    }
00188 
00189    // Add texture coords if any
00190    if (num_coords = cb->getNumTextureCoordinates()) {
00191 
00192       // cerr << "adding texture coords" << endl;
00193       if (!texcoords.empty()) {
00194          cerr << "add_state_coords - warning: "
00195               << "removing unused texcoords" << endl;
00196       }
00197       texcoords.clear();
00198 
00199       // XXX - should this be handled?
00200       const SbMatrix &texmat = cb->getTextureMatrix();
00201 
00202       // cerr << "tex coords: " << num_coords << endl;
00203       for (i = 0; i < num_coords; i++) {
00204          texcoords += cb->getTextureCoordinate2(i);
00205       }
00206    }
00207 }
00208 
00209 void
00210 add_field_coords(SoCallbackAction *cb, const SoMFVec3f &coords)
00211 {
00212   // cerr << "adding field coords" << endl; //-sginsber
00213    if (!points.empty()) {
00214       cerr << "add_field_coords - warning: removing unused points" << endl;
00215    }
00216    points.clear();
00217    const SbMatrix &mat = cb->getModelMatrix();
00218    int i;
00219 
00220    const SbVec3f *verts = coords.getValues(0);
00221    // cerr << "field coords: " << coords.getNum() << endl;//-sginsber
00222    for (i = 0; i < coords.getNum(); i++) {
00223       SbVec3f point;
00224       mat.multVecMatrix(verts[i], point);
00225       points += point;
00226    }
00227 }
00228 
00229 // Translates an SoIndexedFaceSet into a .sm triangles
00230 // Note - only can handle nodes with 3-triangle faces (triangles)
00231 void
00232 indexed_face_set(SoIndexedFaceSet *fs, SoCallbackAction *cb)
00233 {
00234    add_state_coords(cb);
00235 
00236    if (!tris.empty()) {
00237       cerr << "indexed_face_set - warning: removing unused tris" << endl;
00238    }
00239    tris.clear();
00240 
00241    // Add triangles
00242    const int32_t *tri_coords = fs->coordIndex.getValues(0);
00243    for (int i = 0; i < fs->coordIndex.getNum(); i+=4) {
00244       tris.add(Triangle(tri_coords[i], tri_coords[i+1], tri_coords[i+2]));
00245    }
00246 }
00247 
00248 //create a list of xyz vertices -sginsber
00249 void
00250 ind_tri_strip(SoIndexedTriangleStripSet *tristrip, SoCallbackAction *cb)
00251 {
00252    if (tristrip->vertexProperty.getValue() != 0) {
00253      cerr << "ind_tri_strip: vertexProperty != 0" << endl;//-sginsber
00254       // Coordinates are in a SoVertexProperty
00255       SoNode *vertprop = tristrip->vertexProperty.getValue();
00256       add_field_coords(cb, ((SoVertexProperty *) vertprop)->vertex);
00257    } else {
00258      // cerr << "ind_tri_strip: vertexProperty == 0" << endl;
00259       add_state_coords(cb);
00260    }
00261 
00262    //vertices have been added to points array
00263    // cerr << "Points: " << points.num() << endl;
00264    if (!tris.empty()) {
00265       cerr << "indexed_face_set - warning: removing unused tris" << endl;
00266    }
00267    tris.clear();
00268 
00269    // Add triangles
00270    // (from soft/ml/oiv/nsg_inv_fields.C, map_faces_to_nsg())
00271    // cerr << "tristrip - tris" << endl;
00272    const int32_t *tri_coords = tristrip->coordIndex.getValues(0);
00273    int firstvert  = -1;
00274    int secondvert = -1;
00275    for (int i = 0; i < tristrip->coordIndex.getNum(); i++) {
00276       if (tri_coords[i] == -1) {
00277          firstvert = -1;
00278          secondvert = -1;
00279       } else {
00280          if (firstvert != -1 && secondvert != -1 && firstvert != secondvert) {
00281             tris.add(Triangle(firstvert, secondvert,tri_coords[i]));
00282          }
00283          firstvert = secondvert;
00284          secondvert = tri_coords[i];
00285       }
00286    }
00287 }
00288 
00289 
00290 
00291 //called when the color information node for an object is
00292 //encountered. it seems jot can only handle diffuse color
00293 //so thats all that is taken
00294 SoCallbackAction::Response
00295 materialCallback(
00296        void             *,
00297        SoCallbackAction * cbact,
00298        const SoNode     * node)
00299 {     
00300   
00301   // cerr << "Material Callback" << endl;
00302   
00303   if (separate_files) {
00304             
00305     //cerr << "correct material node type" << endl;
00306     SoMaterial* m = (SoMaterial *) node;
00307     
00308     //cerr << "name:" << m->getName().getString() << endl;
00309     //cerr << "type:" << m->getTypeId().getName().getString() << endl;
00310                  
00311     SoMFColor c = m->diffuseColor;    
00312    
00313     const SbColor col = *(c.getValues(0));
00314         
00315     // cerr << "found diffuse color: " << col[0] << " " << col[1] << " " << col[2] << endl;
00316     
00317     SbVec3f vec(col[0],col[1],col[2]);
00318    
00319     objColor = vec;        
00320     
00321   } 
00322   return SoCallbackAction::CONTINUE;
00323 } 
00324  
00325  
00326 //called whenever a shape node is encountered by the 
00327 //SoCallbackAction traversal -sginsber
00328 SoCallbackAction::Response
00329 shapeCallback(
00330    void             *,
00331    SoCallbackAction * cbact,
00332    const SoNode     * node)
00333 {
00334 
00335   // cerr << "Shape Callback" << endl; //-sginsber
00336   
00337 
00338   // Print the node name (if it exists) and address
00339   //if (! !node->getName())
00340   //  printf("named \"%s\" ", node->getName());
00341   //printf("at address %#x\n", node);
00342   
00343   
00344   //we output each object to a separate file. therefor, if tris 
00345   //is not empty, write it out and start a new file -sginsber
00346   if (separate_files) {    
00347     if (!tris.empty()) {
00348       outputMesh(*output_stream);
00349     }
00350     initialize_mesh();
00351     delete output_stream;
00352     char buff[1024];
00353     sprintf(buff, "obj%06d.sm", obj_num++);
00354     output_stream = new ofstream(buff);
00355   }
00356   
00357   if (separate_files) {
00358     // Currently only can do these shortucts if we are doing 1 obj/file
00359     // SoIndexedFaceSet w/ only triangles
00360     //so this is for the triangles -sginsber
00361     if (node->isOfType(SoIndexedFaceSet::getClassTypeId())) {
00362       // cerr << "shapeCallback(): node is of type IndexedFaceSet" << endl; //-sginsber
00363       SoIndexedFaceSet *fs = (SoIndexedFaceSet *) node;
00364       const int32_t *values = fs->coordIndex.getValues(0);
00365       bool ok = true;
00366       for (int i = 0; ok && i < fs->coordIndex.getNum(); i++) {
00367    if ((i + 1) % 4 ==  0) {
00368      ok = values[i] == -1;
00369    } else ok = values[i] != -1;
00370       }
00371       if (ok) {
00372    indexed_face_set(fs, cbact);
00373    return SoCallbackAction::PRUNE;
00374       }
00375     }
00376     //and this is for the vertices -sginsber
00377     else if (node->isOfType(SoIndexedTriangleStripSet::getClassTypeId())) {
00378       // cerr << "shapeCallback(): node is of type SoIdexedTriangleStrip" << endl; //-sginsber
00379       ind_tri_strip((SoIndexedTriangleStripSet *)node, cbact);
00380       return SoCallbackAction::PRUNE;
00381     }      
00382     
00383   }
00384   
00385   return SoCallbackAction::CONTINUE;
00386 }
00387 
00388 
00389 
00390 void
00391 printTriangleCallback(void *, SoCallbackAction *cb,
00392    const SoPrimitiveVertex *vertex1,
00393    const SoPrimitiveVertex *vertex2,
00394    const SoPrimitiveVertex *vertex3)
00395 {
00396 //   printf("Triangle:\n");
00397    int a, b, c;
00398    const SbMatrix &mat = cb->getModelMatrix();
00399    a = printVertex(vertex1, mat);
00400    b = printVertex(vertex2, mat);
00401    c = printVertex(vertex3, mat);
00402    
00403 /*
00404    const SbVec3f &norm = vertex1->getNormal();
00405    // cerr << "Dot: " << norm.dot((vertex2->getPoint()-vertex1->getPoint())
00406          .cross(vertex3->getPoint() - vertex1->getPoint())) << " " ;
00407    switch (cb->getVertexOrdering()) {
00408        case SoShapeHints::UNKNOWN_ORDERING : cerr << "Unknown" << endl;
00409        break;
00410        case SoShapeHints::CLOCKWISE: cerr << "Clockwise" << endl;
00411        break;
00412        case SoShapeHints::COUNTERCLOCKWISE: cerr << "ccw" << endl;
00413        break;
00414    }
00415 */
00416 
00417    if (a == b || a == c ||  b == c) {
00418        badtris++;
00419    } else {
00420       tris.add(Triangle(a, b, c));
00421    }
00422 }
00423 
00424 int
00425 printVertex(const SoPrimitiveVertex *vertex,
00426             const SbMatrix &mat)
00427 {
00428    SbVec3f point;
00429    mat.multVecMatrix(vertex->getPoint(), point);
00430 
00431    // new plan: we add disconnected triangles,
00432    // then fix them up later
00433    
00434    points += point;
00435    return points.num() - 1;
00436 /*
00437    int index = -1;
00438    const float eps = 1e-7;
00439 //   const float eps = 1e-5;
00440 
00441    for (int i = points.num()-1; index == -1 && i >= 0; i--) {
00442       if (points[i].equals(point, eps)) {
00443          index = i;
00444       }
00445    }
00446    if (index == -1) {
00447       index = points.num();
00448       points += point;
00449       if (points.num() % 1000 == 0) {
00450          // fprintf(stderr, "%d vertices\n", points.num());
00451       }
00452    } else {
00453       reppts++;
00454    }
00455    return index;
00456 */
00457 }
00458 
00459 // CODE FOR The Inventor Mentor ENDS HERE
00460 ///////////////////////////////////////////////////////////////
00461 
00462 void
00463 outputMesh(ostream &os)
00464 {
00465    // fprintf(stderr, "Starting to output\n");
00466    BMESHptr mesh = new BMESH;
00467   
00468    int i;
00469    for (i = 0; i < points.num(); i++) {
00470       const float *data = points[i].getValue();
00471       mesh->add_vertex(Wpt(data[0], data[1], data[2]));
00472    }
00473   
00474    for (i = 0; i < tris.num(); i++) {
00475       const int *data = tris[i].data();
00476       mesh->add_face(data[0], data[1], data[2]);
00477    }
00478 
00479    if (!texcoords.empty()) {
00480       const float* data = 0;
00481       for (i = 0; i < mesh->nfaces(); i++) {
00482          // for each face, set texture coordinates of
00483          // the 3 vertices of that face.
00484          Bface* f = mesh->bf(i);
00485 
00486          // 1st vertex
00487          data = texcoords[f->v(1)->index()].getValue();
00488          UVpt a(data[0], data[1]);
00489 
00490          // 2nd vertex
00491          data = texcoords[f->v(2)->index()].getValue();
00492          UVpt b(data[0], data[1]);
00493 
00494          // 3rd vertex
00495          data = texcoords[f->v(3)->index()].getValue();
00496          UVpt c(data[0], data[1]);
00497 
00498          f->set_tex_coords(a, b, c);
00499       }
00500    }
00501 
00502    mesh->changed(BMESH::TOPOLOGY_CHANGED);
00503 
00504    // Remove duplicate vertices
00505    mesh->remove_duplicate_vertices(false); // false = don't keep the bastards
00506 
00507    mesh->write_stream(os);
00508 }
00509 
00510 void
00511 usage(char *arg)
00512 {
00513    cerr << "Translates Open Inventor file from file.iv or stdin (if - is used)"
00514          << endl;
00515    cerr << endl;
00516    cerr << arg << " [-csh?] [file.iv | -]" << endl;
00517    cerr << "into one or more .sm mesh files" << endl;
00518    cerr << "   -c - Correct meshes so there are no duplicate vertices" << endl;
00519    cerr << "   -s - Output each object to a different .sm file" << endl;
00520    cerr << "   -h, -? - this message" << endl;
00521    exit(1);
00522 }
00523 
00524 int
00525 main(int argc, char **argv)
00526 {
00527    stop_watch timer;
00528    timer.set();
00529 
00530    // Initialize Inventor
00531    SoDB::init();
00532    int c = 0;
00533    while ((c = getopt(argc, argv, "cs?h")) != EOF) {
00534       switch (c) {
00535          case 'c': correct = 1;
00536        brcase 's': separate_files = 1;
00537        brcase '?':
00538          case 'h': usage(argv[0]);
00539       }
00540    }
00541 
00542 
00543    // Open and read input scene graph
00544    SoInput     in;
00545    SoNode      *root;
00546    if (argc == optind) {
00547       usage(argv[0]);
00548    } else if (strcmp(argv[optind], "-") == 0) {
00549      // from stdin
00550      in.setFilePointer(stdin);
00551    } else if (! in.openFile(argv[optind])) {
00552    fprintf(stderr, "%s: Cannot open %s\n", argv[0], argv[optind]);
00553    exit(1);
00554    }
00555    root = SoDB::readAll(&in);
00556    if (root == NULL) {
00557    fprintf(stderr, "%s: Problem reading data\n", argv[0]);
00558    exit(1);
00559     }
00560 
00561    root->ref();//reference all instances in scenegraph
00562    // Collect the triangles
00563    // fprintf(stderr, "Starting to convert (line 531)\n");
00564    scenegraph_to_tris(root);
00565 
00566    //call method that sets up textures
00567    //call method that sets up colors
00568 
00569 
00570    // Output the triangles to stdout
00571    if (output_stream) outputMesh(*output_stream);
00572    else outputMesh(cout);
00573    root->unref();
00574 
00575    timer.print_time();
00576    return 0;
00577 }

Generated on Mon Sep 18 11:39:31 2006 for jot by  doxygen 1.4.4