From d8d2bc4193578be6828970e1f354aa1b7612fd3e Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 25 Jul 2008 15:45:40 +0000 Subject: [PATCH] From Ulrich Hertlein, "as I hinted at on osg-users in the "obj loader: map_* only reads last component" thread, this submission broke material/texture loading for some files I have that specify texture matrix scaling. The following link shows a very comprehensive list of .mtl file options: http://local.wasp.uwa.edu.au/~pbourke/dataformats/mtl/ Attached is a patch that should fix spacey filenames and optional texture scale/offset. I have tested it with files I have that I modified to contain spaces in the texture filenames." --- src/osgPlugins/obj/ReaderWriterOBJ.cpp | 24 +++++++- src/osgPlugins/obj/obj.cpp | 78 +++++++++++++++++++++++--- src/osgPlugins/obj/obj.h | 4 +- 3 files changed, 93 insertions(+), 13 deletions(-) diff --git a/src/osgPlugins/obj/ReaderWriterOBJ.cpp b/src/osgPlugins/obj/ReaderWriterOBJ.cpp index db01c804e..cf72dcf39 100644 --- a/src/osgPlugins/obj/ReaderWriterOBJ.cpp +++ b/src/osgPlugins/obj/ReaderWriterOBJ.cpp @@ -163,7 +163,7 @@ inline osg::Vec3 ReaderWriterOBJ::transformNormal(const osg::Vec3& vec, const bo // register with Registry to instantiate the above reader/writer. REGISTER_OSGPLUGIN(obj, ReaderWriterOBJ) -void load_material_texture( obj::Model &model, +static void load_material_texture( obj::Model &model, obj::Material &material, osg::StateSet *stateset, const std::string & filename, @@ -174,7 +174,7 @@ void load_material_texture( obj::Model &model, osg::ref_ptr< osg::Image > image; if ( !model.getDatabasePath().empty() ) { - // first try with databasr path of parent. + // first try with database path of parent. image = osgDB::readImageFile(model.getDatabasePath()+'/'+filename); } @@ -208,6 +208,26 @@ void load_material_texture( obj::Model &model, } } } + + if (material.uScale != 1.0f || material.vScale != 1.0f || + material.uOffset != 0.0f || material.vOffset != 0.0f) + { + osg::Matrix mat; + if (material.uScale != 1.0f || material.vScale != 1.0f) + { + osg::notify(osg::DEBUG_INFO) << "Obj TexMat scale=" << material.uScale << "," << material.vScale << std::endl; + mat *= osg::Matrix::scale(material.uScale, material.vScale, 1.0); + } + if (material.uOffset != 0.0f || material.vOffset != 0.0f) + { + osg::notify(osg::DEBUG_INFO) << "Obj TexMat offset=" << material.uOffset << "," << material.uOffset << std::endl; + mat *= osg::Matrix::translate(material.uOffset, material.vOffset, 0.0); + } + + osg::TexMat* texmat = new osg::TexMat; + texmat->setMatrix(mat); + stateset->setTextureAttributeAndModes( texture_unit,texmat,osg::StateAttribute::ON ); + } } diff --git a/src/osgPlugins/obj/obj.cpp b/src/osgPlugins/obj/obj.cpp index 1310ff958..61b788b61 100644 --- a/src/osgPlugins/obj/obj.cpp +++ b/src/osgPlugins/obj/obj.cpp @@ -26,13 +26,76 @@ using namespace obj; -std::string strip( const std::string& ss ) +static std::string strip( const std::string& ss ) { std::string result; result.assign( ss.begin() + ss.find_first_not_of( ' ' ), ss.begin() + 1 + ss.find_last_not_of( ' ' ) ); return( result ); } +/* + * parse a subset of texture options, following + * http://local.wasp.uwa.edu.au/~pbourke/dataformats/mtl/ + */ +static std::string parseTexture( const std::string& ss, Material& mat) +{ + std::string s(ss); + for (;;) + { + if (s[0] != '-') + break; + + int n; + if (s[1] == 's' || s[1] == 'o') + { + float x, y, z; + if (sscanf(s.c_str(), "%*s %f %f %f%n", &x, &y, &z, &n) != 3) + { + break; + } + + if (s[1] == 's') + { + // texture scale + mat.uScale = x; + mat.vScale = y; + } + else if (s[1] == 'o') + { + // texture offset + mat.uOffset = x; + mat.vOffset = y; + } + } + else if (s[1] == 'm' && s[2] == 'm') + { + // texture color offset and gain + float base, gain; + if (sscanf(s.c_str(), "%*s %f %f%n", &base, &gain, &n) != 2) + { + break; + } + // UNUSED + } + else if (s[1] == 'b' && s[2] == 'm') + { + // blend multiplier + float mult; + if (sscanf(s.c_str(), "%*s %f%n", &mult, &n) != 2) + { + break; + } + // UNUSED + } + else + break; + + s = strip(s.substr(n)); + } + + return s; +} + bool Model::readline(std::istream& fin, char* line, const int LINE_SIZE) { if (LINE_SIZE<1) return false; @@ -141,6 +204,7 @@ bool Model::readMTL(std::istream& fin) float r = 1.0f, g = 1.0f, b = 1.0f, a = 1.0f; Material* material = 0;// &(materialMap[""]); + std::string filename; while (fin) { @@ -351,23 +415,19 @@ bool Model::readMTL(std::istream& fin) } else if (strncmp(line,"map_Ka ",7)==0) { - std::string filename(line+7); - material->map_Ka = filename; + material->map_Ka = parseTexture(strip(line+7), *material); } else if (strncmp(line,"map_Kd ",7)==0) { - material->map_Kd = strip(line+7); - osg::notify(osg::INFO)<< "map_Kd:\'" << material->map_Kd << "\'" << std::endl; + material->map_Kd = parseTexture(strip(line+7), *material); } else if (strncmp(line,"map_Ks ",7)==0) { - material->map_Ks = strip(line+7); - osg::notify(osg::INFO)<< "map_Ks:\'" << material->map_Kd << "\'" << std::endl; + material->map_Ks = parseTexture(strip(line+7), *material); } else if (strncmp(line,"map_opacity ",7)==0) { - material->map_opacity = strip(line+7); - osg::notify(osg::INFO)<< "map_opacity:\'" << material->map_Kd << "\'" << std::endl; + material->map_opacity = parseTexture(strip(line+7), *material); } else if (strcmp(line,"refl")==0 || strncmp(line,"refl ",5)==0) { diff --git a/src/osgPlugins/obj/obj.h b/src/osgPlugins/obj/obj.h index 159cdc07c..4996ccd9b 100644 --- a/src/osgPlugins/obj/obj.h +++ b/src/osgPlugins/obj/obj.h @@ -48,8 +48,8 @@ public: alpha(1.0f), uScale(1.0f), vScale(1.0f), - uOffset(1.0f), - vOffset(1.0f) {} + uOffset(0.0f), + vOffset(0.0f) {} std::string name;