diff --git a/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp b/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp index 39f5bb974..f1e89d6bc 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp @@ -12,6 +12,8 @@ #include "Engine/Tools/TextureTool/TextureTool.h" #include "Engine/Platform/File.h" +#define OPEN_FBX_CONVERT_SPACE 1 + // Import OpenFBX library // Source: https://github.com/nem0/OpenFBX #include @@ -85,12 +87,16 @@ struct OpenFbxImporterData const ModelTool::Options& Options; ofbx::GlobalSettings GlobalSettings; +#if OPEN_FBX_CONVERT_SPACE + Quaternion RootConvertRotation = Quaternion::Identity; Float3 Up; Float3 Front; Float3 Right; bool ConvertRH; +#else + static constexpr bool ConvertRH = false; +#endif float FrameRate; - Quaternion RootConvertRotation = Quaternion::Identity; Array Nodes; Array Bones; @@ -103,7 +109,9 @@ struct OpenFbxImporterData , Path(path) , Options(options) , GlobalSettings(*scene->getGlobalSettings()) +#if OPEN_FBX_CONVERT_SPACE , ConvertRH(GlobalSettings.CoordAxis == ofbx::CoordSystem_RightHanded) +#endif , Nodes(static_cast(scene->getMeshCount() * 4.0f)) { float frameRate = scene->getSceneFrameRate(); @@ -114,6 +122,7 @@ struct OpenFbxImporterData frameRate = 30.0f; } FrameRate = frameRate; +#if OPEN_FBX_CONVERT_SPACE const float coordAxisSign = GlobalSettings.CoordAxis == ofbx::CoordSystem_LeftHanded ? -1.0f : +1.0f; switch (GlobalSettings.UpAxis) { @@ -170,6 +179,7 @@ struct OpenFbxImporterData break; default: ; } +#endif } bool ImportMaterialTexture(ImportedModelData& result, const ofbx::Material* mat, ofbx::Texture::TextureType textureType, int32& textureIndex, TextureEntry::TypeHint type) const @@ -371,6 +381,7 @@ void ProcessNodes(OpenFbxImporterData& data, const ofbx::Object* aNode, int32 pa } auto transform = ToMatrix(aNode->evalLocal(aNode->getLocalTranslation(), aNode->getLocalRotation())); +#if OPEN_FBX_CONVERT_SPACE if (data.ConvertRH) { // Mirror all base vectors at the local Z axis @@ -386,6 +397,7 @@ void ProcessNodes(OpenFbxImporterData& data, const ofbx::Object* aNode, int32 pa transform.M33 = -transform.M33; transform.M43 = -transform.M43; } +#endif transform.Decompose(node.LocalTransform); data.Nodes.Add(node); @@ -494,6 +506,15 @@ bool ImportBones(OpenFbxImporterData& data, String& errorMsg) m.M32 = -m.M32; m.M34 = -m.M34; } + + // Convert bone matrix if scene uses root transform + if (!data.RootConvertRotation.IsIdentity()) + { + Matrix m; + Matrix::RotationQuaternion(data.RootConvertRotation, m); + m.Invert(); + bone.OffsetMatrix = m * bone.OffsetMatrix; + } } } } @@ -1095,6 +1116,14 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt } fileData.Resize(0); + // Tweak scene if exported by Blender + auto& globalInfo = *scene->getGlobalInfo(); + if (StringAnsiView(globalInfo.AppName).StartsWith(StringAnsiView("Blender"), StringSearchCase::IgnoreCase)) + { + auto ptr = const_cast(scene->getGlobalSettings()); + ptr->UpAxis = (ofbx::UpVector)((int32)ptr->UpAxis + 1); + } + // Process imported scene context = New(path, options, scene); auto& globalSettings = context->GlobalSettings; @@ -1105,10 +1134,13 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt // Log scene info LOG(Info, "Loaded FBX model, Frame Rate: {0}, Unit Scale Factor: {1}", context->FrameRate, globalSettings.UnitScaleFactor); + LOG(Info, "{0}, {1}, {2}", String(globalInfo.AppName), String(globalInfo.AppVersion), String(globalInfo.AppVendor)); LOG(Info, "Up: {1}{0}", globalSettings.UpAxis == ofbx::UpVector_AxisX ? TEXT("X") : globalSettings.UpAxis == ofbx::UpVector_AxisY ? TEXT("Y") : TEXT("Z"), globalSettings.UpAxisSign == 1 ? TEXT("+") : TEXT("-")); LOG(Info, "Front: {1}{0}", globalSettings.FrontAxis == ofbx::FrontVector_ParityEven ? TEXT("ParityEven") : TEXT("ParityOdd"), globalSettings.FrontAxisSign == 1 ? TEXT("+") : TEXT("-")); LOG(Info, "{0} Handed{1}", globalSettings.CoordAxis == ofbx::CoordSystem_RightHanded ? TEXT("Right") : TEXT("Left"), globalSettings.CoordAxisSign == 1 ? TEXT("") : TEXT(" (negative)")); +#if OPEN_FBX_CONVERT_SPACE LOG(Info, "Imported scene: Up={0}, Front={1}, Right={2}", context->Up, context->Front, context->Right); +#endif // Extract embedded textures if (EnumHasAnyFlags(data.Types, ImportDataTypes::Textures)) @@ -1138,6 +1170,7 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt } } +#if OPEN_FBX_CONVERT_SPACE // Transform nodes to match the engine coordinates system - DirectX (UpVector = +Y, FrontVector = +Z, CoordSystem = -X (LeftHanded)) if (context->Up == Float3(1, 0, 0) && context->Front == Float3(0, 0, 1) && context->Right == Float3(0, 1, 0)) { @@ -1167,15 +1200,16 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt context->RootConvertRotation = Quaternion::Euler(90, 0, 0);*/ if (!context->RootConvertRotation.IsIdentity()) { - for (int32 i = 0; i < context->Nodes.Count(); i++) + for (auto& node : context->Nodes) { - if (context->Nodes[i].ParentIndex == -1) + if (node.ParentIndex == -1) { - context->Nodes[i].LocalTransform.Orientation = context->RootConvertRotation * context->Nodes[i].LocalTransform.Orientation; + node.LocalTransform.Orientation = context->RootConvertRotation * node.LocalTransform.Orientation; break; } } } +#endif } DeleteMe contextCleanup(options.SplitContext ? nullptr : context);