diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 8b5bd139a..1701b2966 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -77,7 +77,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() @@ -91,7 +91,8 @@ namespace Assimp { , anim_fps() , out(out) , doc(doc) - , mRemoveEmptyBones( removeEmptyBones ) { + , mRemoveEmptyBones( removeEmptyBones ) + , 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 +120,7 @@ namespace Assimp { ConvertGlobalSettings(); TransferDataToScene(); + 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 @@ -3417,8 +3419,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, @@ -3482,6 +3485,46 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa out->mMetaData->Set(14, "CustomFrameRate", doc.GlobalSettings().CustomFrameRate()); } + 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() { ai_assert(!out->mMeshes); @@ -3535,9 +3578,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 a77cb4310..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,6 +424,10 @@ private: void ConvertGlobalSettings(); + // ------------------------------------------------------------------------------------------------ + // Will perform the conversion from a given unit to the requested unit. + void ConvertToUnitScale(FbxUnit unit); + // ------------------------------------------------------------------------------------------------ // copy generated meshes, animations, lights, cameras and textures to the output scene void TransferDataToScene(); @@ -456,6 +469,8 @@ private: const FBX::Document& doc; bool mRemoveEmptyBones; + + FbxUnit mCurrentUnit; }; } 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..988735a77 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 = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false); } // ------------------------------------------------------------------------------------------------ @@ -184,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()); } diff --git a/code/FBXMeshGeometry.cpp b/code/FBXMeshGeometry.cpp index 2debfa651..44a0264ca 100644 --- a/code/FBXMeshGeometry.cpp +++ b/code/FBXMeshGeometry.cpp @@ -568,15 +568,15 @@ 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, 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/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) { 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 *