From 7640e9535de1e51e508a07ed7a36c09d87d321c4 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 9 Mar 2011 14:44:14 +0000 Subject: [PATCH] From Sukender, "1. Made code a bit more readable/cleaner. 2. Removed unecessary code. Also made sure the images names are not truncated in the middle of an UTF8 character. You'll find there a function called utf8TruncateBytes(), which may be moved in core OSG (osgDB/ConvertUTF I guess). Feel free to do it if you feel it that way. " --- src/osgPlugins/3ds/ReaderWriter3DS.cpp | 25 ++++---- src/osgPlugins/3ds/WriterNodeVisitor.cpp | 80 ++++++++++-------------- 2 files changed, 45 insertions(+), 60 deletions(-) diff --git a/src/osgPlugins/3ds/ReaderWriter3DS.cpp b/src/osgPlugins/3ds/ReaderWriter3DS.cpp index b4a57f15f..8cc49bc5b 100644 --- a/src/osgPlugins/3ds/ReaderWriter3DS.cpp +++ b/src/osgPlugins/3ds/ReaderWriter3DS.cpp @@ -268,9 +268,9 @@ ReaderWriter3DS::ReaderObject::ReaderObject(const osgDB::ReaderWriter::Options* { if (opt == "noMatrixTransforms") noMatrixTransforms = true; - if (opt == "checkForEspilonIdentityMatrices") + else if (opt == "checkForEspilonIdentityMatrices") checkForEspilonIdentityMatrices = true; - if (opt == "restoreMatrixTransformsNoMeshes") + else if (opt == "restoreMatrixTransformsNoMeshes") restoreMatrixTransformsNoMeshes = true; } } @@ -487,13 +487,14 @@ osg::Node* ReaderWriter3DS::ReaderObject::processNode(StateSetMap drawStateMap,L // Retreive LOCAL transform static const osg::Matrix::value_type MATRIX_EPSILON = 1e-10; - osg::Matrix osgNodeMatrix( copyLib3dsMatrixToOsgMatrix(node->matrix) ); - + osg::Matrix osgWorldToNodeMatrix( copyLib3dsMatrixToOsgMatrix(node->matrix) ); + osg::Matrix osgWorldToParentNodeMatrix; if (node->parent) { // Matrices evaluated by lib3DS are multiplied by parents' ones - osgNodeMatrix *= osg::Matrix::inverse( copyLib3dsMatrixToOsgMatrix(node->parent->matrix) ); + osgWorldToParentNodeMatrix = copyLib3dsMatrixToOsgMatrix(node->parent->matrix); } + osg::Matrix osgNodeMatrix( osgWorldToNodeMatrix * osg::Matrix::inverse(osgWorldToParentNodeMatrix) ); // Test if we should create an intermediate Group (or MatrixTransform) and which matrix we should apply to the vertices osg::Group* group = NULL; @@ -505,20 +506,20 @@ osg::Node* ReaderWriter3DS::ReaderObject::processNode(StateSetMap drawStateMap,L osg::Matrix meshMat; if (mesh) { - if (!noMatrixTransforms) - { + if (!noMatrixTransforms) + { // There can be a transform directly on a mesh instance (= as if a osg::MatrixTransform and a osg::Geode were merged together) in object->pos/rot/scl - if (!pivoted) { - meshMat = osg::Matrix::inverse(copyLib3dsMatrixToOsgMatrix(mesh->matrix)); - } else { + if (pivoted) { meshMat = osg::Matrix::inverse(copyLib3dsMatrixToOsgMatrix(mesh->matrix)) * osg::Matrix::translate(-pivot); + } else { + meshMat = osg::Matrix::inverse(copyLib3dsMatrixToOsgMatrix(mesh->matrix)); } } else { if (pivoted) { - meshMat = osg::Matrix::inverse(copyLib3dsMatrixToOsgMatrix(mesh->matrix)) * osg::Matrix::translate(-pivot) * copyLib3dsMatrixToOsgMatrix(node->matrix); + meshMat = osg::Matrix::inverse(copyLib3dsMatrixToOsgMatrix(mesh->matrix)) * osg::Matrix::translate(-pivot) * osgWorldToNodeMatrix; } else { - meshMat = osg::Matrix::inverse(copyLib3dsMatrixToOsgMatrix(mesh->matrix)) * copyLib3dsMatrixToOsgMatrix(node->matrix); + meshMat = osg::Matrix::inverse(copyLib3dsMatrixToOsgMatrix(mesh->matrix)) * osgWorldToNodeMatrix; // ==Identity when not pivoted? } osgNodeMatrix = osg::Matrix::identity(); // Not sure it's useful, but it's harmless ;) } diff --git a/src/osgPlugins/3ds/WriterNodeVisitor.cpp b/src/osgPlugins/3ds/WriterNodeVisitor.cpp index 648bd6829..26711238f 100644 --- a/src/osgPlugins/3ds/WriterNodeVisitor.cpp +++ b/src/osgPlugins/3ds/WriterNodeVisitor.cpp @@ -91,6 +91,7 @@ std::string getFileName(const std::string & path) /// Checks if a filename (\b not path) is 8.3 (an empty name is never 8.3, and a path is never 8.3). +/// Please note the '8' and '3' limitations are in \b bytes, not in characters (which is different when using UTF8). bool is83(const std::string & s) { // 012345678901 @@ -441,49 +442,6 @@ WriterNodeVisitor::Material::Material(WriterNodeVisitor & writerNodeVisitor, osg } -// If 'to' is in a subdirectory of 'from' then this function returns the -// subpath. Otherwise it just returns the file name. -// (Same as in FBX plugin) -std::string getPathRelative(const std::string& from/*directory*/, - const std::string& to/*file path*/) -{ - - std::string::size_type slash = to.find_last_of('/'); - std::string::size_type backslash = to.find_last_of('\\'); - if (slash == std::string::npos) - { - if (backslash == std::string::npos) return to; - slash = backslash; - } - else if (backslash != std::string::npos && backslash > slash) - { - slash = backslash; - } - - if (from.empty() || from.length() > to.length()) - return osgDB::getSimpleFileName(to); - - std::string::const_iterator itTo = to.begin(); - for (std::string::const_iterator itFrom = from.begin(); - itFrom != from.end(); ++itFrom, ++itTo) - { - char a = tolower(*itFrom), b = tolower(*itTo); - if (a == '\\') a = '/'; - if (b == '\\') b = '/'; - if (a != b || itTo == to.begin() + slash + 1) - { - return osgDB::getSimpleFileName(to); - } - } - - while (itTo != to.end() && (*itTo == '\\' || *itTo == '/')) - { - ++itTo; - } - - return std::string(itTo, to.end()); -} - /// Converts an extension to a 3-letters long one equivalent. std::string convertExt(const std::string & path, bool extendedFilePaths) { @@ -562,7 +520,7 @@ void WriterNodeVisitor::writeMaterials() } else { - path = getPathRelative(_srcDirectory, mat.image->getFileName()); + path = osgDB::getPathRelative(_srcDirectory, mat.image->getFileName()); } path = convertExt(path, _extendedFilePaths); @@ -597,6 +555,31 @@ void WriterNodeVisitor::writeMaterials() } } +/// Truncates an UTF8 string so that it does not takes more than a given \b bytes amount (\b excluding the potential NULL end character). +/// The function assumes the UTF8 string is valid. +///\return A valid UTF8 string which size is less or equal to \c byteLimit. +// May be moved in osgDB/ConvertUTF? +std::string utf8TruncateBytes(const std::string & s, std::string::size_type byteLimit) { + // Untruncated strings + if (s.size() <= byteLimit) return s; + + // Truncated strings + std::string::const_iterator it=s.begin(), itEnd=s.begin()+byteLimit; + std::string::const_iterator itStop=it; + // Note: itEnd is < s.end(), so that we can always write "it+1" + for(; it!=itEnd; ++it) { + unsigned char c = static_cast(*it); + if ((c & 0x80) == 0) itStop=it+1; // 7 bits ANSI. itStop must then point after that character. + else if ((c & 0x40) != 0) itStop=it; // UTF8 sequence start: this is also past-the-end for the previous character (ANSI or UTF8) + } + return std::string(s.begin(), itStop); +} + +#ifdef OSG_USE_UTF8_FILENAME +# define truncateFilenameBytes(str, size) utf8TruncateBytes(str, size) +#else +# define truncateFilenameBytes(str, size) std::string(str, 0, size) +#endif std::string WriterNodeVisitor::getUniqueName(const std::string& _defaultValue, const std::string & _defaultPrefix, bool nameIsPath) { @@ -615,7 +598,8 @@ std::string WriterNodeVisitor::getUniqueName(const std::string& _defaultValue, c // Handling of paths is not well done yet. Defaulting to something very simple. // We should actually ensure each component is 8 chars long, and final filename is 8.3, and total is <64 chars, or simply ensure total length for extended 3DS paths. std::string defaultValue(nameIsPath ? osgDB::getSimpleFileName(_defaultValue) : _defaultValue); - std::string ext(nameIsPath ? osgDB::getFileExtensionIncludingDot(_defaultValue).substr(0, std::min(_defaultValue.size(), 4)) : ""); // 4 chars = dot + 3 chars + std::string ext(nameIsPath ? osgDB::getFileExtensionIncludingDot(_defaultValue) : ""); + ext = truncateFilenameBytes(ext, std::min(_defaultValue.size(), 4)); // 4 chars = dot + 3 chars if (ext == ".") ext = ""; std::string defaultPrefix(_defaultPrefix.empty() ? "_" : _defaultPrefix); @@ -626,12 +610,12 @@ std::string WriterNodeVisitor::getUniqueName(const std::string& _defaultValue, c { if (defaultValue[i] == '.') { - truncDefaultValue = defaultValue.substr(0, i); + truncDefaultValue = truncateFilenameBytes(defaultValue, i); break; } } if (truncDefaultValue.empty()) - truncDefaultValue = defaultValue.substr(0, std::min(defaultValue.size(), MAX_PREFIX_LEGNTH)); + truncDefaultValue = truncateFilenameBytes(defaultValue, std::min(defaultValue.size(), MAX_PREFIX_LEGNTH)); assert(truncDefaultValue.size() <= MAX_PREFIX_LEGNTH); std::map::iterator pairPrefix; @@ -680,7 +664,7 @@ std::string WriterNodeVisitor::getUniqueName(const std::string& _defaultValue, c // Failed finding a name // Try with a shorter prefix if possible - if (defaultPrefix.length()>1) return getUniqueName(_defaultValue, defaultPrefix.substr(0, defaultPrefix.length()-1), nameIsPath); + if (defaultPrefix.length()>1) return getUniqueName(_defaultValue, truncateFilenameBytes(defaultPrefix, defaultPrefix.length()-1), nameIsPath); // Try with default prefix if not arleady done if (defaultPrefix != std::string("_")) return getUniqueName(_defaultValue, "_", nameIsPath);