Browse Source

Merge pull request #1347 from rickomax/master

Fixed many FBX bugs
Kim Kulling 8 years ago
parent
commit
123d06ca1c
6 changed files with 97 additions and 44 deletions
  1. 40 17
      code/FBXConverter.cpp
  2. 5 0
      code/FBXImportSettings.h
  3. 1 0
      code/FBXImporter.cpp
  4. 29 24
      code/FBXMaterial.cpp
  5. 12 0
      code/FBXParser.h
  6. 10 3
      include/assimp/config.h.in

+ 40 - 17
code/FBXConverter.cpp

@@ -436,6 +436,19 @@ private:
 
 
     aiScene* const out;
     aiScene* const out;
     const FBX::Document& doc;
     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)) {
+				return true;
+			}
+			index++;
+		}
+		return false;
+	}
 };
 };
 
 
 Converter::Converter( aiScene* out, const Document& doc )
 Converter::Converter( aiScene* out, const Document& doc )
@@ -1749,7 +1762,7 @@ unsigned int Converter::ConvertVideo( const Video& video )
     out_tex->mWidth = static_cast<unsigned int>( video.ContentLength() ); // total data size
     out_tex->mWidth = static_cast<unsigned int>( video.ContentLength() ); // total data size
     out_tex->mHeight = 0; // fixed to 0
     out_tex->mHeight = 0; // fixed to 0
 
 
-                            // steal the data from the Video to avoid an additional copy
+    // steal the data from the Video to avoid an additional copy
     out_tex->pcData = reinterpret_cast<aiTexel*>( const_cast<Video&>( video ).RelinquishContent() );
     out_tex->pcData = reinterpret_cast<aiTexel*>( const_cast<Video&>( video ).RelinquishContent() );
 
 
     // try to extract a hint from the file extension
     // try to extract a hint from the file extension
@@ -1783,22 +1796,32 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap&
         path.Set( tex->RelativeFilename() );
         path.Set( tex->RelativeFilename() );
 
 
         const Video* media = tex->Media();
         const Video* media = tex->Media();
-        if ( media != 0 && media->ContentLength() > 0 ) {
-            unsigned int index;
-
-            VideoMap::const_iterator it = textures_converted.find( media );
-            if ( it != textures_converted.end() ) {
-                index = ( *it ).second;
-            }
-            else {
-                index = ConvertVideo( *media );
-                textures_converted[ media ] = index;
-            }
-
-            // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
-            path.data[ 0 ] = '*';
-            path.length = 1 + ASSIMP_itoa10( path.data + 1, MAXLEN - 1, index );
-        }
+        if (media != 0) {
+			bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found)
+			unsigned int index;
+
+			VideoMap::const_iterator it = textures_converted.find(media);
+			if (it != textures_converted.end()) {
+				index = (*it).second;
+				textureReady = true;
+			}
+			else {
+				if (media->ContentLength() > 0) {
+					index = ConvertVideo(*media);
+					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);
+			}
+		}  
 
 
         out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, 0 );
         out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, 0 );
 
 

+ 5 - 0
code/FBXImportSettings.h

@@ -63,6 +63,7 @@ struct ImportSettings
         , readWeights(true)
         , readWeights(true)
         , preservePivots(true)
         , preservePivots(true)
         , optimizeEmptyAnimationCurves(true)
         , optimizeEmptyAnimationCurves(true)
+		, searchEmbeddedTextures(false)
     {}
     {}
 
 
 
 
@@ -137,6 +138,10 @@ struct ImportSettings
      *  values matching the corresponding node transformation.
      *  values matching the corresponding node transformation.
      *  The default value is true. */
      *  The default value is true. */
     bool optimizeEmptyAnimationCurves;
     bool optimizeEmptyAnimationCurves;
+
+	/** search for embedded loaded textures, where no embedded texture data is provided.
+	*  The default value is false. */
+	bool searchEmbeddedTextures;
 };
 };
 
 
 
 

+ 1 - 0
code/FBXImporter.cpp

@@ -131,6 +131,7 @@ void FBXImporter::SetupProperties(const Importer* pImp)
     settings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
     settings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
     settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
     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.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
+	settings.searchEmbeddedTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_SEARCH_EMBEDDED_TEXTURES, false);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

+ 29 - 24
code/FBXMaterial.cpp

@@ -281,7 +281,7 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
     const Scope& sc = GetRequiredScope(element);
     const Scope& sc = GetRequiredScope(element);
 
 
     const Element* const Type = sc["Type"];
     const Element* const Type = sc["Type"];
-    const Element* const FileName = sc["FileName"];
+    const Element* const FileName = sc.FindElementCaseInsensitive("FileName");  //some files retain the information as "Filename", others "FileName", who knows
     const Element* const RelativeFilename = sc["RelativeFilename"];
     const Element* const RelativeFilename = sc["RelativeFilename"];
     const Element* const Content = sc["Content"];
     const Element* const Content = sc["Content"];
 
 
@@ -291,35 +291,40 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
 
 
     if(FileName) {
     if(FileName) {
         fileName = ParseTokenAsString(GetRequiredToken(*FileName,0));
         fileName = ParseTokenAsString(GetRequiredToken(*FileName,0));
-    }
+	}
 
 
     if(RelativeFilename) {
     if(RelativeFilename) {
         relativeFileName = ParseTokenAsString(GetRequiredToken(*RelativeFilename,0));
         relativeFileName = ParseTokenAsString(GetRequiredToken(*RelativeFilename,0));
     }
     }
 
 
     if(Content) {
     if(Content) {
-        const Token& token = GetRequiredToken(*Content, 0);
-        const char* data = token.begin();
-        if(!token.IsBinary()) {
-            DOMWarning("video content is not binary data, ignoring", &element);
-        }
-        else if(static_cast<size_t>(token.end() - data) < 5) {
-            DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element);
-        }
-        else if(*data != 'R') {
-            DOMWarning("video content is not raw binary data, ignoring", &element);
-        }
-        else {
-            // read number of elements
-            uint32_t len = 0;
-            ::memcpy(&len, data + 1, sizeof(len));
-            AI_SWAP4(len);
-
-            contentLength = len;
-
-            content = new uint8_t[len];
-            ::memcpy(content, data + 5, len);
-        }
+		//this field is ommited when the embedded texture is already loaded, let's ignore if it´s not found
+		try {
+			const Token& token = GetRequiredToken(*Content, 0);
+			const char* data = token.begin();
+			if (!token.IsBinary()) {
+				DOMWarning("video content is not binary data, ignoring", &element);
+			}
+			else if (static_cast<size_t>(token.end() - data) < 5) {
+				DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element);
+			}
+			else if (*data != 'R') {
+				DOMWarning("video content is not raw binary data, ignoring", &element);
+			}
+			else {
+				// read number of elements
+				uint32_t len = 0;
+				::memcpy(&len, data + 1, sizeof(len));
+				AI_SWAP4(len);
+
+				contentLength = len;
+
+				content = new uint8_t[len];
+				::memcpy(content, data + 5, len);
+			}
+		} catch (runtime_error runtimeError) {
+			//we don´t need the content data for contents that has already been loaded
+		}
     }
     }
 
 
     props = GetPropertyTable(doc,"Video.FbxVideo",element,sc);
     props = GetPropertyTable(doc,"Video.FbxVideo",element,sc);

+ 12 - 0
code/FBXParser.h

@@ -49,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <map>
 #include <map>
 #include <memory>
 #include <memory>
 #include "LogAux.h"
 #include "LogAux.h"
+#include "fast_atof.h"
 
 
 #include "FBXCompileConfig.h"
 #include "FBXCompileConfig.h"
 #include "FBXTokenizer.h"
 #include "FBXTokenizer.h"
@@ -137,6 +138,17 @@ public:
         return it == elements.end() ? NULL : (*it).second;
         return it == elements.end() ? NULL : (*it).second;
     }
     }
 
 
+	const Element* FindElementCaseInsensitive(const std::string& elementName) const {
+		const char* elementNameCStr = elementName.c_str();
+		for (auto element = elements.begin(); element != elements.end(); ++element)
+		{
+			if (!ASSIMP_strincmp(element->first.c_str(), elementNameCStr, MAXLEN)) {
+				return element->second;
+			}
+		}
+		return NULL;
+	}
+
     ElementCollection GetCollection(const std::string& index) const {
     ElementCollection GetCollection(const std::string& index) const {
         return elements.equal_range(index);
         return elements.equal_range(index);
     }
     }

+ 10 - 3
include/assimp/config.h.in

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -632,8 +632,15 @@ enum aiComponent
 #define AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES \
 #define AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES \
     "IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES"
     "IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES"
 
 
-
-
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will search for embedded loaded textures, where no embedded texture data is provided.
+*
+* The default value is false (0)
+* Property type: bool
+*/
+#define AI_CONFIG_IMPORT_FBX_SEARCH_EMBEDDED_TEXTURES \
+	"IMPORT_FBX_SEARCH_EMBEDDED_TEXTURES"
+	
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 /** @brief  Set the vertex animation keyframe to be imported
 /** @brief  Set the vertex animation keyframe to be imported
  *
  *