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
This commit is contained in:
Robert Osfield 2014-06-25 15:55:21 +00:00
parent a2db511c99
commit aac0a5fbe2
3 changed files with 68 additions and 5 deletions

View File

@ -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.");

View File

@ -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<osg::StateSet>(ss), Material(*this, ss, mat, tex, matNum) ));
_materialMap.insert(std::make_pair(osg::ref_ptr<osg::StateSet>(ss), Material(*this, ss, mat, tex, _preserveMaterialNames, matNum) ));
++_lastMaterialIndex;
return matNum;
}

View File

@ -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<osg::ref_ptr<osg::StateSet> > StateSetStack;
@ -210,6 +211,9 @@ class WriterNodeVisitor: public osg::NodeVisitor
typedef std::set<std::string> NameMap;
NameMap _nodeNameMap;
NameMap _imageNameMap;
typedef std::map<std::string, std::string> 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<osg::Image*, std::string> ImageSet;
ImageSet _imageSet; ///< Map used to avoid renaming and writing twice an image
};