Show
Ignore:
Timestamp:
08/26/04 16:33:38 (10 years ago)
Author:
robert
Message:

Rewrite of OBJ parser + converter to OSG

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/src/osgPlugins/obj/ReaderWriterOBJ.cpp

    r3282 r3323  
    3939#include <osgUtil/TriStripVisitor> 
    4040#include <osgUtil/SmoothingVisitor> 
    41  
    42 #include "glm.h" 
     41#include <osgUtil/Tesselator> 
     42 
     43#include "obj.h" 
    4344 
    4445#include <map> 
    4546#include <set> 
    46  
    47 template <class T> 
    48 struct DerefLess 
    49 { 
    50     bool operator ()(T lhs,T rhs) const { return *lhs < *rhs; } 
    51 }; 
    52  
    5347 
    5448class ReaderWriterOBJ : public osgDB::ReaderWriter 
     
    6458    virtual ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options*); 
    6559 
     60 
     61 
    6662protected: 
    6763 
    68     enum DrawableMode 
    69     { 
    70         DUPLICATE_COORDS, 
    71         USE_SEPERATE_INDICES, 
    72     }; 
    73  
    74     osg::Drawable* makeDrawable(DrawableMode drawableMode, GLMmodel* obj, GLMgroup* grp); 
    75     osg::Drawable* makeDrawable_duplicateCoords(GLMmodel* obj, GLMgroup* grp); 
    76     osg::Drawable* makeDrawable_useSeperateIndices(GLMmodel* obj, GLMgroup* grp); 
    77      
    78     typedef std::map< std::string, osg::ref_ptr<osg::Texture2D> > TextureMap; 
    79     typedef std::set< osg::ref_ptr<osg::Material>, DerefLess< osg::ref_ptr<osg::Material> > > MaterialSet; 
    80     typedef std::set< osg::ref_ptr<osg::StateSet>, DerefLess< osg::ref_ptr<osg::StateSet> > > StateSetSet; 
    81     typedef std::vector< osg::ref_ptr<osg::StateSet> > ObjMatierialOsgStateSetArray; 
    82      
    83     class IndexMap 
    84     { 
    85         public: 
    86  
    87             IndexMap(): 
    88                 _maximumIn(-1), 
    89                 _maximumOut(-1) {} 
    90  
    91             inline void updateMaximum(int index) 
    92             { 
    93                 if (index>_maximumIn) _maximumIn=index; 
    94             } 
    95              
    96             inline void  initialize() 
    97             { 
    98                 _indices.assign(_maximumIn+1,-1); 
    99             } 
    100              
    101             inline void insertIndex(int index) 
    102             { 
    103                 if (_indices[index]<0) _indices[index]=++_maximumOut; 
    104             } 
    105  
    106             inline int index(int i) const { return _indices[i]; } 
    107  
    108             osg::Vec3Array* createVec3Array(const float* array) 
    109             { 
    110                 osg::Vec3Array* vec3array = new osg::Vec3Array(_maximumOut+1); 
    111                 for(unsigned int i=0;i<_indices.size();++i) 
    112                 { 
    113                     if (_indices[i]>=0) (*vec3array)[_indices[i]].set(array[i*3],-array[i*3+2],array[i*3+1]); 
    114                 } 
    115                 return vec3array; 
    116             } 
    117              
    118             osg::Vec2Array* createVec2Array(const float* array) 
    119             { 
    120                 osg::Vec2Array* vec2array = new osg::Vec2Array(_maximumOut+1); 
    121                 for(unsigned int i=0;i<_indices.size();++i) 
    122                 { 
    123                     if (_indices[i]>=0) (*vec2array)[_indices[i]].set(array[i*2],array[i*2+1]); 
    124                 } 
    125                 return vec2array; 
    126             } 
    127  
    128             osg::UByte4Array* createUByte4Array(const osg::UByte4* array) 
    129             { 
    130                 osg::UByte4Array* ubyte4array = new osg::UByte4Array(_maximumOut+1); 
    131                 for(unsigned int i=0;i<_indices.size();++i) 
    132                 { 
    133                     if (_indices[i]>=0) (*ubyte4array)[_indices[i]] = array[i]; 
    134                 } 
    135                 return ubyte4array; 
    136             } 
    137              
    138             typedef std::vector<int> Indices; 
    139  
    140             int _maximumIn; 
    141             int _maximumOut; 
    142             Indices _indices; 
    143              
    144     }; 
    145  
    146  
     64    typedef std::map< std::string, osg::ref_ptr<osg::StateSet> > MaterialToStateSetMap; 
     65     
     66    void buildMaterialToStateSetMap(obj::Model& model, MaterialToStateSetMap& materialToSetSetMap); 
     67     
     68    osg::Geometry* convertElementListToGeometry(obj::Model& model, obj::Model::ElementList& elementList); 
     69     
     70    osg::Node* convertModelToSceneGraph(obj::Model& model); 
     71 
     72    inline osg::Vec3 transformVertex(const osg::Vec3& vec) { return osg::Vec3(vec.x(),-vec.z(),vec.y()); } 
     73    inline osg::Vec3 transformNormal(const osg::Vec3& vec) { return osg::Vec3(vec.x(),-vec.z(),vec.y()); } 
     74     
    14775}; 
    14876 
     
    15078// register with Registry to instantiate the above reader/writer. 
    15179osgDB::RegisterReaderWriterProxy<ReaderWriterOBJ> g_objReaderWriterProxy; 
     80 
     81void ReaderWriterOBJ::buildMaterialToStateSetMap(obj::Model& model, MaterialToStateSetMap& materialToStateSetMap) 
     82{ 
     83    for(obj::Model::MaterialMap::iterator itr = model.materialMap.begin(); 
     84        itr != model.materialMap.end(); 
     85        ++itr) 
     86    { 
     87        obj::Material& material = itr->second; 
     88         
     89        osg::StateSet* stateset = new osg::StateSet; 
     90 
     91        // handle material colors 
     92        { 
     93            osg::Material* osg_material = new osg::Material; 
     94            stateset->setAttribute(osg_material); 
     95 
     96            osg_material->setAmbient(osg::Material::FRONT_AND_BACK,material.ambient); 
     97            osg_material->setDiffuse(osg::Material::FRONT_AND_BACK,material.diffuse); 
     98            osg_material->setSpecular(osg::Material::FRONT_AND_BACK,material.specular); 
     99            osg_material->setShininess(osg::Material::FRONT_AND_BACK,(material.shininess/1000.0f)*128.0f ); // note OBJ shiniess is 0..1000. 
     100        } 
     101         
     102        // handle textures 
     103        if (!material.map_Kd.empty()) 
     104        { 
     105            std::string filename = material.map_Kd; 
     106            osg::Image* image = osgDB::readImageFile(filename); 
     107            if (image) 
     108            { 
     109                osg::Texture2D* texture = new osg::Texture2D(image); 
     110                stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); 
     111            } 
     112        } 
     113 
     114         
     115        materialToStateSetMap[material.name] = stateset; 
     116         
     117    } 
     118} 
     119 
     120osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model, obj::Model::ElementList& elementList) 
     121{ 
     122     
     123    unsigned int numVertexIndices = 0; 
     124    unsigned int numNormalIndices = 0; 
     125    unsigned int numTexCoordIndices = 0; 
     126     
     127    unsigned int numPointElements = 0; 
     128    unsigned int numPolylineElements = 0; 
     129    unsigned int numPolygonElements = 0; 
     130 
     131    obj::Model::ElementList::iterator itr; 
     132    for(itr=elementList.begin(); 
     133        itr!=elementList.end(); 
     134        ++itr) 
     135    { 
     136        obj::Element& element = *(*itr); 
     137 
     138        numVertexIndices += element.vertexIndices.size(); 
     139        numNormalIndices += element.normalIndices.size(); 
     140        numTexCoordIndices += element.texCoordIndices.size(); 
     141 
     142        numPointElements += (element.dataType==obj::Element::POINTS) ? 1 : 0; 
     143        numPolylineElements += (element.dataType==obj::Element::POLYLINE) ? 1 : 0; 
     144        numPolygonElements += (element.dataType==obj::Element::POLYGON) ? 1 : 0; 
     145 
     146    } 
     147 
     148    if (numVertexIndices==0) return 0; 
     149     
     150    if (numNormalIndices!=0 && numNormalIndices!=numVertexIndices) 
     151    { 
     152        osg::notify(osg::NOTICE)<<"Incorrect number of normals, ignore them"<<std::endl; 
     153        numNormalIndices = 0; 
     154    } 
     155     
     156    if (numTexCoordIndices!=0 && numTexCoordIndices!=numVertexIndices) 
     157    { 
     158        osg::notify(osg::NOTICE)<<"Incorrect number of normals, ignore them"<<std::endl; 
     159        numTexCoordIndices = 0; 
     160    } 
     161     
     162    osg::Vec3Array* vertices = numVertexIndices ? new osg::Vec3Array : 0; 
     163    osg::Vec3Array* normals = numNormalIndices ? new osg::Vec3Array : 0; 
     164    osg::Vec2Array* texcoords = numTexCoordIndices ? new osg::Vec2Array : 0; 
     165     
     166    if (vertices) vertices->reserve(numVertexIndices); 
     167    if (normals) normals->reserve(numNormalIndices); 
     168    if (texcoords) texcoords->reserve(numTexCoordIndices); 
     169     
     170    osg::Geometry* geometry = new osg::Geometry; 
     171    if (vertices) geometry->setVertexArray(vertices); 
     172    if (normals) 
     173    { 
     174        geometry->setNormalArray(normals); 
     175        geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); 
     176    } 
     177    if (texcoords) 
     178    { 
     179        geometry->setTexCoordArray(0,texcoords); 
     180    } 
     181     
     182 
     183    if (numPointElements>0) 
     184    { 
     185        unsigned int startPos = vertices->size(); 
     186        unsigned int numPoints = 0; 
     187        for(itr=elementList.begin(); 
     188            itr!=elementList.end(); 
     189            ++itr) 
     190        { 
     191            obj::Element& element = *(*itr); 
     192            if (element.dataType==obj::Element::POINTS) 
     193            { 
     194                for(obj::Element::IndexList::iterator index_itr = element.vertexIndices.begin(); 
     195                    index_itr != element.vertexIndices.end(); 
     196                    ++index_itr) 
     197                { 
     198                    vertices->push_back(transformVertex(model.vertices[*index_itr])); 
     199                    ++numPoints; 
     200                } 
     201                if (numNormalIndices) 
     202                { 
     203                    for(obj::Element::IndexList::iterator index_itr = element.normalIndices.begin(); 
     204                        index_itr != element.normalIndices.end(); 
     205                        ++index_itr) 
     206                    { 
     207                        normals->push_back(transformNormal(model.normals[*index_itr])); 
     208                    } 
     209                } 
     210                if (numTexCoordIndices) 
     211                { 
     212                    for(obj::Element::IndexList::iterator index_itr = element.texCoordIndices.begin(); 
     213                        index_itr != element.texCoordIndices.end(); 
     214                        ++index_itr) 
     215                    { 
     216                        texcoords->push_back(model.texcoords[*index_itr]); 
     217                    } 
     218                } 
     219            } 
     220        } 
     221 
     222        osg::DrawArrays* drawArrays = new osg::DrawArrays(GL_POINTS,startPos,numPoints); 
     223        geometry->addPrimitiveSet(drawArrays); 
     224    } 
     225     
     226    if (numPolylineElements>0) 
     227    { 
     228        unsigned int startPos = vertices->size(); 
     229        osg::DrawArrayLengths* drawArrayLengths = new osg::DrawArrayLengths(GL_LINES,startPos); 
     230 
     231        for(itr=elementList.begin(); 
     232            itr!=elementList.end(); 
     233            ++itr) 
     234        { 
     235            obj::Element& element = *(*itr); 
     236            if (element.dataType==obj::Element::POLYLINE) 
     237            { 
     238                drawArrayLengths->push_back(element.vertexIndices.size()); 
     239 
     240                for(obj::Element::IndexList::iterator index_itr = element.vertexIndices.begin(); 
     241                    index_itr != element.vertexIndices.end(); 
     242                    ++index_itr) 
     243                { 
     244                    vertices->push_back(transformVertex(model.vertices[*index_itr])); 
     245                } 
     246                if (numNormalIndices) 
     247                { 
     248                    for(obj::Element::IndexList::iterator index_itr = element.normalIndices.begin(); 
     249                        index_itr != element.normalIndices.end(); 
     250                        ++index_itr) 
     251                    { 
     252                        normals->push_back(transformNormal(model.normals[*index_itr])); 
     253                    } 
     254                } 
     255                if (numTexCoordIndices) 
     256                { 
     257                    for(obj::Element::IndexList::iterator index_itr = element.texCoordIndices.begin(); 
     258                        index_itr != element.texCoordIndices.end(); 
     259                        ++index_itr) 
     260                    { 
     261                        texcoords->push_back(model.texcoords[*index_itr]); 
     262                    } 
     263                } 
     264            } 
     265        } 
     266 
     267        geometry->addPrimitiveSet(drawArrayLengths); 
     268 
     269    } 
     270 
     271    bool reverseWinding = true; 
     272 
     273    if (numPolygonElements>0) 
     274    { 
     275        unsigned int startPos = vertices->size(); 
     276        osg::DrawArrayLengths* drawArrayLengths = new osg::DrawArrayLengths(GL_POLYGON,startPos); 
     277 
     278        for(itr=elementList.begin(); 
     279            itr!=elementList.end(); 
     280            ++itr) 
     281        { 
     282            obj::Element& element = *(*itr); 
     283            if (element.dataType==obj::Element::POLYGON) 
     284            { 
     285                drawArrayLengths->push_back(element.vertexIndices.size()); 
     286             
     287                if (reverseWinding) 
     288                { 
     289                    // need to reverse so add to OSG arrays in same order as in OBJ, as OSG assume anticlockwise ordering. 
     290                    for(obj::Element::IndexList::reverse_iterator index_itr = element.vertexIndices.rbegin(); 
     291                        index_itr != element.vertexIndices.rend(); 
     292                        ++index_itr) 
     293                    { 
     294                        vertices->push_back(transformVertex(model.vertices[*index_itr])); 
     295                    } 
     296                    if (numNormalIndices) 
     297                    { 
     298                        for(obj::Element::IndexList::reverse_iterator index_itr = element.normalIndices.rbegin(); 
     299                            index_itr != element.normalIndices.rend(); 
     300                            ++index_itr) 
     301                        { 
     302                            normals->push_back(transformNormal(model.normals[*index_itr])); 
     303                        } 
     304                    } 
     305                    if (numTexCoordIndices) 
     306                    { 
     307                        for(obj::Element::IndexList::reverse_iterator index_itr = element.texCoordIndices.rbegin(); 
     308                            index_itr != element.texCoordIndices.rend(); 
     309                            ++index_itr) 
     310                        { 
     311                            texcoords->push_back(model.texcoords[*index_itr]); 
     312                        } 
     313                    } 
     314                } 
     315                else 
     316                { 
     317                    // no need to reverse so add to OSG arrays in same order as in OBJ. 
     318                    for(obj::Element::IndexList::iterator index_itr = element.vertexIndices.begin(); 
     319                        index_itr != element.vertexIndices.end(); 
     320                        ++index_itr) 
     321                    { 
     322                        vertices->push_back(model.vertices[*index_itr]); 
     323                    } 
     324                    if (numNormalIndices) 
     325                    { 
     326                        for(obj::Element::IndexList::iterator index_itr = element.normalIndices.begin(); 
     327                            index_itr != element.normalIndices.end(); 
     328                            ++index_itr) 
     329                        { 
     330                            normals->push_back(model.normals[*index_itr]); 
     331                        } 
     332                    } 
     333                    if (numTexCoordIndices) 
     334                    { 
     335                        for(obj::Element::IndexList::iterator index_itr = element.texCoordIndices.begin(); 
     336                            index_itr != element.texCoordIndices.end(); 
     337                            ++index_itr) 
     338                        { 
     339                            texcoords->push_back(model.texcoords[*index_itr]); 
     340                        } 
     341                    } 
     342                } 
     343            } 
     344        } 
     345 
     346        geometry->addPrimitiveSet(drawArrayLengths); 
     347 
     348    } 
     349     
     350    return geometry; 
     351} 
     352 
     353osg::Node* ReaderWriterOBJ::convertModelToSceneGraph(obj::Model& model) 
     354{ 
     355 
     356    if (model.elementStateMap.empty()) return 0; 
     357 
     358    osg::Group* group = new osg::Group; 
     359 
     360    // set up the materials 
     361    MaterialToStateSetMap materialToSetSetMap; 
     362    buildMaterialToStateSetMap(model, materialToSetSetMap); 
     363 
     364    // go through the groups of related elements and build geometry from them. 
     365    for(obj::Model::ElementStateMap::iterator itr=model.elementStateMap.begin(); 
     366        itr!=model.elementStateMap.end(); 
     367        ++itr) 
     368    { 
     369     
     370        const obj::ElementState& es = itr->first; 
     371        obj::Model::ElementList& el = itr->second; 
     372 
     373        osg::Geometry* geometry = convertElementListToGeometry(model,el); 
     374 
     375        if (geometry) 
     376        { 
     377 
     378            osg::StateSet* stateset = materialToSetSetMap[es.materialName].get(); 
     379            geometry->setStateSet(stateset); 
     380 
     381//            osgUtil::Tesselator tesselator; 
     382//            tesselator.retesselatePolygons(*geometry); 
     383 
     384            osgUtil::TriStripVisitor tsv; 
     385            tsv.stripify(*geometry); 
     386 
     387            if (!geometry->getNormalArray() || geometry->getNormalArray()->getNumElements()==0) 
     388            { 
     389                osgUtil::SmoothingVisitor tsv; 
     390                tsv.smooth(*geometry); 
     391            } 
     392 
     393            osg::Geode* geode = new osg::Geode; 
     394            geode->addDrawable(geometry); 
     395            geode->setName(es.objectName); 
     396 
     397            group->addChild(geode); 
     398 
     399        } 
     400    } 
     401 
     402    return group; 
     403} 
    152404 
    153405 
     
    160412    std::string fileName = osgDB::findDataFile( file ); 
    161413    if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; 
    162  
    163     GLMmodel* obj = glmReadOBJ((char*) fileName.c_str()); 
    164     if (!obj) 
    165         return ReadResult::FILE_NOT_HANDLED; 
    166  
    167     std::string directory = osgDB::getFilePath(fileName); 
    168  
    169  
    170     osg::notify(osg::INFO) << "vertices " << obj->numvertices << std::endl; 
    171     osg::notify(osg::INFO)  << "normals " << obj->numnormals << std::endl; 
    172     osg::notify(osg::INFO)  << "texcoords " << obj->numtexcoords << std::endl; 
    173     osg::notify(osg::INFO)  << "face normals " << obj->numfacetnorms << std::endl; 
    174     osg::notify(osg::INFO)  << "tris " << obj->numtriangles << std::endl; 
    175     osg::notify(osg::INFO)  << "materials " << obj->nummaterials << std::endl; 
    176     osg::notify(osg::INFO)  << "groups " << obj->numgroups << std::endl; 
    177      
    178      
    179 //     if (obj->numnormals==0) 
    180 //     { 
    181 //         osg::notify(osg::NOTICE)  << "No normals in .obj file, automatically calculating normals..."<< std::endl; 
    182 //         glmFacetNormals(obj); 
    183 //         glmVertexNormals(obj,90.0f); 
    184 //     } 
    185  
    186  
    187     unsigned int i; 
    188  
    189  
    190     TextureMap textureMap; 
    191     MaterialSet materialSet; 
    192     StateSetSet statesetSet; 
    193      
    194     // create a sphere mapped texgen just in case we need it. 
    195     osg::ref_ptr<osg::TexGen> osg_texgen = new osg::TexGen; 
    196     osg_texgen->setMode(osg::TexGen::SPHERE_MAP); 
    197  
    198     ObjMatierialOsgStateSetArray osg_mtl(obj->nummaterials); 
    199  
    200     for (i = 0; i < obj->nummaterials; i++) 
    201     { 
    202         GLMmaterial* omtl = &(obj->materials[i]); 
    203         osg::notify(osg::DEBUG_INFO) << "mtl: " << omtl->name << std::endl; 
    204  
    205         osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet; 
    206  
    207         osg::ref_ptr<osg::Material> mtl = new osg::Material; 
    208         mtl->setAmbient(osg::Material::FRONT_AND_BACK, 
    209                         osg::Vec4(omtl->ambient[0], omtl->ambient[1], 
    210                                   omtl->ambient[2], omtl->ambient[3])); 
    211         mtl->setDiffuse(osg::Material::FRONT_AND_BACK, 
    212                         osg::Vec4(omtl->diffuse[0], omtl->diffuse[1], 
    213                                   omtl->diffuse[2], omtl->diffuse[3])); 
    214         mtl->setSpecular(osg::Material::FRONT_AND_BACK, 
    215                          osg::Vec4(omtl->specular[0], omtl->specular[1], 
    216                                    omtl->specular[2], omtl->specular[3])); 
    217         mtl->setEmission(osg::Material::FRONT_AND_BACK, 
    218                          osg::Vec4(omtl->emmissive[0], omtl->emmissive[1], 
    219                                    omtl->emmissive[2], omtl->emmissive[3])); 
    220                                     
    221         // note, osg shininess scales between 0.0 and 1.0. 
    222         mtl->setShininess(osg::Material::FRONT_AND_BACK, omtl->shininess); 
    223         mtl->setAlpha(osg::Material::FRONT_AND_BACK, omtl->alpha); 
    224  
    225         MaterialSet::iterator mitr = materialSet.find(mtl); 
    226         if (mitr==materialSet.end()) 
    227         { 
    228             materialSet.insert(mtl); 
    229         } 
    230         else 
    231         { 
    232             mtl = *mitr; 
    233         } 
    234  
    235         stateset->setAttribute(mtl.get()); 
    236  
    237         if (omtl->alpha<1.0f) { 
    238             stateset->setMode(GL_BLEND,osg::StateAttribute::ON); 
    239             stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); 
    240         } 
    241  
    242         if (omtl->textureName) 
    243         { 
    244             TextureMap::iterator titr = textureMap.find(omtl->textureName); 
    245  
    246             osg::notify(osg::DEBUG_INFO) << "textureName: " << omtl->textureName << std::endl; 
    247  
    248             if (titr==textureMap.end()) 
    249             { 
    250              
    251                 std::string fileName = osgDB::findFileInDirectory(omtl->textureName,directory,osgDB::CASE_INSENSITIVE); 
    252                 if (fileName.empty()) fileName = osgDB::findDataFile(omtl->textureName,osgDB::CASE_INSENSITIVE); 
    253                  
    254                 if (!fileName.empty()) 
    255                 { 
    256  
    257                     osg::notify(osg::DEBUG_INFO) << "filename: " << fileName << std::endl; 
    258  
    259                     osg::Image* osg_image = osgDB::readImageFile(fileName.c_str()); 
    260                     if (osg_image) 
    261                     { 
    262  
    263                         osg::notify(osg::DEBUG_INFO) << "imageRead: " << omtl->textureName << std::endl; 
    264  
    265  
    266                         osg::Texture2D* osg_texture = new osg::Texture2D; 
    267                         osg_texture->setImage(osg_image); 
    268                         stateset->setTextureAttributeAndModes(0,osg_texture,osg::StateAttribute::ON); 
    269                          
    270                         textureMap[omtl->textureName] = osg_texture; 
    271  
    272                         // Adjust the texture matrix if necessary 
    273                         bool needsUVScaling = (1.0 != omtl->textureUScale) || (1.0 != omtl->textureVScale); 
    274                         bool needsUVOffsetting = (0.0 != omtl->textureUOffset) || (0.0 != omtl->textureVOffset); 
    275  
    276                         if (needsUVScaling || needsUVOffsetting) 
    277                         { 
    278                             osg::TexMat* osg_texmat = new osg::TexMat; 
    279  
    280                             osg::Matrix scale; 
    281                             osg::Matrix translate; 
    282                             scale.makeIdentity(); 
    283                             translate.makeIdentity(); 
    284  
    285                             if (needsUVScaling) 
    286                             { 
    287                                 scale.makeScale(omtl->textureUScale, omtl->textureVScale, 1.0f); 
    288                             } 
    289  
    290                             if (needsUVOffsetting) 
    291                             { 
    292                                 translate.makeTranslate(omtl->textureUOffset, omtl->textureVOffset, 0.0f); 
    293                             } 
    294  
    295                             osg_texmat->setMatrix(scale * translate); 
    296                             stateset->setTextureAttributeAndModes(0,osg_texmat,osg::StateAttribute::ON); 
    297                         } 
    298                     } 
    299                     else 
    300                     { 
    301                         osg::notify(osg::NOTICE) << "Warning: Cannot create texture "<<omtl->textureName<< std::endl; 
    302                     } 
    303                 } 
    304                 else 
    305                 { 
    306                     osg::notify(osg::WARN) << "texture '"<<omtl->textureName<<"' not found"<< std::endl; 
    307                 } 
    308                  
    309             } 
    310             else 
    311             { 
    312                 stateset->setTextureAttributeAndModes(0,titr->second.get(),osg::StateAttribute::ON); 
    313             } 
    314         } 
     414     
     415     
     416    std::ifstream fin(fileName.c_str()); 
     417    if (fin) 
     418    { 
     419        obj::Model model; 
     420        model.readOBJ(fin); 
    315421         
    316         if (omtl->textureReflection) 
    317         { 
    318             stateset->setTextureAttributeAndModes(0,osg_texgen.get(),osg::StateAttribute::ON); 
    319         } 
    320          
    321         StateSetSet::iterator sitr = statesetSet.find(stateset); 
    322         if (sitr==statesetSet.end()) 
    323         { 
    324             osg_mtl[i] = stateset; 
    325             statesetSet.insert(stateset); 
    326         } 
    327         else 
    328         { 
    329             osg_mtl[i] = *sitr; 
    330         }         
    331     } 
    332  
    333     // toplevel group or transform 
    334     osg::Group* osg_top = NULL; 
    335     if (obj->position[0] != 0.0f || obj->position[1] != 0.0f || obj->position[2] != 0.0f) { 
    336         osg::MatrixTransform* xform = new osg::MatrixTransform; 
    337         // note obj_x -> osg_x, 
    338         //      obj_y -> osg_z, 
    339         //      obj_z -> osg_y, 
    340         xform->setMatrix(osg::Matrix::translate(obj->position[0], -obj->position[2], obj->position[1])); 
    341         osg_top = xform; 
    342     } 
    343     else 
    344         osg_top = new osg::Group; 
    345  
    346     osg_top->setName(obj->pathname); 
    347  
    348     DrawableMode drawableMode = USE_SEPERATE_INDICES; 
    349 //    DrawableMode drawableMode = DUPLICATE_COORDS; 
    350  
    351     // subgroups 
    352     // XXX one Geode per group is probably not necessary... 
    353     GLMgroup* ogrp = obj->groups; 
    354     while (ogrp) { 
    355         if (ogrp->numtriangles > 0) { 
    356  
    357             osg::Geode* osg_geo = new osg::Geode; 
    358             osg_geo->setName(ogrp->name); 
    359             osg::Drawable* drawable = makeDrawable(drawableMode,obj,ogrp); 
    360              
    361             // state and material (if any) 
    362             if (!osg_mtl.empty()) { 
    363              
    364                 osg::notify(osg::NOTICE)<<"ogrp->material="<<ogrp->material<<std::endl; 
    365              
    366                 drawable->setStateSet(osg_mtl[ogrp->material].get()); 
    367             } 
    368  
    369             osg_geo->addDrawable(drawable); 
    370             osg_top->addChild(osg_geo); 
    371         } 
    372         ogrp = ogrp->next; 
    373     } 
    374  
    375     // free 
    376     glmDelete(obj); 
    377  
    378     return osg_top; 
     422        osg::Node* node = convertModelToSceneGraph(model); 
     423        return node; 
     424    } 
     425     
     426    return ReadResult::FILE_NOT_HANDLED; 
    379427} 
    380428 
    381 osg::Drawable* ReaderWriterOBJ::makeDrawable(DrawableMode drawableMode, GLMmodel* obj, GLMgroup* grp) 
    382 { 
    383     switch(drawableMode) 
    384     { 
    385     case(DUPLICATE_COORDS): return makeDrawable_duplicateCoords(obj,grp); 
    386     case(USE_SEPERATE_INDICES): return makeDrawable_useSeperateIndices(obj,grp); 
    387     } 
    388     return 0; 
    389 } 
    390  
    391 // make drawable from OBJ group 
    392 osg::Drawable* ReaderWriterOBJ::makeDrawable_duplicateCoords(GLMmodel* obj, GLMgroup* grp) 
    393 { 
    394  
    395     GLMtriangle* tris = obj->triangles; 
    396  
    397     unsigned int ntris = grp->numtriangles; 
    398     unsigned int i = 0; 
    399  
    400     // geometry 
    401     osg::Geometry* geom = new osg::Geometry; 
    402      
    403     geom->setUseDisplayList(false); 
    404     // geom->setUseVertexBufferObjects(true); 
    405  
    406     // primitives are only triangles 
    407     geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,0,ntris*3)); 
    408  
    409     // the following code for mapping the coords, normals and texcoords 
    410     // is complicated greatly by the need to create separate out the 
    411     // sets of coords etc for each drawable. 
    412  
    413     bool needColors = obj->useColors && obj->colors; 
    414     bool needNormals = obj->normals && obj->normals; 
    415     bool needTexcoords = obj->texcoords && obj->numtexcoords>0 && grp->hastexcoords; 
    416      
    417      
    418     osg::Vec3Array* coordArray = new osg::Vec3Array(3*ntris); 
    419      
    420     osg::Vec3Array::iterator coords = coordArray->begin(); 
    421     geom->setVertexArray(coordArray); 
    422      
    423     osg::UByte4Array::iterator colors = osg::UByte4Array::iterator();// dummy assignment to get round stupid compiler warnings. 
    424     if (needColors) 
    425     { 
    426         osg::UByte4Array* colorArray = new osg::UByte4Array(3*ntris); 
    427         geom->setColorArray(colorArray); 
    428         geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX); 
    429         colors = colorArray->begin(); 
    430     } 
    431  
    432  
    433     osg::Vec3Array::iterator normals = osg::Vec3Array::iterator();// dummy assignment to get round stupid compiler warnings. 
    434     if (needNormals) 
    435     { 
    436         osg::Vec3Array* normalArray = new osg::Vec3Array(3*ntris); 
    437         geom->setNormalArray(normalArray); 
    438         geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); 
    439         normals = normalArray->begin(); 
    440     } 
    441  
    442     osg::Vec2Array::iterator texcoords = osg::Vec2Array::iterator(); // dummy assignment to get round stupid compiler warnings. 
    443     if (needTexcoords) 
    444     { 
    445         osg::Vec2Array* texCoordArray = new osg::Vec2Array(3*ntris); 
    446         geom->setTexCoordArray(0,texCoordArray); 
    447          
    448         texcoords = texCoordArray->begin(); 
    449     } 
    450  
    451     // first count the number of vertices used in this group. 
    452     for (i = 0; i < ntris; i++) 
    453     { 
    454         GLMtriangle* tri = &(tris[grp->triangles[i]]); 
    455          
    456         for(int corner=0;corner<3;++corner) 
    457         { 
    458             int ci = tri->vindices[corner]*3; 
    459  
    460             // note rotate about the x axis to place the OBJ y up to OSG z up. 
    461             coords->set(obj->vertices[ci],-obj->vertices[ci+2],obj->vertices[ci+1]); 
    462             ++coords; 
    463              
    464             if (needColors) 
    465             { 
    466                 (*colors) = obj->colors[tri->vindices[corner]]; 
    467                 ++colors; 
    468             } 
    469  
    470             if (needNormals) 
    471             { 
    472                 int ni = tri->nindices[corner]*3; 
    473  
    474                 // note rotate about the x axis to place the OBJ y up to OSG z up. 
    475                 normals->set(obj->normals[ni],-obj->normals[ni+2],obj->normals[ni+1]); 
    476                 ++normals; 
    477             } 
    478  
    479             if (needTexcoords) 
    480             { 
    481                 int ti = tri->tindices[corner]*2; 
    482                 texcoords->set(obj->texcoords[ti+0], obj->texcoords[ti+1]); 
    483                 ++texcoords; 
    484             } 
    485         } 
    486     } 
    487  
    488     return geom; 
    489 } 
    490  
    491 osg::Drawable* ReaderWriterOBJ::makeDrawable_useSeperateIndices(GLMmodel* obj, GLMgroup* grp) 
    492 { 
    493  
    494     GLMtriangle* tris = obj->triangles; 
    495  
    496     unsigned int ntris = grp->numtriangles; 
    497     unsigned int i = 0; 
    498  
    499     // geometry 
    500     osg::Geometry* geom = new osg::Geometry; 
    501      
    502     // geom->setUseDisplayList(false); 
    503     // geom->setUseVertexBufferObjects(true); 
    504  
    505     // the following code for mapping the coords, normals and texcoords 
    506     // is complicated greatly by the need to create separate out the 
    507     // sets of coords etc for each drawable. 
    508  
    509     bool needColors = obj->useColors && obj->colors; 
    510     bool needNormals = obj->normals && obj->normals; 
    511     bool needTexcoords = obj->texcoords && obj->numtexcoords>0 && grp->hastexcoords; 
    512      
    513  
    514 //    needNormals = false;     
    515      
    516     IndexMap vertexIndexMap; 
    517     IndexMap normalIndexMap; 
    518     IndexMap texcoordIndexMap; 
    519         
    520     // find maxium value. 
    521     for (i = 0; i < ntris; i++) 
    522     { 
    523         GLMtriangle& tri = tris[grp->triangles[i]]; 
    524         for(int corner=0;corner<3;++corner) 
    525         { 
    526             vertexIndexMap.updateMaximum(tri.vindices[corner]); 
    527             if (needNormals) normalIndexMap.updateMaximum(tri.nindices[corner]); 
    528             if (needTexcoords) texcoordIndexMap.updateMaximum(tri.tindices[corner]); 
    529  
    530         } 
    531     } 
    532      
    533      
    534     // intialialize map. 
    535     vertexIndexMap.initialize(); 
    536     if (needNormals) normalIndexMap.initialize(); 
    537     if (needTexcoords) texcoordIndexMap.initialize(); 
    538      
    539     // populate map. 
    540     for (i = 0; i < ntris; i++) 
    541     { 
    542         GLMtriangle& tri = tris[grp->triangles[i]]; 
    543         for(int corner=0;corner<3;++corner) 
    544         { 
    545             vertexIndexMap.insertIndex(tri.vindices[corner]); 
    546             if (needNormals) normalIndexMap.insertIndex(tri.nindices[corner]); 
    547             if (needTexcoords) texcoordIndexMap.insertIndex(tri.tindices[corner]); 
    548         } 
    549     } 
    550  
    551     // copy data across to geometry. 
    552     geom->setVertexArray(vertexIndexMap.createVec3Array(obj->vertices)); 
    553      
    554     if (needColors) 
    555     { 
    556         geom->setColorArray(vertexIndexMap.createUByte4Array(obj->colors)); 
    557         geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX); 
    558     } 
    559  
    560     if (needNormals) 
    561     { 
    562         geom->setNormalArray(normalIndexMap.createVec3Array(obj->normals)); 
    563         geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); 
    564     } 
    565  
    566     if (needTexcoords) 
    567     { 
    568         geom->setTexCoordArray(0,texcoordIndexMap.createVec2Array(obj->texcoords)); 
    569     } 
    570      
    571      
    572     osg::ref_ptr<osg::UIntArray> vertexIndices = new osg::UIntArray(ntris*3); 
    573     osg::ref_ptr<osg::UIntArray> normalIndices = needNormals ? new osg::UIntArray(ntris*3) : 0; 
    574     osg::ref_ptr<osg::UIntArray> texcoordIndices = needTexcoords ? new osg::UIntArray(ntris*3) : 0; 
    575      
    576     int vi=0; 
    577     for (i = 0; i < ntris; i++) 
    578     { 
    579         GLMtriangle& tri = (tris[grp->triangles[i]]); 
    580          
    581         for(int corner=0;corner<3;++corner,++vi) 
    582         { 
    583             (*vertexIndices)[vi] = vertexIndexMap.index(tri.vindices[corner]); 
    584  
    585             if (needNormals) 
    586             { 
    587                 (*normalIndices)[vi] = normalIndexMap.index(tri.nindices[corner]); 
    588             } 
    589  
    590             if (needTexcoords) 
    591             { 
    592                 (*texcoordIndices)[vi] = texcoordIndexMap.index(tri.tindices[corner]); 
    593             } 
    594         } 
    595     } 
    596      
    597     bool indexArraysEqual=true; 
    598     if (needNormals) indexArraysEqual=(*vertexIndices==*normalIndices); 
    599     if (indexArraysEqual && needTexcoords) indexArraysEqual=(*vertexIndices==*texcoordIndices); 
    600  
    601     if (indexArraysEqual) 
    602     { 
    603         geom->addPrimitiveSet(new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES,vertexIndices->begin(),vertexIndices->end())); 
    604     } 
    605     else 
    606     { 
    607         geom->setVertexIndices(vertexIndices.get()); 
    608         if (needColors) geom->setColorIndices(vertexIndices.get()); 
    609         if (needNormals) geom->setNormalIndices(normalIndices.get()); 
    610         if (needTexcoords) geom->setTexCoordIndices(0,texcoordIndices.get()); 
    611  
    612         // primitives are only triangles 
    613         geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,0,ntris*3)); 
    614  
    615     } 
    616 #if 0 
    617     osgUtil::TriStripVisitor tsv; 
    618     tsv.stripify(*geom); 
    619 #endif 
    620  
    621     if (obj->numnormals==0) 
    622     { 
    623         osgUtil::SmoothingVisitor tsv; 
    624         tsv.smooth(*geom); 
    625     } 
    626     return geom; 
    627 }