From aac0a5fbe216f9a193294566aebe1a3728eb0137 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 25 Jun 2014 15:55:21 +0000 Subject: [PATCH] From Auelien Albert, "I'm working on an application which use 3ds file format as input and use the name of the material to "map" specific data with 3d geometry. The osg 3ds plugin modify the exported materials name in the same way it modifies the node names. I've added an option to preserve originals materials names, with the assurance of unique material names are preserved." git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14283 16af8721-9629-0410-8352-f15c8da7e697 --- src/osgPlugins/3ds/ReaderWriter3DS.cpp | 1 + src/osgPlugins/3ds/WriterNodeVisitor.cpp | 65 ++++++++++++++++++++++-- src/osgPlugins/3ds/WriterNodeVisitor.h | 7 ++- 3 files changed, 68 insertions(+), 5 deletions(-) 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 };