diff --git a/src/osgPlugins/3ds/ReaderWriter3DS.cpp b/src/osgPlugins/3ds/ReaderWriter3DS.cpp index 5b2a14a38..e892ebf59 100644 --- a/src/osgPlugins/3ds/ReaderWriter3DS.cpp +++ b/src/osgPlugins/3ds/ReaderWriter3DS.cpp @@ -238,6 +238,7 @@ ReaderWriter3DS::ReaderWriter3DS() //supportsOption("OutputTextureFiles","Write out the texture images to file"); //supportsOption("flipTexture", "flip texture upside-down"); supportsOption("extended3dsFilePaths", "(Write option) Keeps long texture filenames (not 8.3) when exporting 3DS, but can lead to compatibility problems."); + supportsOption("preserveMaterialNames", "(Write option) Preserve original material names, up to 64 characters. This can lead to compatibility problems."); supportsOption("noMatrixTransforms", "(Read option) Set the plugin to apply matrices into the mesh vertices (\"old behaviour\") instead of restoring them (\"new behaviour\"). You may use this option to avoid a few rounding errors."); supportsOption("checkForEspilonIdentityMatrices", "(Read option) If not set, then consider \"almost identity\" matrices to be identity ones (in case of rounding errors)."); supportsOption("restoreMatrixTransformsNoMeshes", "(Read option) Makes an exception to the behaviour when 'noMatrixTransforms' is not set for mesh instances. When a mesh instance has a transform on it, the reader creates a MatrixTransform above the Geode. If you don't want the hierarchy to be modified, then you can use this option to merge the transform into vertices."); diff --git a/src/osgPlugins/3ds/WriterNodeVisitor.cpp b/src/osgPlugins/3ds/WriterNodeVisitor.cpp index 1a0c2b792..d5ab33020 100644 --- a/src/osgPlugins/3ds/WriterNodeVisitor.cpp +++ b/src/osgPlugins/3ds/WriterNodeVisitor.cpp @@ -360,7 +360,7 @@ void PrimitiveIndexWriter::drawArrays(GLenum mode,GLint first,GLsizei count) -WriterNodeVisitor::Material::Material(WriterNodeVisitor & writerNodeVisitor, osg::StateSet * stateset, osg::Material* mat, osg::Texture* tex, int index) : +WriterNodeVisitor::Material::Material(WriterNodeVisitor & writerNodeVisitor, osg::StateSet * stateset, osg::Material* mat, osg::Texture* tex, bool preserveName, int index) : index(index), diffuse(1,1,1,1), ambient(0.2,0.2,0.2,1), @@ -387,7 +387,14 @@ WriterNodeVisitor::Material::Material(WriterNodeVisitor & writerNodeVisitor, osg //shininess = mat->getShininess(osg::Material::FRONT) <= 0 ? 0 : log( mat->getShininess(osg::Material::FRONT) ) / log(2.f) / 10.f; transparency = 1-diffuse.w(); - name = writerNodeVisitor.getUniqueName(mat->getName(),true,"mat"); + if (preserveName == false) + { + name = writerNodeVisitor.getUniqueName(mat->getName(),true,"mat"); + } + else + { + name = writerNodeVisitor.getMaterialName(mat->getName()); + } osg::StateAttribute * attribute = stateset->getAttribute(osg::StateAttribute::CULLFACE); if (!attribute) { @@ -458,7 +465,8 @@ WriterNodeVisitor::WriterNodeVisitor(Lib3dsFile * file3ds, const std::string & f _cur3dsNode(NULL), _options(options), _imageCount(0), - _extendedFilePaths(false) + _extendedFilePaths(false), + _preserveMaterialNames(false) { if (!fileName.empty()) _directory = options->getDatabasePathList().empty() ? osgDB::getFilePath(fileName) : options->getDatabasePathList().front(); @@ -471,6 +479,8 @@ WriterNodeVisitor::WriterNodeVisitor(Lib3dsFile * file3ds, const std::string & f { if (opt == "extended3dsFilePaths" || opt == "extended3DSFilePaths") _extendedFilePaths = true; + if (opt == "preserveMaterialNames") + _preserveMaterialNames = true; } } } @@ -717,6 +727,53 @@ std::string WriterNodeVisitor::getUniqueName(const std::string& _defaultValue, b return "ERROR"; } +std::string WriterNodeVisitor::getMaterialName(const std::string& inputMaterialName) +{ + std::string result; + + // Search in map if this material name already exists + MaterialNameMap::const_iterator mapIter=_materialNameMap.find(inputMaterialName); + + if (mapIter!=_materialNameMap.end()) + { + // Found, use it ! + result = mapIter->second; + } + else + { + // Not found, create a new (unique) entry mapped to this material name + std::string resultPrefix = inputMaterialName.substr(0, 60); // Up to 64 characters : truncate to 60 characters : 60 + "_" + number + result = resultPrefix; + + NameMap::const_iterator setIter=_materialNameSet.find(result); + int suffixValue=-1; + while (setIter!=_materialNameSet.end()) + { + if (suffixValue < 0) + { + // First add of the suffix + resultPrefix = resultPrefix + "_"; + suffixValue++; + } + + std::stringstream ss; + ss << resultPrefix << suffixValue; + + result = ss.str(); + + setIter=_materialNameSet.find(result); + suffixValue++; + } + + // Add entry in map + _materialNameMap[inputMaterialName] = result; + } + + std::cout << "getMaterialName : " << inputMaterialName << " => " << result << std::endl; + + return result; +} + int WriterNodeVisitor::processStateSet(osg::StateSet* ss) { MaterialMap::const_iterator itr = _materialMap.find(ss); @@ -732,7 +789,7 @@ int WriterNodeVisitor::processStateSet(osg::StateSet* ss) if (mat || tex) { int matNum = _lastMaterialIndex; - _materialMap.insert(std::make_pair(osg::ref_ptr(ss), Material(*this, ss, mat, tex, matNum) )); + _materialMap.insert(std::make_pair(osg::ref_ptr(ss), Material(*this, ss, mat, tex, _preserveMaterialNames, matNum) )); ++_lastMaterialIndex; return matNum; } diff --git a/src/osgPlugins/3ds/WriterNodeVisitor.h b/src/osgPlugins/3ds/WriterNodeVisitor.h index b5e30528b..6adb9ee8a 100644 --- a/src/osgPlugins/3ds/WriterNodeVisitor.h +++ b/src/osgPlugins/3ds/WriterNodeVisitor.h @@ -105,7 +105,7 @@ class WriterNodeVisitor: public osg::NodeVisitor ///\todo Add support for 2nd texture, opacity_map, bump_map, specular_map, shininess_map, self_illum_map, reflection_map. class Material { public: - Material(WriterNodeVisitor & writerNodeVisitor, osg::StateSet * stateset, osg::Material* mat, osg::Texture* tex, int index=-1); + Material(WriterNodeVisitor & writerNodeVisitor, osg::StateSet * stateset, osg::Material* mat, osg::Texture* tex, bool preserveName, int index=-1); int index; ///< Index in the 3DS file osg::Vec4 diffuse, ambient, specular; @@ -191,6 +191,7 @@ class WriterNodeVisitor: public osg::NodeVisitor int processStateSet(osg::StateSet* stateset); std::string getUniqueName(const std::string& defaultvalue, bool isNodeName, const std::string & defaultPrefix = "", int currentPrefixLen = -1); + std::string getMaterialName(const std::string& inputMaterialName); std::string export3DSTexture(const osg::Image * image, const std::string & fileName); typedef std::stack > StateSetStack; @@ -210,6 +211,9 @@ class WriterNodeVisitor: public osg::NodeVisitor typedef std::set NameMap; NameMap _nodeNameMap; NameMap _imageNameMap; + typedef std::map MaterialNameMap; + MaterialNameMap _materialNameMap; + NameMap _materialNameSet; MaterialMap _materialMap; unsigned int _lastMaterialIndex; unsigned int _lastMeshIndex; @@ -217,6 +221,7 @@ class WriterNodeVisitor: public osg::NodeVisitor const osgDB::ReaderWriter::Options* _options; unsigned int _imageCount; bool _extendedFilePaths; + bool _preserveMaterialNames; typedef std::map ImageSet; ImageSet _imageSet; ///< Map used to avoid renaming and writing twice an image };