Merge pull request #2448 from assimp/fbx_convert_to_unit

Fbx convert to unit
pull/2433/head^2
Kim Kulling 2019-05-07 21:43:08 +02:00 committed by GitHub
commit 880e5ee32c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 89 additions and 14 deletions

View File

@ -77,7 +77,7 @@ namespace Assimp {
#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L #define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L
FBXConverter::FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones) FBXConverter::FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit )
: defaultMaterialIndex() : defaultMaterialIndex()
, lights() , lights()
, cameras() , cameras()
@ -91,7 +91,8 @@ namespace Assimp {
, anim_fps() , anim_fps()
, out(out) , out(out)
, doc(doc) , doc(doc)
, mRemoveEmptyBones( removeEmptyBones ) { , mRemoveEmptyBones( removeEmptyBones )
, mCurrentUnit(FbxUnit::cm) {
// animations need to be converted first since this will // animations need to be converted first since this will
// populate the node_anim_chain_bits map, which is needed // populate the node_anim_chain_bits map, which is needed
// to determine which nodes need to be generated. // to determine which nodes need to be generated.
@ -119,6 +120,7 @@ namespace Assimp {
ConvertGlobalSettings(); ConvertGlobalSettings();
TransferDataToScene(); TransferDataToScene();
ConvertToUnitScale(unit);
// if we didn't read any meshes set the AI_SCENE_FLAGS_INCOMPLETE // if we didn't read any meshes set the AI_SCENE_FLAGS_INCOMPLETE
// to make sure the scene passes assimp's validation. FBX files // 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<unsigned int>(keys.size()); na->mNumScalingKeys = static_cast<unsigned int>(keys.size());
na->mScalingKeys = new aiVectorKey[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); InterpolateKeys(na->mScalingKeys, keys, inputs, aiVector3D(1.0f, 1.0f, 1.0f), maxTime, minTime);
}
} }
void FBXConverter::ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, void FBXConverter::ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
@ -3482,6 +3485,46 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa
out->mMetaData->Set(14, "CustomFrameRate", doc.GlobalSettings().CustomFrameRate()); 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() void FBXConverter::TransferDataToScene()
{ {
ai_assert(!out->mMeshes); 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 } // !FBX

View File

@ -76,13 +76,22 @@ namespace FBX {
class Document; class Document;
enum class FbxUnit {
cm = 0,
m,
km,
NumUnits,
Undefined
};
/** /**
* Convert a FBX #Document to #aiScene * Convert a FBX #Document to #aiScene
* @param out Empty scene to be populated * @param out Empty scene to be populated
* @param doc Parsed FBX document * @param doc Parsed FBX document
* @param removeEmptyBones Will remove bones, which do not have any references to vertices. * @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 */ /** Dummy class to encapsulate the conversion process */
class FBXConverter { class FBXConverter {
@ -113,7 +122,7 @@ public:
}; };
public: public:
FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones ); FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit);
~FBXConverter(); ~FBXConverter();
private: private:
@ -415,6 +424,10 @@ private:
void ConvertGlobalSettings(); 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 // copy generated meshes, animations, lights, cameras and textures to the output scene
void TransferDataToScene(); void TransferDataToScene();
@ -456,6 +469,8 @@ private:
const FBX::Document& doc; const FBX::Document& doc;
bool mRemoveEmptyBones; bool mRemoveEmptyBones;
FbxUnit mCurrentUnit;
}; };
} }

View File

@ -65,7 +65,8 @@ struct ImportSettings
, preservePivots(true) , preservePivots(true)
, optimizeEmptyAnimationCurves(true) , optimizeEmptyAnimationCurves(true)
, useLegacyEmbeddedTextureNaming(false) , useLegacyEmbeddedTextureNaming(false)
, removeEmptyBones( true ) { , removeEmptyBones( true )
, convertToMeters( false ) {
// empty // empty
} }
@ -149,6 +150,10 @@ struct ImportSettings
/** Empty bones shall be removed /** Empty bones shall be removed
*/ */
bool removeEmptyBones; bool removeEmptyBones;
/** Set to true to perform a conversion from cm to meter after the import
*/
bool convertToMeters;
}; };

View File

@ -141,6 +141,7 @@ void FBXImporter::SetupProperties(const Importer* pImp)
settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, 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.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
settings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true); 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 // take the raw parse-tree and convert it to a FBX DOM
Document doc(parser,settings); Document doc(parser,settings);
FbxUnit unit(FbxUnit::cm);
if (settings.convertToMeters) {
unit = FbxUnit::m;
}
// convert the FBX DOM to aiScene // 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<Token>()); std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
} }

View File

@ -568,15 +568,15 @@ void MeshGeometry::ReadVertexDataColors(std::vector<aiColor4D>& colors_out, cons
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static const std::string TangentIndexToken = "TangentIndex"; static const char *TangentIndexToken = "TangentIndex";
static const std::string TangentsIndexToken = "TangentsIndex"; static const char *TangentsIndexToken = "TangentsIndex";
void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D>& tangents_out, const Scope& source, void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D>& tangents_out, const Scope& source,
const std::string& MappingInformationType, const std::string& MappingInformationType,
const std::string& ReferenceInformationType) const std::string& ReferenceInformationType)
{ {
const char * str = source.Elements().count( "Tangents" ) > 0 ? "Tangents" : "Tangent"; 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, ResolveVertexDataArray(tangents_out,source,MappingInformationType,ReferenceInformationType,
str, str,
strIdx, strIdx,

View File

@ -117,7 +117,7 @@ namespace FBX {
Element::Element(const Token& key_token, Parser& parser) Element::Element(const Token& key_token, Parser& parser)
: key_token(key_token) : key_token(key_token)
{ {
TokenPtr n = NULL; TokenPtr n = nullptr;
do { do {
n = parser.AdvanceToNextToken(); n = parser.AdvanceToNextToken();
if(!n) { if(!n) {

View File

@ -659,13 +659,20 @@ enum aiComponent
"AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING" "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. * Empty bone are often used to define connections for other models.
*/ */
#define AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES \ #define AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES \
"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 /** @brief Set the vertex animation keyframe to be imported
* *