From Sukender, "
DAE plugin was linking ORIGINAL images in the Collada file, using image->getName() as a path (even if images were modified in memory!). As the behaviour was not the one of other plugins (3DS, FBX, and such), I made the plugin relativise images filenames (as those plugins) and write the image which is in memory. However, in order to avoid removing features, I kept the previous behaviour but moved it in an option. Here are the options of the plugin I changed: - daeForceTexture was unclear in this new context and removed in favor of two new options - daeLinkOriginalTexturesNoForce: Writes reference to the original image if found, instead of writing the image in memory - daeLinkOriginalTexturesForce: Writes reference to the original image even if not found, instead of writing the image in memory Of course, if you specify no option, images are written as for other plugins. Other thing I changed is the UTF8 support as I told you in a previous conversation. Now there is a simple option, "daeNamesUseCodepage", which makes all names except filenames (materials, animation, geometries...) be considered as encoded using current codepage. If so, they'll be converted to UTF8 when writing; else they are written directly. Of course, filenames follow OSG_USE_UTF8_FILENAME as usual. I did "
This commit is contained in:
parent
cc207c1112
commit
90508f282a
@ -109,9 +109,11 @@ ReaderWriterDAE::writeNode( const osg::Node& node,
|
||||
bool usePolygon(false); // Use plugin option "polygon" to enable
|
||||
bool googleMode(false); // Use plugin option "GoogleMode" to enable
|
||||
bool writeExtras(true); // Use plugin option "NoExtras" to disable
|
||||
bool earthTex(false); // Use plugin option "DaeEarthTex" to enable
|
||||
bool zUpAxis(false); // Use plugin option "ZUpAxis" to enable
|
||||
bool forceTexture(false); // Use plugin option "ForceTexture" to enable
|
||||
bool earthTex(false); // Use plugin option "daeEarthTex" to enable
|
||||
bool zUpAxis(false); // Use plugin option "daeZUpAxis" to enable
|
||||
bool linkOrignialTextures(false);
|
||||
bool forceTexture(false);
|
||||
bool namesUseCodepage(false);
|
||||
if( options )
|
||||
{
|
||||
pDAE = (DAE*)options->getPluginData("DAE");
|
||||
@ -131,7 +133,9 @@ ReaderWriterDAE::writeNode( const osg::Node& node,
|
||||
else if (opt == "NoExtras") writeExtras = false;
|
||||
else if (opt == "daeEarthTex") earthTex = true;
|
||||
else if (opt == "daeZUpAxis") zUpAxis = true;
|
||||
else if (opt == "daeForceTexture") forceTexture = true;
|
||||
else if (opt == "daeLinkOriginalTexturesNoForce") { linkOrignialTextures = true; forceTexture = false; }
|
||||
else if (opt == "daeLinkOriginalTexturesForce") { linkOrignialTextures = true; forceTexture = true; }
|
||||
else if (opt == "daeNamesUseCodepage") namesUseCodepage = true;
|
||||
else if (!opt.empty())
|
||||
{
|
||||
OSG_NOTICE << std::endl << "COLLADA dae plugin: unrecognized option \"" << opt << std::endl;
|
||||
@ -150,7 +154,7 @@ ReaderWriterDAE::writeNode( const osg::Node& node,
|
||||
|
||||
osg::NodeVisitor::TraversalMode traversalMode = writeExtras ? osg::NodeVisitor::TRAVERSE_ALL_CHILDREN : osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN;
|
||||
|
||||
osgDAE::daeWriter daeWriter(pDAE, fileURI, usePolygon, googleMode, traversalMode, writeExtras, earthTex, zUpAxis, forceTexture);
|
||||
osgDAE::daeWriter daeWriter(pDAE, fileURI, osgDB::getFilePath(fname), osgDB::getFilePath(node.getName().empty() ? fname : node.getName()), options, usePolygon, googleMode, traversalMode, writeExtras, earthTex, zUpAxis, linkOrignialTextures, forceTexture, namesUseCodepage);
|
||||
daeWriter.setRootNode( node );
|
||||
const_cast<osg::Node*>(&node)->accept( daeWriter );
|
||||
|
||||
@ -178,7 +182,8 @@ ReaderWriterDAE::writeNode( const osg::Node& node,
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static void replace(std::string & str, const char from, const std::string & to) {
|
||||
static void replace(std::string & str, const char from, const std::string & to)
|
||||
{
|
||||
// Replace for all occurences
|
||||
for(std::string::size_type pos=str.find(from); pos!=std::string::npos; pos=str.find(from))
|
||||
{
|
||||
@ -188,7 +193,11 @@ static void replace(std::string & str, const char from, const std::string & to)
|
||||
|
||||
std::string ReaderWriterDAE::ConvertFilePathToColladaCompatibleURI(const std::string& FilePath)
|
||||
{
|
||||
std::string path( cdom::nativePathToUri(FilePath) );
|
||||
#ifdef OSG_USE_UTF8_FILENAME
|
||||
std::string path( cdom::nativePathToUri( FilePath ) );
|
||||
#else
|
||||
std::string path( cdom::nativePathToUri( osgDB::convertStringFromCurrentCodePageToUTF8(FilePath) ) );
|
||||
#endif
|
||||
|
||||
// Unfortunately, cdom::nativePathToUri() does not convert '#' characters to "%23" as expected.
|
||||
// So having /a/#b/c will generate a wrong conversion, as '#' will be misinterpreted as an URI fragment.
|
||||
|
@ -23,7 +23,9 @@ public:
|
||||
supportsOption("NoExtras", "(Write option) Undocumented");
|
||||
supportsOption("daeEarthTex", "(Write option) DAE settings for writing earth textures");
|
||||
supportsOption("daeZUpAxis", "(Write option) Indicates the up axis is Z instead of Y");
|
||||
supportsOption("daeForceTexture", "(Write option) Force writing references to an image for a texture, even if the file is not found");
|
||||
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("StrictTransparency", "(Read option) Undocumented");
|
||||
}
|
||||
|
@ -29,12 +29,14 @@
|
||||
#include <osg/Sequence>
|
||||
#include <osg/Billboard>
|
||||
#include <osg/CameraView>
|
||||
#include <osgDB/ConvertUTF>
|
||||
|
||||
using namespace osgDAE;
|
||||
|
||||
|
||||
void daeWriter::writeAnimations( osg::Node &node )
|
||||
{
|
||||
const std::string nodeNameUTF( _namesUseCodepage ? osgDB::convertStringFromCurrentCodePageToUTF8(node.getName()) : node.getName() );
|
||||
osg::NodeCallback* ncb = node.getUpdateCallback();
|
||||
if (ncb)
|
||||
{
|
||||
@ -54,7 +56,7 @@ void daeWriter::writeAnimations( osg::Node &node )
|
||||
domAnimation* pMainDomAnimation = pDomAnimation;
|
||||
|
||||
osg::ref_ptr<osgAnimation::Animation> animation = animationList[i];
|
||||
std::string animationName = animation->getName();
|
||||
std::string animationName( animation->getName() );
|
||||
if (animationName.empty())
|
||||
animationName = "animation";
|
||||
animationName = uniquify( animationName );
|
||||
@ -65,7 +67,8 @@ void daeWriter::writeAnimations( osg::Node &node )
|
||||
for (size_t j=0; j < animationChannels.size(); j++)
|
||||
{
|
||||
osgAnimation::Channel* channel = animationChannels[j].get();
|
||||
std::string channelName = channel->getName();
|
||||
std::string channelName( channel->getName() );
|
||||
std::string channelNameUTF( _namesUseCodepage ? osgDB::convertStringFromCurrentCodePageToUTF8(channelName) : channelName );
|
||||
|
||||
// Wrap each animation channel into it's own child <animation> when more than 1 channel
|
||||
if (animationChannels.size() > 1)
|
||||
@ -73,15 +76,18 @@ void daeWriter::writeAnimations( osg::Node &node )
|
||||
pDomAnimation = daeSafeCast< domAnimation >( pMainDomAnimation->add( COLLADA_ELEMENT_ANIMATION ) );
|
||||
|
||||
if (channelName.empty())
|
||||
{
|
||||
channelName = "channel";
|
||||
channelNameUTF = channelName;
|
||||
}
|
||||
animationName = uniquify( channelName );
|
||||
pDomAnimation->setId(channelName.c_str());
|
||||
pDomAnimation->setId(channelNameUTF.c_str());
|
||||
}
|
||||
|
||||
std::string sourceName = channelName + "_sampler";
|
||||
std::string inputSourceName = channelName + "_input";
|
||||
std::string outputSourceName = channelName + "_output";
|
||||
std::string interpolationSourceName = channelName + "_interpolation";
|
||||
std::string sourceName( channelNameUTF + "_sampler" );
|
||||
std::string inputSourceName( channelNameUTF + "_input" );
|
||||
std::string outputSourceName( channelNameUTF + "_output" );
|
||||
std::string interpolationSourceName( channelNameUTF + "_interpolation" );
|
||||
|
||||
// Fill dom sources based on sampler
|
||||
osgAnimation::Sampler* animationSampler = channel->getSampler();
|
||||
@ -104,7 +110,7 @@ void daeWriter::writeAnimations( osg::Node &node )
|
||||
osg::Vec3 vec = (*v3kc)[i].getValue();
|
||||
|
||||
// This needs some serious cleanup
|
||||
if (channelName.find("euler") != std::string::npos)
|
||||
if (channelNameUTF.find("euler") != std::string::npos)
|
||||
{
|
||||
frameValues.append(osg::RadiansToDegrees(vec.x()));
|
||||
frameValues.append(osg::RadiansToDegrees(vec.y()));
|
||||
@ -179,7 +185,7 @@ void daeWriter::writeAnimations( osg::Node &node )
|
||||
pDomParam->setType(COLLADA_TYPE_NAME);
|
||||
|
||||
// Split up access to the euler float array into three sources, because we need to target three separate transforms
|
||||
if (channelName.find("euler") != std::string::npos)
|
||||
if (channelNameUTF.find("euler") != std::string::npos)
|
||||
{
|
||||
pDomSource = daeSafeCast< domSource >(pDomAnimation->add(COLLADA_ELEMENT_SOURCE));
|
||||
std::string outputSourceNameX = outputSourceName + "_X";
|
||||
@ -283,7 +289,7 @@ void daeWriter::writeAnimations( osg::Node &node )
|
||||
osg::Node* node = _animatedNodeCollector.getTargetNode(targetName);
|
||||
if (node)
|
||||
{
|
||||
std::string domChannelTargetName = node->getName() + "/rotateX.ANGLE";
|
||||
std::string domChannelTargetName = nodeNameUTF + "/rotateX.ANGLE";
|
||||
pDomChannel->setTarget(domChannelTargetName.c_str());
|
||||
}
|
||||
else
|
||||
@ -327,7 +333,7 @@ void daeWriter::writeAnimations( osg::Node &node )
|
||||
osg::Node* node = _animatedNodeCollector.getTargetNode(targetName);
|
||||
if (node)
|
||||
{
|
||||
std::string domChannelTargetName = node->getName() + "/rotateY.ANGLE";
|
||||
std::string domChannelTargetName = nodeNameUTF + "/rotateY.ANGLE";
|
||||
pDomChannel->setTarget(domChannelTargetName.c_str());
|
||||
}
|
||||
else
|
||||
@ -371,7 +377,7 @@ void daeWriter::writeAnimations( osg::Node &node )
|
||||
osg::Node* node = _animatedNodeCollector.getTargetNode(targetName);
|
||||
if (node)
|
||||
{
|
||||
std::string domChannelTargetName = node->getName() + "/rotateZ.ANGLE";
|
||||
std::string domChannelTargetName = nodeNameUTF + "/rotateZ.ANGLE";
|
||||
pDomChannel->setTarget(domChannelTargetName.c_str());
|
||||
}
|
||||
else
|
||||
@ -457,13 +463,13 @@ void daeWriter::writeAnimations( osg::Node &node )
|
||||
osg::Node* node = _animatedNodeCollector.getTargetNode(targetName);
|
||||
if (node)
|
||||
{
|
||||
std::string domChannelTargetName = node->getName();
|
||||
std::string domChannelTargetName = nodeNameUTF;
|
||||
|
||||
if (channelName.find("position") != std::string::npos)
|
||||
if (channelNameUTF.find("position") != std::string::npos)
|
||||
{
|
||||
domChannelTargetName += "/translate";
|
||||
}
|
||||
else if (channelName.find("scale") != std::string::npos)
|
||||
else if (channelNameUTF.find("scale") != std::string::npos)
|
||||
{
|
||||
domChannelTargetName += "/scale";
|
||||
}
|
||||
|
@ -20,6 +20,9 @@
|
||||
#include <dom/domProfile_COMMON.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <osgDB/ConvertUTF>
|
||||
#include <osgDB/FileNameUtils>
|
||||
#include <osgDB/WriteFile>
|
||||
|
||||
//#include <dom/domLibrary_effects.h>
|
||||
//#include <dom/domLibrary_materials.h>
|
||||
@ -35,7 +38,7 @@ void daeWriter::processMaterial( osg::StateSet *ss, domBind_material *pDomBindMa
|
||||
osg::ref_ptr<osg::StateSet> ssClean = CleanStateSet(ss); // Need to hold a ref to this or the materialMap.find() will delete it
|
||||
domBind_material::domTechnique_common *tc = daeSafeCast< domBind_material::domTechnique_common >( pDomBindMaterial->add( COLLADA_ELEMENT_TECHNIQUE_COMMON ) );
|
||||
domInstance_material *pDomInstanceMaterial = daeSafeCast< domInstance_material >( tc->add( COLLADA_ELEMENT_INSTANCE_MATERIAL ) );
|
||||
std::string symbol = geoName + "_material";
|
||||
const std::string symbol( _namesUseCodepage ? osgDB::convertStringFromCurrentCodePageToUTF8(geoName + "_material") : (geoName + "_material") );
|
||||
pDomInstanceMaterial->setSymbol( symbol.c_str() );
|
||||
|
||||
// See if material already exists in cache
|
||||
@ -53,7 +56,7 @@ void daeWriter::processMaterial( osg::StateSet *ss, domBind_material *pDomBindMa
|
||||
}
|
||||
|
||||
domMaterial *mat = daeSafeCast< domMaterial >( lib_mats->add( COLLADA_ELEMENT_MATERIAL ) );
|
||||
std::string name = ssClean->getName();
|
||||
std::string name( ssClean->getName() );
|
||||
if ( name.empty() )
|
||||
{
|
||||
name = "material";
|
||||
@ -99,16 +102,71 @@ void daeWriter::processMaterial( osg::StateSet *ss, domBind_material *pDomBindMa
|
||||
osg::Image *osgimg = tex->getImage( 0 );
|
||||
|
||||
domImage::domInit_from *imgif = daeSafeCast< domImage::domInit_from >( img->add( COLLADA_ELEMENT_INIT_FROM ) );
|
||||
std::string fileURI = ReaderWriterDAE::ConvertFilePathToColladaCompatibleURI(osgDB::findDataFile(osgimg->getFileName()));
|
||||
if (fileURI=="" && m_ForceTexture)
|
||||
|
||||
std::string fileURI;
|
||||
if (m_linkOrignialTextures)
|
||||
{
|
||||
fileURI = osgimg->getFileName();
|
||||
// We link to orignial images.
|
||||
fileURI = osgDB::findDataFile(osgimg->getFileName());
|
||||
if (fileURI=="" && m_ForceTexture)
|
||||
{
|
||||
fileURI = osgDB::getRealPath(osgimg->getFileName());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We do not link to orignial images. Then must ensure to write the image.
|
||||
// Following code block is borrowed from FBX's WriterNodeVisitor::Material::Material().
|
||||
ImageSet::iterator it = _imageSet.find(osgimg);
|
||||
if (it == _imageSet.end())
|
||||
{
|
||||
fileURI = osgDB::getRealPath(osgDB::convertFileNameToNativeStyle(osgimg->getFileName()));
|
||||
std::string destPath;
|
||||
std::string relativePath;
|
||||
if (fileURI.empty())
|
||||
{
|
||||
static const unsigned int MAX_IMAGE_NUMBER = UINT_MAX-1; // -1 to allow doing +1 without an overflow
|
||||
unsigned int imageNumber;
|
||||
for (imageNumber=_lastGeneratedImageFileName+1; imageNumber<MAX_IMAGE_NUMBER; ++imageNumber)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Image_" << imageNumber << ".tga";
|
||||
relativePath = oss.str();
|
||||
destPath = osgDB::concatPaths(_directory, relativePath);
|
||||
if (_imageFilenameSet.find(destPath) != _imageFilenameSet.end()) break;
|
||||
}
|
||||
_lastGeneratedImageFileName = imageNumber;
|
||||
osgDB::writeImageFile(*osgimg, destPath, _options);
|
||||
}
|
||||
else
|
||||
{
|
||||
relativePath = osgDB::getPathRelative(_srcDirectory, fileURI);
|
||||
destPath = osgDB::getRealPath(osgDB::convertFileNameToNativeStyle( osgDB::concatPaths(_directory, relativePath) ));
|
||||
if (destPath != fileURI)
|
||||
{
|
||||
if (!osgDB::makeDirectoryForFile(destPath))
|
||||
{
|
||||
OSG_NOTICE << "Can't create directory for file '" << destPath << "'. May fail creating the image file." << std::endl;
|
||||
}
|
||||
osgDB::writeImageFile(*osgimg, destPath, _options);
|
||||
}
|
||||
}
|
||||
|
||||
assert(!destPath.empty()); // Else the implementation is to be fixed
|
||||
assert(!relativePath.empty()); // ditto
|
||||
fileURI = relativePath;
|
||||
it = _imageSet.insert(ImageSet::value_type(osgimg, relativePath)).first;
|
||||
_imageFilenameSet.insert(destPath);
|
||||
}
|
||||
// (end of code borrowed from FBX)
|
||||
}
|
||||
|
||||
fileURI = ReaderWriterDAE::ConvertFilePathToColladaCompatibleURI(fileURI);
|
||||
|
||||
daeURI dd(*dae, fileURI);
|
||||
imgif->setValue( dd );
|
||||
// The document URI should contain the canonical path it was created with
|
||||
imgif->getValue().makeRelativeTo(doc->getDocumentURI());
|
||||
if (m_linkOrignialTextures) imgif->getValue().makeRelativeTo(doc->getDocumentURI());
|
||||
|
||||
if (!m_EarthTex)
|
||||
{
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <dom/domConstants.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <osgDB/ConvertUTF>
|
||||
|
||||
|
||||
namespace osgDAE {
|
||||
@ -95,7 +96,7 @@ std::string toString(const osg::Matrix& value)
|
||||
}
|
||||
|
||||
|
||||
daeWriter::daeWriter( DAE *dae_, const std::string &fileURI, bool _usePolygons, bool googleMode, TraversalMode tm, bool _writeExtras, bool earthTex, bool zUpAxis, bool forceTexture) : osg::NodeVisitor( tm ),
|
||||
daeWriter::daeWriter( DAE *dae_, const std::string & fileURI, const std::string & directory, const std::string & srcDirectory, const osgDB::ReaderWriter::Options * options, bool _usePolygons, bool googleMode, TraversalMode tm, bool _writeExtras, bool earthTex, bool zUpAxis, bool linkOrignialTextures, bool forceTexture, bool namesUseCodepage) : osg::NodeVisitor( tm ),
|
||||
dae(dae_),
|
||||
_domLibraryAnimations(NULL),
|
||||
writeExtras(_writeExtras),
|
||||
@ -104,8 +105,14 @@ daeWriter::daeWriter( DAE *dae_, const std::string &fileURI, bool _usePolygons,
|
||||
m_GoogleMode(googleMode),
|
||||
m_EarthTex(earthTex),
|
||||
m_ZUpAxis(zUpAxis),
|
||||
m_linkOrignialTextures(linkOrignialTextures),
|
||||
m_ForceTexture(forceTexture),
|
||||
m_CurrentRenderingHint(osg::StateSet::DEFAULT_BIN)
|
||||
_namesUseCodepage(namesUseCodepage),
|
||||
m_CurrentRenderingHint(osg::StateSet::DEFAULT_BIN),
|
||||
_lastGeneratedImageFileName(0),
|
||||
_directory(directory),
|
||||
_srcDirectory(srcDirectory),
|
||||
_options(options)
|
||||
{
|
||||
success = true;
|
||||
|
||||
@ -198,8 +205,9 @@ void daeWriter::updateCurrentDaeNode()
|
||||
}
|
||||
}
|
||||
|
||||
std::string daeWriter::uniquify( const std::string &name )
|
||||
std::string daeWriter::uniquify( const std::string &_name )
|
||||
{
|
||||
const std::string name( _namesUseCodepage ? osgDB::convertStringFromCurrentCodePageToUTF8(_name) : _name );
|
||||
std::map< std::string, int >::iterator iter = uniqueNames.find( name );
|
||||
if ( iter != uniqueNames.end() )
|
||||
{
|
||||
|
@ -136,7 +136,7 @@ class daeWriter : public osg::NodeVisitor
|
||||
protected:
|
||||
class ArrayNIndices;
|
||||
public:
|
||||
daeWriter( DAE *dae_, const std::string &fileURI, bool usePolygons=false, bool googleMode = false, TraversalMode tm=TRAVERSE_ALL_CHILDREN, bool writeExtras = true, bool earthTex = false, bool zUpAxis=false, bool forceTexture=false);
|
||||
daeWriter( DAE *dae_, const std::string &fileURI, const std::string & directory, const std::string & srcDirectory, const osgDB::ReaderWriter::Options * options, bool usePolygons=false, bool googleMode = false, TraversalMode tm=TRAVERSE_ALL_CHILDREN, bool writeExtras = true, bool earthTex = false, bool zUpAxis=false, bool linkOrignialTextures=false, bool forceTexture=false, bool namesUseCodepage=false);
|
||||
virtual ~daeWriter();
|
||||
|
||||
void setRootNode( const osg::Node &node );
|
||||
@ -310,7 +310,10 @@ private: //members
|
||||
/** indicates if the up axis is on Z axis*/
|
||||
bool m_ZUpAxis;
|
||||
|
||||
/** force the use an image for a texture, even if the file is not found*/
|
||||
/** link to original images instead of exporting */
|
||||
bool m_linkOrignialTextures;
|
||||
|
||||
/** force the use an image for a texture, even if the file is not found (when m_linkOrignialTextures). */
|
||||
bool m_ForceTexture;
|
||||
|
||||
/** Current RenderingHint */
|
||||
@ -318,6 +321,18 @@ private: //members
|
||||
int m_CurrentRenderingHint;
|
||||
|
||||
FindAnimatedNodeVisitor _animatedNodeCollector;
|
||||
|
||||
/** Number used when writing images with no name, to generate a file name. */
|
||||
unsigned int _lastGeneratedImageFileName;
|
||||
std::string _directory;
|
||||
std::string _srcDirectory;
|
||||
const osgDB::ReaderWriter::Options * _options;
|
||||
bool _namesUseCodepage;
|
||||
|
||||
typedef std::map<const osg::Image*, std::string> ImageSet;
|
||||
typedef std::set<std::string> ImageFilenameSet; // Sub-optimal because strings are doubled (in ImageSet). Moreover, an unordered_set (= hashset) would be more efficient (Waiting for unordered_set to be included in C++ standard ;) ).
|
||||
ImageSet _imageSet;
|
||||
ImageFilenameSet _imageFilenameSet;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user