From Sukender, "Collada writer fix : Fixed wrong handling of duplicate names in Collada writer.

The uniquify() method was not checking if the new name was actually in use or not.

Collada with rename option : Added an option to Collada writer, to rename uncommon IDs (geometries, materials...) to something more compatible (especially Google Earth).
Characters which may be interpreted as an URI are replaced with '_'. Useful if you want to ensure names having spaces or slashes to behave correctly. This may be undesired if original naming must be somewhat kept (hence making it an option)."
This commit is contained in:
Robert Osfield 2016-01-21 12:40:11 +00:00
parent 4de2fc120d
commit 2791d280ae
4 changed files with 74 additions and 16 deletions

View File

@ -221,6 +221,7 @@ ReaderWriterDAE::writeNode( const osg::Node& node,
else if (opt == "daeLinkOriginalTexturesNoForce") { pluginOptions.linkOrignialTextures = true; pluginOptions.forceTexture = false; }
else if (opt == "daeLinkOriginalTexturesForce") { pluginOptions.linkOrignialTextures = true; pluginOptions.forceTexture = true; }
else if (opt == "daeNamesUseCodepage") pluginOptions.namesUseCodepage = true;
else if (opt == "daeRenameIds") pluginOptions.renameIds = true;
else if (!opt.empty())
{
OSG_NOTICE << std::endl << "COLLADA dae plugin: unrecognized option \"" << opt << std::endl;

View File

@ -26,13 +26,14 @@ public:
supportsOption("daeLinkOriginalTexturesNoForce", "(Write option) Writes reference to the original image if found, instead of writing the image in memory");
supportsOption("daeLinkOriginalTexturesForce", "(Write option) Writes reference to the original image even if not found, instead of writing the image in memory");
supportsOption("daeNamesUseCodepage", "(Write option) All names except filenames (materials, animation, geometries...) should be considered as encoded using current codepage (UTF8 if not). Filenames follow OSG_USE_UTF8_FILENAME.");
supportsOption("daeRenameIds", "(Write option) Rename all IDs (geometries, materials, etc.) to remove characters which may be interpreted as an URI. Useful if you want to ensure names having spaces or slashes behave correctly. This may be undesired if original naming must be somewhat kept.");
supportsOption("StrictTransparency", "(Read option) Undocumented");
supportsOption("daeTessellateNone", "(Read option) Do not tessellate at all (Polygons are stored as GL_POLYGON - not suitable for concave polygons)");
supportsOption("daeTessellatePolygonsAsTriFans", "(Read option) Tessellate the old way (default), interpreting polygons as triangle fans (faster, but does not work for concave polygons)");
supportsOption("daeTessellatePolygons", "(Read option) Use full tessellation of polygons (slower, works for concave polygons)");
supportsOption("daeUsePredefinedTextureUnits", "(Read option) Texture units have fixed uses (0: ambient occlusion, 1: main texture...). May create non contiguous units (default).");
supportsOption("daeUsePredefinedTextureUnits", "(Read option) Texture units are created in sequence (contiguous units).");
supportsOption("daeUseSequencedTextureUnits", "(Read option) Texture units are created in sequence (contiguous units).");
}
const char* className() const { return "COLLADA 1.4.x DAE reader/writer"; }

View File

@ -20,7 +20,7 @@
#include <sstream>
#include <osgDB/ConvertUTF>
#include <limits>
namespace osgDAE {
@ -71,6 +71,20 @@ daeWriter::ArrayNIndices::ArrayNIndices( osg::Array* valArray, osg::IndexArray*
}
std::string toString(const osg::Vec2f& value)
{
std::stringstream str;
str << value.x() << " " << value.y();
return str.str();
}
std::string toString(const osg::Vec2d& value)
{
std::stringstream str;
str << value.x() << " " << value.y();
return str.str();
}
std::string toString(const osg::Vec3f& value)
{
std::stringstream str;
@ -85,7 +99,22 @@ std::string toString(const osg::Vec3d& value)
return str.str();
}
std::string toString(const osg::Matrix& value)
std::string toString(const osg::Vec4f& value)
{
std::stringstream str;
str << value.x() << " " << value.y() << " " << value.z() << " " << value.w();
return str.str();
}
std::string toString(const osg::Vec4d& value)
{
std::stringstream str;
str << value.x() << " " << value.y() << " " << value.z() << " " << value.w();
return str.str();
}
template <typename T>
std::string matrixToString(T value)
{
std::stringstream str;
str << value(0,0) << " " << value(1,0) << " " << value(2,0) << " " << value(3,0) << " "
@ -95,6 +124,15 @@ std::string toString(const osg::Matrix& value)
return str.str();
}
std::string toString(const osg::Matrixf& value)
{
return matrixToString<osg::Matrixf>(value);
}
std::string toString(const osg::Matrixd& value)
{
return matrixToString<osg::Matrixd>(value);
}
daeWriter::Options::Options()
: usePolygons(false),
@ -104,7 +142,8 @@ daeWriter::Options::Options()
linkOrignialTextures(false),
forceTexture(false),
namesUseCodepage(false),
relativiseImagesPathNbUpDirs(0)
relativiseImagesPathNbUpDirs(0),
renameIds(false)
{}
daeWriter::daeWriter( DAE *dae_, const std::string & fileURI, const std::string & directory, const std::string & srcDirectory, const osgDB::ReaderWriter::Options * options, TraversalMode tm, const Options * pluginOptions) : osg::NodeVisitor( tm ),
@ -211,20 +250,29 @@ void daeWriter::updateCurrentDaeNode()
std::string daeWriter::uniquify( const std::string &_name )
{
const std::string name( _pluginOptions.namesUseCodepage ? osgDB::convertStringFromCurrentCodePageToUTF8(_name) : _name );
std::map< std::string, int >::iterator iter = uniqueNames.find( name );
if ( iter != uniqueNames.end() )
const std::string baseName( _pluginOptions.namesUseCodepage ? osgDB::convertStringFromCurrentCodePageToUTF8(_name) : _name );
std::string newName( baseName );
if (_pluginOptions.renameIds)
{
iter->second++;
// Turn 'newName' into a simple ID
// Note: ConvertFilePathToColladaCompatibleURI(newName) did not the job: names such as "C:\somedir\somefile" become "/C:/somedir/somefile" and are not interpreted as a simple ID within Google Earth.
static const char * const REPLACE_CHARS = " /\\:#?=%&*";
for(std::size_t found = newName.find_first_of(REPLACE_CHARS); found != std::string::npos; found = newName.find_first_of(REPLACE_CHARS)) newName[found] = '_';
}
// Loop while newName is in use
UniqueNames::iterator iter;
for (iter = uniqueNames.find(newName); iter != uniqueNames.end(); iter = uniqueNames.find(newName))
{
if (iter->second == std::numeric_limits<UniqueNames::mapped_type>::max()) throw std::runtime_error("Not implemented: renaming DAE name above given limit.");
iter->second++; // Increment usage count
std::ostringstream num;
num << std::dec << iter->second;
return name + "_" + num.str();
}
else
{
uniqueNames.insert( std::make_pair( name, 0 ) );
return name;
newName = baseName + "_" + num.str();
}
uniqueNames.insert( std::make_pair( newName, 0 ) );
return newName;
}
void daeWriter::createAssetTag( bool isZUpAxis )

View File

@ -89,9 +89,14 @@ std::string toString(T value)
return str.str();
}
std::string toString(const osg::Vec2f& value);
std::string toString(const osg::Vec2d& value);
std::string toString(const osg::Vec3f& value);
std::string toString(const osg::Vec3d& value);
std::string toString(const osg::Matrix& value);
std::string toString(const osg::Vec4f& value);
std::string toString(const osg::Vec4d& value);
std::string toString(const osg::Matrixf& value);
std::string toString(const osg::Matrixd& value);
// Collects all nodes that are targeted by an animation
class FindAnimatedNodeVisitor : public osg::NodeVisitor
@ -164,6 +169,8 @@ public:
bool forceTexture;
bool namesUseCodepage;
unsigned int relativiseImagesPathNbUpDirs;
/** Rename all IDs (geometries, materials, etc.) to remove characters which may be interpreted as an URI. */
bool renameIds;
};
daeWriter(DAE *dae_, const std::string &fileURI, const std::string & directory, const std::string & srcDirectory, const osgDB::ReaderWriter::Options * options, TraversalMode tm=TRAVERSE_ALL_CHILDREN, const Options * pluginOptions=NULL);
virtual ~daeWriter();
@ -264,7 +271,8 @@ protected: //members
typedef std::map< osgAnimation::RigGeometry*, domController *> OsgRigGeometryDomControllerMap;
typedef std::map< osgAnimation::MorphGeometry*, domController *> OsgMorphGeometryDomControllerMap;
std::map< std::string, int > uniqueNames;
typedef std::map< std::string, int > UniqueNames;
UniqueNames uniqueNames;
OsgGeometryDomGeometryMap geometryMap;
OsgRigGeometryDomControllerMap _osgRigGeometryDomControllerMap;
OsgMorphGeometryDomControllerMap _osgMorphGeometryDomControllerMap;