diff options
author | RevoluPowered <gordon@gordonite.tech> | 2019-11-05 17:06:06 +0000 |
---|---|---|
committer | RevoluPowered <gordon@gordonite.tech> | 2019-11-05 20:38:26 +0000 |
commit | 5fb160c7c692c469488f11aca90a36ac3248dfee (patch) | |
tree | d1eba0971b63f8f8e39e6f2752fc8d9944960318 /thirdparty/assimp/code/FBX | |
parent | 0bd877780fb7b344b5ed1d2fa7765078616f069b (diff) |
Updated assimp to 308db73 from https://github.com/assimp/assimp/
Diffstat (limited to 'thirdparty/assimp/code/FBX')
-rw-r--r-- | thirdparty/assimp/code/FBX/FBXCompileConfig.h | 8 | ||||
-rw-r--r-- | thirdparty/assimp/code/FBX/FBXConverter.cpp | 288 | ||||
-rw-r--r-- | thirdparty/assimp/code/FBX/FBXConverter.h | 14 | ||||
-rw-r--r-- | thirdparty/assimp/code/FBX/FBXDocument.h | 39 | ||||
-rw-r--r-- | thirdparty/assimp/code/FBX/FBXExporter.cpp | 2 |
5 files changed, 126 insertions, 225 deletions
diff --git a/thirdparty/assimp/code/FBX/FBXCompileConfig.h b/thirdparty/assimp/code/FBX/FBXCompileConfig.h index 3a3841fa5b..03536a1823 100644 --- a/thirdparty/assimp/code/FBX/FBXCompileConfig.h +++ b/thirdparty/assimp/code/FBX/FBXCompileConfig.h @@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_FBX_COMPILECONFIG_H #include <map> +#include <set> // #if _MSC_VER > 1500 || (defined __GNUC___) @@ -54,16 +55,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # else # define fbx_unordered_map map # define fbx_unordered_multimap multimap +# define fbx_unordered_set set +# define fbx_unordered_multiset multiset #endif #ifdef ASSIMP_FBX_USE_UNORDERED_MULTIMAP # include <unordered_map> +# include <unordered_set> # if _MSC_VER > 1600 # define fbx_unordered_map unordered_map # define fbx_unordered_multimap unordered_multimap +# define fbx_unordered_set unordered_set +# define fbx_unordered_multiset unordered_multiset # else # define fbx_unordered_map tr1::unordered_map # define fbx_unordered_multimap tr1::unordered_multimap +# define fbx_unordered_set tr1::unordered_set +# define fbx_unordered_multiset tr1::unordered_multiset # endif #endif diff --git a/thirdparty/assimp/code/FBX/FBXConverter.cpp b/thirdparty/assimp/code/FBX/FBXConverter.cpp index bf51884f79..d8a22d9f74 100644 --- a/thirdparty/assimp/code/FBX/FBXConverter.cpp +++ b/thirdparty/assimp/code/FBX/FBXConverter.cpp @@ -78,7 +78,7 @@ namespace Assimp { #define MAGIC_NODE_TAG "_$AssimpFbx$" -#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L +#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000LL FBXConverter::FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones ) : defaultMaterialIndex() @@ -97,6 +97,14 @@ namespace Assimp { // populate the node_anim_chain_bits map, which is needed // to determine which nodes need to be generated. ConvertAnimations(); + // Embedded textures in FBX could be connected to nothing but to itself, + // for instance Texture -> Video connection only but not to the main graph, + // The idea here is to traverse all objects to find these Textures and convert them, + // so later during material conversion it will find converted texture in the textures_converted array. + if (doc.Settings().readTextures) + { + ConvertOrphantEmbeddedTextures(); + } ConvertRootNode(); if (doc.Settings().readAllMaterials) { @@ -121,46 +129,6 @@ namespace Assimp { ConvertGlobalSettings(); TransferDataToScene(); - // Now convert all bone positions to the correct mOffsetMatrix - std::vector<aiBone*> bones; - std::vector<aiNode*> nodes; - std::map<aiBone*, aiNode*> bone_stack; - BuildBoneList(out->mRootNode, out->mRootNode, out, bones); - BuildNodeList(out->mRootNode, nodes ); - - - BuildBoneStack(out->mRootNode, out->mRootNode, out, bones, bone_stack, nodes); - - std::cout << "Bone stack size: " << bone_stack.size() << std::endl; - - for( std::pair<aiBone*, aiNode*> kvp : bone_stack ) - { - aiBone *bone = kvp.first; - aiNode *bone_node = kvp.second; - std::cout << "active node lookup: " << bone->mName.C_Str() << std::endl; - // lcl transform grab - done in generate_nodes :) - - //bone->mOffsetMatrix = bone_node->mTransformation; - aiNode * armature = GetArmatureRoot(bone_node, bones); - - ai_assert(armature); - - // set up bone armature id - bone->mArmature = armature; - - // set this bone node to be referenced properly - ai_assert(bone_node); - bone->mNode = bone_node; - - // apply full hierarchy to transform for basic offset - while( bone_node->mParent ) - { - bone->mRestMatrix = bone_node->mTransformation * bone->mRestMatrix; - bone_node = bone_node->mParent; - } - } - - // if we didn't read any meshes set the AI_SCENE_FLAGS_INCOMPLETE // to make sure the scene passes assimp's validation. FBX files // need not contain geometry (i.e. camera animations, raw armatures). @@ -179,167 +147,6 @@ namespace Assimp { std::for_each(textures.begin(), textures.end(), Util::delete_fun<aiTexture>()); } - /* Returns the armature root node */ - /* This is required to be detected for a bone initially, it will recurse up until it cannot find another - * bone and return the node - * No known failure points. (yet) - */ - aiNode * FBXConverter::GetArmatureRoot(aiNode *bone_node, std::vector<aiBone*> &bone_list) - { - while(bone_node) - { - if(!IsBoneNode(bone_node->mName, bone_list)) - { - std::cout << "Found valid armature: " << bone_node->mName.C_Str() << std::endl; - return bone_node; - } - - bone_node = bone_node->mParent; - } - - std::cout << "can't find armature! node: " << bone_node << std::endl; - - return NULL; - } - - /* Simple IsBoneNode check if this could be a bone */ - bool FBXConverter::IsBoneNode(const aiString &bone_name, std::vector<aiBone*>& bones ) - { - for( aiBone *bone : bones) - { - if(bone->mName == bone_name) - { - return true; - } - } - - return false; - } - - - /* Pop this node by name from the stack if found */ - /* Used in multiple armature situations with duplicate node / bone names */ - /* Known flaw: cannot have nodes with bone names, will be fixed in later release */ - /* (serious to be fixed) Known flaw: nodes which have more than one bone could be prematurely dropped from stack */ - aiNode* FBXConverter::GetNodeFromStack(const aiString &node_name, std::vector<aiNode*> &nodes) - { - std::vector<aiNode*>::iterator iter; - aiNode *found = NULL; - for( iter = nodes.begin(); iter < nodes.end(); ++iter ) - { - aiNode *element = *iter; - ai_assert(element); - // node valid and node name matches - if(element->mName == node_name) - { - found = element; - break; - } - } - - if(found != NULL) { - // now pop the element from the node list - nodes.erase(iter); - - return found; - } - return NULL; - } - - /* Prepare flat node list which can be used for non recursive lookups later */ - void FBXConverter::BuildNodeList(aiNode *current_node, std::vector<aiNode *> &nodes) - { - assert(current_node); - - for( unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) - { - aiNode *child = current_node->mChildren[nodeId]; - assert(child); - - nodes.push_back(child); - - BuildNodeList(child, nodes); - } - } - - /* Reprocess all nodes to calculate bone transforms properly based on the REAL mOffsetMatrix not the local. */ - /* Before this would use mesh transforms which is wrong for bone transforms */ - /* Before this would work for simple character skeletons but not complex meshes with multiple origins */ - /* Source: sketch fab log cutter fbx */ - void FBXConverter::BuildBoneList(aiNode *current_node, const aiNode * root_node, const aiScene *scene, std::vector<aiBone*> &bones ) - { - assert(scene); - for( unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) - { - aiNode *child = current_node->mChildren[nodeId]; - assert(child); - - // check for bones - for( unsigned int meshId = 0; meshId < child->mNumMeshes; ++meshId) - { - assert(child->mMeshes); - unsigned int mesh_index = child->mMeshes[meshId]; - aiMesh *mesh = scene->mMeshes[ mesh_index ]; - assert(mesh); - - for( unsigned int boneId = 0; boneId < mesh->mNumBones; ++boneId) - { - aiBone *bone = mesh->mBones[boneId]; - ai_assert(bone); - - // duplicate meshes exist with the same bones sometimes :) - // so this must be detected - if( std::find(bones.begin(), bones.end(), bone) == bones.end() ) - { - // add the element once - bones.push_back(bone); - } - } - - // find mesh and get bones - // then do recursive lookup for bones in root node hierarchy - } - - BuildBoneList(child, root_node, scene, bones); - } - } - - /* A bone stack allows us to have multiple armatures, with the same bone names - * A bone stack allows us also to retrieve bones true transform even with duplicate names :) - */ - void FBXConverter::BuildBoneStack(aiNode *current_node, const aiNode *root_node, const aiScene *scene, - const std::vector<aiBone *> &bones, - std::map<aiBone *, aiNode *> &bone_stack, - std::vector<aiNode*> &node_stack ) - { - ai_assert(scene); - ai_assert(root_node); - ai_assert(!node_stack.empty()); - - for( aiBone * bone : bones) - { - ai_assert(bone); - aiNode* node = GetNodeFromStack(bone->mName, node_stack); - if(node == NULL) - { - node_stack.clear(); - BuildNodeList(out->mRootNode, node_stack ); - std::cout << "Resetting bone stack: null element " << bone->mName.C_Str() << std::endl; - - node = GetNodeFromStack(bone->mName, node_stack); - - if(!node) { - std::cout << "serious import issue armature failed to be detected?" << std::endl; - continue; - } - } - - std::cout << "Successfully added bone to stack and have valid armature: " << bone->mName.C_Str() << std::endl; - - bone_stack.insert(std::pair<aiBone*, aiNode*>(bone, node)); - } - } - void FBXConverter::ConvertRootNode() { out->mRootNode = new aiNode(); std::string unique_name; @@ -514,6 +321,12 @@ namespace Assimp { std::swap_ranges(nodes.begin(), nodes.end(), parent->mChildren); } + else + { + parent->mNumChildren = 0; + parent->mChildren = nullptr; + } + } catch (std::exception&) { Util::delete_fun<aiNode> deleter; @@ -1329,7 +1142,7 @@ namespace Assimp { binormals = &tempBinormals; } else { - binormals = NULL; + binormals = nullptr; } } @@ -1379,7 +1192,7 @@ namespace Assimp { ConvertMaterialForMesh(out_mesh, model, mesh, mindices[0]); } - if (doc.Settings().readWeights && mesh.DeformerSkin() != NULL) { + if (doc.Settings().readWeights && mesh.DeformerSkin() != nullptr) { ConvertWeights(out_mesh, model, mesh, absolute_transform, parent, root_node, NO_MATERIAL_SEPARATION, nullptr); } @@ -1459,7 +1272,7 @@ namespace Assimp { const std::vector<aiVector3D>& vertices = mesh.GetVertices(); const std::vector<unsigned int>& faces = mesh.GetFaceIndexCounts(); - const bool process_weights = doc.Settings().readWeights && mesh.DeformerSkin() != NULL; + const bool process_weights = doc.Settings().readWeights && mesh.DeformerSkin() != nullptr; unsigned int count_faces = 0; unsigned int count_vertices = 0; @@ -1519,7 +1332,7 @@ namespace Assimp { binormals = &tempBinormals; } else { - binormals = NULL; + binormals = nullptr; } } @@ -1708,9 +1521,9 @@ namespace Assimp { unsigned int count = 0; const unsigned int* const out_idx = geo.ToOutputVertexIndex(index, count); - // ToOutputVertexIndex only returns NULL if index is out of bounds + // ToOutputVertexIndex only returns nullptr if index is out of bounds // which should never happen - ai_assert(out_idx != NULL); + ai_assert(out_idx != nullptr); index_out_indices.push_back(no_index_sentinel); count_out_indices.push_back(0); @@ -1777,11 +1590,11 @@ namespace Assimp { std::vector<size_t> &out_indices, std::vector<size_t> &index_out_indices, std::vector<size_t> &count_out_indices, const aiMatrix4x4 &absolute_transform, aiNode *parent, aiNode *root_node) { - assert(cl); // make sure cluster valid + ai_assert(cl); // make sure cluster valid std::string deformer_name = cl->TargetNode()->Name(); aiString bone_name = aiString(FixNodeName(deformer_name)); - aiBone *bone = NULL; + aiBone *bone = nullptr; if (bone_map.count(deformer_name)) { std::cout << "retrieved bone from lookup " << bone_name.C_Str() << ". Deformer: " << deformer_name @@ -1969,7 +1782,7 @@ namespace Assimp { 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()) { index = (*it).second; textureReady = true; @@ -1977,7 +1790,7 @@ namespace Assimp { else { if (media->ContentLength() > 0) { index = ConvertVideo(*media); - textures_converted[media] = index; + textures_converted[*media] = index; textureReady = true; } } @@ -2501,13 +2314,13 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa if (media != nullptr && media->ContentLength() > 0) { unsigned int index; - VideoMap::const_iterator it = textures_converted.find(media); + VideoMap::const_iterator it = textures_converted.find(*media); if (it != textures_converted.end()) { index = (*it).second; } else { index = ConvertVideo(*media); - textures_converted[media] = index; + textures_converted[*media] = index; } // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) @@ -2935,7 +2748,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa // sanity check whether the input is ok static void validateAnimCurveNodes(const std::vector<const AnimationCurveNode*>& curves, bool strictMode) { - const Object* target(NULL); + const Object* target(nullptr); for (const AnimationCurveNode* node : curves) { if (!target) { target = node->Target(); @@ -2966,7 +2779,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa #ifdef ASSIMP_BUILD_DEBUG validateAnimCurveNodes(curves, doc.Settings().strictMode); #endif - const AnimationCurveNode* curve_node = NULL; + const AnimationCurveNode* curve_node = nullptr; for (const AnimationCurveNode* node : curves) { ai_assert(node); @@ -3814,7 +3627,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa ai_assert(!out->mMeshes); ai_assert(!out->mNumMeshes); - // note: the trailing () ensures initialization with NULL - not + // note: the trailing () ensures initialization with nullptr - not // many C++ users seem to know this, so pointing it out to avoid // confusion why this code works. @@ -3861,6 +3674,47 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa } } + void FBXConverter::ConvertOrphantEmbeddedTextures() + { + // in C++14 it could be: + // for (auto&& [id, object] : objects) + for (auto&& id_and_object : doc.Objects()) + { + auto&& id = std::get<0>(id_and_object); + auto&& object = std::get<1>(id_and_object); + // If an object doesn't have parent + if (doc.ConnectionsBySource().count(id) == 0) + { + const Texture* realTexture = nullptr; + try + { + const auto& element = object->GetElement(); + const Token& key = element.KeyToken(); + const char* obtype = key.begin(); + const size_t length = static_cast<size_t>(key.end() - key.begin()); + if (strncmp(obtype, "Texture", length) == 0) + { + const Texture* texture = static_cast<const Texture*>(object->Get()); + if (texture->Media() && texture->Media()->ContentLength() > 0) + { + realTexture = texture; + } + } + } + catch (...) + { + // do nothing + } + if (realTexture) + { + const Video* media = realTexture->Media(); + unsigned int index = ConvertVideo(*media); + textures_converted[*media] = index; + } + } + } + } + // ------------------------------------------------------------------------------------------------ void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones) { diff --git a/thirdparty/assimp/code/FBX/FBXConverter.h b/thirdparty/assimp/code/FBX/FBXConverter.h index 619da92c17..46693bdca6 100644 --- a/thirdparty/assimp/code/FBX/FBXConverter.h +++ b/thirdparty/assimp/code/FBX/FBXConverter.h @@ -427,6 +427,10 @@ private: // copy generated meshes, animations, lights, cameras and textures to the output scene void TransferDataToScene(); + // ------------------------------------------------------------------------------------------------ + // FBX file could have embedded textures not connected to anything + void ConvertOrphantEmbeddedTextures(); + private: // 0: not assigned yet, others: index is value - 1 unsigned int defaultMaterialIndex; @@ -438,21 +442,21 @@ private: std::vector<aiCamera*> cameras; std::vector<aiTexture*> textures; - using MaterialMap = std::map<const Material*, unsigned int>; + using MaterialMap = std::fbx_unordered_map<const Material*, unsigned int>; MaterialMap materials_converted; - using VideoMap = std::map<const Video*, unsigned int>; + using VideoMap = std::fbx_unordered_map<const Video, unsigned int>; VideoMap textures_converted; - using MeshMap = std::map<const Geometry*, std::vector<unsigned int> >; + using MeshMap = std::fbx_unordered_map<const Geometry*, std::vector<unsigned int> >; MeshMap meshes_converted; // fixed node name -> which trafo chain components have animations? - using NodeAnimBitMap = std::map<std::string, unsigned int> ; + using NodeAnimBitMap = std::fbx_unordered_map<std::string, unsigned int> ; NodeAnimBitMap node_anim_chain_bits; // number of nodes with the same name - using NodeNameCache = std::unordered_map<std::string, unsigned int>; + using NodeNameCache = std::fbx_unordered_map<std::string, unsigned int>; NodeNameCache mNodeNames; // Deformer name is not the same as a bone name - it does contain the bone name though :) diff --git a/thirdparty/assimp/code/FBX/FBXDocument.h b/thirdparty/assimp/code/FBX/FBXDocument.h index 18e5c38f13..a60d7d9efa 100644 --- a/thirdparty/assimp/code/FBX/FBXDocument.h +++ b/thirdparty/assimp/code/FBX/FBXDocument.h @@ -637,6 +637,20 @@ public: return ptr; } + bool operator==(const Video& other) const + { + return ( + type == other.type + && relativeFileName == other.relativeFileName + && fileName == other.fileName + ); + } + + bool operator<(const Video& other) const + { + return std::tie(type, relativeFileName, fileName) < std::tie(other.type, other.relativeFileName, other.fileName); + } + private: std::string type; std::string relativeFileName; @@ -1005,10 +1019,10 @@ public: // during their entire lifetime (Document). FBX files have // up to many thousands of objects (most of which we never use), // so the memory overhead for them should be kept at a minimum. -typedef std::map<uint64_t, LazyObject*> ObjectMap; +typedef std::fbx_unordered_map<uint64_t, LazyObject*> ObjectMap; typedef std::fbx_unordered_map<std::string, std::shared_ptr<const PropertyTable> > PropertyTemplateMap; -typedef std::multimap<uint64_t, const Connection*> ConnectionMap; +typedef std::fbx_unordered_multimap<uint64_t, const Connection*> ConnectionMap; /** DOM class for global document settings, a single instance per document can * be accessed via Document.Globals(). */ @@ -1177,4 +1191,25 @@ private: } // Namespace FBX } // Namespace Assimp +namespace std +{ + template <> + struct hash<const Assimp::FBX::Video> + { + std::size_t operator()(const Assimp::FBX::Video& video) const + { + using std::size_t; + using std::hash; + using std::string; + + size_t res = 17; + res = res * 31 + hash<string>()(video.Name()); + res = res * 31 + hash<string>()(video.RelativeFilename()); + res = res * 31 + hash<string>()(video.Type()); + + return res; + } + }; +} + #endif // INCLUDED_AI_FBX_DOCUMENT_H diff --git a/thirdparty/assimp/code/FBX/FBXExporter.cpp b/thirdparty/assimp/code/FBX/FBXExporter.cpp index 25d057df1c..9316dc4f02 100644 --- a/thirdparty/assimp/code/FBX/FBXExporter.cpp +++ b/thirdparty/assimp/code/FBX/FBXExporter.cpp @@ -1289,7 +1289,7 @@ void FBXExporter::WriteObjects () for(unsigned int lr = 1; lr < m->GetNumUVChannels(); ++ lr) { - FBX::Node layerExtra("Layer", int32_t(1)); + FBX::Node layerExtra("Layer", int32_t(lr)); layerExtra.AddChild("Version", int32_t(100)); FBX::Node leExtra("LayerElement"); leExtra.AddChild("Type", "LayerElementUV"); |