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 *