Forráskód Böngészése

Collada ZAE import must convert manifest and image paths

Moved ConvertPath into ColladaParser and use it when reading all filenames from the XML

Added more EXPECTS to the Collada tests
RichardTea 6 éve
szülő
commit
ce5c71d2e7

+ 1 - 1
code/Collada/ColladaHelper.h

@@ -583,7 +583,7 @@ struct Image
     /** Embedded image data */
     /** Embedded image data */
     std::vector<uint8_t> mImageData;
     std::vector<uint8_t> mImageData;
 
 
-    /** File format hint ofembedded image data */
+    /** File format hint of embedded image data */
     std::string mEmbeddedFormat;
     std::string mEmbeddedFormat;
 };
 };
 
 

+ 3 - 53
code/Collada/ColladaLoader.cpp

@@ -1735,6 +1735,7 @@ void ColladaLoader::BuildMaterials(ColladaParser& pParser, aiScene* /*pScene*/)
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Resolves the texture name for the given effect texture entry
 // Resolves the texture name for the given effect texture entry
+// and loads the texture data 
 aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser& pParser,
 aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser& pParser,
     const Collada::Effect& pEffect, const std::string& pName)
     const Collada::Effect& pEffect, const std::string& pName)
 {
 {
@@ -1762,7 +1763,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser& pParse
 
 
         //set default texture file name
         //set default texture file name
         result.Set(name + ".jpg");
         result.Set(name + ".jpg");
-        ConvertPath(result);
+        ColladaParser::ConvertPath(result);
         return result;
         return result;
     }
     }
 
 
@@ -1781,7 +1782,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser& pParse
 
 
 
 
         // setup format hint
         // setup format hint
-        if (imIt->second.mEmbeddedFormat.length() > 3) {
+        if (imIt->second.mEmbeddedFormat.length() >= HINTMAXTEXTURELEN) {
             ASSIMP_LOG_WARN("Collada: texture format hint is too long, truncating to 3 characters");
             ASSIMP_LOG_WARN("Collada: texture format hint is too long, truncating to 3 characters");
         }
         }
         strncpy(tex->achFormatHint, imIt->second.mEmbeddedFormat.c_str(), 3);
         strncpy(tex->achFormatHint, imIt->second.mEmbeddedFormat.c_str(), 3);
@@ -1802,61 +1803,10 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser& pParse
         }
         }
 
 
         result.Set(imIt->second.mFileName);
         result.Set(imIt->second.mFileName);
-        ConvertPath(result);
     }
     }
     return result;
     return result;
 }
 }
 
 
-// ------------------------------------------------------------------------------------------------
-// Convert a path read from a collada file to the usual representation
-void ColladaLoader::ConvertPath(aiString& ss)
-{
-    // TODO: collada spec, p 22. Handle URI correctly.
-    // For the moment we're just stripping the file:// away to make it work.
-    // Windows doesn't seem to be able to find stuff like
-    // 'file://..\LWO\LWO2\MappingModes\earthSpherical.jpg'
-    if (0 == strncmp(ss.data, "file://", 7))
-    {
-        ss.length -= 7;
-        memmove(ss.data, ss.data + 7, ss.length);
-        ss.data[ss.length] = '\0';
-    }
-
-    // Maxon Cinema Collada Export writes "file:///C:\andsoon" with three slashes...
-    // I need to filter it without destroying linux paths starting with "/somewhere"
-#if defined( _MSC_VER )
-    if (ss.data[0] == '/' && isalpha((unsigned char)ss.data[1]) && ss.data[2] == ':') {
-#else
-    if (ss.data[0] == '/' && isalpha(ss.data[1]) && ss.data[2] == ':') {
-#endif
-        --ss.length;
-        ::memmove(ss.data, ss.data + 1, ss.length);
-        ss.data[ss.length] = 0;
-    }
-
-    // find and convert all %xy special chars
-    char* out = ss.data;
-    for (const char* it = ss.data; it != ss.data + ss.length; /**/)
-    {
-        if (*it == '%' && (it + 3) < ss.data + ss.length)
-        {
-            // separate the number to avoid dragging in chars from behind into the parsing
-            char mychar[3] = { it[1], it[2], 0 };
-            size_t nbr = strtoul16(mychar);
-            it += 3;
-            *out++ = (char)(nbr & 0xFF);
-        }
-        else
-        {
-            *out++ = *it++;
-        }
-    }
-
-    // adjust length and terminator of the shortened string
-    *out = 0;
-    ss.length = (ptrdiff_t)(out - ss.data);
-}
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Reads a float value from an accessor and its data array.
 // Reads a float value from an accessor and its data array.
 ai_real ColladaLoader::ReadFloat(const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex, size_t pOffset) const
 ai_real ColladaLoader::ReadFloat(const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex, size_t pOffset) const

+ 1 - 4
code/Collada/ColladaLoader.h

@@ -94,7 +94,7 @@ public:
 public:
 public:
     /** Returns whether the class can handle the format of the given file.
     /** Returns whether the class can handle the format of the given file.
      * See BaseImporter::CanRead() for details. */
      * See BaseImporter::CanRead() for details. */
-    bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const override;
+    bool CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const override;
 
 
 protected:
 protected:
     /** Return importer meta information.
     /** Return importer meta information.
@@ -184,9 +184,6 @@ protected:
     aiString FindFilenameForEffectTexture( const ColladaParser& pParser,
     aiString FindFilenameForEffectTexture( const ColladaParser& pParser,
         const Collada::Effect& pEffect, const std::string& pName);
         const Collada::Effect& pEffect, const std::string& pName);
 
 
-    /** Converts a path read from a collada file to the usual representation */
-    void ConvertPath( aiString& ss);
-
     /** Reads a float value from an accessor and its data array.
     /** Reads a float value from an accessor and its data array.
      * @param pAccessor The accessor to use for reading
      * @param pAccessor The accessor to use for reading
      * @param pData The data array to read from
      * @param pData The data array to read from

+ 66 - 3
code/Collada/ColladaParser.cpp

@@ -183,13 +183,66 @@ std::string ColladaParser::ReadZaeManifest(ZipArchiveIOSystem &zip_archive) {
                 if (filepath == nullptr)
                 if (filepath == nullptr)
                     return std::string();
                     return std::string();
 
 
-                return std::string(filepath);
+                aiString ai_str(filepath);
+                ConvertPath(ai_str);
+
+                return std::string(ai_str.C_Str());
             }
             }
         }
         }
     }
     }
     return std::string();
     return std::string();
 }
 }
 
 
+// ------------------------------------------------------------------------------------------------
+// Convert a path read from a collada file to the usual representation
+void ColladaParser::ConvertPath(aiString& ss)
+{
+    // TODO: collada spec, p 22. Handle URI correctly.
+    // For the moment we're just stripping the file:// away to make it work.
+    // Windows doesn't seem to be able to find stuff like
+    // 'file://..\LWO\LWO2\MappingModes\earthSpherical.jpg'
+    if (0 == strncmp(ss.data, "file://", 7))
+    {
+        ss.length -= 7;
+        memmove(ss.data, ss.data + 7, ss.length);
+        ss.data[ss.length] = '\0';
+    }
+
+    // Maxon Cinema Collada Export writes "file:///C:\andsoon" with three slashes...
+    // I need to filter it without destroying linux paths starting with "/somewhere"
+#if defined( _MSC_VER )
+    if (ss.data[0] == '/' && isalpha((unsigned char)ss.data[1]) && ss.data[2] == ':') {
+#else
+    if (ss.data[0] == '/' && isalpha(ss.data[1]) && ss.data[2] == ':') {
+#endif
+        --ss.length;
+        ::memmove(ss.data, ss.data + 1, ss.length);
+        ss.data[ss.length] = 0;
+    }
+
+    // find and convert all %xy special chars
+    char* out = ss.data;
+    for (const char* it = ss.data; it != ss.data + ss.length; /**/)
+    {
+        if (*it == '%' && (it + 3) < ss.data + ss.length)
+        {
+            // separate the number to avoid dragging in chars from behind into the parsing
+            char mychar[3] = { it[1], it[2], 0 };
+            size_t nbr = strtoul16(mychar);
+            it += 3;
+            *out++ = (char)(nbr & 0xFF);
+        }
+        else
+        {
+            *out++ = *it++;
+        }
+    }
+
+    // adjust length and terminator of the shortened string
+    *out = 0;
+    ss.length = (ptrdiff_t)(out - ss.data);
+}
+
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Read bool from text contents of current element
 // Read bool from text contents of current element
 bool ColladaParser::ReadBoolFromTextContent()
 bool ColladaParser::ReadBoolFromTextContent()
@@ -1120,7 +1173,12 @@ void ColladaParser::ReadImage(Collada::Image& pImage)
                     if (!mReader->isEmptyElement()) {
                     if (!mReader->isEmptyElement()) {
                         // element content is filename - hopefully
                         // element content is filename - hopefully
                         const char* sz = TestTextContent();
                         const char* sz = TestTextContent();
-                        if (sz)pImage.mFileName = sz;
+                        if (sz)
+                        {
+                            aiString filepath(sz);
+                            ConvertPath(filepath);
+                            pImage.mFileName = filepath.C_Str();
+                        }
                         TestClosing("init_from");
                         TestClosing("init_from");
                     }
                     }
                     if (!pImage.mFileName.length()) {
                     if (!pImage.mFileName.length()) {
@@ -1153,7 +1211,12 @@ void ColladaParser::ReadImage(Collada::Image& pImage)
                 {
                 {
                     // element content is filename - hopefully
                     // element content is filename - hopefully
                     const char* sz = TestTextContent();
                     const char* sz = TestTextContent();
-                    if (sz)pImage.mFileName = sz;
+                    if (sz)
+                    {
+                        aiString filepath(sz);
+                        ConvertPath(filepath);
+                        pImage.mFileName = filepath.C_Str();
+                    }
                     TestClosing("ref");
                     TestClosing("ref");
                 }
                 }
                 else if (IsElement("hex") && !pImage.mFileName.length())
                 else if (IsElement("hex") && !pImage.mFileName.length())

+ 4 - 1
code/Collada/ColladaParser.h

@@ -66,12 +66,15 @@ namespace Assimp
     {
     {
         friend class ColladaLoader;
         friend class ColladaLoader;
 
 
+        /** Converts a path read from a collada file to the usual representation */
+        static void ConvertPath(aiString& ss);
+
     protected:
     protected:
         /** Map for generic metadata as aiString */
         /** Map for generic metadata as aiString */
         typedef std::map<std::string, aiString> StringMetaData;
         typedef std::map<std::string, aiString> StringMetaData;
 
 
         /** Constructor from XML file */
         /** Constructor from XML file */
-        ColladaParser( IOSystem* pIOHandler, const std::string& pFile);
+        ColladaParser(IOSystem* pIOHandler, const std::string& pFile);
 
 
         /** Destructor */
         /** Destructor */
         ~ColladaParser();
         ~ColladaParser();

+ 25 - 2
test/unit/utColladaImportExport.cpp

@@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "AbstractImportExportBase.h"
 #include "AbstractImportExportBase.h"
 
 
 #include <assimp/Importer.hpp>
 #include <assimp/Importer.hpp>
+#include <assimp/scene.h>
 #include <assimp/postprocess.h>
 #include <assimp/postprocess.h>
 
 
 using namespace Assimp;
 using namespace Assimp;
@@ -53,7 +54,18 @@ public:
     virtual bool importerTest() {
     virtual bool importerTest() {
         Assimp::Importer importer;
         Assimp::Importer importer;
         const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/Collada/duck.dae", aiProcess_ValidateDataStructure );
         const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/Collada/duck.dae", aiProcess_ValidateDataStructure );
-        return nullptr != scene;
+        if (scene == nullptr)
+            return false;
+
+        // Expected number of items
+        EXPECT_EQ(scene->mNumMeshes, 1);
+        EXPECT_EQ(scene->mNumMaterials, 1);
+        EXPECT_EQ(scene->mNumAnimations, 0);
+        EXPECT_EQ(scene->mNumTextures, 0);
+        EXPECT_EQ(scene->mNumLights, 1);
+        EXPECT_EQ(scene->mNumCameras, 1);
+
+        return true;
     }
     }
 };
 };
 
 
@@ -66,7 +78,18 @@ public:
     virtual bool importerTest() {
     virtual bool importerTest() {
         Assimp::Importer importer;
         Assimp::Importer importer;
         const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck.zae", aiProcess_ValidateDataStructure);
         const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck.zae", aiProcess_ValidateDataStructure);
-        return nullptr != scene;
+        if (scene == nullptr)
+            return false;
+
+        // Expected number of items
+        EXPECT_EQ(scene->mNumMeshes, 1);
+        EXPECT_EQ(scene->mNumMaterials, 1);
+        EXPECT_EQ(scene->mNumAnimations, 0);
+        EXPECT_EQ(scene->mNumTextures, 1);
+        EXPECT_EQ(scene->mNumLights, 1);
+        EXPECT_EQ(scene->mNumCameras, 1);
+
+        return true;
     }
     }
 };
 };