Bläddra i källkod

FBX Embedding Fix

FBX files may use a texture reference from an embedded texture that hasn't been loaded yet. This patch fixes this issue, storing all texture filenames, that can be acessed later via "scene::GetEmbeddedTexture", when all textures are already loaded.
Some warnings have been added to other file formats that uses embedded data.
rickomax 7 år sedan
förälder
incheckning
4623c2f14c
6 ändrade filer med 49 tillägg och 23 borttagningar
  1. 5 0
      code/ColladaLoader.cpp
  2. 12 18
      code/FBXConverter.cpp
  3. 4 4
      code/FBXImportSettings.h
  4. 1 1
      code/FBXImporter.cpp
  5. 21 0
      include/assimp/scene.h
  6. 6 0
      include/assimp/texture.h

+ 5 - 0
code/ColladaLoader.cpp

@@ -1778,6 +1778,11 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
         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 thru 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()));

+ 12 - 18
code/FBXConverter.cpp

@@ -436,18 +436,6 @@ private:
 
     aiScene* const out;
     const FBX::Document& doc;
-
-	bool FindTextureIndexByFilename(const Video& video, unsigned int& index) {
-		index = 0;
-		const char* videoFileName = video.FileName().c_str();
-		for (auto texture = textures_converted.begin(); texture != textures_converted.end(); ++texture) {
-			if (!strcmp(texture->first->FileName().c_str(), videoFileName)) {
-                index = texture->second;
-				return true;
-			}
-		}
-		return false;
-	}
 };
 
 Converter::Converter( aiScene* out, const Document& doc )
@@ -1776,6 +1764,8 @@ unsigned int Converter::ConvertVideo( const Video& video )
         memcpy( out_tex->achFormatHint, ext.c_str(), ext.size() );
     }
 
+    out_tex->mFilename.Set(video.FileName().c_str());
+
     return static_cast<unsigned int>( textures.size() - 1 );
 }
 
@@ -1810,15 +1800,19 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap&
 					textures_converted[media] = index;
 					textureReady = true;
 				}
-				else if (doc.Settings().searchEmbeddedTextures) { //try to find the texture on the already-loaded textures by the filename, if the flag is on					
-					textureReady = FindTextureIndexByFilename(*media, index);
-				}
 			}
 
 			// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture), if the texture is ready
-			if (textureReady) {
-				path.data[0] = '*';
-				path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
+			if (doc.Settings().useLegacyEmbeddedTextureNaming) {
+                if (textureReady) {
+                    // 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 thru 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
+                    path.data[0] = '*';
+                    path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
+                }
 			}
 		}  
 

+ 4 - 4
code/FBXImportSettings.h

@@ -63,7 +63,7 @@ struct ImportSettings
         , readWeights(true)
         , preservePivots(true)
         , optimizeEmptyAnimationCurves(true)
-		, searchEmbeddedTextures(false)
+        , useLegacyEmbeddedTextureNaming(false)
     {}
 
 
@@ -139,9 +139,9 @@ struct ImportSettings
      *  The default value is true. */
     bool optimizeEmptyAnimationCurves;
 
-	/** search for embedded loaded textures, where no embedded texture data is provided.
-	*  The default value is false. */
-	bool searchEmbeddedTextures;
+    /** use legacy naming for embedded textures eg: (*0, *1, *2)
+    **/
+    bool useLegacyEmbeddedTextureNaming;
 };
 
 

+ 1 - 1
code/FBXImporter.cpp

@@ -135,7 +135,7 @@ void FBXImporter::SetupProperties(const Importer* pImp)
     settings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
     settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
     settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
-	settings.searchEmbeddedTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_SEARCH_EMBEDDED_TEXTURES, false);
+    settings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
 }
 
 // ------------------------------------------------------------------------------------------------

+ 21 - 0
include/assimp/scene.h

@@ -366,6 +366,27 @@ struct aiScene
         return mAnimations != NULL && mNumAnimations > 0; 
     }
 
+    //! Returns a short filename from a full path
+    static const char* GetShortFilename(const char* filename) {
+        const char* lastSlash = strrchr(filename, '/');
+        if (lastSlash == '\0') {
+            lastSlash = strrchr(filename, '\\');
+        }
+        const char* shortFilename = lastSlash != '\0' ? lastSlash + 1 : filename;
+        return shortFilename;
+    }
+
+    //! Returns an embedded texture
+    const aiTexture* GetEmbeddedTexture(const char* filename) {
+        const char* shortFilename = GetShortFilename(filename);
+        for (unsigned int i = 0; i < mNumTextures; i++) {
+            const char* shortTextureFilename = GetShortFilename(mTextures[i]->mFilename.C_Str());
+            if (strcmp(shortTextureFilename, shortFilename) == 0) {
+                return mTextures[i];
+            }
+        }
+        return nullptr;
+    }
 #endif // __cplusplus
 
     /**  Internal data, do not touch */

+ 6 - 0
include/assimp/texture.h

@@ -179,6 +179,12 @@ struct aiTexture
      */
     C_STRUCT aiTexel* pcData;
 
+    /** Texture original filename
+    *
+    * Used to get the texture reference
+    */
+    C_STRUCT aiString mFilename;
+
 #ifdef __cplusplus
 
     //! For compressed textures (mHeight == 0): compare the