diff --git a/CMakeLists.txt b/CMakeLists.txt index 66ae4aa..1092208 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,10 +17,11 @@ set(CMAKE_CXX_STANDARD 11) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}") include(ExternalProject) -if(NOT EXISTS "${CMAKE_BINARY_DIR}/Findboost_filesystem.cmake") +if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan_paths.cmake") message(FATAL_ERROR "The Conan package manager must run ('install') first. ${typical_usage_str}") endif() +include("${CMAKE_BINARY_DIR}/conan_paths.cmake") # FBX foreach (FBXSDK_VERSION "2019.2") diff --git a/README.md b/README.md index 00ea066..f1f6fe5 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,8 @@ Options: Whether to use 32-bit indices. --compute-normals (never|broken|missing|always) When to compute vertex normals from mesh geometry. + --anim-framerate (bake24|bake30|bake60) + Select baked animation framerate. --flip-u Flip all U texture coordinates. --no-flip-u Don't flip U texture coordinates. --flip-v Flip all V texture coordinates. diff --git a/npm/tests/test/fbx2gltf.ts b/npm/tests/test/fbx2gltf.ts index 93e5a27..34ec3d3 100644 --- a/npm/tests/test/fbx2gltf.ts +++ b/npm/tests/test/fbx2gltf.ts @@ -1,3 +1,12 @@ +/** + * Copyright (c) 2014-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + import {assert, expect} from 'chai'; import * as fbx2gltf from 'fbx2gltf'; import {readFileSync} from 'fs'; diff --git a/npm/tests/test/mocha.opts b/npm/tests/test/mocha.opts index bb4e390..1745889 100644 --- a/npm/tests/test/mocha.opts +++ b/npm/tests/test/mocha.opts @@ -1,3 +1,10 @@ +# Copyright (c) 2014-present, Facebook, Inc. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. An additional grant +# of patent rights can be found in the PATENTS file in the same directory. + --ui mocha-typescript --require source-map-support/register --recursive test diff --git a/src/FBX2glTF.cpp b/src/FBX2glTF.cpp index 2171c0a..1b09eee 100644 --- a/src/FBX2glTF.cpp +++ b/src/FBX2glTF.cpp @@ -96,6 +96,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."); @@ -295,7 +315,7 @@ int main(int argc, char* argv[]) { if (verboseOutput) { fmt::printf("Loading FBX File: %s\n", inputPath); } - if (!LoadFBXFile(raw, inputPath, {"png", "jpg", "jpeg"})) { + if (!LoadFBXFile(raw, inputPath, {"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 5a0bb0a..79be9f9 100644 --- a/src/FBX2glTF.h +++ b/src/FBX2glTF.h @@ -69,6 +69,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. */ @@ -115,4 +121,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 0c28498..8e68d21 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(); @@ -1027,7 +1038,8 @@ static void FindFbxTextures( bool LoadFBXFile( RawModel& raw, const std::string fbxFileName, - const std::set& textureExtensions) { + const std::set& textureExtensions, + const GltfOptions& options) { FbxManager* pManager = FbxManager::Create(); FbxIOSettings* pIoSettings = FbxIOSettings::Create(pManager, IOSROOT); pManager->SetIOSettings(pIoSettings); @@ -1073,7 +1085,7 @@ bool LoadFBXFile( 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 7933af1..f998001 100644 --- a/src/fbx/Fbx2Raw.hpp +++ b/src/fbx/Fbx2Raw.hpp @@ -14,6 +14,7 @@ bool LoadFBXFile( RawModel& raw, const std::string fbxFileName, - const std::set& textureExtensions); + const std::set& textureExtensions, + const GltfOptions& options); json TranscribeProperty(FbxProperty& prop); \ No newline at end of file diff --git a/src/fbx/FbxSkinningAccess.cpp b/src/fbx/FbxSkinningAccess.cpp index f76d8ec..795cece 100644 --- a/src/fbx/FbxSkinningAccess.cpp +++ b/src/fbx/FbxSkinningAccess.cpp @@ -75,7 +75,8 @@ FbxSkinningAccess::FbxSkinningAccess(const FbxMesh* pMesh, FbxScene* pScene, Fbx } } for (int i = 0; i < controlPointCount; i++) { - vertexJointWeights[i] = vertexJointWeights[i].Normalized(); + const float weightSumRcp = 1.0 / (vertexJointWeights[i][0] + vertexJointWeights[i][1] + vertexJointWeights[i][2] + vertexJointWeights[i][3]); + vertexJointWeights[i] *= weightSumRcp; } } }