OSGOBJSceneFileType.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *             Copyright (C) 2000-2002 by the OpenSG Forum                   *
00006  *                                                                           *
00007  *                            www.opensg.org                                 *
00008  *                                                                           *
00009  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00010  *                                                                           *
00011 \*---------------------------------------------------------------------------*/
00012 /*---------------------------------------------------------------------------*\
00013  *                                License                                    *
00014  *                                                                           *
00015  * This library is free software; you can redistribute it and/or modify it   *
00016  * under the terms of the GNU Library General Public License as published    *
00017  * by the Free Software Foundation, version 2.                               *
00018  *                                                                           *
00019  * This library is distributed in the hope that it will be useful, but       *
00020  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00022  * Library General Public License for more details.                          *
00023  *                                                                           *
00024  * You should have received a copy of the GNU Library General Public         *
00025  * License along with this library; if not, write to the Free Software       *
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00027  *                                                                           *
00028 \*---------------------------------------------------------------------------*/
00029 /*---------------------------------------------------------------------------*\
00030  *                                Changes                                    *
00031  *                                                                           *
00032  * 2002/10/16: added transparency path. Thanks to Franck Sourdin             *
00033  *            (sourdin@ai.cluny.ensam.fr) for it!                            *
00034  *                                                                           *
00035  *                                                                           *
00036  *                                                                           *
00037  *                                                                           *
00038 \*---------------------------------------------------------------------------*/
00039
00040 //-------------------------------
00041 //  Includes
00042 //-------------------------------
00043
00044 #include <cstdio>
00045 #include <climits>
00046
00047 #include "OSGConfig.h"
00048
00049 #include "OSGGL.h"
00050
00051 #include <iostream>
00052 #include <fstream>
00053 #include <vector>
00054
00055 #include "OSGLog.h"
00056
00057 #include "OSGNode.h"
00058 #include "OSGGeometry.h"
00059 #include "OSGTypedGeoVectorProperty.h"
00060 #include "OSGTypedGeoIntegralProperty.h"
00061 #ifndef OSG_EMBEDDED
00062 #include "OSGGeoFunctions.h"
00063 #endif
00064 #include "OSGSimpleTexturedMaterial.h"
00065 #ifndef OSG_EMBEDDED
00066 #include "OSGImageFileHandler.h"
00067 #include "OSGPathHandler.h"
00068 #endif
00069 #include "OSGGroup.h"
00070 #ifndef OSG_EMBEDDED
00071 #include "OSGSceneFileHandler.h"
00072 #endif
00073 #include "OSGTriangleIterator.h"
00074
00075 #include "OSGOBJSceneFileType.h"
00076
00077 OSG_USING_NAMESPACE
00078
00079
00085 #if defined(OSG_WIN32_ICL) && !defined(OSG_CHECK_FIELDSETARG)
00086 #pragma warning (disable : 383)
00087 #endif
00088 
00089 /*****************************
00090  *   Types
00091  *****************************/
00092 // Static Class Varible implementations:
00093 const Char8 *OBJSceneFileType::_suffixA[] =  { "obj" };
00094
00095 OBJSceneFileType  OBJSceneFileType::_the(_suffixA,
00096                                           sizeof(_suffixA),
00097                                          false,
00098                                          10,
00099                                          (SceneFileType::OSG_READ_SUPPORTED |
00100                                           SceneFileType::OSG_WRITE_SUPPORTED));
00101
00102 /*****************************
00103  *    Classvariables
00104  *****************************/
00105
00106
00107 /********************************
00108  *    Class methodes
00109  *******************************/
00110
00111
00112 /*******************************
00113 *public
00114 *******************************/
00115
00116 //----------------------------
00117 // Function name: read
00118 //----------------------------
00119 //
00120 //Parameters:
00121 //p: Scene &image, const char *fileName
00122 //GlobalVars:
00123 //g:
00124 //Returns:
00125 //r:bool
00126 // Caution
00127 //c:
00128 //Assumations:
00129 //a:
00130 //Describtions:
00131 //d: read the image from the given file
00132 //SeeAlso:
00133 //s:
00134 //
00135 //------------------------------
00136 NodeTransitPtr OBJSceneFileType::read(      std::istream &is,
00137                                       const Char8        *,
00138                                             Resolver        ) const
00139 {
00140     NodeUnrecPtr rootPtr, nodePtr;
00141     std::string elem;
00142     std::map<std::string, DataElem>::const_iterator elemI;
00143     Vec3r vec3r;
00144     Pnt3r pnt3r;
00145     Vec2r vec2r;
00146     Real32 x,y,z;
00147     GeoPnt3rPropertyUnrecPtr coordPtr    = GeoPnt3rProperty::create();
00148     GeoVec2rPropertyUnrecPtr texCoordPtr = GeoVec2rProperty::create();
00149     GeoVec3rPropertyUnrecPtr normalPtr   = GeoVec3rProperty::create();
00150     GeometryUnrecPtr geoPtr;
00151     GeoIntegralPropertyUnrecPtr posIndexPtr, texIndexPtr, normalIndexPtr;
00152     GeoIntegralPropertyUnrecPtr lensPtr;
00153     GeoIntegralPropertyUnrecPtr typePtr;
00154     DataElem dataElem;
00155     Char8 strBuf[8192], *token, *nextToken;
00156     Int32 strBufSize = sizeof(strBuf)/sizeof(Char8);
00157     Int32 index, posIndex = 0, indexType;
00158     Int32 i,j,n,primCount[3];
00159     std::list<Mesh> meshList;
00160     std::map<std::string, SimpleTexturedMaterialUnrecPtr> mtlMap;
00161     std::map<std::string, SimpleTexturedMaterialUnrecPtr>::iterator mtlI;
00162     Mesh emptyMesh;
00163     Face emptyFace;
00164     TiePoint  emptyTie;
00165     Int32 indexMask, meshIndexMask;
00166     std::list<Face>::iterator faceI;
00167     std::list<Mesh>::iterator meshI;
00168     bool isSingleIndex;
00169
00170     // create the first mesh entry
00171     meshList.push_back(emptyMesh);
00172     meshI = meshList.begin();
00173
00174     if(is)
00175     {
00176         primCount[0] = 0;
00177         primCount[1] = 0;
00178         primCount[2] = 0;
00179
00180         for(is >> elem; is.eof() == false; is >> elem)
00181         {
00182             if(elem[0] == '#' || elem[0] == '$')
00183             {
00184                 is.ignore(INT_MAX, '\n');
00185             }
00186             else
00187             {
00188 #ifndef OSG_EMBEDDED
00189                 SceneFileHandler::the()->updateReadProgress();
00190 #endif
00191                 elemI = _dataElemMap.find(elem);
00192                 dataElem = ((elemI == _dataElemMap.end()) ?
00193                         UNKNOWN_DE : elemI->second );
00194                 switch (dataElem)
00195                 {
00196                     case OBJECT_DE:
00197                     case GROUP_DE:
00198                     case SMOOTHING_GROUP_DE:
00199                         is.ignore(INT_MAX, '\n');
00200                     break;
00201                     case VERTEX_DE:
00202                         primCount[0]++;
00203                         is >> x >> y >> z;
00204                         pnt3r.setValues(x,y,z);
00205                         coordPtr->addValue(pnt3r);
00206                     break;
00207                     case VERTEX_TEXTURECOORD_DE:
00208                         primCount[1]++;
00209                         is >> x >> y;
00210                         vec2r.setValues(x,y);
00211                         texCoordPtr->addValue(vec2r);
00212                     break;
00213                     case VERTEX_NORMAL_DE:
00214                         primCount[2]++;
00215                         is >> x >> y >> z;
00216                         vec3r.setValues(x,y,z);
00217                         normalPtr->addValue(vec3r);
00218                     break;
00219                     case LIB_MTL_DE:
00220                         is >> elem;
00221                         readMTL ( elem.c_str(), mtlMap );
00222                         is.ignore(INT_MAX, '\n');
00223                     break;
00224                     case USE_MTL_DE:
00225                         is >> elem;
00226                         if (meshI->faceList.empty() == false)
00227                         {
00228                             meshList.push_front(emptyMesh);
00229                             meshI = meshList.begin();
00230                         }
00231                         mtlI = mtlMap.find(elem);
00232                         if (mtlI == mtlMap.end())
00233                         {
00234                             FFATAL (("Unkown mtl %s\n", elem.c_str()));
00235                         }
00236                         else
00237                         {
00238                             meshI->mtlPtr = mtlI->second;
00239                         }
00240                     break;
00241                     case FACE_DE:
00242                         meshI->faceList.push_front(emptyFace);
00243                         faceI = meshI->faceList.begin();
00244                         is.get(strBuf,strBufSize);
00245                         token = strBuf;
00246                         indexType = 0;
00247                         while(token && *token)
00248                         {
00249                             for (; *token == '/'; token++)
00250                                 indexType++;
00251                             for (; isspace(*token); token++)
00252                                 indexType = 0;
00253                             index = strtol(token, &nextToken, 10);
00254                             if (token == nextToken)
00255                                 break;
00256                             if (indexType == 0)
00257                                 faceI->tieVec.push_back(emptyTie);
00258                             if (index >= 0)
00259                                 index--;
00260                             else
00261                                 index =  primCount[indexType] + index;
00262                             faceI->tieVec.back().index[indexType] = index;
00263                             token = nextToken;
00264                         }
00265                     break;
00266                     case UNKNOWN_DE:
00267                     default:
00268                         FWARNING (( "Unkown obj data elem: %s\n", elem.c_str()));
00269                         is.ignore(INT_MAX, '\n');
00270                     break;
00271                 }
00272             }
00273         }
00274
00275 #if 0
00276         std::cerr << "------------------------------------------------" << std::endl;
00277         i = 0;
00278         for (meshI = meshList.begin(); meshI != meshList.end(); meshI++)
00279         {
00280             std::cerr << "Mesh " << i << " faceCount :"
00281                       << meshI->faceList.size() << std::endl;
00282             j = 0 ;
00283             for ( faceI = meshI->faceList.begin(); faceI != meshI->faceList.end();
00284                   faceI++)
00285             std::cerr << "MESH " <<  i << "face: " << j++ << "tie num: "
00286                       << faceI->tieVec.size() << std::endl;
00287             i++;
00288         }
00289         std::cerr << "------------------------------------------------" << std::endl;
00290 #endif
00291 
00292         // create Geometry objects
00293         for (meshI = meshList.begin(); meshI != meshList.end(); meshI++)
00294         {
00295             geoPtr   = Geometry::create();
00296             posIndexPtr = NULL;
00297             texIndexPtr = NULL;
00298             normalIndexPtr = NULL;
00299             lensPtr  = GeoUIntProperty::create();
00300             typePtr  = GeoUInt8Property::create();
00301
00302             // create and check mesh index mask
00303             meshIndexMask = 0;
00304             isSingleIndex = true;
00305             if ( meshI->faceList.empty() == false)
00306             {
00307                 for ( faceI = meshI->faceList.begin();
00308                   faceI != meshI->faceList.end(); faceI++)
00309                 {
00310                     indexMask = 0;
00311                     n = faceI->tieVec.size();
00312                     for (i = 0; i < n; i++)
00313                     {
00314                         for (j = 0; j < 3; j++)
00315                         {
00316                             if ((index = (faceI->tieVec[i].index[j])) >= 0)
00317                             {
00318                                 indexMask |= (1 << j);
00319                                 if (j)
00320                                     isSingleIndex &= (posIndex == index);
00321                                 else
00322                                     posIndex = index;
00323                             }
00324                         }
00325                     }
00326                     if (meshIndexMask == 0)
00327                     {
00328                         meshIndexMask = indexMask;
00329                     }
00330                     else if (meshIndexMask != indexMask)
00331                     {
00332                         // consider this real-world example:
00333                        // [...]
00334                        // f 1603//1747 1679//1744 1678//1743
00335                        // s 1
00336                        // f 9/1/10 5/2/9 1680/3/1748 1681/4/174
00337                        // [...]
00338                        // Some faces contain texture coords and others do not.
00339                        // The old version did just skip this geometry.
00340                        // This version should continue if there's at least
00341                        // the vertex index
00342                        // I've seen the change in the maskIndex only after a smooth group,
00343                        // so it's perhaps smarter to not ignore the smooth group further up in this code
00344                        if( !(indexMask & 1) )
00345                        {
00346                          // if there are vertex indices there's no reason to get in here
00347                           FFATAL (( "IndexMask unmatch, can not create geo\n"));
00348                           meshIndexMask = 0;
00349                           break;
00350                        }
00351                        else
00352                        {
00353                          // consider the minimum similarities of mesh masks
00354                          meshIndexMask &= indexMask;
00355                        }
00356                     }
00357                 }
00358             }
00359             else
00360             {
00361                 FWARNING (("Mesh with empty faceList\n"));
00362             }
00363
00364             // fill the geo properties
00365             if (meshIndexMask)
00366             {
00367                 geoPtr->setPositions ( coordPtr );
00368                 posIndexPtr = GeoUIntProperty::create();
00369                 if(!isSingleIndex)
00370                     geoPtr->setIndex(posIndexPtr, Geometry::PositionsIndex);
00371                 geoPtr->setLengths   ( lensPtr );
00372                 geoPtr->setTypes     ( typePtr );
00373
00374                 if ( (meshIndexMask & 2) && texCoordPtr->size() > 0 )
00375                 {
00376                     geoPtr->setTexCoords ( texCoordPtr );
00377                     texIndexPtr = GeoUIntProperty::create();
00378                     if(!isSingleIndex)
00379                         geoPtr->setIndex(texIndexPtr, Geometry::TexCoordsIndex);
00380                 }
00381                 else
00382                 {
00383                     geoPtr->setTexCoords ( NULL );
00384                 }
00385
00386                 if ( (meshIndexMask & 4) && normalPtr->size() > 0 )
00387                 {
00388                     geoPtr->setNormals   ( normalPtr );
00389                     normalIndexPtr = GeoUIntProperty::create();
00390                     if(!isSingleIndex)
00391                         geoPtr->setIndex(normalIndexPtr, Geometry::NormalsIndex);
00392                 }
00393                 else
00394                 {
00395                     geoPtr->setNormals   ( NULL );
00396                 }
00397
00398                 if (meshI->mtlPtr == NULL)
00399                 {
00400                     meshI->mtlPtr = SimpleTexturedMaterial::create();
00401                     meshI->mtlPtr->setDiffuse( Color3r( .8f, .8f, .8f ) );
00402                     meshI->mtlPtr->setSpecular( Color3r( 1.f, 1.f, 1.f ) );
00403                     meshI->mtlPtr->setShininess( 20.f );
00404                 }
00405                 geoPtr->setMaterial  ( meshI->mtlPtr );
00406
00407                 for ( faceI = meshI->faceList.begin();
00408                       faceI != meshI->faceList.end(); faceI++)
00409                 {
00410                     n = faceI->tieVec.size();
00411
00412                     // add the lens entry
00413                     lensPtr->push_back(n);
00414
00415                     // add the type entry
00416                     typePtr->push_back(GL_POLYGON);
00417
00418                     // create the index values
00419                     for (i = 0; i < n; i++)
00420                     {
00421                         if (isSingleIndex)
00422                         {
00423                             posIndexPtr->push_back(faceI->tieVec[i].index[0]);
00424                         }
00425                         else
00426                         {
00427                             posIndexPtr->push_back(faceI->tieVec[i].index[0]);
00428                             if(texIndexPtr != NULL)
00429                                 texIndexPtr->push_back(faceI->tieVec[i].index[1]);
00430                             if(normalIndexPtr != NULL)
00431                                 normalIndexPtr->push_back(faceI->tieVec[i].index[2]);
00432                         }
00433                     }
00434                 }
00435
00436                 if(isSingleIndex)
00437                 {
00438                     geoPtr->setIndex(posIndexPtr, Geometry::PositionsIndex);
00439                     geoPtr->setIndex(posIndexPtr, Geometry::NormalsIndex  );
00440                     geoPtr->setIndex(posIndexPtr, Geometry::TexCoordsIndex);
00441                 }
00442
00443                 // need to port the geometry functions ...
00444                 createSharedIndex( geoPtr );
00445
00446                 // check if we have normals
00447                 // need to port the geometry functions ...
00448
00449 #ifndef OSG_EMBEDDED
00450                 if(geoPtr->getNormals() == NULL)
00451                     calcVertexNormals(geoPtr);
00452 #endif
00453 
00454                 // create and link the node
00455                 nodePtr = Node::create();
00456                 nodePtr->setCore( geoPtr );
00457
00458                 if (meshList.size() > 1)
00459                 {
00460                     if (rootPtr == NULL)
00461                     {
00462                         rootPtr = Node::create();
00463
00464                         GroupUnrecPtr tmpPtr = Group::create();
00465
00466                         rootPtr->setCore ( tmpPtr );
00467                         rootPtr->addChild(nodePtr);
00468                     }
00469                     else
00470                     {
00471                         rootPtr->addChild(nodePtr);
00472                     }
00473                 }
00474                 else
00475                 {
00476                     rootPtr = nodePtr;
00477                 }
00478             }
00479         }
00480     }
00481
00482 #ifndef OSG_EMBEDDED
00483     SceneFileHandler::the()->updateReadProgress(100);
00484 #endif
00485     return NodeTransitPtr(rootPtr);
00486 }
00487
00488 void OBJSceneFileType::write(Node * const  node,
00489                              std::ostream &os,
00490                              UInt32 &pIndex,
00491                              UInt32 &nIndex,
00492                              UInt32 &tIndex) const
00493 {
00494 #ifndef OSG_EMBEDDED
00495     UInt32 i,pCount=0,nCount=0,tCount=0;
00496     Geometry *g = dynamic_cast<Geometry *>(node->getCore());
00497     if(g != NULL)
00498     {
00499         // HACK separate it in several geometry nodes.
00500         os << "g Geometry" << std::endl;
00501         os << "usemtl Geometry" << std::endl;
00502         Matrixr mat = node->getToWorld();
00503         // write vertices
00504         if(g->getPositions())
00505         {
00506             pCount = g->getPositions()->getSize();
00507             for(i=0 ; i< pCount ; ++i)
00508             {
00509                 Pnt3r v;
00510                 g->getPositions()->getValue(v, i);
00511                 mat.mult(v, v);
00512                 os << "v " << v[0] << " " << v[1] << " " << v[2] << std::endl;
00513             }
00514         }
00515         // write normals
00516         if(g->getNormals())
00517         {
00518             nCount = g->getNormals()->getSize();
00519             for(i=0 ; i< nCount ; ++i)
00520             {
00521                 Vec3r v;
00522                 g->getNormals()->getValue(v, i);
00523                 mat.mult(v, v);
00524                 os << "vn " << v[0] << " " << v[1] << " " << v[2] << std::endl;
00525             }
00526         }
00527         // texture coords
00528         if(g->getTexCoords())
00529         {
00530             tCount = g->getTexCoords()->getSize();
00531             for(i=0 ; i< tCount ; ++i)
00532             {
00533                 Vec2f v;
00534                 g->getTexCoords()->getValue(v, i);
00535                 os << "vt " << v[0] << " " << v[1] << std::endl;
00536             }
00537         }
00538         // write indices
00539         TriangleIterator f;
00540         for(f=g->beginTriangles() ; f!=g->endTriangles() ; ++f)
00541         {
00542             os << "f";
00543             for(i=0 ; i<3 ; ++i)
00544             {
00545                 os << " " << f.getPositionIndex(i) + pIndex;
00546                 if(nCount || tCount)
00547                 {
00548                     os << "/";
00549                     if(tCount)
00550                         os << f.getTexCoordsIndex(i) + tIndex;
00551                     if(nCount)
00552                         os << "/" << f.getNormalIndex(i) + nIndex;
00553                 }
00554             }
00555             os << std::endl;
00556         }
00557         pIndex += pCount;
00558         tIndex += tCount;
00559         nIndex += nCount;
00560     }
00561     for(MFUnrecChildNodePtr::const_iterator nI =node->getMFChildren()->begin();
00562                                             nI!=node->getMFChildren()->end();
00563                                           ++nI)
00564     {
00565         write((*nI),os,pIndex,nIndex,tIndex);
00566     }
00567 #endif
00568 }
00569
00570 bool OBJSceneFileType::write(Node * const node, std::ostream &os,
00571                              const Char8 *fileNameOrExtension) const
00572 {
00573     UInt32 pIndex=1;
00574     UInt32 tIndex=1;
00575     UInt32 nIndex=1;
00576
00577     write(node,os,pIndex,tIndex,nIndex);
00578
00579     return true;
00580 }
00581
00582 /******************************
00583 *protected
00584 ******************************/
00585
00586
00587 /******************************
00588 *private
00589 ******************************/
00590
00591
00592 /***************************
00593 *instance methodes
00594 ***************************/
00595
00596
00597 /***************************
00598 *public
00599 ***************************/
00600
00601
00605 //----------------------------
00606 // Function name: OBJSceneFileType
00607 //----------------------------
00608 //
00609 //Parameters:
00610 //p: const char *suffixArray[], UInit16 suffixByteCount
00611 //GlobalVars:
00612 //g:
00613 //Returns:
00614 //r:
00615 // Caution
00616 //c:
00617 //Assumations:
00618 //a:
00619 //Describtions:
00620 //d: Default Constructor
00621 //SeeAlso:
00622 //s:
00623 //
00624 //------------------------------
00625
00626 OBJSceneFileType::OBJSceneFileType(const Char8  *suffixArray[],
00627                                          UInt16  suffixByteCount,
00628                                          bool    override,
00629                                          UInt32  overridePriority,
00630                                          UInt32  flags) :
00631     SceneFileType(suffixArray,
00632                   suffixByteCount,
00633                   override,
00634                   overridePriority,
00635                   flags),
00636     _dataElemMap()
00637
00638 {
00639     initElemMap();
00640 }
00641
00642 //----------------------------
00643 // Function name: OBJSceneFileType
00644 //----------------------------
00645 //
00646 //Parameters:
00647 //p: const OBJSceneFileType &obj
00648 //GlobalVars:
00649 //g:
00650 //Returns:
00651 //r:
00652 // Caution
00653 //c:
00654 //Assumations:
00655 //a:
00656 //Describtions:
00657 //d: Copy Constructor
00658 //SeeAlso:
00659 //s:
00660 //
00661 //------------------------------
00662
00663 OBJSceneFileType::OBJSceneFileType(const OBJSceneFileType &obj) :
00664     SceneFileType(obj)
00665 {
00666     initElemMap();
00667 }
00668
00669 //----------------------------
00670 // Function name: ~OBJSceneFileType
00671 //----------------------------
00672 //
00673 //Parameters:
00674 //p: void
00675 //GlobalVars:
00676 //g:
00677 //Returns:
00678 //r:
00679 // Caution
00680 //c:
00681 //Assumations:
00682 //a:
00683 //Describtions:
00684 //d: Destructor
00685 //SeeAlso:
00686 //s:
00687 //
00688 //------------------------------
00689
00690 OBJSceneFileType &OBJSceneFileType::the(void)
00691 {
00692     return _the;
00693 }
00694
00695 OBJSceneFileType::~OBJSceneFileType(void)
00696 {
00697     return;
00698 }
00699
00700 const Char8 *OBJSceneFileType::getName(void) const
00701 {
00702     return "Wavefront Geometry";
00703 }
00704
00705
00706 /*------------access----------------*/
00707
00708 /*------------properies-------------*/
00709
00710 /*------------your Category---------*/
00711
00712 /*------------Operators-------------*/
00713
00714
00715
00716 /****************************
00717  *protected
00718  ****************************/
00719
00720
00721 /****************************
00722  *private
00723  ****************************/
00724
00725
00726 void OBJSceneFileType::initElemMap(void)
00727 {
00728     if (_dataElemMap.empty())
00729     {
00730         _dataElemMap[""]        = UNKNOWN_DE;
00731
00732         _dataElemMap["v"]       = VERTEX_DE;
00733         _dataElemMap["vt"]      = VERTEX_TEXTURECOORD_DE;
00734         _dataElemMap["vn"]      = VERTEX_NORMAL_DE;
00735         _dataElemMap["f"]       = FACE_DE;
00736         _dataElemMap["fo"]      = FACE_DE;
00737         _dataElemMap["mtllib"]  = LIB_MTL_DE;
00738         _dataElemMap["usemtl"]  = USE_MTL_DE;
00739         _dataElemMap["g"]       = GROUP_DE;
00740         _dataElemMap["s"]       = SMOOTHING_GROUP_DE;
00741         _dataElemMap["o"]       = OBJECT_DE;
00742     }
00743
00744     if (_mtlElemMap.empty())
00745     {
00746         _mtlElemMap[""]        = UNKNOWN_ME;
00747
00748         _mtlElemMap["newmtl"]  = NEW_MTL_ME;
00749         _mtlElemMap["Kd"]      = MTL_DIFFUSE_ME;
00750         _mtlElemMap["Ka"]      = MTL_AMBIENT_ME;
00751         _mtlElemMap["Ks"]      = MTL_SPECULAR_ME;
00752         _mtlElemMap["Ns"]      = MTL_SHININESS_ME;
00753         _mtlElemMap["Tr"]      = MTL_TRANSPARENCY_ME;
00754         _mtlElemMap["d"]       = MTL_DISSOLVE_ME;
00755         _mtlElemMap["map_Kd"]  = MTL_MAP_KD_ME;
00756         _mtlElemMap["map_Ka"]  = MTL_MAP_KA_ME;
00757         _mtlElemMap["map_Ks"]  = MTL_MAP_KS_ME;
00758         _mtlElemMap["illum"]   = MTL_ILLUM_ME;
00759         _mtlElemMap["refl"]    = MTL_REFL_ME;
00760     }
00761 }
00762
00763 Int32 OBJSceneFileType::readMTL ( const Char8 *fileName,
00764                                   std::map<std::string,
00765                                   SimpleTexturedMaterialUnrecPtr> & mtlMap )
00766   const
00767 {
00768     if(fileName == NULL || strlen(fileName) == 0)
00769         return 0;
00770
00771     Int32 mtlCount = 0;
00772
00773 #ifndef OSG_EMBEDDED
00774     PathHandler *pathHandler = SceneFileHandler::the()->getPathHandler();
00775 #endif
00776     std::string fullFilePath;
00777 #ifndef OSG_EMBEDDED
00778     if(pathHandler != NULL)
00779         fullFilePath = pathHandler->findFile(fileName);
00780     else
00781         fullFilePath = fileName;
00782 #endif
00783 
00784     if(fullFilePath.empty())
00785     {
00786         FWARNING (("Couldn't open '%s'!\n", fileName));
00787         return 0;
00788     }
00789
00790     std::ifstream in(fullFilePath.c_str());
00791     SimpleTexturedMaterialUnrecPtr mtlPtr = NULL;
00792     Real32 a,b,c;
00793     std::string elem;
00794     std::map<std::string, MaterialElem>::const_iterator elemI;
00795     MaterialElem mtlElem;
00796     std::map<std::string, OSG::ImageUnrecPtr> imageMap;
00797     std::map<std::string, OSG::ImageUnrecPtr>::iterator iI;
00798     ImageUnrecPtr image = NULL;
00799     bool constDiffuse = false, constAmbient = false, constSpecular = false;
00800
00801     if (in)
00802     {
00803         for (in >> elem; in.eof() == false; in >> elem)
00804         {
00805             if (elem[0] == '#' || elem[0] == '$' )
00806             {
00807                 in.ignore(INT_MAX, '\n');
00808             }
00809             else
00810             {
00811                 elemI = _mtlElemMap.find(elem);
00812                 mtlElem = ((elemI == _mtlElemMap.end()) ?
00813                      UNKNOWN_ME : elemI->second);
00814                 if (mtlElem == NEW_MTL_ME)
00815                 {
00816                     in >> elem;
00817                     mtlPtr = SimpleTexturedMaterial::create();
00818                     mtlPtr->setColorMaterial(GL_NONE);
00819                     mtlPtr->setEnvMode(GL_MODULATE);
00820                     mtlMap[elem] = mtlPtr;
00821                     mtlCount++;
00822                     constDiffuse  = false;
00823                     constAmbient  = false;
00824                     constSpecular = false;
00825                 }
00826                 else
00827                 {
00828                     if (mtlPtr == NULL)
00829                     {
00830                         FFATAL (( "Invalid Mtl token: %s, newmtl expected in %s\n",
00831                                 elem.c_str(), fileName ));
00832                         in.ignore(INT_MAX, '\n');
00833                     }
00834                     else
00835                     {
00836                         switch (mtlElem)
00837                         {
00838                             case MTL_DIFFUSE_ME:
00839                                 in >> a >> b >> c;
00840                                 if (!constDiffuse)
00841                                     mtlPtr->setDiffuse( Color3r( a,b,c ));
00842                             break;
00843                             case MTL_AMBIENT_ME:
00844                                 in >> a >> b >> c;
00845                                 if (!constAmbient)
00846                                     mtlPtr->setAmbient( Color3r( a,b,c ));
00847                             break;
00848                             case MTL_SPECULAR_ME:
00849                                 in >> a >> b >> c;
00850                                 if (!constSpecular)
00851                                     mtlPtr->setSpecular( Color3r( a,b,c ));
00852                             break;
00853                             case MTL_SHININESS_ME:
00854                                 in >> a;
00855                                 mtlPtr->setShininess(a);
00856                             break;
00857                             case MTL_ILLUM_ME:
00858                                 ; // TODO: What to do with illum ?!?
00859                                 in >> elem;
00860                                 // FFATAL (("obj mtl illum not handled yet\n"));
00861                             break;
00862                             case MTL_REFL_ME:
00863                                 mtlPtr->setEnvMap(true);
00864                             break;
00865                             case MTL_TRANSPARENCY_ME:
00866                                 in >> a;
00867                                 mtlPtr->setTransparency(a);
00868                             break;
00869                             case MTL_DISSOLVE_ME:
00870                                 in >> a;
00871                                 mtlPtr->setTransparency(1.f - a);
00872                                 break;
00873                             case MTL_MAP_KD_ME:
00874                             case MTL_MAP_KA_ME:
00875                             case MTL_MAP_KS_ME:
00876                                 image = NULL;
00877                                 in >> elem;
00878                                 iI = imageMap.find(elem);
00879                                 if (iI == imageMap.end())
00880                                 {
00881 #ifndef OSG_EMBEDDED
00882                                     std::string fullElemPath;
00883                                     if(pathHandler != NULL)
00884                                         fullElemPath = pathHandler->findFile(elem.c_str());
00885                                     else
00886                                         fullElemPath = elem.c_str();
00887                                     image = OSG::ImageFileHandler::the()->read(fullElemPath.c_str());
00888
00889                                     if(image != NULL)
00890                                     {
00891                                         image->setForceAlphaBinary(
00892                                             image->calcIsAlphaBinary());
00893
00894                                         imageMap[elem] = image;
00895                                     }
00896 #endif
00897                                 }
00898                                 else
00899                                 {
00900                                     image = iI->second;
00901                                 }
00902                                 if (image != NULL)
00903                                 {
00904                                     mtlPtr->setImage(image);
00905                                     switch (mtlElem)
00906                                     {
00907                                         case MTL_MAP_KD_ME:
00908                                             constDiffuse = true;
00909                                             mtlPtr->setDiffuse  ( Color3r( 1.f, 1.f, 1.f) );
00910                                         break;
00911                                         case MTL_MAP_KA_ME:
00912                                             constAmbient = true;
00913                                             mtlPtr->setAmbient  ( Color3r( 1.f, 1.f, 1.f) );
00914                                         break;
00915                                         case MTL_MAP_KS_ME:
00916                                             constSpecular = true;
00917                                             mtlPtr->setSpecular ( Color3r( 1.f, 1.f, 1.f) );
00918                                         break;
00919                                         default:
00920                                         break;
00921                                     }
00922                                 }
00923                                 else
00924                                 {
00925                                     FFATAL (( "Can not find %s texture file in mtl %s \n",
00926                                             elem.c_str(), fileName ));
00927                                 }
00928                             break;
00929                             default:
00930                                 FWARNING (( "Invalid %s entry in %s\n",
00931                                             elem.c_str(), fileName ));
00932                                 in.ignore(INT_MAX, '\n');
00933                         }
00934                     }
00935                 }
00936             }
00937         }
00938     }
00939     return mtlCount;
00940 }