Merge branch 'master' of https://github.com/facebookincubator/FBX2glTF into sync-upstream

This commit is contained in:
Rishabh Battulwar 2018-08-02 16:54:44 -07:00
commit cd7ecd8f82
8 changed files with 127 additions and 45 deletions

View File

@ -27,7 +27,7 @@ endif()
# DRACO
ExternalProject_Add(Draco
GIT_REPOSITORY https://github.com/google/draco
GIT_TAG 1.2.5
GIT_TAG 1.3.1
PREFIX draco
INSTALL_DIR
CMAKE_ARGS
@ -130,28 +130,48 @@ if (APPLE)
endif()
set(SOURCE_FILES
src/utils/File_Utils.cpp
src/utils/Image_Utils.cpp
src/utils/String_Utils.cpp
src/main.cpp
src/FBX2glTF.h
src/Fbx2Raw.cpp
src/Fbx2Raw.h
src/Raw2Gltf.cpp
src/Raw2Gltf.h
src/RawModel.cpp
src/glTF/BufferData.cpp
src/glTF/MaterialData.cpp
src/glTF/MeshData.cpp
src/glTF/NodeData.cpp
src/glTF/PrimitiveData.cpp
src/glTF/BufferViewData.cpp
src/glTF/BufferViewData.h
src/RawModel.h
src/glTF/AccessorData.cpp
src/glTF/AccessorData.h
src/glTF/ImageData.cpp
src/glTF/TextureData.cpp
src/glTF/SkinData.cpp
src/glTF/AnimationData.cpp
src/glTF/AnimationData.h
src/glTF/BufferData.cpp
src/glTF/BufferData.h
src/glTF/BufferViewData.cpp
src/glTF/BufferViewData.h
src/glTF/CameraData.cpp
src/glTF/CameraData.h
src/glTF/ImageData.cpp
src/glTF/ImageData.h
src/glTF/MaterialData.cpp
src/glTF/MaterialData.h
src/glTF/MeshData.cpp
src/glTF/MeshData.h
src/glTF/NodeData.cpp
src/glTF/NodeData.h
src/glTF/PrimitiveData.cpp
src/glTF/PrimitiveData.h
src/glTF/SamplerData.h
src/glTF/SceneData.cpp
src/glTF/SceneData.h
src/glTF/SkinData.cpp
src/glTF/SkinData.h
src/glTF/TextureData.cpp
src/glTF/TextureData.h
src/main.cpp
src/mathfu.h
src/utils/File_Utils.cpp
src/utils/File_Utils.h
src/utils/Image_Utils.cpp
src/utils/Image_Utils.h
src/utils/String_Utils.cpp
src/utils/String_Utils.h
)
add_executable(FBX2glTF ${SOURCE_FILES})

View File

@ -236,12 +236,12 @@ ratification process**
Given the command line flag --pbr-metallic-roughness, we throw ourselves into
the warm embrace of glTF 2.0's PBR preference.
As mentioned above, there is lilttle consensus in the world on how PBR should be
As mentioned above, there is little consensus in the world on how PBR should be
represented in FBX. At present, we support only one format: Stingray PBS. This
is a featue that comes bundled with Maya, and any PBR model exported through
is a feature that comes bundled with Maya, and any PBR model exported through
that route should be digested propertly by FBX2glTF.
(A happy note: Allegorithmic's Susbstance Painter also exports Stingray PBS,
(A happy note: Allegorithmic's Substance Painter also exports Stingray PBS,
when hooked up to Maya.)
## Draco Compression

View File

@ -11,16 +11,21 @@
#define __FBX2GLTF_H__
#if defined ( _WIN32 )
// This can be a macro under Windows, confusing FMT
#undef isnan
// Tell Windows not to define min() and max() macros
#define NOMINMAX
#include <Windows.h>
#endif
const std::string FBX2GLTF_VERSION = "0.9.5";
#include <fmt/printf.h>
#include <fbxsdk.h>
#if defined ( _WIN32 )
// this is defined in fbxmath.h
#undef isnan
#endif
#include "mathfu.h"
#endif // !__FBX2GLTF_H__

View File

@ -17,6 +17,7 @@
#include <cstdint>
#include <cstdio>
#include <cassert>
#include <cmath>
#include "FBX2glTF.h"
#include "utils/File_Utils.h"
@ -401,12 +402,14 @@ public:
for (int deformerIndex = 0; deformerIndex < pMesh->GetDeformerCount(); deformerIndex++) {
FbxSkin *skin = reinterpret_cast< FbxSkin * >( pMesh->GetDeformer(deformerIndex, FbxDeformer::eSkin));
if (skin != nullptr) {
const int clusterCount = skin->GetClusterCount();
if (clusterCount == 0) {
continue;
}
int controlPointCount = pMesh->GetControlPointsCount();
vertexJointIndices.resize(controlPointCount, Vec4i(0, 0, 0, 0));
vertexJointWeights.resize(controlPointCount, Vec4f(0.0f, 0.0f, 0.0f, 0.0f));
const int clusterCount = skin->GetClusterCount();
for (int clusterIndex = 0; clusterIndex < clusterCount; clusterIndex++) {
FbxCluster *cluster = skin->GetCluster(clusterIndex);
const int indexCount = cluster->GetControlPointIndicesCount();
@ -1262,7 +1265,7 @@ static void ReadAnimations(RawModel &raw, FbxScene *pScene)
for (int targetIx = 0; targetIx < targetCount; targetIx++) {
if (curve) {
float result = findInInterval(influence, targetIx-1);
if (!isnan(result)) {
if (!std::isnan(result)) {
// we're transitioning into targetIx
channel.weights.push_back(result);
hasMorphs = true;
@ -1270,7 +1273,7 @@ static void ReadAnimations(RawModel &raw, FbxScene *pScene)
}
if (targetIx != targetCount-1) {
result = findInInterval(influence, targetIx);
if (!isnan(result)) {
if (!std::isnan(result)) {
// we're transitioning AWAY from targetIx
channel.weights.push_back(1.0f - result);
hasMorphs = true;

View File

@ -827,7 +827,7 @@ ModelData *Raw2Gltf(
&& surfaceModel.GetVertexCount() > 65535);
std::shared_ptr<PrimitiveData> primitive;
if (options.useDraco) {
if (options.draco.enabled) {
int triangleCount = surfaceModel.GetTriangleCount();
// initialize Draco mesh with vertex index information
@ -943,17 +943,29 @@ ModelData *Raw2Gltf(
primitive->AddTarget(pAcc.get(), nAcc.get(), tAcc.get(), channel.name);
}
}
if (options.useDraco) {
if (options.draco.enabled) {
// Set up the encoder.
draco::Encoder encoder;
// TODO: generalize / allow configuration
encoder.SetSpeedOptions(5, 5);
encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, 14);
encoder.SetAttributeQuantization(draco::GeometryAttribute::TEX_COORD, 10);
encoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL, 10);
encoder.SetAttributeQuantization(draco::GeometryAttribute::COLOR, 8);
encoder.SetAttributeQuantization(draco::GeometryAttribute::GENERIC, 8);
if (options.draco.compressionLevel != -1) {
int dracoSpeed = 10 - options.draco.compressionLevel;
encoder.SetSpeedOptions(dracoSpeed, dracoSpeed);
}
if (options.draco.quantBitsPosition != -1) {
encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, options.draco.quantBitsPosition);
}
if (options.draco.quantBitsTexCoord != -1) {
encoder.SetAttributeQuantization(draco::GeometryAttribute::TEX_COORD, options.draco.quantBitsTexCoord);
}
if (options.draco.quantBitsNormal != -1) {
encoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL, options.draco.quantBitsNormal);
}
if (options.draco.quantBitsColor != -1) {
encoder.SetAttributeQuantization(draco::GeometryAttribute::COLOR, options.draco.quantBitsColor);
}
if (options.draco.quantBitsGeneric != -1) {
encoder.SetAttributeQuantization(draco::GeometryAttribute::GENERIC, options.draco.quantBitsGeneric);
}
draco::EncoderBuffer dracoBuffer;
draco::Status status = encoder.EncodeMeshToBuffer(*primitive->dracoMesh, &dracoBuffer);
@ -1070,14 +1082,14 @@ ModelData *Raw2Gltf(
if (options.useKHRMatUnlit) {
extensionsUsed.push_back(KHR_MATERIALS_CMN_UNLIT);
}
if (options.useDraco) {
if (options.draco.enabled) {
extensionsUsed.push_back(KHR_DRACO_MESH_COMPRESSION);
extensionsRequired.push_back(KHR_DRACO_MESH_COMPRESSION);
}
json glTFJson {
{ "asset", {
{ "generator", "FBX2glTF" },
{ "generator", "FBX2glTF v" + FBX2GLTF_VERSION },
{ "version", "2.0" }}},
{ "scene", rootScene.ix }
};

View File

@ -269,11 +269,20 @@ void RawModel::Condense()
surfaces.clear();
std::set<int> survivingSurfaceIds;
for (auto &triangle : triangles) {
int oldSurfaceIndex = triangle.surfaceIndex;
const RawSurface &surface = oldSurfaces[triangle.surfaceIndex];
const int surfaceIndex = AddSurface(surface.name.c_str(), surface.id);
surfaces[surfaceIndex] = surface;
triangle.surfaceIndex = surfaceIndex;
survivingSurfaceIds.emplace(surface.id);
}
// clear out references to meshes that no longer exist
for (auto &node : nodes) {
if (node.surfaceId != 0 && survivingSurfaceIds.find(node.surfaceId) == survivingSurfaceIds.end()) {
node.surfaceId = 0;
}
}
}
@ -341,7 +350,9 @@ void RawModel::TransformGeometry(ComputeNormalsOption normals)
if (verboseOutput) {
if (normals == ComputeNormalsOption::BROKEN) {
fmt::printf("Repaired %lu empty normals.\n", computedNormalsCount);
if (computedNormalsCount > 0) {
fmt::printf("Repaired %lu empty normals.\n", computedNormalsCount);
}
} else {
fmt::printf("Computed %lu normals.\n", computedNormalsCount);
}

View File

@ -46,8 +46,18 @@ struct GltfOptions
bool outputBinary { false };
/** If non-binary, whether to inline all resources, for a single (large) .glTF file. */
bool embedResources { false };
/** Whether to use KHR_draco_mesh_compression to minimize static geometry size. */
bool useDraco { false };
/** Whether and how to use KHR_draco_mesh_compression to minimize static geometry size. */
struct {
bool enabled = false;
int compressionLevel = -1;
int quantBitsPosition = -1;
int quantBitsTexCoord = -1;
int quantBitsNormal = -1;
int quantBitsColor = -1;
int quantBitsGeneric = -1;
} draco;
/** Whether to use KHR_materials_unlit to extend materials definitions. */
bool useKHRMatUnlit { false };
/** Whether to populate the pbrMetallicRoughness substruct in materials. */

View File

@ -34,7 +34,8 @@ int main(int argc, char *argv[])
{
cxxopts::Options options(
"FBX2glTF",
"FBX2glTF 2.0: Generate a glTF 2.0 representation of an FBX model.");
fmt::sprintf("FBX2glTF %s: Generate a glTF 2.0 representation of an FBX model.", FBX2GLTF_VERSION)
);
std::string inputPath;
std::string outputPath;
@ -62,7 +63,25 @@ int main(int argc, char *argv[])
cxxopts::value<std::vector<std::string>>())
(
"d,draco", "Apply Draco mesh compression to geometries.",
cxxopts::value<bool>(gltfOptions.useDraco))
cxxopts::value<bool>(gltfOptions.draco.enabled))
(
"draco-compression-level", "The compression level to tune Draco to, from 0 to 10. (default: 7)",
cxxopts::value<int>(gltfOptions.draco.compressionLevel))
(
"draco-bits-for-positions", "How many bits to quantize position to. (default: 14)",
cxxopts::value<int>(gltfOptions.draco.quantBitsPosition))
(
"draco-bits-for-uv", "How many bits to quantize UV coordinates to. (default: 10)",
cxxopts::value<int>(gltfOptions.draco.quantBitsTexCoord))
(
"draco-bits-for-normals", "How many bits to quantize normals to. (default: 10)",
cxxopts::value<int>(gltfOptions.draco.quantBitsNormal))
(
"draco-bits-for-colors", "How many bits to quantize color to. (default: 8)",
cxxopts::value<int>(gltfOptions.draco.quantBitsColor))
(
"draco-bits-for-other", "How many bits to quantize other vertex attributes to to. (default: 8)",
cxxopts::value<int>(gltfOptions.draco.quantBitsGeneric))
(
"compute-normals", "When to compute normals for vertices (never|broken|missing|always).",
cxxopts::value<std::vector<std::string>>())
@ -98,11 +117,7 @@ int main(int argc, char *argv[])
}
if (options.count("version")) {
fmt::printf(
R"(
FBX2glTF version 2.0
Copyright (c) 2016-2017 Oculus VR, LLC.
)");
fmt::printf("FBX2glTF version %s\nCopyright (c) 2016-2017 Oculus VR, LLC.\n", FBX2GLTF_VERSION);
return 0;
}
@ -128,6 +143,12 @@ Copyright (c) 2016-2017 Oculus VR, LLC.
gltfOptions.usePBRMetRough = true;
}
if (gltfOptions.draco.compressionLevel != -1 &&
(gltfOptions.draco.compressionLevel < 1 || gltfOptions.draco.compressionLevel > 10)) {
fmt::printf("Draco compression level must lie in [1, 10].\n");
return 0;
}
if (options.count("flip-u") > 0) {
texturesTransforms.emplace_back([](Vec2f uv) { return Vec2f(1.0f - uv[0], uv[1]); });
}