From 4a9cd0845171070fb971eb90c03f7ca6b8234039 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 6 May 2019 20:51:04 +0200 Subject: [PATCH 1/4] Prepaation for conversion. --- code/FBXConverter.cpp | 7 ++++++- code/FBXConverter.h | 17 +++++++++++++++++ code/FBXMeshGeometry.cpp | 4 ++-- code/FBXParser.cpp | 2 +- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 76b6c6b4e..ab600e53d 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -90,7 +90,8 @@ namespace Assimp { , anim_fps() , out(out) , doc(doc) - , mRemoveEmptyBones( removeEmptyBones ) { + , mRemoveEmptyBones( removeEmptyBones ) + , mCurrentUnit( FbxUnit::Undefined ) { // animations need to be converted first since this will // populate the node_anim_chain_bits map, which is needed // to determine which nodes need to be generated. @@ -3474,6 +3475,10 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa out->mMetaData->Set(14, "CustomFrameRate", doc.GlobalSettings().CustomFrameRate()); } + void FBXConverter::ConvertToUnitScale(FbxUnit unit) { + + } + void FBXConverter::TransferDataToScene() { ai_assert(!out->mMeshes); diff --git a/code/FBXConverter.h b/code/FBXConverter.h index a77cb4310..75f24713e 100644 --- a/code/FBXConverter.h +++ b/code/FBXConverter.h @@ -415,6 +415,21 @@ private: void ConvertGlobalSettings(); + enum class FbxUnit { + cm = 0, + m, + km, + inch, + foot, + mile, + yard, + NumUnits, + + Undefined + }; + + void ConvertToUnitScale(FbxUnit unit); + // ------------------------------------------------------------------------------------------------ // copy generated meshes, animations, lights, cameras and textures to the output scene void TransferDataToScene(); @@ -456,6 +471,8 @@ private: const FBX::Document& doc; bool mRemoveEmptyBones; + + FbxUnit mCurrentUnit; }; } diff --git a/code/FBXMeshGeometry.cpp b/code/FBXMeshGeometry.cpp index 2debfa651..468ba1c2e 100644 --- a/code/FBXMeshGeometry.cpp +++ b/code/FBXMeshGeometry.cpp @@ -568,8 +568,8 @@ void MeshGeometry::ReadVertexDataColors(std::vector& colors_out, cons } // ------------------------------------------------------------------------------------------------ -static const std::string TangentIndexToken = "TangentIndex"; -static const std::string TangentsIndexToken = "TangentsIndex"; +static const char *TangentIndexToken = "TangentIndex"; +static const char *TangentsIndexToken = "TangentsIndex"; void MeshGeometry::ReadVertexDataTangents(std::vector& tangents_out, const Scope& source, const std::string& MappingInformationType, diff --git a/code/FBXParser.cpp b/code/FBXParser.cpp index b255c4734..fe63866a0 100644 --- a/code/FBXParser.cpp +++ b/code/FBXParser.cpp @@ -117,7 +117,7 @@ namespace FBX { Element::Element(const Token& key_token, Parser& parser) : key_token(key_token) { - TokenPtr n = NULL; + TokenPtr n = nullptr; do { n = parser.AdvanceToNextToken(); if(!n) { From 4155f005bee4a06c4bb724d748e9a3c69166d1c8 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 6 May 2019 21:21:58 +0200 Subject: [PATCH 2/4] Add implementation to convert from cm to m. --- code/FBXConverter.cpp | 44 +++++++++++++++++++++++++++++++++++--- code/FBXConverter.h | 6 ++---- code/FBXImportSettings.h | 7 +++++- code/FBXImporter.cpp | 1 + code/FBXMeshGeometry.cpp | 2 +- include/assimp/config.h.in | 9 +++++++- 6 files changed, 59 insertions(+), 10 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index ab600e53d..bd8347408 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -91,7 +91,7 @@ namespace Assimp { , out(out) , doc(doc) , mRemoveEmptyBones( removeEmptyBones ) - , mCurrentUnit( FbxUnit::Undefined ) { + , mCurrentUnit(FbxUnit::cm) { // animations need to be converted first since this will // populate the node_anim_chain_bits map, which is needed // to determine which nodes need to be generated. @@ -119,6 +119,7 @@ namespace Assimp { ConvertGlobalSettings(); TransferDataToScene(); + ConvertToUnitScale(doc.GlobalSettings().UnitScaleFactor()); // if we didn't read any meshes set the AI_SCENE_FLAGS_INCOMPLETE // to make sure the scene passes assimp's validation. FBX files @@ -3410,8 +3411,9 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa na->mNumScalingKeys = static_cast(keys.size()); na->mScalingKeys = new aiVectorKey[keys.size()]; - if (keys.size() > 0) + if (keys.size() > 0) { InterpolateKeys(na->mScalingKeys, keys, inputs, aiVector3D(1.0f, 1.0f, 1.0f), maxTime, minTime); + } } void FBXConverter::ConvertTranslationKeys(aiNodeAnim* na, const std::vector& nodes, @@ -3475,8 +3477,44 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa out->mMetaData->Set(14, "CustomFrameRate", doc.GlobalSettings().CustomFrameRate()); } - void FBXConverter::ConvertToUnitScale(FbxUnit unit) { + void FBXConverter::ConvertToUnitScale( FbxUnit unit ) { + if (mCurrentUnit == unit) { + return; + } + ai_real scale = 1.0; + if (mCurrentUnit == FbxUnit::cm) { + if (unit == FbxUnit::m) { + scale = (ai_real)0.01; + } else if (unit == FbxUnit::km) { + scale = (ai_real)0.00001; + } + } else if (mCurrentUnit == FbxUnit::m) { + if (unit == FbxUnit::cm) { + scale = (ai_real)100.0; + } else if (unit == FbxUnit::km) { + scale = (ai_real)0.001; + } + } else if (mCurrentUnit == FbxUnit::km) { + if (unit == FbxUnit::cm) { + scale = (ai_real)100000.0; + } else if (unit == FbxUnit::m) { + scale = (ai_real)1000.0; + } + } + + for (auto mesh : meshes) { + if (nullptr == mesh) { + continue; + } + + if (mesh->HasPositions()) { + for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { + aiVector3D &pos = mesh->mVertices[i]; + pos *= scale; + } + } + } } void FBXConverter::TransferDataToScene() diff --git a/code/FBXConverter.h b/code/FBXConverter.h index 75f24713e..dbbeee158 100644 --- a/code/FBXConverter.h +++ b/code/FBXConverter.h @@ -419,15 +419,13 @@ private: cm = 0, m, km, - inch, - foot, - mile, - yard, NumUnits, Undefined }; + // ------------------------------------------------------------------------------------------------ + // Will perform the conversion from a given unit to the requested unit. void ConvertToUnitScale(FbxUnit unit); // ------------------------------------------------------------------------------------------------ diff --git a/code/FBXImportSettings.h b/code/FBXImportSettings.h index eaf127382..1a4c80f8b 100644 --- a/code/FBXImportSettings.h +++ b/code/FBXImportSettings.h @@ -65,7 +65,8 @@ struct ImportSettings , preservePivots(true) , optimizeEmptyAnimationCurves(true) , useLegacyEmbeddedTextureNaming(false) - , removeEmptyBones( true ) { + , removeEmptyBones( true ) + , convertToMeters( false ) { // empty } @@ -149,6 +150,10 @@ struct ImportSettings /** Empty bones shall be removed */ bool removeEmptyBones; + + /** Set to true to perform a conversion from cm to meter after the import + */ + bool convertToMeters; }; diff --git a/code/FBXImporter.cpp b/code/FBXImporter.cpp index 60a19223c..4f75b9c2e 100644 --- a/code/FBXImporter.cpp +++ b/code/FBXImporter.cpp @@ -141,6 +141,7 @@ void FBXImporter::SetupProperties(const Importer* pImp) 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 = pImpl->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false); } // ------------------------------------------------------------------------------------------------ diff --git a/code/FBXMeshGeometry.cpp b/code/FBXMeshGeometry.cpp index 468ba1c2e..44a0264ca 100644 --- a/code/FBXMeshGeometry.cpp +++ b/code/FBXMeshGeometry.cpp @@ -576,7 +576,7 @@ void MeshGeometry::ReadVertexDataTangents(std::vector& tangents_out, const std::string& ReferenceInformationType) { const char * str = source.Elements().count( "Tangents" ) > 0 ? "Tangents" : "Tangent"; - const char * strIdx = source.Elements().count( "Tangents" ) > 0 ? TangentsIndexToken.c_str() : TangentIndexToken.c_str(); + const char * strIdx = source.Elements().count( "Tangents" ) > 0 ? TangentsIndexToken : TangentIndexToken; ResolveVertexDataArray(tangents_out,source,MappingInformationType,ReferenceInformationType, str, strIdx, diff --git a/include/assimp/config.h.in b/include/assimp/config.h.in index 07be7cdad..c42aa63da 100644 --- a/include/assimp/config.h.in +++ b/include/assimp/config.h.in @@ -659,13 +659,20 @@ enum aiComponent "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING" // --------------------------------------------------------------------------- -/** @brief Set wether the FBX importer shall not remove empty bones. +/** @brief Set wether the importer shall not remove empty bones. * * Empty bone are often used to define connections for other models. */ #define AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES \ "AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES" + +// --------------------------------------------------------------------------- +/** @brief Set wether the FBX importer shall convert the unit from cm to m. + */ +#define AI_CONFIG_FBX_CONVERT_TO_M \ + "AI_CONFIG_FBX_CONVERT_TO_M" + // --------------------------------------------------------------------------- /** @brief Set the vertex animation keyframe to be imported * From e917b288a160e466288982cb0e148d5ac7ce6945 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 6 May 2019 21:38:45 +0200 Subject: [PATCH 3/4] fix a typo. --- code/FBXImporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/FBXImporter.cpp b/code/FBXImporter.cpp index 4f75b9c2e..339a9421a 100644 --- a/code/FBXImporter.cpp +++ b/code/FBXImporter.cpp @@ -141,7 +141,7 @@ void FBXImporter::SetupProperties(const Importer* pImp) 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 = pImpl->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false); + settings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false); } // ------------------------------------------------------------------------------------------------ From 390452bd06f510c3c2933ab5915ef2add1b35fec Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 7 May 2019 20:32:45 +0200 Subject: [PATCH 4/4] Fix the build. --- code/FBXConverter.cpp | 8 ++++---- code/FBXConverter.h | 22 +++++++++++----------- code/FBXImporter.cpp | 6 +++++- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index bd8347408..f45129cae 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -76,7 +76,7 @@ namespace Assimp { #define CONVERT_FBX_TIME(time) static_cast(time) / 46186158000L - FBXConverter::FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones) + FBXConverter::FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit ) : defaultMaterialIndex() , lights() , cameras() @@ -119,7 +119,7 @@ namespace Assimp { ConvertGlobalSettings(); TransferDataToScene(); - ConvertToUnitScale(doc.GlobalSettings().UnitScaleFactor()); + ConvertToUnitScale(unit); // if we didn't read any meshes set the AI_SCENE_FLAGS_INCOMPLETE // to make sure the scene passes assimp's validation. FBX files @@ -3570,9 +3570,9 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa } // ------------------------------------------------------------------------------------------------ - void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones) + void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit) { - FBXConverter converter(out, doc, removeEmptyBones); + FBXConverter converter(out, doc, removeEmptyBones, unit); } } // !FBX diff --git a/code/FBXConverter.h b/code/FBXConverter.h index dbbeee158..f75222d5b 100644 --- a/code/FBXConverter.h +++ b/code/FBXConverter.h @@ -76,13 +76,22 @@ 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 * @param doc Parsed FBX document * @param removeEmptyBones Will remove bones, which do not have any references to vertices. */ -void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones ); +void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit); /** Dummy class to encapsulate the conversion process */ class FBXConverter { @@ -113,7 +122,7 @@ public: }; public: - FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones ); + FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit); ~FBXConverter(); private: @@ -415,15 +424,6 @@ private: void ConvertGlobalSettings(); - enum class FbxUnit { - cm = 0, - m, - km, - NumUnits, - - Undefined - }; - // ------------------------------------------------------------------------------------------------ // Will perform the conversion from a given unit to the requested unit. void ConvertToUnitScale(FbxUnit unit); diff --git a/code/FBXImporter.cpp b/code/FBXImporter.cpp index 339a9421a..988735a77 100644 --- a/code/FBXImporter.cpp +++ b/code/FBXImporter.cpp @@ -185,8 +185,12 @@ void FBXImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS // 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); + ConvertToAssimpScene(pScene,doc, settings.removeEmptyBones, unit); std::for_each(tokens.begin(),tokens.end(),Util::delete_fun()); }