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 }