summaryrefslogtreecommitdiff
path: root/thirdparty/assimp/code/FBX
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/assimp/code/FBX')
-rw-r--r--thirdparty/assimp/code/FBX/FBXCompileConfig.h8
-rw-r--r--thirdparty/assimp/code/FBX/FBXConverter.cpp345
-rw-r--r--thirdparty/assimp/code/FBX/FBXConverter.h94
-rw-r--r--thirdparty/assimp/code/FBX/FBXDocument.h39
-rw-r--r--thirdparty/assimp/code/FBX/FBXExportProperty.cpp6
-rw-r--r--thirdparty/assimp/code/FBX/FBXExporter.cpp122
-rw-r--r--thirdparty/assimp/code/FBX/FBXExporter.h2
-rw-r--r--thirdparty/assimp/code/FBX/FBXImporter.cpp217
-rw-r--r--thirdparty/assimp/code/FBX/FBXMeshGeometry.cpp20
9 files changed, 526 insertions, 327 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 3f64016ea4..d8a22d9f74 100644
--- a/thirdparty/assimp/code/FBX/FBXConverter.cpp
+++ b/thirdparty/assimp/code/FBX/FBXConverter.cpp
@@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXImporter.h"
#include <assimp/StringComparison.h>
+#include <assimp/MathFunctions.h>
#include <assimp/scene.h>
@@ -67,7 +68,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sstream>
#include <iomanip>
#include <cstdint>
-
+#include <iostream>
+#include <stdlib.h>
namespace Assimp {
namespace FBX {
@@ -76,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()
@@ -95,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) {
@@ -144,7 +154,7 @@ namespace Assimp {
out->mRootNode->mName.Set(unique_name);
// root has ID 0
- ConvertNodes(0L, *out->mRootNode);
+ ConvertNodes(0L, out->mRootNode, out->mRootNode);
}
static std::string getAncestorBaseName(const aiNode* node)
@@ -178,8 +188,11 @@ namespace Assimp {
GetUniqueName(original_name, unique_name);
return unique_name;
}
-
- void FBXConverter::ConvertNodes(uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform) {
+ /// todo: pre-build node hierarchy
+ /// todo: get bone from stack
+ /// todo: make map of aiBone* to aiNode*
+ /// then update convert clusters to the new format
+ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node) {
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(id, "Model");
std::vector<aiNode*> nodes;
@@ -190,62 +203,69 @@ namespace Assimp {
try {
for (const Connection* con : conns) {
-
// ignore object-property links
if (con->PropertyName().length()) {
- continue;
+ // really important we document why this is ignored.
+ FBXImporter::LogInfo("ignoring property link - no docs on why this is ignored");
+ continue; //?
}
+ // convert connection source object into Object base class
const Object* const object = con->SourceObject();
if (nullptr == object) {
- FBXImporter::LogWarn("failed to convert source object for Model link");
+ FBXImporter::LogError("failed to convert source object for Model link");
continue;
}
+ // FBX Model::Cube, Model::Bone001, etc elements
+ // This detects if we can cast the object into this model structure.
const Model* const model = dynamic_cast<const Model*>(object);
if (nullptr != model) {
nodes_chain.clear();
post_nodes_chain.clear();
- aiMatrix4x4 new_abs_transform = parent_transform;
-
- std::string unique_name = MakeUniqueNodeName(model, parent);
-
+ aiMatrix4x4 new_abs_transform = parent->mTransformation;
+ std::string node_name = FixNodeName(model->Name());
// even though there is only a single input node, the design of
// assimp (or rather: the complicated transformation chain that
// is employed by fbx) means that we may need multiple aiNode's
// to represent a fbx node's transformation.
- const bool need_additional_node = GenerateTransformationNodeChain(*model, unique_name, nodes_chain, post_nodes_chain);
+
+ // generate node transforms - this includes pivot data
+ // if need_additional_node is true then you t
+ const bool need_additional_node = GenerateTransformationNodeChain(*model, node_name, nodes_chain, post_nodes_chain);
+
+ // assert that for the current node we must have at least a single transform
ai_assert(nodes_chain.size());
if (need_additional_node) {
- nodes_chain.push_back(new aiNode(unique_name));
+ nodes_chain.push_back(new aiNode(node_name));
}
//setup metadata on newest node
SetupNodeMetadata(*model, *nodes_chain.back());
// link all nodes in a row
- aiNode* last_parent = &parent;
- for (aiNode* prenode : nodes_chain) {
- ai_assert(prenode);
+ aiNode* last_parent = parent;
+ for (aiNode* child : nodes_chain) {
+ ai_assert(child);
- if (last_parent != &parent) {
+ if (last_parent != parent) {
last_parent->mNumChildren = 1;
last_parent->mChildren = new aiNode*[1];
- last_parent->mChildren[0] = prenode;
+ last_parent->mChildren[0] = child;
}
- prenode->mParent = last_parent;
- last_parent = prenode;
+ child->mParent = last_parent;
+ last_parent = child;
- new_abs_transform *= prenode->mTransformation;
+ new_abs_transform *= child->mTransformation;
}
// attach geometry
- ConvertModel(*model, *nodes_chain.back(), new_abs_transform);
+ ConvertModel(*model, nodes_chain.back(), root_node, new_abs_transform);
// check if there will be any child nodes
const std::vector<const Connection*>& child_conns
@@ -257,7 +277,7 @@ namespace Assimp {
for (aiNode* postnode : post_nodes_chain) {
ai_assert(postnode);
- if (last_parent != &parent) {
+ if (last_parent != parent) {
last_parent->mNumChildren = 1;
last_parent->mChildren = new aiNode*[1];
last_parent->mChildren[0] = postnode;
@@ -279,15 +299,15 @@ namespace Assimp {
);
}
- // attach sub-nodes (if any)
- ConvertNodes(model->ID(), *last_parent, new_abs_transform);
+ // recursion call - child nodes
+ ConvertNodes(model->ID(), last_parent, root_node);
if (doc.Settings().readLights) {
- ConvertLights(*model, unique_name);
+ ConvertLights(*model, node_name);
}
if (doc.Settings().readCameras) {
- ConvertCameras(*model, unique_name);
+ ConvertCameras(*model, node_name);
}
nodes.push_back(nodes_chain.front());
@@ -296,11 +316,17 @@ namespace Assimp {
}
if (nodes.size()) {
- parent.mChildren = new aiNode*[nodes.size()]();
- parent.mNumChildren = static_cast<unsigned int>(nodes.size());
+ parent->mChildren = new aiNode*[nodes.size()]();
+ parent->mNumChildren = static_cast<unsigned int>(nodes.size());
- std::swap_ranges(nodes.begin(), nodes.end(), parent.mChildren);
+ std::swap_ranges(nodes.begin(), nodes.end(), parent->mChildren);
}
+ else
+ {
+ parent->mNumChildren = 0;
+ parent->mChildren = nullptr;
+ }
+
}
catch (std::exception&) {
Util::delete_fun<aiNode> deleter;
@@ -553,7 +579,7 @@ namespace Assimp {
return;
}
- const float angle_epsilon = 1e-6f;
+ const float angle_epsilon = Math::getEpsilon<float>();
out = aiMatrix4x4();
@@ -694,7 +720,7 @@ namespace Assimp {
std::fill_n(chain, static_cast<unsigned int>(TransformationComp_MAXIMUM), aiMatrix4x4());
// generate transformation matrices for all the different transformation components
- const float zero_epsilon = 1e-6f;
+ const float zero_epsilon = Math::getEpsilon<float>();
const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
const aiVector3D& PreRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);
@@ -802,7 +828,7 @@ namespace Assimp {
// is_complex needs to be consistent with NeedsComplexTransformationChain()
// or the interplay between this code and the animation converter would
// not be guaranteed.
- ai_assert(NeedsComplexTransformationChain(model) == ((chainBits & chainMaskComplex) != 0));
+ //ai_assert(NeedsComplexTransformationChain(model) == ((chainBits & chainMaskComplex) != 0));
// now, if we have more than just Translation, Scaling and Rotation,
// we need to generate a full node chain to accommodate for assimp's
@@ -904,7 +930,8 @@ namespace Assimp {
}
}
- void FBXConverter::ConvertModel(const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform)
+ void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root_node,
+ const aiMatrix4x4 &absolute_transform)
{
const std::vector<const Geometry*>& geos = model.GetGeometry();
@@ -916,11 +943,12 @@ namespace Assimp {
const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*>(geo);
const LineGeometry* const line = dynamic_cast<const LineGeometry*>(geo);
if (mesh) {
- const std::vector<unsigned int>& indices = ConvertMesh(*mesh, model, node_global_transform, nd);
+ const std::vector<unsigned int>& indices = ConvertMesh(*mesh, model, parent, root_node,
+ absolute_transform);
std::copy(indices.begin(), indices.end(), std::back_inserter(meshes));
}
else if (line) {
- const std::vector<unsigned int>& indices = ConvertLine(*line, model, node_global_transform, nd);
+ const std::vector<unsigned int>& indices = ConvertLine(*line, model, parent, root_node);
std::copy(indices.begin(), indices.end(), std::back_inserter(meshes));
}
else {
@@ -929,15 +957,16 @@ namespace Assimp {
}
if (meshes.size()) {
- nd.mMeshes = new unsigned int[meshes.size()]();
- nd.mNumMeshes = static_cast<unsigned int>(meshes.size());
+ parent->mMeshes = new unsigned int[meshes.size()]();
+ parent->mNumMeshes = static_cast<unsigned int>(meshes.size());
- std::swap_ranges(meshes.begin(), meshes.end(), nd.mMeshes);
+ std::swap_ranges(meshes.begin(), meshes.end(), parent->mMeshes);
}
}
- std::vector<unsigned int> FBXConverter::ConvertMesh(const MeshGeometry& mesh, const Model& model,
- const aiMatrix4x4& node_global_transform, aiNode& nd)
+ std::vector<unsigned int>
+ FBXConverter::ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node,
+ const aiMatrix4x4 &absolute_transform)
{
std::vector<unsigned int> temp;
@@ -961,18 +990,18 @@ namespace Assimp {
const MatIndexArray::value_type base = mindices[0];
for (MatIndexArray::value_type index : mindices) {
if (index != base) {
- return ConvertMeshMultiMaterial(mesh, model, node_global_transform, nd);
+ return ConvertMeshMultiMaterial(mesh, model, parent, root_node, absolute_transform);
}
}
}
// faster code-path, just copy the data
- temp.push_back(ConvertMeshSingleMaterial(mesh, model, node_global_transform, nd));
+ temp.push_back(ConvertMeshSingleMaterial(mesh, model, absolute_transform, parent, root_node));
return temp;
}
std::vector<unsigned int> FBXConverter::ConvertLine(const LineGeometry& line, const Model& model,
- const aiMatrix4x4& node_global_transform, aiNode& nd)
+ aiNode *parent, aiNode *root_node)
{
std::vector<unsigned int> temp;
@@ -983,7 +1012,7 @@ namespace Assimp {
return temp;
}
- aiMesh* const out_mesh = SetupEmptyMesh(line, nd);
+ aiMesh* const out_mesh = SetupEmptyMesh(line, root_node);
out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
// copy vertices
@@ -1018,7 +1047,7 @@ namespace Assimp {
return temp;
}
- aiMesh* FBXConverter::SetupEmptyMesh(const Geometry& mesh, aiNode& nd)
+ aiMesh* FBXConverter::SetupEmptyMesh(const Geometry& mesh, aiNode *parent)
{
aiMesh* const out_mesh = new aiMesh();
meshes.push_back(out_mesh);
@@ -1035,17 +1064,18 @@ namespace Assimp {
}
else
{
- out_mesh->mName = nd.mName;
+ out_mesh->mName = parent->mName;
}
return out_mesh;
}
- unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model,
- const aiMatrix4x4& node_global_transform, aiNode& nd)
+ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model,
+ const aiMatrix4x4 &absolute_transform, aiNode *parent,
+ aiNode *root_node)
{
const MatIndexArray& mindices = mesh.GetMaterialIndices();
- aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd);
+ aiMesh* const out_mesh = SetupEmptyMesh(mesh, parent);
const std::vector<aiVector3D>& vertices = mesh.GetVertices();
const std::vector<unsigned int>& faces = mesh.GetFaceIndexCounts();
@@ -1112,7 +1142,7 @@ namespace Assimp {
binormals = &tempBinormals;
}
else {
- binormals = NULL;
+ binormals = nullptr;
}
}
@@ -1162,8 +1192,9 @@ namespace Assimp {
ConvertMaterialForMesh(out_mesh, model, mesh, mindices[0]);
}
- if (doc.Settings().readWeights && mesh.DeformerSkin() != NULL) {
- ConvertWeights(out_mesh, model, mesh, node_global_transform, NO_MATERIAL_SEPARATION);
+ if (doc.Settings().readWeights && mesh.DeformerSkin() != nullptr) {
+ ConvertWeights(out_mesh, model, mesh, absolute_transform, parent, root_node, NO_MATERIAL_SEPARATION,
+ nullptr);
}
std::vector<aiAnimMesh*> animMeshes;
@@ -1208,8 +1239,10 @@ namespace Assimp {
return static_cast<unsigned int>(meshes.size() - 1);
}
- std::vector<unsigned int> FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
- const aiMatrix4x4& node_global_transform, aiNode& nd)
+ std::vector<unsigned int>
+ FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, aiNode *parent,
+ aiNode *root_node,
+ const aiMatrix4x4 &absolute_transform)
{
const MatIndexArray& mindices = mesh.GetMaterialIndices();
ai_assert(mindices.size());
@@ -1220,7 +1253,7 @@ namespace Assimp {
for (MatIndexArray::value_type index : mindices) {
if (had.find(index) == had.end()) {
- indices.push_back(ConvertMeshMultiMaterial(mesh, model, index, node_global_transform, nd));
+ indices.push_back(ConvertMeshMultiMaterial(mesh, model, index, parent, root_node, absolute_transform));
had.insert(index);
}
}
@@ -1228,18 +1261,18 @@ namespace Assimp {
return indices;
}
- unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
- MatIndexArray::value_type index,
- const aiMatrix4x4& node_global_transform,
- aiNode& nd)
+ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model,
+ MatIndexArray::value_type index,
+ aiNode *parent, aiNode *root_node,
+ const aiMatrix4x4 &absolute_transform)
{
- aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd);
+ aiMesh* const out_mesh = SetupEmptyMesh(mesh, parent);
const MatIndexArray& mindices = mesh.GetMaterialIndices();
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;
@@ -1299,7 +1332,7 @@ namespace Assimp {
binormals = &tempBinormals;
}
else {
- binormals = NULL;
+ binormals = nullptr;
}
}
@@ -1398,7 +1431,7 @@ namespace Assimp {
ConvertMaterialForMesh(out_mesh, model, mesh, index);
if (process_weights) {
- ConvertWeights(out_mesh, model, mesh, node_global_transform, index, &reverseMapping);
+ ConvertWeights(out_mesh, model, mesh, absolute_transform, parent, root_node, index, &reverseMapping);
}
std::vector<aiAnimMesh*> animMeshes;
@@ -1448,10 +1481,10 @@ namespace Assimp {
return static_cast<unsigned int>(meshes.size() - 1);
}
- void FBXConverter::ConvertWeights(aiMesh* out, const Model& model, const MeshGeometry& geo,
- const aiMatrix4x4& node_global_transform,
- unsigned int materialIndex,
- std::vector<unsigned int>* outputVertStartIndices)
+ void FBXConverter::ConvertWeights(aiMesh *out, const Model &model, const MeshGeometry &geo,
+ const aiMatrix4x4 &absolute_transform,
+ aiNode *parent, aiNode *root_node, unsigned int materialIndex,
+ std::vector<unsigned int> *outputVertStartIndices)
{
ai_assert(geo.DeformerSkin());
@@ -1462,13 +1495,12 @@ namespace Assimp {
const Skin& sk = *geo.DeformerSkin();
std::vector<aiBone*> bones;
- bones.reserve(sk.Clusters().size());
const bool no_mat_check = materialIndex == NO_MATERIAL_SEPARATION;
ai_assert(no_mat_check || outputVertStartIndices);
try {
-
+ // iterate over the sub deformers
for (const Cluster* cluster : sk.Clusters()) {
ai_assert(cluster);
@@ -1482,15 +1514,16 @@ namespace Assimp {
index_out_indices.clear();
out_indices.clear();
+
// now check if *any* of these weights is contained in the output mesh,
// taking notes so we don't need to do it twice.
for (WeightIndexArray::value_type index : indices) {
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);
@@ -1519,68 +1552,107 @@ namespace Assimp {
}
}
}
-
+
// if we found at least one, generate the output bones
// XXX this could be heavily simplified by collecting the bone
// data in a single step.
- ConvertCluster(bones, model, *cluster, out_indices, index_out_indices,
- count_out_indices, node_global_transform);
+ ConvertCluster(bones, cluster, out_indices, index_out_indices,
+ count_out_indices, absolute_transform, parent, root_node);
}
+
+ bone_map.clear();
}
- catch (std::exception&) {
+ catch (std::exception&e) {
std::for_each(bones.begin(), bones.end(), Util::delete_fun<aiBone>());
throw;
}
if (bones.empty()) {
+ out->mBones = nullptr;
+ out->mNumBones = 0;
return;
- }
-
- out->mBones = new aiBone*[bones.size()]();
- out->mNumBones = static_cast<unsigned int>(bones.size());
+ } else {
+ out->mBones = new aiBone *[bones.size()]();
+ out->mNumBones = static_cast<unsigned int>(bones.size());
- std::swap_ranges(bones.begin(), bones.end(), out->mBones);
+ std::swap_ranges(bones.begin(), bones.end(), out->mBones);
+ }
}
- void FBXConverter::ConvertCluster(std::vector<aiBone*>& bones, const Model& /*model*/, const Cluster& cl,
- std::vector<size_t>& out_indices,
- std::vector<size_t>& index_out_indices,
- std::vector<size_t>& count_out_indices,
- const aiMatrix4x4& node_global_transform)
+ const aiNode* FBXConverter::GetNodeByName( const aiString& name, aiNode *current_node )
{
+ aiNode * iter = current_node;
+ //printf("Child count: %d", iter->mNumChildren);
+ return iter;
+ }
- aiBone* const bone = new aiBone();
- bones.push_back(bone);
+ void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl,
+ 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) {
+ ai_assert(cl); // make sure cluster valid
+ std::string deformer_name = cl->TargetNode()->Name();
+ aiString bone_name = aiString(FixNodeName(deformer_name));
- bone->mName = FixNodeName(cl.TargetNode()->Name());
+ aiBone *bone = nullptr;
- bone->mOffsetMatrix = cl.TransformLink();
- bone->mOffsetMatrix.Inverse();
+ if (bone_map.count(deformer_name)) {
+ std::cout << "retrieved bone from lookup " << bone_name.C_Str() << ". Deformer: " << deformer_name
+ << std::endl;
+ bone = bone_map[deformer_name];
+ } else {
+ std::cout << "created new bone " << bone_name.C_Str() << ". Deformer: " << deformer_name << std::endl;
+ bone = new aiBone();
+ bone->mName = bone_name;
- bone->mOffsetMatrix = bone->mOffsetMatrix * node_global_transform;
+ // store local transform link for post processing
+ bone->mOffsetMatrix = cl->TransformLink();
+ bone->mOffsetMatrix.Inverse();
- bone->mNumWeights = static_cast<unsigned int>(out_indices.size());
- aiVertexWeight* cursor = bone->mWeights = new aiVertexWeight[out_indices.size()];
+ aiMatrix4x4 matrix = (aiMatrix4x4)absolute_transform;
- const size_t no_index_sentinel = std::numeric_limits<size_t>::max();
- const WeightArray& weights = cl.GetWeights();
+ bone->mOffsetMatrix = bone->mOffsetMatrix * matrix; // * mesh_offset
- const size_t c = index_out_indices.size();
- for (size_t i = 0; i < c; ++i) {
- const size_t index_index = index_out_indices[i];
- if (index_index == no_index_sentinel) {
- continue;
- }
+ //
+ // Now calculate the aiVertexWeights
+ //
+
+ aiVertexWeight *cursor = nullptr;
+
+ bone->mNumWeights = static_cast<unsigned int>(out_indices.size());
+ cursor = bone->mWeights = new aiVertexWeight[out_indices.size()];
- const size_t cc = count_out_indices[i];
- for (size_t j = 0; j < cc; ++j) {
- aiVertexWeight& out_weight = *cursor++;
+ const size_t no_index_sentinel = std::numeric_limits<size_t>::max();
+ const WeightArray& weights = cl->GetWeights();
- out_weight.mVertexId = static_cast<unsigned int>(out_indices[index_index + j]);
- out_weight.mWeight = weights[i];
+ const size_t c = index_out_indices.size();
+ for (size_t i = 0; i < c; ++i) {
+ const size_t index_index = index_out_indices[i];
+
+ if (index_index == no_index_sentinel) {
+ continue;
+ }
+
+ const size_t cc = count_out_indices[i];
+ for (size_t j = 0; j < cc; ++j) {
+ // cursor runs from first element relative to the start
+ // or relative to the start of the next indexes.
+ aiVertexWeight& out_weight = *cursor++;
+
+ out_weight.mVertexId = static_cast<unsigned int>(out_indices[index_index + j]);
+ out_weight.mWeight = weights[i];
+ }
}
+
+ bone_map.insert(std::pair<const std::string, aiBone *>(deformer_name, bone));
}
+
+ std::cout << "bone research: Indicies size: " << out_indices.size() << std::endl;
+
+ // lookup must be populated in case something goes wrong
+ // this also allocates bones to mesh instance outside
+ local_mesh_bones.push_back(bone);
}
void FBXConverter::ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo,
@@ -1710,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;
@@ -1718,7 +1790,7 @@ namespace Assimp {
else {
if (media->ContentLength() > 0) {
index = ConvertVideo(*media);
- textures_converted[media] = index;
+ textures_converted[*media] = index;
textureReady = true;
}
}
@@ -2242,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)
@@ -2676,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();
@@ -2707,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);
@@ -2967,7 +3039,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa
TransformationCompDefaultValue(comp)
);
- const float epsilon = 1e-6f;
+ const float epsilon = Math::getEpsilon<float>();
return (dyn_val - static_val).SquareLength() < epsilon;
}
@@ -3555,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.
@@ -3602,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 ab610058a4..46693bdca6 100644
--- a/thirdparty/assimp/code/FBX/FBXConverter.h
+++ b/thirdparty/assimp/code/FBX/FBXConverter.h
@@ -76,16 +76,6 @@ namespace Assimp {
namespace FBX {
class Document;
-
-enum class FbxUnit {
- cm = 0,
- m,
- km,
- NumUnits,
-
- Undefined
-};
-
/**
* Convert a FBX #Document to #aiScene
* @param out Empty scene to be populated
@@ -133,7 +123,7 @@ private:
// ------------------------------------------------------------------------------------------------
// collect and assign child nodes
- void ConvertNodes(uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform = aiMatrix4x4());
+ void ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node);
// ------------------------------------------------------------------------------------------------
void ConvertLights(const Model& model, const std::string &orig_name );
@@ -189,32 +179,35 @@ private:
void SetupNodeMetadata(const Model& model, aiNode& nd);
// ------------------------------------------------------------------------------------------------
- void ConvertModel(const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform);
+ void ConvertModel(const Model &model, aiNode *parent, aiNode *root_node,
+ const aiMatrix4x4 &absolute_transform);
// ------------------------------------------------------------------------------------------------
// MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
- std::vector<unsigned int> ConvertMesh(const MeshGeometry& mesh, const Model& model,
- const aiMatrix4x4& node_global_transform, aiNode& nd);
+ std::vector<unsigned int>
+ ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node,
+ const aiMatrix4x4 &absolute_transform);
// ------------------------------------------------------------------------------------------------
std::vector<unsigned int> ConvertLine(const LineGeometry& line, const Model& model,
- const aiMatrix4x4& node_global_transform, aiNode& nd);
+ aiNode *parent, aiNode *root_node);
// ------------------------------------------------------------------------------------------------
- aiMesh* SetupEmptyMesh(const Geometry& mesh, aiNode& nd);
+ aiMesh* SetupEmptyMesh(const Geometry& mesh, aiNode *parent);
// ------------------------------------------------------------------------------------------------
- unsigned int ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model,
- const aiMatrix4x4& node_global_transform, aiNode& nd);
+ unsigned int ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model,
+ const aiMatrix4x4 &absolute_transform, aiNode *parent,
+ aiNode *root_node);
// ------------------------------------------------------------------------------------------------
- std::vector<unsigned int> ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
- const aiMatrix4x4& node_global_transform, aiNode& nd);
+ std::vector<unsigned int>
+ ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node,
+ const aiMatrix4x4 &absolute_transform);
// ------------------------------------------------------------------------------------------------
- unsigned int ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
- MatIndexArray::value_type index,
- const aiMatrix4x4& node_global_transform, aiNode& nd);
+ unsigned int ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, MatIndexArray::value_type index,
+ aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform);
// ------------------------------------------------------------------------------------------------
static const unsigned int NO_MATERIAL_SEPARATION = /* std::numeric_limits<unsigned int>::max() */
@@ -227,17 +220,17 @@ private:
* - outputVertStartIndices is only used when a material index is specified, it gives for
* each output vertex the DOM index it maps to.
*/
- void ConvertWeights(aiMesh* out, const Model& model, const MeshGeometry& geo,
- const aiMatrix4x4& node_global_transform = aiMatrix4x4(),
- unsigned int materialIndex = NO_MATERIAL_SEPARATION,
- std::vector<unsigned int>* outputVertStartIndices = NULL);
-
+ void ConvertWeights(aiMesh *out, const Model &model, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
+ aiNode *parent = NULL, aiNode *root_node = NULL,
+ unsigned int materialIndex = NO_MATERIAL_SEPARATION,
+ std::vector<unsigned int> *outputVertStartIndices = NULL);
+ // lookup
+ static const aiNode* GetNodeByName( const aiString& name, aiNode *current_node );
// ------------------------------------------------------------------------------------------------
- void ConvertCluster(std::vector<aiBone*>& bones, const Model& /*model*/, const Cluster& cl,
- std::vector<size_t>& out_indices,
- std::vector<size_t>& index_out_indices,
- std::vector<size_t>& count_out_indices,
- const aiMatrix4x4& node_global_transform);
+ void ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl,
+ 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);
// ------------------------------------------------------------------------------------------------
void ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo,
@@ -434,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;
@@ -445,28 +442,47 @@ 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 :)
+ // Deformer names in FBX are always unique in an FBX file.
+ std::map<const std::string, aiBone *> bone_map;
+
double anim_fps;
aiScene* const out;
const FBX::Document& doc;
- FbxUnit mCurrentUnit;
+
+ static void BuildBoneList(aiNode *current_node, const aiNode *root_node, const aiScene *scene,
+ std::vector<aiBone*>& bones);
+
+ void 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 );
+
+ static void BuildNodeList(aiNode *current_node, std::vector<aiNode *> &nodes);
+
+ static aiNode *GetNodeFromStack(const aiString &node_name, std::vector<aiNode *> &nodes);
+
+ static aiNode *GetArmatureRoot(aiNode *bone_node, std::vector<aiBone*> &bone_list);
+
+ static bool IsBoneNode(const aiString &bone_name, std::vector<aiBone *> &bones);
};
}
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/FBXExportProperty.cpp b/thirdparty/assimp/code/FBX/FBXExportProperty.cpp
index f8593e6295..f2a63b72b9 100644
--- a/thirdparty/assimp/code/FBX/FBXExportProperty.cpp
+++ b/thirdparty/assimp/code/FBX/FBXExportProperty.cpp
@@ -59,11 +59,7 @@ namespace FBX {
FBXExportProperty::FBXExportProperty(bool v)
: type('C')
-, data(1) {
- data = {
- uint8_t(v)
- };
-}
+, data(1, uint8_t(v)) {}
FBXExportProperty::FBXExportProperty(int16_t v)
: type('Y')
diff --git a/thirdparty/assimp/code/FBX/FBXExporter.cpp b/thirdparty/assimp/code/FBX/FBXExporter.cpp
index 8ebc8555a2..9316dc4f02 100644
--- a/thirdparty/assimp/code/FBX/FBXExporter.cpp
+++ b/thirdparty/assimp/code/FBX/FBXExporter.cpp
@@ -67,6 +67,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector>
#include <array>
#include <unordered_set>
+#include <numeric>
// RESOURCES:
// https://code.blender.org/2013/08/fbx-binary-file-format-specification/
@@ -1005,6 +1006,9 @@ void FBXExporter::WriteObjects ()
object_node.EndProperties(outstream, binary, indent);
object_node.BeginChildren(outstream, binary, indent);
+ bool bJoinIdenticalVertices = mProperties->GetPropertyBool("bJoinIdenticalVertices", true);
+ std::vector<std::vector<int32_t>> vVertexIndice;//save vertex_indices as it is needed later
+
// geometry (aiMesh)
mesh_uids.clear();
indent = 1;
@@ -1031,21 +1035,35 @@ void FBXExporter::WriteObjects ()
std::vector<int32_t> vertex_indices;
// map of vertex value to its index in the data vector
std::map<aiVector3D,size_t> index_by_vertex_value;
- int32_t index = 0;
- for (size_t vi = 0; vi < m->mNumVertices; ++vi) {
- aiVector3D vtx = m->mVertices[vi];
- auto elem = index_by_vertex_value.find(vtx);
- if (elem == index_by_vertex_value.end()) {
- vertex_indices.push_back(index);
- index_by_vertex_value[vtx] = index;
- flattened_vertices.push_back(vtx[0]);
- flattened_vertices.push_back(vtx[1]);
- flattened_vertices.push_back(vtx[2]);
- ++index;
- } else {
- vertex_indices.push_back(int32_t(elem->second));
+ if(bJoinIdenticalVertices){
+ int32_t index = 0;
+ for (size_t vi = 0; vi < m->mNumVertices; ++vi) {
+ aiVector3D vtx = m->mVertices[vi];
+ auto elem = index_by_vertex_value.find(vtx);
+ if (elem == index_by_vertex_value.end()) {
+ vertex_indices.push_back(index);
+ index_by_vertex_value[vtx] = index;
+ flattened_vertices.push_back(vtx[0]);
+ flattened_vertices.push_back(vtx[1]);
+ flattened_vertices.push_back(vtx[2]);
+ ++index;
+ } else {
+ vertex_indices.push_back(int32_t(elem->second));
+ }
+ }
+ }
+ else { // do not join vertex, respect the export flag
+ vertex_indices.resize(m->mNumVertices);
+ std::iota(vertex_indices.begin(), vertex_indices.end(), 0);
+ for(unsigned int v = 0; v < m->mNumVertices; ++ v) {
+ aiVector3D vtx = m->mVertices[v];
+ flattened_vertices.push_back(vtx.x);
+ flattened_vertices.push_back(vtx.y);
+ flattened_vertices.push_back(vtx.z);
}
}
+ vVertexIndice.push_back(vertex_indices);
+
FBX::Node::WritePropertyNode(
"Vertices", flattened_vertices, outstream, binary, indent
);
@@ -1116,6 +1134,51 @@ void FBXExporter::WriteObjects ()
normals.End(outstream, binary, indent, true);
}
+ // colors, if any
+ // TODO only one color channel currently
+ const int32_t colorChannelIndex = 0;
+ if (m->HasVertexColors(colorChannelIndex)) {
+ FBX::Node vertexcolors("LayerElementColor", int32_t(colorChannelIndex));
+ vertexcolors.Begin(outstream, binary, indent);
+ vertexcolors.DumpProperties(outstream, binary, indent);
+ vertexcolors.EndProperties(outstream, binary, indent);
+ vertexcolors.BeginChildren(outstream, binary, indent);
+ indent = 3;
+ FBX::Node::WritePropertyNode(
+ "Version", int32_t(101), outstream, binary, indent
+ );
+ char layerName[8];
+ sprintf(layerName, "COLOR_%d", colorChannelIndex);
+ FBX::Node::WritePropertyNode(
+ "Name", (const char*)layerName, outstream, binary, indent
+ );
+ FBX::Node::WritePropertyNode(
+ "MappingInformationType", "ByPolygonVertex",
+ outstream, binary, indent
+ );
+ FBX::Node::WritePropertyNode(
+ "ReferenceInformationType", "Direct",
+ outstream, binary, indent
+ );
+ std::vector<double> color_data;
+ color_data.reserve(4 * polygon_data.size());
+ for (size_t fi = 0; fi < m->mNumFaces; ++fi) {
+ const aiFace &f = m->mFaces[fi];
+ for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) {
+ const aiColor4D &c = m->mColors[colorChannelIndex][f.mIndices[pvi]];
+ color_data.push_back(c.r);
+ color_data.push_back(c.g);
+ color_data.push_back(c.b);
+ color_data.push_back(c.a);
+ }
+ }
+ FBX::Node::WritePropertyNode(
+ "Colors", color_data, outstream, binary, indent
+ );
+ indent = 2;
+ vertexcolors.End(outstream, binary, indent, true);
+ }
+
// uvs, if any
for (size_t uvi = 0; uvi < m->GetNumUVChannels(); ++uvi) {
if (m->mNumUVComponents[uvi] > 2) {
@@ -1209,6 +1272,11 @@ void FBXExporter::WriteObjects ()
le.AddChild("Type", "LayerElementNormal");
le.AddChild("TypedIndex", int32_t(0));
layer.AddChild(le);
+ // TODO only 1 color channel currently
+ le = FBX::Node("LayerElement");
+ le.AddChild("Type", "LayerElementColor");
+ le.AddChild("TypedIndex", int32_t(0));
+ layer.AddChild(le);
le = FBX::Node("LayerElement");
le.AddChild("Type", "LayerElementMaterial");
le.AddChild("TypedIndex", int32_t(0));
@@ -1221,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");
@@ -1748,28 +1816,8 @@ void FBXExporter::WriteObjects ()
// connect it
connections.emplace_back("C", "OO", deformer_uid, mesh_uids[mi]);
- // we will be indexing by vertex...
- // but there might be a different number of "vertices"
- // between assimp and our output FBX.
- // this code is cut-and-pasted from the geometry section above...
- // ideally this should not be so.
- // ---
- // index of original vertex in vertex data vector
- std::vector<int32_t> vertex_indices;
- // map of vertex value to its index in the data vector
- std::map<aiVector3D,size_t> index_by_vertex_value;
- int32_t index = 0;
- for (size_t vi = 0; vi < m->mNumVertices; ++vi) {
- aiVector3D vtx = m->mVertices[vi];
- auto elem = index_by_vertex_value.find(vtx);
- if (elem == index_by_vertex_value.end()) {
- vertex_indices.push_back(index);
- index_by_vertex_value[vtx] = index;
- ++index;
- } else {
- vertex_indices.push_back(int32_t(elem->second));
- }
- }
+ //computed before
+ std::vector<int32_t>& vertex_indices = vVertexIndice[mi];
// TODO, FIXME: this won't work if anything is not in the bind pose.
// for now if such a situation is detected, we throw an exception.
@@ -2435,7 +2483,7 @@ void FBXExporter::WriteModelNodes(
void FBXExporter::WriteAnimationCurveNode(
StreamWriterLE& outstream,
int64_t uid,
- std::string name, // "T", "R", or "S"
+ const std::string& name, // "T", "R", or "S"
aiVector3D default_value,
std::string property_name, // "Lcl Translation" etc
int64_t layer_uid,
diff --git a/thirdparty/assimp/code/FBX/FBXExporter.h b/thirdparty/assimp/code/FBX/FBXExporter.h
index 71fb55c57f..1ae727eda9 100644
--- a/thirdparty/assimp/code/FBX/FBXExporter.h
+++ b/thirdparty/assimp/code/FBX/FBXExporter.h
@@ -156,7 +156,7 @@ namespace Assimp
void WriteAnimationCurveNode(
StreamWriterLE& outstream,
int64_t uid,
- std::string name, // "T", "R", or "S"
+ const std::string& name, // "T", "R", or "S"
aiVector3D default_value,
std::string property_name, // "Lcl Translation" etc
int64_t animation_layer_uid,
diff --git a/thirdparty/assimp/code/FBX/FBXImporter.cpp b/thirdparty/assimp/code/FBX/FBXImporter.cpp
index 271935a568..afcc1ddc78 100644
--- a/thirdparty/assimp/code/FBX/FBXImporter.cpp
+++ b/thirdparty/assimp/code/FBX/FBXImporter.cpp
@@ -48,26 +48,26 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXImporter.h"
-#include "FBXTokenizer.h"
+#include "FBXConverter.h"
+#include "FBXDocument.h"
#include "FBXParser.h"
+#include "FBXTokenizer.h"
#include "FBXUtil.h"
-#include "FBXDocument.h"
-#include "FBXConverter.h"
-#include <assimp/StreamReader.h>
#include <assimp/MemoryIOWrapper.h>
-#include <assimp/Importer.hpp>
+#include <assimp/StreamReader.h>
#include <assimp/importerdesc.h>
+#include <assimp/Importer.hpp>
namespace Assimp {
-template<>
-const char* LogFunctions<FBXImporter>::Prefix() {
- static auto prefix = "FBX: ";
- return prefix;
+template <>
+const char *LogFunctions<FBXImporter>::Prefix() {
+ static auto prefix = "FBX: ";
+ return prefix;
}
-}
+} // namespace Assimp
using namespace Assimp;
using namespace Assimp::Formatter;
@@ -76,136 +76,123 @@ using namespace Assimp::FBX;
namespace {
static const aiImporterDesc desc = {
- "Autodesk FBX Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportTextFlavour,
- 0,
- 0,
- 0,
- 0,
- "fbx"
+ "Autodesk FBX Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "fbx"
};
}
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by #Importer
-FBXImporter::FBXImporter()
-{
+FBXImporter::FBXImporter() {
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
-FBXImporter::~FBXImporter()
-{
+FBXImporter::~FBXImporter() {
}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
-bool FBXImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
-{
- const std::string& extension = GetExtension(pFile);
- if (extension == std::string( desc.mFileExtensions ) ) {
- return true;
- }
-
- else if ((!extension.length() || checkSig) && pIOHandler) {
- // at least ASCII-FBX files usually have a 'FBX' somewhere in their head
- const char* tokens[] = {"fbx"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
- }
- return false;
+bool FBXImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
+ const std::string &extension = GetExtension(pFile);
+ if (extension == std::string(desc.mFileExtensions)) {
+ return true;
+ }
+
+ else if ((!extension.length() || checkSig) && pIOHandler) {
+ // at least ASCII-FBX files usually have a 'FBX' somewhere in their head
+ const char *tokens[] = { "fbx" };
+ return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
// List all extensions handled by this loader
-const aiImporterDesc* FBXImporter::GetInfo () const
-{
- return &desc;
+const aiImporterDesc *FBXImporter::GetInfo() const {
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
// Setup configuration properties for the loader
-void FBXImporter::SetupProperties(const Importer* pImp)
-{
- settings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true);
- settings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false);
- settings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true);
- settings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true);
- settings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true);
- settings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true);
- settings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true);
- 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.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
- settings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
- settings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
+void FBXImporter::SetupProperties(const Importer *pImp) {
+ settings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true);
+ settings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false);
+ settings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true);
+ settings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true);
+ settings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true);
+ settings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true);
+ settings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true);
+ 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.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
+ settings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
+ settings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
}
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
-void FBXImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
-{
- std::unique_ptr<IOStream> stream(pIOHandler->Open(pFile,"rb"));
- if (!stream) {
- ThrowException("Could not open file for reading");
- }
-
- // read entire file into memory - no streaming for this, fbx
- // files can grow large, but the assimp output data structure
- // then becomes very large, too. Assimp doesn't support
- // streaming for its output data structures so the net win with
- // streaming input data would be very low.
- std::vector<char> contents;
- contents.resize(stream->FileSize()+1);
- stream->Read( &*contents.begin(), 1, contents.size()-1 );
- contents[ contents.size() - 1 ] = 0;
- const char* const begin = &*contents.begin();
-
- // broadphase tokenizing pass in which we identify the core
- // syntax elements of FBX (brackets, commas, key:value mappings)
- TokenList tokens;
- try {
-
- bool is_binary = false;
- if (!strncmp(begin,"Kaydara FBX Binary",18)) {
- is_binary = true;
- TokenizeBinary(tokens,begin,contents.size());
- }
- else {
- Tokenize(tokens,begin);
- }
-
- // use this information to construct a very rudimentary
- // parse-tree representing the FBX scope structure
- Parser parser(tokens, is_binary);
-
- // take the raw parse-tree and convert it to a FBX DOM
- Document doc(parser,settings);
-
- FbxUnit unit(FbxUnit::cm);
- if (settings.convertToMeters) {
- unit = FbxUnit::m;
- }
-
- // convert the FBX DOM to aiScene
- ConvertToAssimpScene(pScene, doc, settings.removeEmptyBones);
-
- // size relative to cm
- float size_relative_to_cm = doc.GlobalSettings().UnitScaleFactor();
-
- // Set FBX file scale is relative to CM must be converted to M for
- // assimp universal format (M)
- SetFileScale( size_relative_to_cm * 0.01f);
-
- std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
- }
- catch(std::exception&) {
- std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
- throw;
- }
+void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
+ std::unique_ptr<IOStream> stream(pIOHandler->Open(pFile, "rb"));
+ if (!stream) {
+ ThrowException("Could not open file for reading");
+ }
+
+ // read entire file into memory - no streaming for this, fbx
+ // files can grow large, but the assimp output data structure
+ // then becomes very large, too. Assimp doesn't support
+ // streaming for its output data structures so the net win with
+ // streaming input data would be very low.
+ std::vector<char> contents;
+ contents.resize(stream->FileSize() + 1);
+ stream->Read(&*contents.begin(), 1, contents.size() - 1);
+ contents[contents.size() - 1] = 0;
+ const char *const begin = &*contents.begin();
+
+ // broadphase tokenizing pass in which we identify the core
+ // syntax elements of FBX (brackets, commas, key:value mappings)
+ TokenList tokens;
+ try {
+
+ bool is_binary = false;
+ if (!strncmp(begin, "Kaydara FBX Binary", 18)) {
+ is_binary = true;
+ TokenizeBinary(tokens, begin, contents.size());
+ } else {
+ Tokenize(tokens, begin);
+ }
+
+ // use this information to construct a very rudimentary
+ // parse-tree representing the FBX scope structure
+ Parser parser(tokens, is_binary);
+
+ // take the raw parse-tree and convert it to a FBX DOM
+ Document doc(parser, settings);
+
+ // convert the FBX DOM to aiScene
+ ConvertToAssimpScene(pScene, doc, settings.removeEmptyBones);
+
+ // size relative to cm
+ float size_relative_to_cm = doc.GlobalSettings().UnitScaleFactor();
+
+ // Set FBX file scale is relative to CM must be converted to M for
+ // assimp universal format (M)
+ SetFileScale(size_relative_to_cm * 0.01f);
+
+ std::for_each(tokens.begin(), tokens.end(), Util::delete_fun<Token>());
+ } catch (std::exception &) {
+ std::for_each(tokens.begin(), tokens.end(), Util::delete_fun<Token>());
+ throw;
+ }
}
#endif // !ASSIMP_BUILD_NO_FBX_IMPORTER
diff --git a/thirdparty/assimp/code/FBX/FBXMeshGeometry.cpp b/thirdparty/assimp/code/FBX/FBXMeshGeometry.cpp
index 5c9a0e309d..1386e2383c 100644
--- a/thirdparty/assimp/code/FBX/FBXMeshGeometry.cpp
+++ b/thirdparty/assimp/code/FBX/FBXMeshGeometry.cpp
@@ -610,11 +610,11 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
const std::string& ReferenceInformationType)
{
const size_t face_count = m_faces.size();
- if(face_count <= 0)
+ if( 0 == face_count )
{
return;
}
-
+
// materials are handled separately. First of all, they are assigned per-face
// and not per polyvert. Secondly, ReferenceInformationType=IndexToDirect
// has a slightly different meaning for materials.
@@ -625,16 +625,14 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
if (materials_out.empty()) {
FBXImporter::LogError(Formatter::format("expected material index, ignoring"));
return;
- }
- else if (materials_out.size() > 1) {
+ } else if (materials_out.size() > 1) {
FBXImporter::LogWarn(Formatter::format("expected only a single material index, ignoring all except the first one"));
materials_out.clear();
}
materials_out.resize(m_vertices.size());
std::fill(materials_out.begin(), materials_out.end(), materials_out.at(0));
- }
- else if (MappingInformationType == "ByPolygon" && ReferenceInformationType == "IndexToDirect") {
+ } else if (MappingInformationType == "ByPolygon" && ReferenceInformationType == "IndexToDirect") {
materials_out.resize(face_count);
if(materials_out.size() != face_count) {
@@ -643,18 +641,16 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
);
return;
}
- }
- else {
+ } else {
FBXImporter::LogError(Formatter::format("ignoring material assignments, access type not implemented: ")
<< MappingInformationType << "," << ReferenceInformationType);
}
}
// ------------------------------------------------------------------------------------------------
ShapeGeometry::ShapeGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
- : Geometry(id, element, name, doc)
-{
- const Scope* sc = element.Compound();
- if (!sc) {
+: Geometry(id, element, name, doc) {
+ const Scope *sc = element.Compound();
+ if (nullptr == sc) {
DOMError("failed to read Geometry object (class: Shape), no data scope found");
}
const Element& Indexes = GetRequiredElement(*sc, "Indexes", &element);