Fixed many FBX bugs
Fixed a bug where FBX loader won´t load embedded textures that don´t have the Content data filled. Some FBX files only fill this data once, so any embedded texture with the same source filename, should use the pre-loaded data. Fixed another bug where FBX Texture "Filename" field came different than on some files than the one defined by the code. One suggestion is load all properties by the case-insensitive function created. Added the "AI_CONFIG_IMPORT_FBX_SEARCH_EMBEDDED_TEXTURES" flag to tell the importer to load embedded texture data from already loaded ones.pull/1347/head
parent
c9912fd481
commit
c86013b08d
|
@ -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 ) {
|
if (media != 0) {
|
||||||
unsigned int index;
|
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 );
|
VideoMap::const_iterator it = textures_converted.find(media);
|
||||||
if ( it != textures_converted.end() ) {
|
if (it != textures_converted.end()) {
|
||||||
index = ( *it ).second;
|
index = (*it).second;
|
||||||
}
|
textureReady = true;
|
||||||
else {
|
}
|
||||||
index = ConvertVideo( *media );
|
else {
|
||||||
textures_converted[ media ] = index;
|
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)
|
// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture), if the texture is ready
|
||||||
path.data[ 0 ] = '*';
|
if (textureReady) {
|
||||||
path.length = 1 + ASSIMP_itoa10( path.data + 1, MAXLEN - 1, index );
|
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 );
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -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);
|
//this field is ommited when the embedded texture is already loaded, let's ignore if it´s not found
|
||||||
const char* data = token.begin();
|
try {
|
||||||
if(!token.IsBinary()) {
|
const Token& token = GetRequiredToken(*Content, 0);
|
||||||
DOMWarning("video content is not binary data, ignoring", &element);
|
const char* data = token.begin();
|
||||||
}
|
if (!token.IsBinary()) {
|
||||||
else if(static_cast<size_t>(token.end() - data) < 5) {
|
DOMWarning("video content is not binary data, ignoring", &element);
|
||||||
DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element);
|
}
|
||||||
}
|
else if (static_cast<size_t>(token.end() - data) < 5) {
|
||||||
else if(*data != 'R') {
|
DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element);
|
||||||
DOMWarning("video content is not raw binary data, ignoring", &element);
|
}
|
||||||
}
|
else if (*data != 'R') {
|
||||||
else {
|
DOMWarning("video content is not raw binary data, ignoring", &element);
|
||||||
// read number of elements
|
}
|
||||||
uint32_t len = 0;
|
else {
|
||||||
::memcpy(&len, data + 1, sizeof(len));
|
// read number of elements
|
||||||
AI_SWAP4(len);
|
uint32_t len = 0;
|
||||||
|
::memcpy(&len, data + 1, sizeof(len));
|
||||||
|
AI_SWAP4(len);
|
||||||
|
|
||||||
contentLength = len;
|
contentLength = len;
|
||||||
|
|
||||||
content = new uint8_t[len];
|
content = new uint8_t[len];
|
||||||
::memcpy(content, data + 5, 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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue