From 13f463d3368e5871b643e907c0e6c6ba6a863ccc Mon Sep 17 00:00:00 2001 From: hhalen Date: Mon, 8 Apr 2019 18:48:16 -0700 Subject: [PATCH 1/3] Fix skinning weight normalization. Previous code would call Normalized() on a Vec4f containing the weights. This normalizes the vector, i.e. makes the length of the vector equal to 1.0. For skinning weights what we want is the sum of the weights to be 1.0, which is a different. This commit fixes that. --- src/fbx/FbxSkinningAccess.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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; } } } From 4ed510ca8e0c6e523976b46767b63949dc8eefed Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Wed, 17 Apr 2019 18:06:09 -0700 Subject: [PATCH 2/3] Add required Facebook copyright headers. --- npm/tests/test/fbx2gltf.ts | 9 +++++++++ npm/tests/test/mocha.opts | 7 +++++++ 2 files changed, 16 insertions(+) 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 From 4bb4bdbac13ed386a0eec3c4bb97607d3c9da6a6 Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 12 Apr 2019 15:08:23 +0100 Subject: [PATCH 3/3] animation framerate option --- README.md | 2 ++ src/FBX2glTF.cpp | 22 +++++++++++++++++++++- src/FBX2glTF.h | 8 ++++++++ src/fbx/Fbx2Raw.cpp | 21 ++++++++++++++++++--- src/fbx/Fbx2Raw.hpp | 2 +- 5 files changed, 50 insertions(+), 5 deletions(-) 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