00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
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" 
00052 #include "dev/dev.H"
00053 #include "dev/devpoll.H"
00054 #include "mesh/gtexture.H"
00055 
00056 
00057 DEVice_2d *DEVice_2d::last = 0;
00058 ARRAY<DEVpoll *> DEVpoll::_pollable;
00059 
00060 
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 
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 
00104 
00105 
00106 
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 
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 
00140 
00141 
00142 void
00143 scenegraph_to_tris(SoNode *root)
00144 {
00145   
00146   
00147   
00148   SoCallbackAction myAction;
00149   
00150   myAction.addPreCallback(SoMaterial::getClassTypeId(),
00151            materialCallback, NULL);
00152   
00153   
00154   
00155   myAction.addPreCallback(SoShape::getClassTypeId(), 
00156            shapeCallback, NULL);
00157 
00158   
00159      
00160   
00161   
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   
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    
00181    int32_t num_coords = cb->getNumCoordinates();
00182    
00183    for (i = 0; i < num_coords; i++) {
00184       SbVec3f point;
00185       mat.multVecMatrix(cb->getCoordinate3(i), point);
00186       points += point;
00187    }
00188 
00189    
00190    if (num_coords = cb->getNumTextureCoordinates()) {
00191 
00192       
00193       if (!texcoords.empty()) {
00194          cerr << "add_state_coords - warning: "
00195               << "removing unused texcoords" << endl;
00196       }
00197       texcoords.clear();
00198 
00199       
00200       const SbMatrix &texmat = cb->getTextureMatrix();
00201 
00202       
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   
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    
00222    for (i = 0; i < coords.getNum(); i++) {
00223       SbVec3f point;
00224       mat.multVecMatrix(verts[i], point);
00225       points += point;
00226    }
00227 }
00228 
00229 
00230 
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    
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 
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;
00254       
00255       SoNode *vertprop = tristrip->vertexProperty.getValue();
00256       add_field_coords(cb, ((SoVertexProperty *) vertprop)->vertex);
00257    } else {
00258      
00259       add_state_coords(cb);
00260    }
00261 
00262    
00263    
00264    if (!tris.empty()) {
00265       cerr << "indexed_face_set - warning: removing unused tris" << endl;
00266    }
00267    tris.clear();
00268 
00269    
00270    
00271    
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 
00292 
00293 
00294 SoCallbackAction::Response
00295 materialCallback(
00296        void             *,
00297        SoCallbackAction * cbact,
00298        const SoNode     * node)
00299 {     
00300   
00301   
00302   
00303   if (separate_files) {
00304             
00305     
00306     SoMaterial* m = (SoMaterial *) node;
00307     
00308     
00309     
00310                  
00311     SoMFColor c = m->diffuseColor;    
00312    
00313     const SbColor col = *(c.getValues(0));
00314         
00315     
00316     
00317     SbVec3f vec(col[0],col[1],col[2]);
00318    
00319     objColor = vec;        
00320     
00321   } 
00322   return SoCallbackAction::CONTINUE;
00323 } 
00324  
00325  
00326 
00327 
00328 SoCallbackAction::Response
00329 shapeCallback(
00330    void             *,
00331    SoCallbackAction * cbact,
00332    const SoNode     * node)
00333 {
00334 
00335   
00336   
00337 
00338   
00339   
00340   
00341   
00342   
00343   
00344   
00345   
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     
00359     
00360     
00361     if (node->isOfType(SoIndexedFaceSet::getClassTypeId())) {
00362       
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     
00377     else if (node->isOfType(SoIndexedTriangleStripSet::getClassTypeId())) {
00378       
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 
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 
00405 
00406 
00407 
00408 
00409 
00410 
00411 
00412 
00413 
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    
00432    
00433    
00434    points += point;
00435    return points.num() - 1;
00436 
00437 
00438 
00439 
00440 
00441 
00442 
00443 
00444 
00445 
00446 
00447 
00448 
00449 
00450 
00451 
00452 
00453 
00454 
00455 
00456 
00457 }
00458 
00459 
00460 
00461 
00462 void
00463 outputMesh(ostream &os)
00464 {
00465    
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          
00483          
00484          Bface* f = mesh->bf(i);
00485 
00486          
00487          data = texcoords[f->v(1)->index()].getValue();
00488          UVpt a(data[0], data[1]);
00489 
00490          
00491          data = texcoords[f->v(2)->index()].getValue();
00492          UVpt b(data[0], data[1]);
00493 
00494          
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    
00505    mesh->remove_duplicate_vertices(false); 
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    
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    
00544    SoInput     in;
00545    SoNode      *root;
00546    if (argc == optind) {
00547       usage(argv[0]);
00548    } else if (strcmp(argv[optind], "-") == 0) {
00549      
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();
00562    
00563    
00564    scenegraph_to_tris(root);
00565 
00566    
00567    
00568 
00569 
00570    
00571    if (output_stream) outputMesh(*output_stream);
00572    else outputMesh(cout);
00573    root->unref();
00574 
00575    timer.print_time();
00576    return 0;
00577 }