diff --git a/README.md b/README.md index 14992c5..f7f3464 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,8 @@ Usage: (never|auto|always). --compute-normals arg When to compute normals for vertices (never|broken|missing|always). + --anim-framerate arg Select baked animation framerate + (bake24|bake30|bake60). -k, --keep-attribute arg Used repeatedly to build a limiting set of vertex attributes to keep. -v, --verbose Enable verbose output. diff --git a/src/FBX2glTF.cpp b/src/FBX2glTF.cpp index 270fcd7..75c6de2 100644 --- a/src/FBX2glTF.cpp +++ b/src/FBX2glTF.cpp @@ -103,6 +103,26 @@ int main(int argc, char* argv[]) { "When to compute vertex normals from mesh geometry.") ->type_name("(never|broken|missing|always)"); + app.add_option( + "--anim-framerate", + [&](std::vector choices) -> bool { + for (const std::string choice : choices) { + if (choice == "bake24") { + gltfOptions.animationFramerate = AnimationFramerateOptions::BAKE24; + } else if (choice == "bake30") { + gltfOptions.animationFramerate = AnimationFramerateOptions::BAKE30; + } else if (choice == "bake60") { + gltfOptions.animationFramerate = AnimationFramerateOptions::BAKE60; + } else { + fmt::printf("Unknown --anim-framerate: %s\n", choice); + throw CLI::RuntimeError(1); + } + } + return true; + }, + "Select baked animation framerate.") + ->type_name("(bake24|bake30|bake60)"); + const auto opt_flip_u = app.add_flag("--flip-u", "Flip all U texture coordinates."); const auto opt_no_flip_u = app.add_flag("--no-flip-u", "Don't flip U texture coordinates."); const auto opt_flip_v = app.add_flag("--flip-v", "Flip all V texture coordinates."); @@ -302,7 +322,7 @@ int main(int argc, char* argv[]) { if (verboseOutput) { fmt::printf("Loading FBX File: %s\n", inputPath); } - if (!LoadFBXFile(raw, inputPath.c_str(), "png;jpg;jpeg")) { + if (!LoadFBXFile(raw, inputPath.c_str(), "png;jpg;jpeg", gltfOptions)) { fmt::fprintf(stderr, "ERROR:: Failed to parse FBX: %s\n", inputPath); return 1; } diff --git a/src/FBX2glTF.h b/src/FBX2glTF.h index 5d3f07a..aae19fb 100644 --- a/src/FBX2glTF.h +++ b/src/FBX2glTF.h @@ -56,6 +56,12 @@ enum class UseLongIndicesOptions { ALWAYS, // only ever use 32-bit indices }; +enum class AnimationFramerateOptions { + BAKE24, // bake animations at 24 fps + BAKE30, // bake animations at 30 fps + BAKE60, // bake animations at 60 fps +}; + /** * User-supplied options that dictate the nature of the glTF being generated. */ @@ -103,4 +109,6 @@ struct GltfOptions ComputeNormalsOption computeNormals = ComputeNormalsOption::BROKEN; /** When to use 32-bit indices. */ UseLongIndicesOptions useLongIndices = UseLongIndicesOptions::AUTO; + /** Select baked animation framerate. */ + AnimationFramerateOptions animationFramerate = AnimationFramerateOptions::BAKE24; }; diff --git a/src/fbx/Fbx2Raw.cpp b/src/fbx/Fbx2Raw.cpp index 9a11bdd..a51d582 100644 --- a/src/fbx/Fbx2Raw.cpp +++ b/src/fbx/Fbx2Raw.cpp @@ -721,8 +721,19 @@ static void ReadNodeHierarchy( } } -static void ReadAnimations(RawModel& raw, FbxScene* pScene) { +static void ReadAnimations(RawModel& raw, FbxScene* pScene, const GltfOptions& options) { FbxTime::EMode eMode = FbxTime::eFrames24; + switch (options.animationFramerate) { + case AnimationFramerateOptions::BAKE24: + eMode = FbxTime::eFrames24; + break; + case AnimationFramerateOptions::BAKE30: + eMode = FbxTime::eFrames30; + break; + case AnimationFramerateOptions::BAKE60: + eMode = FbxTime::eFrames60; + break; + } const double epsilon = 1e-5f; const int animationCount = pScene->GetSrcObjectCount(); @@ -996,7 +1007,11 @@ static void FindFbxTextures( } } -bool LoadFBXFile(RawModel& raw, const char* fbxFileName, const char* textureExtensions) { +bool LoadFBXFile( + RawModel& raw, + const char* fbxFileName, + const char* textureExtensions, + const GltfOptions& options) { FbxManager* pManager = FbxManager::Create(); FbxIOSettings* pIoSettings = FbxIOSettings::Create(pManager, IOSROOT); pManager->SetIOSettings(pIoSettings); @@ -1042,7 +1057,7 @@ bool LoadFBXFile(RawModel& raw, const char* fbxFileName, const char* textureExte ReadNodeHierarchy(raw, pScene, pScene->GetRootNode(), 0, ""); ReadNodeAttributes(raw, pScene, pScene->GetRootNode(), textureLocations); - ReadAnimations(raw, pScene); + ReadAnimations(raw, pScene, options); pScene->Destroy(); pManager->Destroy(); diff --git a/src/fbx/Fbx2Raw.hpp b/src/fbx/Fbx2Raw.hpp index a5fd231..47ffece 100644 --- a/src/fbx/Fbx2Raw.hpp +++ b/src/fbx/Fbx2Raw.hpp @@ -11,6 +11,6 @@ #include "raw/RawModel.hpp" -bool LoadFBXFile(RawModel& raw, const char* fbxFileName, const char* textureExtensions); +bool LoadFBXFile(RawModel& raw, const char* fbxFileName, const char* textureExtensions, const GltfOptions& options); json TranscribeProperty(FbxProperty& prop); \ No newline at end of file