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
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #include <stdlib.h>
00045 #include <stdio.h>
00046
00047 #include "OSGConfig.h"
00048
00049 #include <OSGGL.h>
00050
00051 #include <iostream>
00052 #include <fstream>
00053
00054 #include <vector>
00055
00056 #include <OSGLog.h>
00057
00058 #include <OSGNode.h>
00059 #include <OSGGeometry.h>
00060 #include <OSGGeoProperty.h>
00061 #include <OSGGeoFunctions.h>
00062 #include <OSGSimpleTexturedMaterial.h>
00063 #include <OSGImageFileHandler.h>
00064 #include <OSGPathHandler.h>
00065 #include <OSGGroup.h>
00066 #include <OSGSceneFileHandler.h>
00067
00068 #include "OSGOBJSceneFileType.h"
00069
00070 OSG_USING_NAMESPACE
00071
00072
00078 #if defined(OSG_WIN32_ICL) && !defined(OSG_CHECK_FIELDSETARG)
00079 #pragma warning (disable : 383)
00080 #endif
00081
00082
00083
00084
00085
00086 const Char8 *OBJSceneFileType::_suffixA[] = { "obj" };
00087
00088 OBJSceneFileType OBJSceneFileType::_the (_suffixA,
00089 sizeof(_suffixA),
00090 false,
00091 10,
00092 SceneFileType::OSG_READ_SUPPORTED);
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 NodePtr OBJSceneFileType::read(std::istream &is, const Char8 *) const
00129 {
00130 NodePtr rootPtr, nodePtr;
00131 std::string elem;
00132 std::map<std::string, DataElem>::const_iterator elemI;
00133 Vec3f vec3f;
00134 Vec2f vec2f;
00135 Real32 x,y,z;
00136 GeoPositionsPtr coordPtr = GeoPositions3f::create();
00137 GeoTexCoordsPtr texCoordPtr = GeoTexCoords2f::create();
00138 GeoNormalsPtr normalPtr = GeoNormals3f::create();
00139 GeometryPtr geoPtr;
00140 GeoIndicesPtr indexPtr;
00141 GeoPLengthsPtr lensPtr;
00142 GeoPTypesPtr typePtr;
00143 DataElem dataElem;
00144 Char8 strBuf[8192], *token, *nextToken;
00145 Int32 strBufSize = sizeof(strBuf)/sizeof(Char8);
00146 Int32 index, posIndex = 0, indexType;
00147 Int32 i,j,n,primCount[3];
00148 std::list<Mesh> meshList;
00149 std::map<std::string, SimpleTexturedMaterialPtr> mtlMap;
00150 std::map<std::string, SimpleTexturedMaterialPtr>::iterator mtlI;
00151 Mesh emptyMesh;
00152 Face emptyFace;
00153 TiePoint emptyTie;
00154 Int32 indexMask, meshIndexMask;
00155 std::list<Face>::iterator faceI;
00156 std::list<Mesh>::iterator meshI;
00157 bool isSingleIndex;
00158
00159
00160 meshList.push_back(emptyMesh);
00161 meshI = meshList.begin();
00162
00163 if(is)
00164 {
00165 primCount[0] = 0;
00166 primCount[1] = 0;
00167 primCount[2] = 0;
00168
00169 beginEditCP(coordPtr);
00170 beginEditCP(texCoordPtr);
00171 beginEditCP(normalPtr);
00172
00173 for (is >> elem; is.eof() == false; is >> elem)
00174 if (elem[0] == '#' ||
00175 elem[0] == '$'
00176 )
00177 is.ignore(INT_MAX, '\n');
00178 else
00179 {
00180 elemI = _dataElemMap.find(elem);
00181 dataElem = ((elemI == _dataElemMap.end()) ?
00182 UNKNOWN_DE : elemI->second );
00183 switch (dataElem)
00184 {
00185 case OBJECT_DE:
00186 case GROUP_DE:
00187 case SMOOTHING_GROUP_DE:
00188 is.ignore(INT_MAX, '\n');
00189 break;
00190 case VERTEX_DE:
00191 primCount[0]++;
00192 is >> x >> y >> z;
00193 vec3f.setValues(x,y,z);
00194 coordPtr->push_back(vec3f);
00195 break;
00196 case VERTEX_TEXTURECOORD_DE:
00197 primCount[1]++;
00198 is >> x >> y;
00199 vec2f.setValues(x,y);
00200 texCoordPtr->push_back(vec2f);
00201 break;
00202 case VERTEX_NORMAL_DE:
00203 primCount[2]++;
00204 is >> x >> y >> z;
00205 vec3f.setValues(x,y,z);
00206 normalPtr->push_back(vec3f);
00207 break;
00208 case LIB_MTL_DE:
00209 is >> elem;
00210 readMTL ( elem.c_str(), mtlMap );
00211 is.ignore(INT_MAX, '\n');
00212 break;
00213 case USE_MTL_DE:
00214 is >> elem;
00215 if (meshI->faceList.empty() == false)
00216 {
00217 meshList.push_front(emptyMesh);
00218 meshI = meshList.begin();
00219 }
00220 mtlI = mtlMap.find(elem);
00221 if (mtlI == mtlMap.end())
00222 {
00223 FFATAL (("Unkown mtl %s\n", elem.c_str()));
00224 }
00225 else
00226 meshI->mtlPtr = mtlI->second;
00227 break;
00228 case FACE_DE:
00229 meshI->faceList.push_front(emptyFace);
00230 faceI = meshI->faceList.begin();
00231 is.get(strBuf,strBufSize);
00232 token = strBuf;
00233 indexType = 0;
00234 while (token && *token)
00235 {
00236 for (; *token == '/'; token++)
00237 indexType++;
00238 for (; isspace(*token); token++)
00239 indexType = 0;
00240 index = strtol(token, &nextToken, 10);
00241 if (token == nextToken)
00242 break;
00243 if (indexType == 0)
00244 faceI->tieVec.push_back(emptyTie);
00245 if (index >= 0)
00246 index--;
00247 else
00248 index = primCount[indexType] + index;
00249 faceI->tieVec.back().index[indexType] = index;
00250 token = nextToken;
00251 }
00252 break;
00253 case UNKNOWN_DE:
00254 default:
00255 FWARNING (( "Unkown obj data elem: %s\n",
00256 elem.c_str()));
00257 is.ignore(INT_MAX, '\n');
00258 break;
00259 }
00260 }
00261
00262 endEditCP(coordPtr);
00263 endEditCP(texCoordPtr);
00264 endEditCP(normalPtr);
00265
00266 #if 0
00267 std::cerr << "------------------------------------------------" << std::endl;
00268 i = 0;
00269 for (meshI = meshList.begin(); meshI != meshList.end(); meshI++) {
00270 std::cerr << "Mesh " << i << " faceCount :"
00271 << meshI->faceList.size() << std::endl;
00272 j = 0 ;
00273 for ( faceI = meshI->faceList.begin(); faceI != meshI->faceList.end();
00274 faceI++)
00275 std::cerr << "MESH " << i << "face: " << j++ << "tie num: "
00276 << faceI->tieVec.size() << std::endl;
00277 i++;
00278 }
00279 std::cerr << "------------------------------------------------" << std::endl;
00280 =======
00281 #endif
00282
00283 for (meshI = meshList.begin(); meshI != meshList.end(); meshI++)
00284 {
00285 geoPtr = Geometry::create();
00286 indexPtr = GeoIndicesUI32::create();
00287 lensPtr = GeoPLengthsUI32::create();
00288 typePtr = GeoPTypesUI8::create();
00289
00290
00291 meshIndexMask = 0;
00292 isSingleIndex = true;
00293 if ( meshI->faceList.empty() == false)
00294 for ( faceI = meshI->faceList.begin();
00295 faceI != meshI->faceList.end(); faceI++)
00296 {
00297 indexMask = 0;
00298 n = faceI->tieVec.size();
00299 for (i = 0; i < n; i++)
00300 for (j = 0; j < 3; j++)
00301 {
00302 if ((index = (faceI->tieVec[i].index[j])) >= 0) {
00303 indexMask |= (1 << j);
00304 if (j)
00305 isSingleIndex &= (posIndex == index);
00306 else
00307 posIndex = index;
00308 }
00309 }
00310 if (meshIndexMask == 0)
00311 meshIndexMask = indexMask;
00312 else
00313 if (meshIndexMask != indexMask)
00314 {
00315 FFATAL (( "IndexMask unmatch, can not create geo\n"));
00316 meshIndexMask = 0;
00317 break;
00318 }
00319 }
00320 else
00321 {
00322 FWARNING (("Mesh with empty faceList\n"));
00323 }
00324
00325
00326 if (meshIndexMask)
00327 {
00328 beginEditCP ( geoPtr );
00329 {
00330 geoPtr->setPositions ( coordPtr );
00331 geoPtr->setIndices ( indexPtr );
00332 geoPtr->setLengths ( lensPtr );
00333 geoPtr->setTypes ( typePtr );
00334
00335 if ( texCoordPtr->size() > 0 )
00336 {
00337 geoPtr->setTexCoords ( texCoordPtr );
00338 }
00339 else
00340 {
00341 geoPtr->setTexCoords ( NullFC );
00342 meshIndexMask &= ~Geometry::MapTexCoords;
00343 }
00344
00345 if ( normalPtr->size() > 0 )
00346 {
00347 geoPtr->setNormals ( normalPtr );
00348 }
00349 else
00350 {
00351 geoPtr->setNormals ( NullFC );
00352 meshIndexMask &= ~Geometry::MapNormal;
00353 }
00354
00355 if (isSingleIndex)
00356 {
00357 indexType = 0;
00358 if (meshIndexMask & 1)
00359 indexType |= Geometry::MapPosition;
00360 if (meshIndexMask & 2)
00361 indexType |= Geometry::MapTexCoords;
00362 if (meshIndexMask & 4)
00363 indexType |= Geometry::MapNormal;
00364 geoPtr->getIndexMapping().push_back( indexType );
00365 }
00366 else
00367 {
00368 if (meshIndexMask & 1)
00369 {
00370 indexType = Geometry::MapPosition;
00371 geoPtr->getIndexMapping().push_back( indexType);
00372 }
00373 if (meshIndexMask & 2)
00374 {
00375 indexType = Geometry::MapTexCoords;
00376 geoPtr->getIndexMapping().push_back( indexType);
00377 }
00378 if (meshIndexMask & 4)
00379 {
00380 indexType = Geometry::MapNormal;
00381 geoPtr->getIndexMapping().push_back( indexType);
00382 }
00383 }
00384
00385 if (meshI->mtlPtr == NullFC)
00386 {
00387 meshI->mtlPtr = SimpleTexturedMaterial::create();
00388 beginEditCP( meshI->mtlPtr );
00389 {
00390 meshI->mtlPtr->setDiffuse( Color3f( .8, .8, .8 ) );
00391 meshI->mtlPtr->setSpecular( Color3f( 1, 1, 1 ) );
00392 meshI->mtlPtr->setShininess( 20 );
00393 }
00394 endEditCP( meshI->mtlPtr );
00395 }
00396 geoPtr->setMaterial ( meshI->mtlPtr );
00397 }
00398 endEditCP ( geoPtr );
00399
00400 beginEditCP(lensPtr);
00401 beginEditCP(typePtr);
00402 beginEditCP(indexPtr);
00403
00404 for ( faceI = meshI->faceList.begin();
00405 faceI != meshI->faceList.end(); faceI++)
00406 {
00407 n = faceI->tieVec.size();
00408
00409
00410 lensPtr->push_back(n);
00411
00412
00413 typePtr->push_back(GL_POLYGON);
00414
00415
00416 for (i = 0; i < n; i++)
00417 if (isSingleIndex)
00418 indexPtr->push_back( faceI->tieVec[i].index[0]);
00419 else
00420 for (j = 0; j < 3; j++)
00421 if ( meshIndexMask & (1 << j))
00422 indexPtr->push_back( faceI->tieVec[i].index[j]);
00423 }
00424
00425 endEditCP(indexPtr);
00426 endEditCP(typePtr);
00427 endEditCP(lensPtr);
00428
00429 createSharedIndex( geoPtr );
00430
00431
00432 if ((meshIndexMask & 4) == 0)
00433 calcVertexNormals(geoPtr);
00434
00435
00436 nodePtr = Node::create();
00437 beginEditCP ( nodePtr );
00438 {
00439 nodePtr->setCore( geoPtr );
00440 }
00441 endEditCP ( nodePtr );
00442
00443 if (meshList.size() > 1)
00444 {
00445 if (rootPtr == NullFC)
00446 {
00447 rootPtr = Node::create();
00448 beginEditCP (rootPtr);
00449 {
00450 rootPtr->setCore ( Group::create() );
00451 rootPtr->addChild(nodePtr);
00452 }
00453 endEditCP (rootPtr);
00454 }
00455 else
00456 {
00457 beginEditCP(rootPtr);
00458 {
00459 rootPtr->addChild(nodePtr);
00460 }
00461 endEditCP (rootPtr);
00462 }
00463 }
00464 else
00465 rootPtr = nodePtr;
00466 }
00467 }
00468 }
00469
00470
00471 return rootPtr;
00472 }
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 OBJSceneFileType::OBJSceneFileType(const Char8 *suffixArray[],
00519 UInt16 suffixByteCount,
00520 bool override,
00521 UInt32 overridePriority,
00522 UInt32 flags) :
00523 SceneFileType(suffixArray,
00524 suffixByteCount,
00525 override,
00526 overridePriority,
00527 flags),
00528 _dataElemMap()
00529
00530 {
00531 initElemMap();
00532 }
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 OBJSceneFileType::OBJSceneFileType(const OBJSceneFileType &obj) :
00556 SceneFileType(obj)
00557 {
00558 initElemMap();
00559 }
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582 OBJSceneFileType &OBJSceneFileType::the(void)
00583 {
00584 return _the;
00585 }
00586
00587 OBJSceneFileType::~OBJSceneFileType(void)
00588 {
00589 return;
00590 }
00591
00592 const Char8 *OBJSceneFileType::getName(void) const
00593 {
00594 return "OBJ GEOMETRY";
00595 }
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618 void OBJSceneFileType::initElemMap(void)
00619 {
00620 if (_dataElemMap.empty())
00621 {
00622 _dataElemMap[""] = UNKNOWN_DE;
00623
00624 _dataElemMap["v"] = VERTEX_DE;
00625 _dataElemMap["vt"] = VERTEX_TEXTURECOORD_DE;
00626 _dataElemMap["vn"] = VERTEX_NORMAL_DE;
00627 _dataElemMap["f"] = FACE_DE;
00628 _dataElemMap["fo"] = FACE_DE;
00629 _dataElemMap["mtllib"] = LIB_MTL_DE;
00630 _dataElemMap["usemtl"] = USE_MTL_DE;
00631 _dataElemMap["g"] = GROUP_DE;
00632 _dataElemMap["s"] = SMOOTHING_GROUP_DE;
00633 _dataElemMap["o"] = OBJECT_DE;
00634 }
00635
00636 if (_mtlElemMap.empty())
00637 {
00638 _mtlElemMap[""] = UNKNOWN_ME;
00639
00640 _mtlElemMap["newmtl"] = NEW_MTL_ME;
00641 _mtlElemMap["Kd"] = MTL_DIFFUSE_ME;
00642 _mtlElemMap["Ka"] = MTL_AMBIENT_ME;
00643 _mtlElemMap["Ks"] = MTL_SPECULAR_ME;
00644 _mtlElemMap["Ns"] = MTL_SHININESS_ME;
00645 _mtlElemMap["Tr"] = MTL_TRANSPARENCY_ME;
00646 _mtlElemMap["map_Kd"] = MTL_MAP_KD_ME;
00647 _mtlElemMap["map_Ka"] = MTL_MAP_KA_ME;
00648 _mtlElemMap["map_Ks"] = MTL_MAP_KS_ME;
00649 _mtlElemMap["illum"] = MTL_ILLUM_ME;
00650 _mtlElemMap["refl"] = MTL_REFL_ME;
00651 }
00652 }
00653
00654 Int32 OBJSceneFileType::readMTL ( const Char8 *fileName,
00655 std::map<std::string, SimpleTexturedMaterialPtr> & mtlMap )
00656 const
00657 {
00658 if(fileName == NULL || strlen(fileName) == 0)
00659 return 0;
00660
00661 Int32 mtlCount = 0;
00662
00663 PathHandler *pathHandler = SceneFileHandler::the().getPathHandler();
00664 std::string fullFilePath;
00665 if(pathHandler != NULL)
00666 fullFilePath = pathHandler->findFile(fileName);
00667 else
00668 fullFilePath = fileName;
00669
00670 if(fullFilePath.empty())
00671 {
00672 FWARNING (("Couldn't open '%s'!\n", fileName));
00673 return 0;
00674 }
00675
00676 std::ifstream in(fullFilePath.c_str());
00677 SimpleTexturedMaterialPtr mtlPtr = NullFC;
00678 Real32 a,b,c;
00679 std::string elem;
00680 std::map<std::string, MaterialElem>::const_iterator elemI;
00681 MaterialElem mtlElem;
00682 std::map<std::string, OSG::ImagePtr> imageMap;
00683 std::map<std::string, OSG::ImagePtr>::iterator iI;
00684 ImagePtr image = NullFC;
00685 bool constDiffuse = false, constAmbient = false, constSpecular = false;
00686
00687 if (in)
00688 for (in >> elem; in.eof() == false; in >> elem)
00689 if (elem[0] == '#' || elem[0] == '$' )
00690 in.ignore(INT_MAX, '\n');
00691 else
00692 {
00693 elemI = _mtlElemMap.find(elem);
00694 mtlElem = ((elemI == _mtlElemMap.end()) ?
00695 UNKNOWN_ME : elemI->second);
00696 if (mtlElem == NEW_MTL_ME)
00697 {
00698 in >> elem;
00699 if (mtlPtr != NullFC)
00700 endEditCP(mtlPtr);
00701 mtlPtr = SimpleTexturedMaterial::create();
00702 beginEditCP(mtlPtr);
00703 mtlPtr->setColorMaterial(GL_NONE);
00704 mtlPtr->setEnvMode(GL_MODULATE);
00705 mtlMap[elem] = mtlPtr;
00706 mtlCount++;
00707 constDiffuse = false;
00708 constAmbient = false;
00709 constSpecular = false;
00710 }
00711 else
00712 {
00713 if (mtlPtr == NullFC)
00714 {
00715 FFATAL (( "Invalid Mtl token: %s, newmtl expected in %s\n",
00716 elem.c_str(), fileName ));
00717 in.ignore(INT_MAX, '\n');
00718 }
00719 else
00720 {
00721 switch (mtlElem)
00722 {
00723 case MTL_DIFFUSE_ME:
00724 in >> a >> b >> c;
00725 if (!constDiffuse)
00726 mtlPtr->setDiffuse( Color3f( a,b,c ));
00727 break;
00728 case MTL_AMBIENT_ME:
00729 in >> a >> b >> c;
00730 if (!constAmbient)
00731 mtlPtr->setAmbient( Color3f( a,b,c ));
00732 break;
00733 case MTL_SPECULAR_ME:
00734 in >> a >> b >> c;
00735 if (!constSpecular)
00736 mtlPtr->setSpecular( Color3f( a,b,c ));
00737 break;
00738 case MTL_SHININESS_ME:
00739 in >> a;
00740 mtlPtr->setShininess(a);
00741 break;
00742 case MTL_ILLUM_ME:
00743 ;
00744 in >> elem;
00745
00746 break;
00747 case MTL_REFL_ME:
00748 mtlPtr->setEnvMap(true);
00749 break;
00750 case MTL_TRANSPARENCY_ME:
00751 in >> a;
00752 mtlPtr->setTransparency(a);
00753 break;
00754 case MTL_MAP_KD_ME:
00755 case MTL_MAP_KA_ME:
00756 case MTL_MAP_KS_ME:
00757 image = NullFC;
00758 in >> elem;
00759 iI = imageMap.find(elem);
00760 if (iI == imageMap.end())
00761 {
00762 std::string fullElemPath;
00763 if(pathHandler != NULL)
00764 fullElemPath = pathHandler->findFile(elem.c_str());
00765 else
00766 fullElemPath = elem.c_str();
00767 image = OSG::ImageFileHandler::the().read(fullElemPath.c_str());
00768 imageMap[elem] = image;
00769 }
00770 else
00771 {
00772 image = iI->second;
00773 }
00774 if (image != NullFC) {
00775 mtlPtr->setImage(image);
00776 switch (mtlElem) {
00777 case MTL_MAP_KD_ME:
00778 constDiffuse = true;
00779 mtlPtr->setDiffuse ( Color3f( 1, 1, 1) );
00780 break;
00781 case MTL_MAP_KA_ME:
00782 constAmbient = true;
00783 mtlPtr->setAmbient ( Color3f( 1, 1, 1) );
00784 break;
00785 case MTL_MAP_KS_ME:
00786 constSpecular = true;
00787 mtlPtr->setSpecular ( Color3f( 1, 1, 1) );
00788 break;
00789 default:
00790 break;
00791 }
00792 }
00793 else
00794 {
00795 FFATAL (( "Can not find %s texture file in mtl %s \n",
00796 elem.c_str(), fileName ));
00797 }
00798 break;
00799 default:
00800 FWARNING (( "Invalid %s entry in %s\n",
00801 elem.c_str(), fileName ));
00802 in.ignore(INT_MAX, '\n');
00803 }
00804 }
00805 }
00806 }
00807
00808 if (mtlPtr != NullFC)
00809 endEditCP(mtlPtr);
00810
00811 return mtlCount;
00812 }
00813
00814
00815
00816
00817
00818 #ifdef __sgi
00819 #pragma set woff 1174
00820 #endif
00821
00822 #ifdef OSG_LINUX_ICC
00823 #pragma warning( disable : 177 )
00824 #endif
00825
00826 namespace
00827 {
00828 static Char8 cvsid_cpp[] = "@(#)$Id: $";
00829 static Char8 cvsid_hpp[] = OSGOBJSCENEFILETYPE_HEADER_CVSID;
00830 }
00831