Hi Robert, The obj loader was overriding the existing database path list with the file path of the model, instead of prepending the file path to the path list. The latter seems to be more common behavior for most of the existing loader plugins. Also, the local options weren't actually being used when processing the scene graph for textures. I've attached the fix for both issues.
Cheers, Farshid
// -*-c++-*- /* * Wavefront OBJ loader for Open Scene Graph * * Copyright (C) 2001,2007 Ulrich Hertlein <[email protected]> * * Modified by Robert Osfield to support per Drawable coord, normal and * texture coord arrays, bug fixes, and support for texture mapping. * * Writing support added 2007 by Stephan Huber, http://digitalmind.de, * some ideas taken from the dae-plugin * * The Open Scene Graph (OSG) is a cross platform C++/OpenGL library for * real-time rendering of large 3D photo-realistic models. * The OSG homepage is http://www.openscenegraph.org/ */ #if defined(_MSC_VER) #pragma warning( disable : 4786 ) #endif #include <stdlib.h> #include <string> #include <osg/Notify> #include <osg/Node> #include <osg/MatrixTransform> #include <osg/Geode> #include <osg/Vec3f> #include <osg/Geometry> #include <osg/StateSet> #include <osg/Material> #include <osg/Texture2D> #include <osg/TexGen> #include <osg/TexMat> #include <osgDB/Registry> #include <osgDB/ReadFile> #include <osgDB/FileUtils> #include <osgDB/FileNameUtils> #include <osgUtil/TriStripVisitor> #include <osgUtil/SmoothingVisitor> #include <osgUtil/Tessellator> #include "obj.h" #include "OBJWriterNodeVisitor.h" #include <map> #include <set> class ReaderWriterOBJ : public osgDB::ReaderWriter { public: ReaderWriterOBJ() { supportsExtension("obj","Alias Wavefront OBJ format"); supportsOption("noRotation","Do not do the default rotate about X axis"); supportsOption("noTesselateLargePolygons","Do not do the default tesselation of large polygons"); supportsOption("noTriStripPolygons","Do not do the default tri stripping of polygons"); supportsOption("generateFacetNormals","generate facet normals for verticies without normals"); supportsOption("DIFFUSE=<unit>", "Set texture unit for diffuse texture"); supportsOption("AMBIENT=<unit>", "Set texture unit for ambient texture"); supportsOption("SPECULAR=<unit>", "Set texture unit for specular texture"); supportsOption("SPECULAR_EXPONENT=<unit>", "Set texture unit for specular exponent texture"); supportsOption("OPACITY=<unit>", "Set texture unit for opacity/dissolve texture"); supportsOption("BUMP=<unit>", "Set texture unit for bumpmap texture"); supportsOption("DISPLACEMENT=<unit>", "Set texture unit for displacement texture"); supportsOption("REFLECTION=<unit>", "Set texture unit for reflection texture"); } virtual const char* className() const { return "Wavefront OBJ Reader"; } virtual ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* options) const; virtual ReadResult readNode(std::istream& fin, const Options* options) const; virtual WriteResult writeObject(const osg::Object& obj,const std::string& fileName,const Options* options=NULL) const { const osg::Node* node = dynamic_cast<const osg::Node*>(&obj); if (node) return writeNode(*node, fileName, options); else return WriteResult(WriteResult::FILE_NOT_HANDLED); } virtual WriteResult writeNode(const osg::Node& node,const std::string& fileName,const Options* options =NULL) const { if (!acceptsExtension(osgDB::getFileExtension(fileName))) return WriteResult(WriteResult::FILE_NOT_HANDLED); osgDB::ofstream f(fileName.c_str()); std::string materialFile = osgDB::getNameLessExtension(fileName) + ".mtl"; OBJWriterNodeVisitor nv(f, osgDB::getSimpleFileName(materialFile)); // we must cast away constness (const_cast<osg::Node*>(&node))->accept(nv); osgDB::ofstream mf(materialFile.c_str()); nv.writeMaterials(mf); return WriteResult(WriteResult::FILE_SAVED); } virtual WriteResult writeObject(const osg::Object& obj,std::ostream& fout,const Options* options=NULL) const { const osg::Node* node = dynamic_cast<const osg::Node*>(&obj); if (node) return writeNode(*node, fout, options); else return WriteResult(WriteResult::FILE_NOT_HANDLED); } virtual WriteResult writeNode(const osg::Node& node,std::ostream& fout,const Options* =NULL) const { // writing to a stream does not support materials OBJWriterNodeVisitor nv(fout); // we must cast away constness (const_cast<osg::Node*>(&node))->accept(nv); return WriteResult(WriteResult::FILE_SAVED); } protected: struct ObjOptionsStruct { bool rotate; bool noTesselateLargePolygons; bool noTriStripPolygons; bool generateFacetNormals; bool fixBlackMaterials; // This is the order in which the materials will be assigned to texture maps, unless // otherwise overriden typedef std::vector< std::pair<int,obj::Material::Map::TextureMapType> > TextureAllocationMap; TextureAllocationMap textureUnitAllocation; }; typedef std::map< std::string, osg::ref_ptr<osg::StateSet> > MaterialToStateSetMap; void buildMaterialToStateSetMap(obj::Model& model, MaterialToStateSetMap& materialToSetSetMapObj, ObjOptionsStruct& localOptions, const Options* options) const; osg::Geometry* convertElementListToGeometry(obj::Model& model, obj::Model::ElementList& elementList, ObjOptionsStruct& localOptions) const; osg::Node* convertModelToSceneGraph(obj::Model& model, ObjOptionsStruct& localOptions, const Options* options) const; inline osg::Vec3 transformVertex(const osg::Vec3& vec, const bool rotate) const ; inline osg::Vec3 transformNormal(const osg::Vec3& vec, const bool rotate) const ; ObjOptionsStruct parseOptions(const Options* options) const; }; inline osg::Vec3 ReaderWriterOBJ::transformVertex(const osg::Vec3& vec, const bool rotate) const { if(rotate==true) { return osg::Vec3(vec.x(),-vec.z(),vec.y()); } else { return vec; } } inline osg::Vec3 ReaderWriterOBJ::transformNormal(const osg::Vec3& vec, const bool rotate) const { if(rotate==true) { return osg::Vec3(vec.x(),-vec.z(),vec.y()); } else { return vec; } } // register with Registry to instantiate the above reader/writer. REGISTER_OSGPLUGIN(obj, ReaderWriterOBJ) static void load_material_texture( obj::Model &model, obj::Material::Map &map, osg::StateSet *stateset, const unsigned int texture_unit, const osgDB::Options* options) { std::string filename = map.name; if (!filename.empty()) { osg::ref_ptr< osg::Image > image; if ( !model.getDatabasePath().empty() ) { // first try with database path of parent. image = osgDB::readRefImageFile(model.getDatabasePath()+'/'+filename, options); } if ( !image.valid() ) { // if not already set then try the filename as is. image = osgDB::readRefImageFile(filename, options); } if ( image.valid() ) { osg::Texture2D* texture = new osg::Texture2D( image.get() ); osg::Texture::WrapMode textureWrapMode; if(map.clamp == true) { textureWrapMode = osg::Texture::CLAMP_TO_BORDER; texture->setBorderColor(osg::Vec4(0.0,0.0,0.0,0.0)); // transparent //stateset->setMode(GL_BLEND, osg::StateAttribute::ON); //stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); } else { textureWrapMode = osg::Texture::REPEAT; } texture->setWrap(osg::Texture2D::WRAP_R, textureWrapMode); texture->setWrap(osg::Texture2D::WRAP_S, textureWrapMode); texture->setWrap(osg::Texture2D::WRAP_T, textureWrapMode); stateset->setTextureAttributeAndModes( texture_unit, texture,osg::StateAttribute::ON ); if ( map.type == obj::Material::Map::REFLECTION ) { osg::TexGen* texgen = new osg::TexGen; texgen->setMode(osg::TexGen::SPHERE_MAP); stateset->setTextureAttributeAndModes( texture_unit,texgen,osg::StateAttribute::ON ); } if ( image->isImageTranslucent()) { OSG_INFO<<"Found transparent image"<<std::endl; stateset->setMode(GL_BLEND, osg::StateAttribute::ON); stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); } } } if (map.uScale != 1.0f || map.vScale != 1.0f || map.uOffset != 0.0f || map.vOffset != 0.0f) { osg::Matrix mat; if (map.uScale != 1.0f || map.vScale != 1.0f) { OSG_DEBUG << "Obj TexMat scale=" << map.uScale << "," << map.vScale << std::endl; mat *= osg::Matrix::scale(map.uScale, map.vScale, 1.0); } if (map.uOffset != 0.0f || map.vOffset != 0.0f) { OSG_DEBUG << "Obj TexMat offset=" << map.uOffset << "," << map.uOffset << std::endl; mat *= osg::Matrix::translate(map.uOffset, map.vOffset, 0.0); } osg::TexMat* texmat = new osg::TexMat; texmat->setMatrix(mat); stateset->setTextureAttributeAndModes( texture_unit,texmat,osg::StateAttribute::ON ); } } void ReaderWriterOBJ::buildMaterialToStateSetMap(obj::Model& model, MaterialToStateSetMap& materialToStateSetMap, ObjOptionsStruct& localOptions, const Options* options) const { if (localOptions.fixBlackMaterials) { // hack to fix Maya exported models that contian all black materials. int numBlack = 0; int numNotBlack = 0; obj::Model::MaterialMap::iterator itr; for(itr = model.materialMap.begin(); itr != model.materialMap.end(); ++itr) { obj::Material& material = itr->second; if (material.ambient==osg::Vec4(0.0f,0.0f,0.0f,1.0f) && material.diffuse==osg::Vec4(0.0f,0.0f,0.0f,1.0f)) { ++numBlack; } else { ++numNotBlack; } } if (numNotBlack==0 && numBlack!=0) { for(itr = model.materialMap.begin(); itr != model.materialMap.end(); ++itr) { obj::Material& material = itr->second; if (material.ambient==osg::Vec4(0.0f,0.0f,0.0f,1.0f) && material.diffuse==osg::Vec4(0.0f,0.0f,0.0f,1.0f)) { material.ambient.set(0.3f,0.3f,0.3f,1.0f); material.diffuse.set(1.0f,1.0f,1.0f,1.0f); } } } } for(obj::Model::MaterialMap::iterator itr = model.materialMap.begin(); itr != model.materialMap.end(); ++itr) { obj::Material& material = itr->second; osg::ref_ptr< osg::StateSet > stateset = new osg::StateSet; bool isTransparent = false; // handle material colors // http://java3d.j3d.org/utilities/loaders/obj/sun.html if (material.illum != 0) { osg::Material* osg_material = new osg::Material; stateset->setAttribute(osg_material); osg_material->setName(material.name); osg_material->setAmbient(osg::Material::FRONT_AND_BACK,material.ambient); osg_material->setDiffuse(osg::Material::FRONT_AND_BACK,material.diffuse); osg_material->setEmission(osg::Material::FRONT_AND_BACK,material.emissive); if (material.illum == 2) { osg_material->setSpecular(osg::Material::FRONT_AND_BACK,material.specular); } else { osg_material->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(0,0,0,1)); } osg_material->setShininess(osg::Material::FRONT_AND_BACK,(material.Ns/1000.0f)*128.0f ); // note OBJ shiniess is 0..1000. if (material.ambient[3]!=1.0 || material.diffuse[3]!=1.0 || material.specular[3]!=1.0|| material.emissive[3]!=1.0) { OSG_INFO<<"Found transparent material"<<std::endl; isTransparent = true; } } // If the user has explicitly set the required texture type to unit map via the options // string, then we load ONLY those textures that are in the map. if(localOptions.textureUnitAllocation.size()>0) { for(unsigned int i=0;i<localOptions.textureUnitAllocation.size();i++) { // firstly, get the option set pair int unit = localOptions.textureUnitAllocation[i].first; obj::Material::Map::TextureMapType type = localOptions.textureUnitAllocation[i].second; // secondly, see if this texture type (e.g. DIFFUSE) is one of those in the material int index = -1; for(unsigned int j=0;j<material.maps.size();j++) { if(material.maps[j].type == type) { index = (int) j; break; } } if(index>=0) load_material_texture( model, material.maps[index], stateset.get(), unit, options ); } } // If the user has set no options, then we load them up in the order contained in the enum. This // latter method is an attempt not to break user's existing code else { int unit = 0; for(int i=0;i<(int) obj::Material::Map::UNKNOWN;i++) // for each type { obj::Material::Map::TextureMapType type = (obj::Material::Map::TextureMapType) i; // see if this texture type (e.g. DIFFUSE) is one of those in the material int index = -1; for(unsigned int j=0;j<material.maps.size();j++) { if(material.maps[j].type == type) { index = (int) j; break; } } if(index>=0) { load_material_texture( model, material.maps[index], stateset.get(), unit, options ); unit++; } } } if (isTransparent) { stateset->setMode(GL_BLEND, osg::StateAttribute::ON); stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); } materialToStateSetMap[material.name] = stateset.get(); } } osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model, obj::Model::ElementList& elementList, ObjOptionsStruct& localOptions) const { unsigned int numVertexIndices = 0; unsigned int numNormalIndices = 0; unsigned int numTexCoordIndices = 0; unsigned int numPointElements = 0; unsigned int numPolylineElements = 0; unsigned int numPolygonElements = 0; obj::Model::ElementList::iterator itr; if (localOptions.generateFacetNormals == true) { for(itr=elementList.begin(); itr!=elementList.end(); ++itr) { obj::Element& element = *(*itr); if (element.dataType==obj::Element::POINTS || element.dataType==obj::Element::POLYLINE) continue; if (element.normalIndices.size() == 0) { // fill in the normals int a = element.vertexIndices[0]; int b = element.vertexIndices[1]; int c = element.vertexIndices[2]; osg::Vec3f ab(model.vertices[b]); osg::Vec3f ac(model.vertices[c]); ab -= model.vertices[a]; ac -= model.vertices[a]; osg::Vec3f Norm( ab ^ ac ); Norm.normalize(); int normal_idx = model.normals.size(); model.normals.push_back(Norm); for (unsigned i=0 ; i < element.vertexIndices.size() ; i++) element.normalIndices.push_back(normal_idx); } } } for(itr=elementList.begin(); itr!=elementList.end(); ++itr) { obj::Element& element = *(*itr); numVertexIndices += element.vertexIndices.size(); numNormalIndices += element.normalIndices.size(); numTexCoordIndices += element.texCoordIndices.size(); numPointElements += (element.dataType==obj::Element::POINTS) ? 1 : 0; numPolylineElements += (element.dataType==obj::Element::POLYLINE) ? 1 : 0; numPolygonElements += (element.dataType==obj::Element::POLYGON) ? 1 : 0; } if (numVertexIndices==0) return 0; if (numNormalIndices!=0 && numNormalIndices!=numVertexIndices) { OSG_NOTICE<<"Incorrect number of normals, ignore them"<<std::endl; numNormalIndices = 0; } if (numTexCoordIndices!=0 && numTexCoordIndices!=numVertexIndices) { OSG_NOTICE<<"Incorrect number of normals, ignore them"<<std::endl; numTexCoordIndices = 0; } osg::Vec3Array* vertices = numVertexIndices ? new osg::Vec3Array : 0; osg::Vec3Array* normals = numNormalIndices ? new osg::Vec3Array : 0; osg::Vec2Array* texcoords = numTexCoordIndices ? new osg::Vec2Array : 0; if (vertices) vertices->reserve(numVertexIndices); if (normals) normals->reserve(numNormalIndices); if (texcoords) texcoords->reserve(numTexCoordIndices); osg::Geometry* geometry = new osg::Geometry; if (vertices) geometry->setVertexArray(vertices); if (normals) { geometry->setNormalArray(normals, osg::Array::BIND_PER_VERTEX); } if (texcoords) { geometry->setTexCoordArray(0,texcoords); } if (numPointElements>0) { unsigned int startPos = vertices->size(); unsigned int numPoints = 0; for(itr=elementList.begin(); itr!=elementList.end(); ++itr) { obj::Element& element = *(*itr); if (element.dataType==obj::Element::POINTS) { for(obj::Element::IndexList::iterator index_itr = element.vertexIndices.begin(); index_itr != element.vertexIndices.end(); ++index_itr) { vertices->push_back(transformVertex(model.vertices[*index_itr],localOptions.rotate)); ++numPoints; } if (numNormalIndices) { for(obj::Element::IndexList::iterator index_itr = element.normalIndices.begin(); index_itr != element.normalIndices.end(); ++index_itr) { normals->push_back(transformNormal(model.normals[*index_itr],localOptions.rotate)); } } if (numTexCoordIndices) { for(obj::Element::IndexList::iterator index_itr = element.texCoordIndices.begin(); index_itr != element.texCoordIndices.end(); ++index_itr) { texcoords->push_back(model.texcoords[*index_itr]); } } } } osg::DrawArrays* drawArrays = new osg::DrawArrays(GL_POINTS,startPos,numPoints); geometry->addPrimitiveSet(drawArrays); } if (numPolylineElements>0) { unsigned int startPos = vertices->size(); osg::DrawArrayLengths* drawArrayLengths = new osg::DrawArrayLengths(GL_LINES,startPos); for(itr=elementList.begin(); itr!=elementList.end(); ++itr) { obj::Element& element = *(*itr); if (element.dataType==obj::Element::POLYLINE) { drawArrayLengths->push_back(element.vertexIndices.size()); for(obj::Element::IndexList::iterator index_itr = element.vertexIndices.begin(); index_itr != element.vertexIndices.end(); ++index_itr) { vertices->push_back(transformVertex(model.vertices[*index_itr],localOptions.rotate)); } if (numNormalIndices) { for(obj::Element::IndexList::iterator index_itr = element.normalIndices.begin(); index_itr != element.normalIndices.end(); ++index_itr) { normals->push_back(transformNormal(model.normals[*index_itr],localOptions.rotate)); } } if (numTexCoordIndices) { for(obj::Element::IndexList::iterator index_itr = element.texCoordIndices.begin(); index_itr != element.texCoordIndices.end(); ++index_itr) { texcoords->push_back(model.texcoords[*index_itr]); } } } } geometry->addPrimitiveSet(drawArrayLengths); } // #define USE_DRAWARRAYLENGTHS if (numPolygonElements>0) { unsigned int startPos = vertices->size(); #ifdef USE_DRAWARRAYLENGTHS osg::DrawArrayLengths* drawArrayLengths = new osg::DrawArrayLengths(GL_POLYGON,startPos); geometry->addPrimitiveSet(drawArrayLengths); #endif for(itr=elementList.begin(); itr!=elementList.end(); ++itr) { obj::Element& element = *(*itr); if (element.dataType==obj::Element::POLYGON) { #ifdef USE_DRAWARRAYLENGTHS drawArrayLengths->push_back(element.vertexIndices.size()); #else if (element.vertexIndices.size()>4) { osg::DrawArrays* drawArrays = new osg::DrawArrays(GL_POLYGON,startPos,element.vertexIndices.size()); startPos += element.vertexIndices.size(); geometry->addPrimitiveSet(drawArrays); } else { osg::DrawArrays* drawArrays = new osg::DrawArrays(GL_TRIANGLE_FAN,startPos,element.vertexIndices.size()); startPos += element.vertexIndices.size(); geometry->addPrimitiveSet(drawArrays); } #endif if (model.needReverse(element)) { // need to reverse so add to OSG arrays in same order as in OBJ, as OSG assume anticlockwise ordering. for(obj::Element::IndexList::reverse_iterator index_itr = element.vertexIndices.rbegin(); index_itr != element.vertexIndices.rend(); ++index_itr) { vertices->push_back(transformVertex(model.vertices[*index_itr],localOptions.rotate)); } if (numNormalIndices) { for(obj::Element::IndexList::reverse_iterator index_itr = element.normalIndices.rbegin(); index_itr != element.normalIndices.rend(); ++index_itr) { normals->push_back(transformNormal(model.normals[*index_itr],localOptions.rotate)); } } if (numTexCoordIndices) { for(obj::Element::IndexList::reverse_iterator index_itr = element.texCoordIndices.rbegin(); index_itr != element.texCoordIndices.rend(); ++index_itr) { texcoords->push_back(model.texcoords[*index_itr]); } } } else { // no need to reverse so add to OSG arrays in same order as in OBJ. for(obj::Element::IndexList::iterator index_itr = element.vertexIndices.begin(); index_itr != element.vertexIndices.end(); ++index_itr) { vertices->push_back(transformVertex(model.vertices[*index_itr],localOptions.rotate)); } if (numNormalIndices) { for(obj::Element::IndexList::iterator index_itr = element.normalIndices.begin(); index_itr != element.normalIndices.end(); ++index_itr) { normals->push_back(transformNormal(model.normals[*index_itr],localOptions.rotate)); } } if (numTexCoordIndices) { for(obj::Element::IndexList::iterator index_itr = element.texCoordIndices.begin(); index_itr != element.texCoordIndices.end(); ++index_itr) { texcoords->push_back(model.texcoords[*index_itr]); } } } } } } return geometry; } osg::Node* ReaderWriterOBJ::convertModelToSceneGraph(obj::Model& model, ObjOptionsStruct& localOptions, const Options* options) const { if (model.elementStateMap.empty()) return 0; osg::Group* group = new osg::Group; // set up the materials MaterialToStateSetMap materialToStateSetMap; buildMaterialToStateSetMap(model, materialToStateSetMap, localOptions, options); // go through the groups of related elements and build geometry from them. for(obj::Model::ElementStateMap::iterator itr=model.elementStateMap.begin(); itr!=model.elementStateMap.end(); ++itr) { const obj::ElementState& es = itr->first; obj::Model::ElementList& el = itr->second; osg::Geometry* geometry = convertElementListToGeometry(model,el,localOptions); if (geometry) { MaterialToStateSetMap::const_iterator it = materialToStateSetMap.find(es.materialName); if (it == materialToStateSetMap.end()) { OSG_WARN << "Obj unable to find material '" << es.materialName << "'" << std::endl; } osg::StateSet* stateset = materialToStateSetMap[es.materialName].get(); geometry->setStateSet(stateset); // tesseleate any large polygons if (!localOptions.noTesselateLargePolygons) { osgUtil::Tessellator tessellator; tessellator.retessellatePolygons(*geometry); } // tri strip polygons to improve graphics peformance if (!localOptions.noTriStripPolygons) { osgUtil::TriStripVisitor tsv; tsv.stripify(*geometry); } // if no normals present add them. if (localOptions.generateFacetNormals==false && (!geometry->getNormalArray() || geometry->getNormalArray()->getNumElements()==0)) { osgUtil::SmoothingVisitor sv; sv.smooth(*geometry); } osg::Geode* geode = new osg::Geode; geode->addDrawable(geometry); if (es.objectName.empty()) { geode->setName(es.groupName); } else if (es.groupName.empty()) { geode->setName(es.objectName); } else { geode->setName(es.groupName + std::string(":") + es.objectName); } group->addChild(geode); } } return group; } ReaderWriterOBJ::ObjOptionsStruct ReaderWriterOBJ::parseOptions(const osgDB::ReaderWriter::Options* options) const { ObjOptionsStruct localOptions; localOptions.rotate = true; localOptions.noTesselateLargePolygons = false; localOptions.noTriStripPolygons = false; localOptions.generateFacetNormals = false; localOptions.fixBlackMaterials = true; if (options!=NULL) { std::istringstream iss(options->getOptionString()); std::string opt; while (iss >> opt) { // split opt into pre= and post= std::string pre_equals; std::string post_equals; size_t found = opt.find("="); if(found!=std::string::npos) { pre_equals = opt.substr(0,found); post_equals = opt.substr(found+1); } else { pre_equals = opt; } if (pre_equals == "noRotation") { localOptions.rotate = false; } else if (pre_equals == "noTesselateLargePolygons") { localOptions.noTesselateLargePolygons = true; } else if (pre_equals == "noTriStripPolygons") { localOptions.noTriStripPolygons = true; } else if (pre_equals == "generateFacetNormals") { localOptions.generateFacetNormals = true; } else if (post_equals.length()>0) { obj::Material::Map::TextureMapType type = obj::Material::Map::UNKNOWN; // Now we check to see if we have anything forcing a texture allocation if (pre_equals == "DIFFUSE") type = obj::Material::Map::DIFFUSE; else if (pre_equals == "AMBIENT") type = obj::Material::Map::AMBIENT; else if (pre_equals == "SPECULAR") type = obj::Material::Map::SPECULAR; else if (pre_equals == "SPECULAR_EXPONENT") type = obj::Material::Map::SPECULAR_EXPONENT; else if (pre_equals == "OPACITY") type = obj::Material::Map::OPACITY; else if (pre_equals == "BUMP") type = obj::Material::Map::BUMP; else if (pre_equals == "DISPLACEMENT") type = obj::Material::Map::DISPLACEMENT; else if (pre_equals == "REFLECTION") type = obj::Material::Map::REFLECTION; if (type!=obj::Material::Map::UNKNOWN) { int unit = atoi(post_equals.c_str()); // (probably should use istringstream rather than atoi) localOptions.textureUnitAllocation.push_back(std::make_pair(unit,(obj::Material::Map::TextureMapType) type)); OSG_NOTICE<<"Obj Found map in options, ["<<pre_equals<<"]="<<unit<<std::endl; } } } } return localOptions; } // read file and convert to OSG. osgDB::ReaderWriter::ReadResult ReaderWriterOBJ::readNode(const std::string& file, const osgDB::ReaderWriter::Options* options) const { std::string ext = osgDB::getLowerCaseFileExtension(file); if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; std::string fileName = osgDB::findDataFile( file, options ); if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; osgDB::ifstream fin(fileName.c_str()); if (fin) { // code for setting up the database path so that internally referenced file are searched for on relative paths. osg::ref_ptr<Options> local_opt = options ? static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options; local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName)); obj::Model model; model.setDatabasePath(osgDB::getFilePath(fileName.c_str())); model.readOBJ(fin, local_opt.get()); ObjOptionsStruct localOptions = parseOptions(options); osg::Node* node = convertModelToSceneGraph(model, localOptions, local_opt.get()); return node; } return ReadResult::FILE_NOT_HANDLED; } osgDB::ReaderWriter::ReadResult ReaderWriterOBJ::readNode(std::istream& fin, const Options* options) const { if (fin) { fin.imbue(std::locale::classic()); obj::Model model; model.readOBJ(fin, options); ObjOptionsStruct localOptions = parseOptions(options); osg::Node* node = convertModelToSceneGraph(model, localOptions, options); return node; } return ReadResult::FILE_NOT_HANDLED; }
_______________________________________________ osg-submissions mailing list [email protected] http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org
