소스 검색

Read embedded textures from Collada ZAE

RichardTea 6 년 전
부모
커밋
2a72c9b616
5개의 변경된 파일48개의 추가작업 그리고 27개의 파일을 삭제
  1. 2 6
      code/Collada/ColladaHelper.h
  2. 19 17
      code/Collada/ColladaLoader.cpp
  3. 3 3
      code/Collada/ColladaLoader.h
  4. 21 1
      code/Collada/ColladaParser.cpp
  5. 3 0
      code/Collada/ColladaParser.h

+ 2 - 6
code/Collada/ColladaHelper.h

@@ -580,15 +580,11 @@ struct Image
 {
     std::string mFileName;
 
-    /** If image file name is zero, embedded image data
-     */
+    /** Embedded image data */
     std::vector<uint8_t> mImageData;
 
-    /** If image file name is zero, file format of
-     *  embedded image data.
-     */
+    /** File format hint ofembedded image data */
     std::string mEmbeddedFormat;
-
 };
 
 /** An animation channel. */

+ 19 - 17
code/Collada/ColladaLoader.cpp

@@ -235,6 +235,9 @@ void ColladaLoader::InternReadFile(const std::string& pFile, aiScene* pScene, IO
     // store all materials
     StoreSceneMaterials(pScene);
 
+    // store all textures
+    StoreSceneTextures(pScene);
+
     // store all lights
     StoreSceneLights(pScene);
 
@@ -927,8 +930,7 @@ void ColladaLoader::StoreSceneLights(aiScene* pScene)
 void ColladaLoader::StoreSceneTextures(aiScene* pScene)
 {
     pScene->mNumTextures = static_cast<unsigned int>(mTextures.size());
-    if (mTextures.size() > 0)
-    {
+    if (mTextures.size() > 0) {
         pScene->mTextures = new aiTexture*[mTextures.size()];
         std::copy(mTextures.begin(), mTextures.end(), pScene->mTextures);
         mTextures.clear();
@@ -1728,7 +1730,7 @@ void ColladaLoader::BuildMaterials(ColladaParser& pParser, aiScene* /*pScene*/)
         mat->AddProperty(&colSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
         const ai_real specExp = 5.0;
         mat->AddProperty(&specExp, 1, AI_MATKEY_SHININESS);
-    }
+}
 #endif
 }
 
@@ -1766,14 +1768,19 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser& pParse
     }
 
     // if this is an embedded texture image setup an aiTexture for it
-    if (imIt->second.mFileName.empty())
+    if (!imIt->second.mImageData.empty())
     {
-        if (imIt->second.mImageData.empty()) {
-            throw DeadlyImportError("Collada: Invalid texture, no data or file reference given");
-        }
-
         aiTexture* tex = new aiTexture();
 
+        // Store embedded texture name reference
+        tex->mFilename.Set(imIt->second.mFileName.c_str());
+        result.Set(imIt->second.mFileName);
+
+        // TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
+//        result.data[0] = '*';
+//        result.length = 1 + ASSIMP_itoa10(result.data + 1, static_cast<unsigned int>(MAXLEN - 1), static_cast<int32_t>(mTextures.size()));
+
+
         // setup format hint
         if (imIt->second.mEmbeddedFormat.length() > 3) {
             ASSIMP_LOG_WARN("Collada: texture format hint is too long, truncating to 3 characters");
@@ -1786,20 +1793,15 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser& pParse
         tex->pcData = (aiTexel*)new char[tex->mWidth];
         memcpy(tex->pcData, &imIt->second.mImageData[0], tex->mWidth);
 
-        // TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
-        // In FBX files textures are now stored internally by Assimp with their filename included
-        // Now Assimp can lookup through the loaded textures after all data is processed
-        // We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it
-        // This may occur on this case too, it has to be studied
-        // setup texture reference string
-        result.data[0] = '*';
-        result.length = 1 + ASSIMP_itoa10(result.data + 1, static_cast<unsigned int>(MAXLEN - 1), static_cast<int32_t>(mTextures.size()));
-
         // and add this texture to the list
         mTextures.push_back(tex);
     }
     else
     {
+        if (imIt->second.mFileName.empty()) {
+            throw DeadlyImportError("Collada: Invalid texture, no data or file reference given");
+        }
+
         result.Set(imIt->second.mFileName);
         ConvertPath(result);
     }

+ 3 - 3
code/Collada/ColladaLoader.h

@@ -100,14 +100,14 @@ protected:
     /** Return importer meta information.
      * See #BaseImporter::GetInfo for the details
      */
-    const aiImporterDesc* GetInfo () const;
+    const aiImporterDesc* GetInfo () const override;
 
-    void SetupProperties(const Importer* pImp);
+    void SetupProperties(const Importer* pImp) override;
 
     /** Imports the given file into the given scene structure.
      * See BaseImporter::InternReadFile() for details
      */
-    void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+    void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) override;
 
     /** Recursively constructs a scene node for the given parser node and returns it. */
     aiNode* BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode);

+ 21 - 1
code/Collada/ColladaParser.cpp

@@ -132,7 +132,7 @@ ColladaParser::ColladaParser(IOSystem* pIOHandler, const std::string& pFile)
 
     // read embedded textures
     if (zip_archive && zip_archive->isOpen()) {
-        // TODO
+        ReadEmbeddedTextures(*zip_archive);
     }
 }
 
@@ -3056,6 +3056,26 @@ void ColladaParser::ReadMaterialVertexInputBinding(Collada::SemanticMappingTable
     }
 }
 
+void Assimp::ColladaParser::ReadEmbeddedTextures(ZipArchiveIOSystem& zip_archive)
+{
+    // Attempt to load any undefined Collada::Image in ImageLibrary
+    for (ImageLibrary::iterator it = mImageLibrary.begin(); it != mImageLibrary.end(); ++it) {
+        Collada::Image &image = (*it).second;
+
+        if (image.mImageData.empty()) {
+            std::unique_ptr<IOStream> image_file(zip_archive.Open(image.mFileName.c_str()));
+            if (image_file) {
+                image.mImageData.resize(image_file->FileSize());
+                image_file->Read(image.mImageData.data(), image_file->FileSize(), 1);
+                image.mEmbeddedFormat = BaseImporter::GetExtension(image.mFileName);
+                if (image.mEmbeddedFormat == "jpeg") {
+                    image.mEmbeddedFormat = "jpg";
+                }
+            }
+        }
+    }
+}
+
 // ------------------------------------------------------------------------------------------------
 // Reads a mesh reference in a node and adds it to the node's mesh list
 void ColladaParser::ReadNodeGeometry(Node* pNode)

+ 3 - 0
code/Collada/ColladaParser.h

@@ -239,6 +239,9 @@ namespace Assimp
         // Processes bind_vertex_input and bind elements
         void ReadMaterialVertexInputBinding( Collada::SemanticMappingTable& tbl);
 
+        /** Reads embedded textures from a ZAE archive*/
+        void ReadEmbeddedTextures(ZipArchiveIOSystem &zip_archive);
+
     protected:
         /** Aborts the file reading with an exception */
         AI_WONT_RETURN void ThrowException( const std::string& pError) const AI_WONT_RETURN_SUFFIX;