import multiple animation files

This commit is contained in:
Simon 2019-04-13 15:30:55 +01:00
parent 13f463d336
commit 47001c9ce3
7 changed files with 82 additions and 18 deletions

View File

@ -47,6 +47,7 @@ Usage:
from the FBX.
--khr-materials-unlit Use KHR_materials_unlit extension to specify
Unlit shader.
--animation-files Read multiple fbx animation files.
--blend-shape-normals Include blend shape normals, if reported
present by the FBX SDK.
--blend-shape-tangents Include blend shape tangents, if reported
@ -75,6 +76,10 @@ Some of these switches are not obvious:
Your FBX is likely constructed with the assumption that `(0, 0)` is bottom
left, whereas glTF has `(0, 0)` as top left. To produce spec-compliant glTF,
we must flip the texcoords. To request unflipped coordinates:
- '--animation-files' will try to read in additional animations from multiple
fbx files with numbers added to the base name (eg. test1.fbx, test2.fbx, ...).
It will apply animations to geometry in the base file by matching the node
names, so make sure all nodes have a unique name.
- `--long-indices` lets you force the use of either 16-bit or 32-bit indices.
The default option is auto, which make the choice on a per-mesh-size basis.
- `--compute-normals` controls when automatic vertex normals should be computed

View File

@ -125,6 +125,11 @@ int main(int argc, char* argv[]) {
[&](size_t count) { gltfOptions.useKHRLightsPunctual = (count == 0); },
"Don't use KHR_lights_punctual extension to export FBX lights.");
app.add_flag(
"--animation-files",
gltfOptions.readAnimationFiles,
"Read multiple fbx animation files.");
app.add_flag(
"--user-properties",
gltfOptions.enableUserProperties,
@ -302,7 +307,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;
}

View File

@ -95,6 +95,9 @@ struct GltfOptions
/** Whether to include lights through the KHR_punctual_lights extension. */
bool useKHRLightsPunctual { true };
/** Whether to read multiple fbx animation files. */
bool readAnimationFiles { false };
/** Whether to include blend shape normals, if present according to the SDK. */
bool useBlendShapeNormals { false };
/** Whether to include blend shape tangents, if present according to the SDK. */

View File

@ -721,7 +721,7 @@ static void ReadNodeHierarchy(
}
}
static void ReadAnimations(RawModel& raw, FbxScene* pScene) {
static void ReadAnimations(RawModel& raw, FbxScene* pScene, bool nodeNameLookup) {
FbxTime::EMode eMode = FbxTime::eFrames24;
const double epsilon = 1e-5f;
@ -772,7 +772,14 @@ static void ReadAnimations(RawModel& raw, FbxScene* pScene) {
bool hasMorphs = false;
RawChannel channel;
channel.nodeIndex = raw.GetNodeById(pNode->GetUniqueID());
if (nodeNameLookup) {
channel.nodeIndex = raw.GetNodeByName(pNode->GetName());
} else {
channel.nodeIndex = raw.GetNodeById(pNode->GetUniqueID());
}
if (channel.nodeIndex == -1) {
continue;
}
for (FbxLongLong frameIndex = firstFrameIndex; frameIndex <= lastFrameIndex; frameIndex++) {
FbxTime pTime;
@ -996,11 +1003,7 @@ static void FindFbxTextures(
}
}
bool LoadFBXFile(RawModel& raw, const char* fbxFileName, const char* textureExtensions) {
FbxManager* pManager = FbxManager::Create();
FbxIOSettings* pIoSettings = FbxIOSettings::Create(pManager, IOSROOT);
pManager->SetIOSettings(pIoSettings);
static FbxScene* LoadScene(FbxManager* pManager, const char* fbxFileName) {
FbxImporter* pImporter = FbxImporter::Create(pManager, "");
if (!pImporter->Initialize(fbxFileName, -1, pManager->GetIOSettings())) {
@ -1008,8 +1011,7 @@ bool LoadFBXFile(RawModel& raw, const char* fbxFileName, const char* textureExte
fmt::printf("%s\n", pImporter->GetStatus().GetErrorString());
}
pImporter->Destroy();
pManager->Destroy();
return false;
return nullptr;
}
FbxScene* pScene = FbxScene::Create(pManager, "fbxScene");
@ -1017,14 +1019,9 @@ bool LoadFBXFile(RawModel& raw, const char* fbxFileName, const char* textureExte
pImporter->Destroy();
if (pScene == nullptr) {
pImporter->Destroy();
pManager->Destroy();
return false;
return nullptr;
}
std::map<const FbxTexture*, FbxString> textureLocations;
FindFbxTextures(pScene, fbxFileName, textureExtensions, textureLocations);
// Use Y up for glTF
FbxAxisSystem::MayaYUp.ConvertScene(pScene);
@ -1037,14 +1034,54 @@ bool LoadFBXFile(RawModel& raw, const char* fbxFileName, const char* textureExte
if (sceneSystemUnit != FbxSystemUnit::cm) {
FbxSystemUnit::cm.ConvertScene(pScene);
}
return pScene;
}
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);
FbxScene* pScene = LoadScene(pManager, fbxFileName);
if (pScene == nullptr) {
pManager->Destroy();
return false;
}
// this is always 0.01, but let's opt for clarity.
scaleFactor = FbxSystemUnit::m.GetConversionFactorFrom(FbxSystemUnit::cm);
std::map<const FbxTexture*, FbxString> textureLocations;
FindFbxTextures(pScene, fbxFileName, textureExtensions, textureLocations);
ReadNodeHierarchy(raw, pScene, pScene->GetRootNode(), 0, "");
ReadNodeAttributes(raw, pScene, pScene->GetRootNode(), textureLocations);
ReadAnimations(raw, pScene);
ReadAnimations(raw, pScene, false);
pScene->Destroy();
// read additional animation files
bool readAnimationFiles = options.readAnimationFiles;
int animationFileNumber = 1;
while (readAnimationFiles) {
std::string animationFileName = StringUtils::GetFolderString(fbxFileName) +
StringUtils::GetFileBaseString(fbxFileName) +
std::to_string(animationFileNumber) + ".fbx";
FbxScene* pAnimationScene = LoadScene(pManager, animationFileName.c_str());
if (pAnimationScene != nullptr) {
ReadAnimations(raw, pAnimationScene, true);
pAnimationScene->Destroy();
animationFileNumber++;
} else {
readAnimationFiles = false;
}
}
pManager->Destroy();
return true;

View File

@ -11,6 +11,10 @@
#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);

View File

@ -641,6 +641,15 @@ int RawModel::GetNodeById(const long nodeId) const {
return -1;
}
int RawModel::GetNodeByName(const char* name) const {
for (size_t i = 0; i < nodes.size(); i++) {
if (nodes[i].name == name) {
return (int)i;
}
}
return -1;
}
int RawModel::GetSurfaceById(const long surfaceId) const {
for (size_t i = 0; i < surfaces.size(); i++) {
if (surfaces[i].id == surfaceId) {

View File

@ -509,6 +509,7 @@ class RawModel {
return nodes[index];
}
int GetNodeById(const long nodeId) const;
int GetNodeByName(const char* name) const;
// Create individual attribute arrays.
// Returns true if the vertices store the particular attribute.