diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..9ff5cde --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +.dockerignore +Dockerfile +sdk diff --git a/.gitattributes b/.gitattributes index 9074a99..f2a3a0b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,14 @@ +# FBX SDK +*.a filter=lfs diff=lfs merge=lfs -text +*.dylib filter=lfs diff=lfs merge=lfs -text +*.so filter=lfs diff=lfs merge=lfs -text +*.dll filter=lfs diff=lfs merge=lfs -text +*.lib filter=lfs diff=lfs merge=lfs -text + +# TEST FILES *.glb filter=lfs diff=lfs merge=lfs -text *.fbx filter=lfs diff=lfs merge=lfs -text *.tga filter=lfs diff=lfs merge=lfs -text *.png filter=lfs diff=lfs merge=lfs -text *.jpg filter=lfs diff=lfs merge=lfs -text + diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..22006d7 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,63 @@ +git: + lfs_skip_smudge: true + +matrix: + include: + - os: linux + dist: xenial + env: + - APP_NAME="FBX2glTF-linux-x64" + - CONAN_CONFIG="-s compiler.libcxx=libstdc++11" + - FBXSDK_TARBALL="https://github.com/zellski/FBXSDK-Linux/archive/2019.2.tar.gz" + - TAR_WILDCARDS="--wildcards" + - os: osx + osx_image: xcode10.2 + env: + - APP_NAME="FBX2glTF-darwin-x64" + - CONAN_CONFIG="-s compiler=apple-clang -s compiler.version=10.0 -s compiler.libcxx=libc++" + - FBXSDK_TARBALL="https://github.com/zellski/FBXSDK-Darwin/archive/2019.2.tar.gz" + - TAR_WILDCARDS="" +compiler: gcc +language: generic + +#disabled for now +#cache: +# directories: +# - ${HOME}/.conan + +addons: + apt: + packages: zstd + homebrew: + packages: zstd + +install: +- curl -sL "${FBXSDK_TARBALL}" | tar xz --strip-components=1 ${TAR_WILDCARDS} */sdk +- zstd -d -r --rm sdk +- git clone --depth 1 git://github.com/astropy/ci-helpers.git +- source ci-helpers/travis/setup_conda.sh +- conda config --set always_yes yes +- conda info -a +- conda create -n travis_env python=3.7 pip +- conda activate travis_env +- pip install conan +- conan user +- conan remote add --force bincrafters https://api.bintray.com/conan/bincrafters/public-conan + +script: +- conan install . -i build -s build_type=Release ${CONAN_CONFIG} +- conan build . -bf build +- mv build/FBX2glTF build/${APP_NAME} + +notifications: + webhooks: + - "https://code.facebook.com/travis/webhook/" +deploy: + provider: releases + api_key: + secure: V9CTmZKM7yvsT/WCesJ/tLTuapSf0oIp73zyZrwID7zQtXaq1QJSna4tWM2T0qeZIYhniH1/mqEr2jZVW1txmYn9ZxUMH1Nmp9zzOGl/q+JlRrJUi6HRUWWhCMz003L90whngyOcGI+T7rHtcVcby4owVsze15SrQqqV74NXI8DYNIbNgQR1Nwmqsrg0QirFPEBaIKDAiKonnRDWKPy2P8vqnN9fLhj00uHLwuvahlKAnWFEbNnFbiRScKifB+Mlo6Pf6r64iikrxS2jBxAgSsvPLkuemWLmaHTeGbJMM82aqh5vGSvgYcExvZi+0RdXeIcBdv/jaivM/xge4aZ+4P+IJoX32ZNCcYFMsqES+a6TztkywMs2k1r5gV6LrTjeXJsINSW+BDFdmrwmkudETc4gelQgkMmEkdCwFHENtZGl65z8HJDQKcu9F8NQlhNU7Z5rwQNLmYccvktSDhwbFSG5eq2kFFfcbVx3ovvn1voRTNnyhhVD2ZnLepSQInAVkZbaLkE90bQ+t9icf8uDdHDn17zOQaAZuecPlSW1y4XUCJnZCi0JPLhdSmQYiF60LHYI6xDneC8pmIz8kCUbk921zu8bJBy7zKHmfHy2vqNlPKuRULRIs5QzY31jf2PVZHzB5zX3KSqx9Dd+3DtgbLX2HLaZnANbkQc0rr1X2kk= + file: build/${APP_NAME} + skip_cleanup: true + on: + repo: facebookincubator/FBX2glTF + tags: true diff --git a/CMakeLists.txt b/CMakeLists.txt index b4e434b..8bf5a09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,15 @@ cmake_minimum_required(VERSION 3.5) project(FBX2glTF) +set(typical_usage_str + "Example usage:\n\ + > mkdir -p build_debug\n\ + > conan install . -i build_debug -s build_type=Debug -e FBXSDK_SDKS=/home/zell/FBXSDK\n\ + > conan build . -bf build_debug") + if ("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") message(FATAL_ERROR - "Building from within the source tree is not supported.\n" - "Hint: mkdir -p build; cmake -H. -Bbuild; make -Cbuild\n") + "Building from within the source tree is not supported! ${typical_usage_str}") endif () set(CMAKE_CXX_STANDARD 11) @@ -28,35 +33,27 @@ if (NOT FBXSDK_FOUND) ) endif() +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") + set(CMAKE_THREAD_PREFER_PTHREAD TRUE) find_package(Threads REQUIRED) -find_package(Iconv QUIET) + +list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_BINARY_DIR}") + +# stuff we get from Conan +find_package(boost_filesystem MODULE REQUIRED) +find_package(boost_optional MODULE REQUIRED) +find_package(libxml2 MODULE REQUIRED) +find_package(zlib MODULE REQUIRED) +find_package(fmt MODULE REQUIRED) # create a compilation database for e.g. clang-tidy set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -if (WIN32) - # this will suffice for now; don't really care about 32-bit - set(LIBXML2_INCLUDE_DIRS ${FBXSDK_INCLUDE_DIR}) - set(LIBXML2_LIBRARIES ${FBXSDK_ROOT}/lib/vs2017/x64/release/libxml2-mt.lib) - set(LIBXML2_LIBRARIES_DEBUG ${FBXSDK_ROOT}/lib/vs2017/x64/debug/libxml2-mt.lib) - if (NOT LIBXML2_INCLUDE_DIRS OR NOT LIBXML2_LIBRARIES) - message(FATAL_ERROR "Cannot find libxml2.lib in the expected location.") - endif() - - set(ZLIB_INCLUDE_DIRS ${FBXSDK_INCLUDE_DIR}) - set(ZLIB_LIBRARIES ${FBXSDK_ROOT}/lib/vs2017/x64/release/zlib-mt.lib) - set(ZLIB_LIBRARIES_DEBUG ${FBXSDK_ROOT}/lib/vs2017/x64/debug/zlib-mt.lib) - if (NOT ZLIB_LIBRARIES) - message(FATAL_ERROR "Cannot find zlib.lib in the expected location.") - endif() - -else() - find_package(LibXml2 REQUIRED) - find_package(ZLIB REQUIRED) -endif() - - # DRACO ExternalProject_Add(Draco GIT_REPOSITORY https://github.com/google/draco @@ -110,22 +107,6 @@ ExternalProject_Add(CPPCodec ) set(CPPCODEC_INCLUDE_DIR "${CMAKE_BINARY_DIR}/cppcodec/src/CPPCodec") -# FMT -ExternalProject_Add(Fmt - PREFIX fmt - GIT_REPOSITORY https://github.com/fmtlib/fmt - GIT_TAG 4.0.0 - CMAKE_CACHE_ARGS "-DFMT_DOC:BOOL=OFF" "-DFMT_INSTALL:BOOL=ON" "-DFMT_TEST:BOOL=OFF" - CMAKE_ARGS - -DCMAKE_INSTALL_PREFIX= -) -set(FMT_INCLUDE_DIR "${CMAKE_BINARY_DIR}/fmt/include") -if (WIN32) - set(FMT_LIB "${CMAKE_BINARY_DIR}/fmt/lib/fmt.lib") -else() - set(FMT_LIB "${CMAKE_BINARY_DIR}/fmt/lib/libfmt.a") -endif() - if (APPLE) find_library(CF_FRAMEWORK CoreFoundation) message("CoreFoundation Framework: ${CF_FRAMEWORK}") @@ -190,7 +171,6 @@ set(LIB_SOURCE_FILES src/utils/File_Utils.hpp src/utils/Image_Utils.cpp src/utils/Image_Utils.hpp - src/utils/String_Utils.cpp src/utils/String_Utils.hpp third_party/CLI11/CLI11.hpp ) @@ -205,7 +185,6 @@ add_dependencies(libFBX2glTF MathFu FiFoMap CPPCodec - Fmt ) if (NOT MSVC) @@ -222,51 +201,40 @@ endif() target_link_libraries(libFBX2glTF ${FRAMEWORKS} + boost_filesystem::boost_filesystem + boost_optional::boost_optional ${DRACO_LIB} - ${FMT_LIB} optimized ${FBXSDK_LIBRARY} debug ${FBXSDK_LIBRARY_DEBUG} + fmt::fmt + libxml2::libxml2 + zlib::zlib ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT} ) -if (WIN32) - target_link_libraries(libFBX2glTF - optimized ${LIBXML2_LIBRARIES} - debug ${LIBXML2_LIBRARIES_DEBUG} - optimized ${ZLIB_LIBRARIES} - debug ${ZLIB_LIBRARIES_DEBUG} - ) +if (APPLE) + find_package(Iconv MODULE REQUIRED) + target_link_libraries(libFBX2glTF Iconv) else() - target_link_libraries(libFBX2glTF - ${LIBXML2_LIBRARIES} - ${ZLIB_LIBRARIES} - ) + find_package(libiconv MODULE REQUIRED) + target_link_libraries(libFBX2glTF libiconv::libiconv) endif() -target_include_directories(libFBX2glTF SYSTEM PUBLIC +target_include_directories(libFBX2glTF PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src - "third_party/stb" - "third_party/json" ) target_include_directories(libFBX2glTF SYSTEM PUBLIC - Iconv::Iconv + "third_party/stb" + "third_party/json" ${FBXSDK_INCLUDE_DIR} ${DRACO_INCLUDE_DIR} ${MATHFU_INCLUDE_DIRS} ${FIFO_MAP_INCLUDE_DIR} ${CPPCODEC_INCLUDE_DIR} - ${FMT_INCLUDE_DIR} - ${LIBXML2_INCLUDE_DIR} - ${ZLIB_INCLUDE_DIRS} ) -if (Iconv_FOUND) - target_link_libraries(libFBX2glTF Iconv::Iconv) - target_include_directories(libFBX2glTF SYSTEM PUBLIC Iconv::Iconv) -endif() - target_include_directories(appFBX2glTF PUBLIC "third_party/CLI11" ) diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..67cb1a3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,29 @@ +FROM ubuntu:16.04 + +RUN apt-get update && \ + apt-get install -y software-properties-common && \ + add-apt-repository ppa:jonathonf/python-3.6 && \ + add-apt-repository ppa:git-core/ppa && \ + apt-get update && \ + apt-get install -y python3.6 curl build-essential cmake libxml2-dev zlib1g-dev git && \ + curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py && python3 get-pip.py && \ + pip install conan && \ + conan remote add bincrafters https://api.bintray.com/conan/bincrafters/public-conan + +# Install FBX SDK +RUN mkdir -p /fbx2gltf/sdk/Linux/2019.2 && \ + curl -L https://www.autodesk.com/content/dam/autodesk/www/adn/fbx/20192/fbx20192_fbxsdk_linux.tar.gz -o fbx20192_fbxsdk_linux.tar.gz && \ + tar -xvf fbx20192_fbxsdk_linux.tar.gz && \ + echo "yes\nn" | ./fbx20192_fbxsdk_linux /fbx2gltf/sdk/Linux/2019.2 && \ + rm -rf /fbxsdktemp + +COPY . /fbx2gltf + +WORKDIR /fbx2gltf + +# Build and install +RUN conan install . -i docker-build -s build_type=Release -s compiler=gcc -s compiler.version=5 -s compiler.libcxx=libstdc++11 && \ + conan build -bf docker-build . && \ + cp docker-build/FBX2glTF /usr/bin && \ + cd / && \ + rm -rf /fbx2gltf /root/.conan diff --git a/FindFBX.cmake b/FindFBX.cmake index fdf904d..0c29dc1 100644 --- a/FindFBX.cmake +++ b/FindFBX.cmake @@ -24,28 +24,23 @@ else() endif() if (NOT DEFINED FBXSDK_VERSION) - set(FBXSDK_VERSION "2018.1.1") + set(FBXSDK_VERSION "2019.2") endif() set(_fbxsdk_vstudio_version "vs2017") message("Looking for FBX SDK version: ${FBXSDK_VERSION}") -if (DEFINED FBXSDK_SDKS) - get_filename_component(FBXSDK_SDKS_ABS ${FBXSDK_SDKS} ABSOLUTE) - - set(FBXSDK_APPLE_ROOT "${FBXSDK_SDKS_ABS}/Darwin/${FBXSDK_VERSION}") - set(FBXSDK_LINUX_ROOT "${FBXSDK_SDKS_ABS}/Linux/${FBXSDK_VERSION}") - set(FBXSDK_WINDOWS_ROOT "${FBXSDK_SDKS_ABS}/Windows/${FBXSDK_VERSION}") -else() - set(FBXSDK_APPLE_ROOT - "/Applications/Autodesk/FBX SDK/${FBXSDK_VERSION}") - set(FBXSDK_LINUX_ROOT - "/usr") - set(FBXSDK_WINDOWS_ROOT - "C:/Program Files/Autodesk/FBX/FBX SDK/${FBXSDK_VERSION}") +if (NOT DEFINED FBXSDK_SDKS) + set(FBXSDK_SDKS "${CMAKE_CURRENT_SOURCE_DIR}/sdk") endif() +get_filename_component(FBXSDK_SDKS_ABS ${FBXSDK_SDKS} ABSOLUTE) + +set(FBXSDK_APPLE_ROOT "${FBXSDK_SDKS_ABS}/Darwin/${FBXSDK_VERSION}") +set(FBXSDK_LINUX_ROOT "${FBXSDK_SDKS_ABS}/Linux/${FBXSDK_VERSION}") +set(FBXSDK_WINDOWS_ROOT "${FBXSDK_SDKS_ABS}/Windows/${FBXSDK_VERSION}") + if (APPLE) set(_fbxsdk_root "${FBXSDK_APPLE_ROOT}") set(_fbxsdk_libdir_debug "lib/clang/debug") diff --git a/LICENSE b/LICENSE index be6addb..2801536 100644 --- a/LICENSE +++ b/LICENSE @@ -2,7 +2,7 @@ BSD License For FBX2glTF software -Copyright (c) 2014-present, Facebook, Inc. All rights reserved. +Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/PATENTS b/PATENTS deleted file mode 100644 index 4168ccd..0000000 --- a/PATENTS +++ /dev/null @@ -1,33 +0,0 @@ -Additional Grant of Patent Rights Version 2 - -"Software" means the FBX2glTF software contributed by Facebook, Inc. - -Facebook, Inc. ("Facebook") hereby grants to each recipient of the Software -("you") a perpetual, worldwide, royalty-free, non-exclusive, irrevocable -(subject to the termination provision below) license under any Necessary -Claims, to make, have made, use, sell, offer to sell, import, and otherwise -transfer the Software. For avoidance of doubt, no license is granted under -Facebook’s rights in any patent claims that are infringed by (i) modifications -to the Software made by you or any third party or (ii) the Software in -combination with any software or other technology. - -The license granted hereunder will terminate, automatically and without notice, -if you (or any of your subsidiaries, corporate affiliates or agents) initiate -directly or indirectly, or take a direct financial interest in, any Patent -Assertion: (i) against Facebook or any of its subsidiaries or corporate -affiliates, (ii) against any party if such Patent Assertion arises in whole or -in part from any software, technology, product or service of Facebook or any of -its subsidiaries or corporate affiliates, or (iii) against any party relating -to the Software. Notwithstanding the foregoing, if Facebook or any of its -subsidiaries or corporate affiliates files a lawsuit alleging patent -infringement against you in the first instance, and you respond by filing a -patent infringement counterclaim in that lawsuit against that party that is -unrelated to the Software, the license granted hereunder will not terminate -under section (i) of this paragraph due to such counterclaim. - -A "Necessary Claim" is a claim of a patent owned by Facebook that is -necessarily infringed by the Software standing alone. - -A "Patent Assertion" is any lawsuit or other action alleging direct, indirect, -or contributory infringement or inducement to infringe any patent, including a -cross-claim or counterclaim. diff --git a/README.md b/README.md index 14992c5..659d088 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # FBX2glTF +[![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) This is a command line tool for converting 3D model assets on Autodesk's venerable [FBX](https://www.autodesk.com/products/fbx/overview) format to @@ -8,7 +9,10 @@ a modern runtime asset delivery format. Precompiled binaries releases for Windows, Mac OS X and Linux may be found [here](https://github.com/facebookincubator/FBX2glTF/releases). -Bleeding-edge binaries are periodically built and publicly available [here](https://dev.azure.com/parwinzell/FBX2glTF/): click a build (usually the most recent), then the 'Artefacts' dropdown in the upper right. +Bleeding-edge binaries for Windows may be found [here](https://ci.appveyor.com/project/Facebook/fbx2gltf/build/artifacts). Linux and Mac OS X to come; meanwhile, you can [build your own](#building-it-on-your-own). + +[![Build Status](https://travis-ci.com/facebookincubator/FBX2glTF.svg?branch=master)](https://travis-ci.com/facebookincubator/FBX2glTF) +[![Build status](https://ci.appveyor.com/api/projects/status/5mq4vbc44vmyec4w?svg=true)](https://ci.appveyor.com/project/Facebook/fbx2gltf) ## Running @@ -28,47 +32,66 @@ Or perhaps, as part of a more complex pipeline: You can always run the binary with --help to see what options it takes: ``` -FBX2glTF 2.0: Generate a glTF 2.0 representation of an FBX model. -Usage: - FBX2glTF [OPTION...] [] +FBX2glTF 0.9.6: Generate a glTF 2.0 representation of an FBX model. +Usage: FBX2glTF [OPTIONS] [FBX Model] - -i, --input arg The FBX model to convert. - -o, --output arg Where to generate the output, without suffix. - -e, --embed Inline buffers as data:// URIs within - generated non-binary glTF. - -b, --binary Output a single binary format .glb file. - -d, --draco Apply Draco mesh compression to geometries. - --flip-u Flip all U texture coordinates. - --flip-v Flip all V texture coordinates (default - behaviour!) - --no-flip-v Suppress the default flipping of V texture - coordinates - --pbr-metallic-roughness Try to glean glTF 2.0 native PBR attributes - from the FBX. - --khr-materials-unlit Use KHR_materials_unlit extension to specify - Unlit shader. - --blend-shape-normals Include blend shape normals, if reported - present by the FBX SDK. - --blend-shape-tangents Include blend shape tangents, if reported - present by the FBX SDK. - --long-indices arg Whether to use 32-bit indices - (never|auto|always). - --compute-normals arg When to compute normals for vertices - (never|broken|missing|always). - -k, --keep-attribute arg Used repeatedly to build a limiting set of - vertex attributes to keep. - -v, --verbose Enable verbose output. - -h, --help Show this help. - -V, --version Display the current program version. +Positionals: + FBX Model FILE The FBX model to convert. + +Options: + -h,--help Print this help message and exit + -v,--verbose Include blend shape tangents, if reported present by the FBX SDK. + -V,--version + -i,--input FILE The FBX model to convert. + -o,--output TEXT Where to generate the output, without suffix. + -e,--embed Inline buffers as data:// URIs within generated non-binary glTF. + -b,--binary Output a single binary format .glb file. + --long-indices (never|auto|always) + 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. + --no-flip-v Don't flip V texture coordinates. + --no-khr-lights-punctual Don't use KHR_lights_punctual extension to export FBX lights. + --user-properties Transcribe FBX User Properties into glTF node and material 'extras'. + --blend-shape-normals Include blend shape normals, if reported present by the FBX SDK. + --blend-shape-tangents Include blend shape tangents, if reported present by the FBX SDK. + -k,--keep-attribute (position|normal|tangent|binormial|color|uv0|uv1|auto) ... + Used repeatedly to build a limiting set of vertex attributes to keep. + + +Materials: + --pbr-metallic-roughness Try to glean glTF 2.0 native PBR attributes from the FBX. + --khr-materials-unlit Use KHR_materials_unlit extension to request an unlit shader. + + +Draco: + -d,--draco Apply Draco mesh compression to geometries. + --draco-compression-level INT in [0 - 10]=7 + The compression level to tune Draco to. + --draco-bits-for-position INT in [1 - 32]=14 + How many bits to quantize position to. + --draco-bits-for-uv INT in [1 - 32]=10 + How many bits to quantize UV coordinates to. + --draco-bits-for-normals INT in [1 - 32]=10 + How many bits to quantize nornals to. + --draco-bits-for-colors INT in [1 - 32]=8 + How many bits to quantize colors to. + --draco-bits-for-other INT in [1 - 32]=8 + How many bits to quantize all other vertex attributes to. ``` Some of these switches are not obvious: - `--embed` is the way to get a single distributable file without using the - binary format. It encodes the binary buffer(s) as a single enormous - base64-encoded `data://` URI. This is a very slow and space-consuming way to - accomplish what the binary format was invented to do simply and efficiently, - but it can be useful e.g. for loaders that don't understand the .glb format. + binary format. It encodes the binary buffer(s) as a single base64-encoded + `data://` URI. This is a very slow and space-consuming way to accomplish what + the binary format was invented to do simply and efficiently, but it can be + useful e.g. for loaders that don't understand the .glb format. - `--flip-u` and `--flip-v`, when enabled, will apply a `x -> (1.0 - x)` function to all `u` or `v` texture coordinates respectively. The `u` version is perhaps not commonly used, but flipping `v` is **the default behaviour**. @@ -104,49 +127,70 @@ Some of these switches are not obvious: ## Building it on your own -This build process has been tested on Linux, Mac OS X and Windows. It requires -CMake 3.5+ and a reasonably C++11 compliant toolchain. - We currently depend on the open source projects [Draco](https://github.com/google/draco), [MathFu](https://github.com/google/mathfu), [Json](https://github.com/nlohmann/json), [cppcodec](https://github.com/tplgy/cppcodec), -[cxxopts](https://github.com/jarro2783/cxxopts), +[CLI11](https://github.com/CLIUtils/CLI11), +[stb](https://github.com/nothings/stb), and [fmt](https://github.com/fmtlib/fmt); -all of which are automatically downloaded, configured and built. +all of which are automatically downloaded and/or built. -You must manually download and install the -[Autodesk FBX SDK](https://www.autodesk.com/products/fbx/overview) and -accept its license agreement. - -**At present, only version 2018.1.1 of the FBX SDK is supported**. The +**At present, only version 2019.2 of the FBX SDK is supported**. The build system will not successfully locate any other version. ### Linux and MacOS X -Compilation on Unix machines should be as simple as: +Your development environment will need to have: +- build essentials (gcc for Linux, clang for Mac) +- cmake +- python 3.* and associated pip3/pip command +- zstd + +Then, compilation on Unix machines will look something like: ``` - > cd - > cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=Release - > make -Cbuild -j4 install +# Determine SDK location & build settings for Linux vs (Recent) Mac OS X +> if [[ "$OSTYPE" == "darwin" ]]; then + export CONAN_CONFIG="-s compiler=apple-clang -s compiler.version=10.0 -s compiler.libcxx=libc++" + export FBXSDK_TARBALL="https://github.com/zellski/FBXSDK-Darwin/archive/2019.2.tar.gz" +else + export CONAN_CONFIG="-s compiler.libcxx=libstdc++11" + export FBXSDK_TARBALL="https://github.com/zellski/FBXSDK-Linux/archive/2019.2.tar.gz" + fi + +# Fetch Project +> GIT_LFS_SKIP_SMUDGE=1 git clone https://github.com/facebookincubator/FBX2glTF.git +> cd FBX2glTF + +# Fetch and unpack FBX SDK +> curl -sL "${FBXSDK_TARBALL}" | tar xz --strip-components=1 --wildcards */sdk +# Then decompress the contents +> zstd -d -r --rm sdk + +# Install and configure Conan, if needed +> pip3 install conan # or sometimes just "pip"; you may need to install Python/PIP +> conan remote add --force bincrafters https://api.bintray.com/conan/bincrafters/public-conan + +# Initialize & run build +> conan install . -i build -s build_type=Release ${CONAN_CONFIG} +> conan build . -bf build ``` -If all goes well, you will end up with a statically linked executable. +If all goes well, you will end up with a statically linked executable in `./build/FBX2glTF`. ### Windows + the below is out of date + Windows users may [download](https://cmake.org/download) CMake for Windows, install it and [run it](https://cmake.org/runningcmake/) on the FBX2glTF checkout (choose a build directory distinct from the source). As part of this process, you will be asked to choose which generator -to use. **At present, only Visual Studio 2017 is supported.** Older +to use. **At present, only Visual Studio 2017 or 2019 is supported.** Older versions of the IDE are unlikely to successfully build the tool. -*(MinGW support is plausible. The difficulty is linking statically against the -FBX SDK .lib file. Contributions welcome.)* - Note that the `CMAKE_BUILD_TYPE` variable from the Unix Makefile system is entirely ignored here; it is when you open the generated solution that you will be choose one of the canonical build types — *Debug*, @@ -272,4 +316,4 @@ TODO items can be found - Amanda Watson ## License -FBX2glTF is BSD-licensed. We also provide an additional patent grant. +FBX2glTF is licensed under the [3-clause BSD license](LICENSE). diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..4ae70e7 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,58 @@ +# version format +version: 1.0.{build} + +environment: + matrix: + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + PYTHON: "C:\\Python36-x64" + FBXSDK_SDKS: sdk + +stack: python %PYTHON% + +#temporarily disabled +#cache: +# - C:\Users\appveyor\.conan\data -> appveyor.yml, conanfile.py + +init: + - git config --global filter.lfs.required false + - git config --global filter.lfs.smudge "git-lfs smudge --skip %f" + - git config --global filter.lfs.process "git-lfs filter-process --skip" + +install: + - cinst zstandard + - ps: Start-FileDownload 'https://github.com/zellski/FBXSDK-Windows/archive/2019.2.tar.gz' + - 7z e 2019.2.tar.gz + - 7z x 2019.2.tar + - ps: move -v .\FBXSDK-Windows-2019.2\sdk\ . + - ps: zstd -d -r --rm sdk + - cmd: echo "Downloading conan..." + - cmd: set PATH=%PYTHON%;%PYTHON%\Scripts;%PATH% + - cmd: python --version + - cmd: python -m pip install --upgrade pip + - cmd: pip install conan + - cmd: conan user # Create the conan data directory + - cmd: conan remote add bincrafters https://api.bintray.com/conan/bincrafters/public-conan + - cmd: conan --version + +build_script: + - cmd: conan install . -i build -s build_type=Release -s compiler="Visual Studio" -s compiler.version=15 + - cmd: conan build -bf build . + - cmd: move build\Release\FBX2glTF.exe build\Release\FBX2glTF-windows-x64.exe + +test: off + +artifacts: + - path: build/Release/FBX2glTF-windows-x64.exe + +deploy: + tag: $(APPVEYOR_REPO_TAG_NAME) + description: '' + provider: GitHub + auth_token: + secure: OSvhQP0O9uaH+OFOJpbGiiBMRTOJ+H/VJHqVBhq39RNDnOfUEr/yjJNKh3JSdNqj + artifact: build/Release/FBX2glTF-windows-x64.exe + draft: true + prerelease: true + on: + branch: master + APPVEYOR_REPO_TAG: true diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 0000000..cd618a0 --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,101 @@ +# C/C++ with GCC +# Build your C/C++ project with GCC using make. +# Add steps that publish test results, save build artifacts, deploy, and more: +# https://docs.microsoft.com/azure/devops/pipelines/apps/c-cpp/gcc + +jobs: +- job: Linux + pool: + vmImage: 'Ubuntu 16.04' + + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.6' + architecture: 'x64' + + - script: python -m pip install --upgrade pip setuptools wheel + displayName: 'Install Python tools' + + - script: | + pip install conan + conan remote add bincrafters https://api.bintray.com/conan/bincrafters/public-conan + displayName: 'Install & configure Conan' + + - script: | + conan install . -i build -s build_type=Release -e FBXSDK_SDKS=sdk + displayName: 'Resolve binary dependencies and build CMake files.' + + - script: | + conan build -bf build . + mv build/FBX2glTF build/FBX2glTF-linux-x64 + displayName: 'Build FBX2glTF' + + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: 'build/FBX2glTF-linux-x64' + artifactName: 'binaries' + +- job: Mac + pool: + vmImage: 'macOS-10.14' + + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.6' + architecture: 'x64' + + - script: python -m pip install --upgrade pip setuptools wheel + displayName: 'Install Python tools' + + - script: | + pip install conan + conan remote add bincrafters https://api.bintray.com/conan/bincrafters/public-conan + displayName: 'Install Conan' + + - script: | + conan install . -i build -s compiler=apple-clang -s compiler=apple-clang -s compiler.version=10.0 -s compiler.libcxx=libc++ -s build_type=Release -e FBXSDK_SDKS=sdk + displayName: 'Resolve binary dependencies and build CMake files.' + + - script: | + conan build -bf build . + mv build/FBX2glTF build/FBX2glTF-darwin-x64 + displayName: 'Build FBX2glTF' + + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: 'build/FBX2glTF-darwin-x64' + artifactName: 'binaries' + +- job: Windows + pool: + vmImage: 'vs2017-win2016' + + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.6' + architecture: 'x64' + + - script: python -m pip install --upgrade pip setuptools wheel + displayName: 'Install Python tools' + + - script: | + pip install conan + conan remote add bincrafters https://api.bintray.com/conan/bincrafters/public-conan + displayName: 'Install Conan' + + - script: | + conan install . -i build -s build_type=Release -e FBXSDK_SDKS=sdk + displayName: 'Resolve binary dependencies and build CMake files.' + + - script: | + conan build -bf build . + move build\Release\FBX2glTF.exe build\Release\FBX2glTF-windows-x64.exe + displayName: 'Build FBX2glTF' + + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: 'build/Release/FBX2glTF-windows-x64.exe' + artifactName: 'binaries' diff --git a/conanfile.py b/conanfile.py new file mode 100644 index 0000000..be675d0 --- /dev/null +++ b/conanfile.py @@ -0,0 +1,33 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +# + +import os + +from conans import ConanFile, CMake + + +class FBX2glTFConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + requires = ( + ("boost_filesystem/1.69.0@bincrafters/stable"), + ("libiconv/1.15@bincrafters/stable"), + ("zlib/1.2.11@conan/stable"), + ("libxml2/2.9.9@bincrafters/stable"), + ("fmt/5.3.0@bincrafters/stable"), + ) + generators = "cmake_find_package", "cmake_paths" + + def configure(self): + if ( + self.settings.compiler == "gcc" + and self.settings.compiler.libcxx == "libstdc++" + ): + raise Exception( + "Rerun 'conan install' with argument: '-s compiler.libcxx=libstdc++11'" + ) + + def build(self): + cmake = CMake(self) + cmake.definitions["FBXSDK_SDKS"] = os.getenv("FBXSDK_SDKS", "sdk") + cmake.configure() + cmake.build() diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..b8195b6 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,5 @@ +version: '3.7' +services: + fbx2gltf: + build: + context: . diff --git a/npm/fbx2gltf/LICENSE b/npm/fbx2gltf/LICENSE index 832cda8..8d53340 100644 --- a/npm/fbx2gltf/LICENSE +++ b/npm/fbx2gltf/LICENSE @@ -2,7 +2,7 @@ BSD License For FBX2glTF software -Copyright (c) 2014-present, Facebook, Inc. All rights reserved. +Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/npm/fbx2gltf/PATENTS b/npm/fbx2gltf/PATENTS deleted file mode 100644 index 4168ccd..0000000 --- a/npm/fbx2gltf/PATENTS +++ /dev/null @@ -1,33 +0,0 @@ -Additional Grant of Patent Rights Version 2 - -"Software" means the FBX2glTF software contributed by Facebook, Inc. - -Facebook, Inc. ("Facebook") hereby grants to each recipient of the Software -("you") a perpetual, worldwide, royalty-free, non-exclusive, irrevocable -(subject to the termination provision below) license under any Necessary -Claims, to make, have made, use, sell, offer to sell, import, and otherwise -transfer the Software. For avoidance of doubt, no license is granted under -Facebook’s rights in any patent claims that are infringed by (i) modifications -to the Software made by you or any third party or (ii) the Software in -combination with any software or other technology. - -The license granted hereunder will terminate, automatically and without notice, -if you (or any of your subsidiaries, corporate affiliates or agents) initiate -directly or indirectly, or take a direct financial interest in, any Patent -Assertion: (i) against Facebook or any of its subsidiaries or corporate -affiliates, (ii) against any party if such Patent Assertion arises in whole or -in part from any software, technology, product or service of Facebook or any of -its subsidiaries or corporate affiliates, or (iii) against any party relating -to the Software. Notwithstanding the foregoing, if Facebook or any of its -subsidiaries or corporate affiliates files a lawsuit alleging patent -infringement against you in the first instance, and you respond by filing a -patent infringement counterclaim in that lawsuit against that party that is -unrelated to the Software, the license granted hereunder will not terminate -under section (i) of this paragraph due to such counterclaim. - -A "Necessary Claim" is a claim of a patent owned by Facebook that is -necessarily infringed by the Software standing alone. - -A "Patent Assertion" is any lawsuit or other action alleging direct, indirect, -or contributory infringement or inducement to infringe any patent, including a -cross-claim or counterclaim. diff --git a/npm/fbx2gltf/README.md b/npm/fbx2gltf/README.md index c774a8c..a558045 100644 --- a/npm/fbx2gltf/README.md +++ b/npm/fbx2gltf/README.md @@ -1,5 +1,8 @@ # FBX2glTF +[![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) + + This is a command line tool for converting 3D model assets on the well-established [FBX](https://www.autodesk.com/products/fbx/overview) format to [glTF 2.0](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0), @@ -53,6 +56,9 @@ The home of this tool is [here](https://github.com/facebookincubator/FBX2glTF). # Legal +FBX2glTF is licensed under the [3-clause BSD license](LICENSE). + +``` This software contains Autodesk® FBX® code developed by Autodesk, Inc. Copyright 2017 Autodesk, Inc. All rights, reserved. Such code is provided “as is” and Autodesk, Inc. disclaims any and all warranties, whether express or implied, @@ -64,4 +70,4 @@ of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of such code. - +``` diff --git a/npm/fbx2gltf/package.json b/npm/fbx2gltf/package.json index a9e35df..8ac0ea3 100644 --- a/npm/fbx2gltf/package.json +++ b/npm/fbx2gltf/package.json @@ -19,7 +19,6 @@ "homepage": "https://github.com/facebookincubator/FBX2glTF", "files": [ "LICENSE", - "PATENTS", "README.md", "bin", "index.js" @@ -27,4 +26,4 @@ "dependencies": { "rimraf": "^2.6.2" } -} +} \ No newline at end of file diff --git a/src/FBX2glTF.cpp b/src/FBX2glTF.cpp index 610a407..30a7aa7 100644 --- a/src/FBX2glTF.cpp +++ b/src/FBX2glTF.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include @@ -13,13 +12,6 @@ #include #include -#if defined(__unix__) || defined(__APPLE__) - -#include - -#define _stricmp strcasecmp -#endif - #include #include "FBX2glTF.h" @@ -103,6 +95,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."); @@ -284,10 +296,7 @@ int main(int argc, char* argv[]) { if (outputPath.empty()) { // if -o is not given, default to the basename of the .fbx - outputPath = fmt::format( - ".{}{}", - (const char)StringUtils::GetPathSeparator(), - StringUtils::GetFileBaseString(inputPath)); + outputPath = "./" + FileUtils::GetFileBase(inputPath); } // the output folder in .gltf mode, not used for .glb std::string outputFolder; @@ -295,14 +304,17 @@ int main(int argc, char* argv[]) { // the path of the actual .glb or .gltf file std::string modelPath; if (gltfOptions.outputBinary) { - // in binary mode, we write precisely where we're asked - modelPath = outputPath + ".glb"; - + const auto& suffix = FileUtils::GetFileSuffix(outputPath); + // add .glb to output path, unless it already ends in exactly that + if (suffix.has_value() && suffix.value() == "glb") { + modelPath = outputPath; + } else { + modelPath = outputPath + ".glb"; + } } else { // in gltf mode, we create a folder and write into that - outputFolder = - fmt::format("{}_out{}", outputPath.c_str(), (const char)StringUtils::GetPathSeparator()); - modelPath = outputFolder + StringUtils::GetFileNameString(outputPath) + ".gltf"; + outputFolder = fmt::format("{}_out/", outputPath.c_str()); + modelPath = outputFolder + FileUtils::GetFileName(outputPath) + ".gltf"; } if (!FileUtils::CreatePath(modelPath.c_str())) { fmt::fprintf(stderr, "ERROR: Failed to create folder: %s'\n", outputFolder.c_str()); @@ -315,7 +327,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, {"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 67b73cb..411bb57 100644 --- a/src/FBX2glTF.h +++ b/src/FBX2glTF.h @@ -1,17 +1,17 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once +#include #include -#if defined ( _WIN32 ) +#if defined(_WIN32) // Tell Windows not to define min() and max() macros #define NOMINMAX #include @@ -20,20 +20,22 @@ #define FBX2GLTF_VERSION std::string("0.9.6") #include + #include -#if defined ( _WIN32 ) +#if defined(_WIN32) // this is defined in fbxmath.h #undef isnan +#undef snprintf #endif #include "mathfu.hpp" // give all modules access to our tweaked JSON -#include #include +#include -template +template using workaround_fifo_map = nlohmann::fifo_map, A>; using json = nlohmann::basic_json; @@ -41,70 +43,87 @@ using json = nlohmann::basic_json; extern bool verboseOutput; /** -* The variuos situations in which the user may wish for us to (re-)compute normals for our vertices. -*/ + * Centralises all the laborious downcasting from your OS' 64-bit + * index variables down to the uint32s that glTF is built out of. + */ +inline uint32_t to_uint32(size_t n) { + assert(n < UINT_MAX); + return static_cast(n); +} + +/** + * The variuos situations in which the user may wish for us to (re-)compute normals for our + * vertices. + */ enum class ComputeNormalsOption { - NEVER, // do not ever compute any normals (results in broken glTF for some sources) - BROKEN, // replace zero-length normals in any mesh that has a normal layer - MISSING, // if a mesh lacks normals, compute them all - ALWAYS // compute a new normal for every vertex, obliterating whatever may have been there before + NEVER, // do not ever compute any normals (results in broken glTF for some sources) + BROKEN, // replace zero-length normals in any mesh that has a normal layer + MISSING, // if a mesh lacks normals, compute them all + ALWAYS // compute a new normal for every vertex, obliterating whatever may have been there before }; enum class UseLongIndicesOptions { - NEVER, // only ever use 16-bit indices - AUTO, // use shorts or longs depending on vertex count - ALWAYS, // only ever use 32-bit indices + NEVER, // only ever use 16-bit indices + AUTO, // use shorts or longs depending on vertex count + 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. -*/ -struct GltfOptions -{ - /** - * If negative, disabled. Otherwise, a bitfield of RawVertexAttributes that - * specify the largest set of attributes that'll ever be kept for a vertex. - * The special bit RAW_VERTEX_ATTRIBUTE_AUTO triggers smart mode, where the - * attributes to keep are inferred from which textures are supplied. - */ - int keepAttribs { -1 }; - /** Whether to output a .glb file, the binary format of glTF. */ - bool outputBinary { false }; - /** If non-binary, whether to inline all resources, for a single (large) .glTF file. */ - bool embedResources { false }; + * User-supplied options that dictate the nature of the glTF being generated. + */ +struct GltfOptions { + /** + * If negative, disabled. Otherwise, a bitfield of RawVertexAttributes that + * specify the largest set of attributes that'll ever be kept for a vertex. + * The special bit RAW_VERTEX_ATTRIBUTE_AUTO triggers smart mode, where the + * attributes to keep are inferred from which textures are supplied. + */ + int keepAttribs{-1}; + /** Whether to output a .glb file, the binary format of glTF. */ + bool outputBinary{false}; + /** If non-binary, whether to inline all resources, for a single (large) .glTF file. */ + bool embedResources{false}; - /** Whether and how to use KHR_draco_mesh_compression to minimize static geometry size. */ - struct { - bool enabled = false; - int compressionLevel = 7; - int quantBitsPosition = 14; - int quantBitsTexCoord = 10; - int quantBitsNormal = 10; - int quantBitsColor = 8; - int quantBitsGeneric = 8; - } draco; + /** Whether and how to use KHR_draco_mesh_compression to minimize static geometry size. */ + struct { + bool enabled = false; + int compressionLevel = 7; + int quantBitsPosition = 14; + int quantBitsTexCoord = 10; + int quantBitsNormal = 10; + int quantBitsColor = 8; + int quantBitsGeneric = 8; + } draco; - /** Whether to include FBX User Properties as 'extras' metadata in glTF nodes. */ - bool enableUserProperties { false }; + /** Whether to include FBX User Properties as 'extras' metadata in glTF nodes. */ + bool enableUserProperties{false}; - /** Whether to use KHR_materials_unlit to extend materials definitions. */ - bool useKHRMatUnlit { false }; - /** Whether to populate the pbrMetallicRoughness substruct in materials. */ - bool usePBRMetRough { false }; + /** Whether to use KHR_materials_unlit to extend materials definitions. */ + bool useKHRMatUnlit{false}; + /** Whether to populate the pbrMetallicRoughness substruct in materials. */ + bool usePBRMetRough{false}; - /** Whether to include lights through the KHR_punctual_lights extension. */ - bool useKHRLightsPunctual { true }; + /** Whether to include lights through the KHR_punctual_lights extension. */ + bool useKHRLightsPunctual{true}; - /** 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. */ - bool useBlendShapeTangents { false }; - /** Whether to normalized skinning weights. */ - bool normalizeSkinningWeights { true }; - /** Maximum number of bone influences per vertex. */ - int maxSkinningWeights { 4 }; - /** When to compute vertex normals from geometry. */ - ComputeNormalsOption computeNormals = ComputeNormalsOption::BROKEN; - /** When to use 32-bit indices. */ - UseLongIndicesOptions useLongIndices = UseLongIndicesOptions::AUTO; + /** 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. */ + bool useBlendShapeTangents{false}; + /** Whether to normalized skinning weights. */ + bool normalizeSkinningWeights { true }; + /** Maximum number of bone influences per vertex. */ + int maxSkinningWeights { 4 }; + /** When to compute vertex normals from geometry. */ + 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 d4d2f29..56c66c7 100644 --- a/src/fbx/Fbx2Raw.cpp +++ b/src/fbx/Fbx2Raw.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "Fbx2Raw.hpp" @@ -715,8 +714,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(); @@ -726,24 +736,58 @@ static void ReadAnimations(RawModel& raw, FbxScene* pScene) { pScene->SetCurrentAnimationStack(pAnimStack); - FbxTakeInfo* takeInfo = pScene->GetTakeInfo(animStackName); - if (takeInfo == nullptr) { - fmt::printf("Warning:: animation '%s' has no Take information. Skipping.\n", animStackName); - // not all animstacks have a take - continue; + /** + * Individual animations are often concatenated on the timeline, and the + * only certain way to identify precisely what interval they occupy is to + * depth-traverse the entire animation stack, and examine the actual keys. + * + * There is a deprecated concept of an "animation take" which is meant to + * provide precisely this time interval information, but the data is not + * actually derived by the SDK from source-of-truth data structures, but + * rather provided directly by the FBX exporter, and not sanity checked. + * + * Some exporters calculate it correctly. Others do not. In any case, we + * now ignore it completely. + */ + FbxLongLong firstFrameIndex = -1; + FbxLongLong lastFrameIndex = -1; + for (int layerIx = 0; layerIx < pAnimStack->GetMemberCount(); layerIx++) { + FbxAnimLayer* layer = pAnimStack->GetMember(layerIx); + for (int nodeIx = 0; nodeIx < layer->GetMemberCount(); nodeIx++) { + auto* node = layer->GetMember(nodeIx); + FbxTimeSpan nodeTimeSpan; + // Multiple curves per curve node is not even supported by the SDK. + for (int curveIx = 0; curveIx < node->GetCurveCount(0); curveIx++) { + FbxAnimCurve* curve = node->GetCurve(0U, curveIx); + if (curve == nullptr) { + continue; + } + // simply take the interval as first key to last key + int firstKeyIndex = 0; + int lastKeyIndex = std::max(firstKeyIndex, curve->KeyGetCount() - 1); + FbxLongLong firstCurveFrame = curve->KeyGetTime(firstKeyIndex).GetFrameCount(eMode); + FbxLongLong lastCurveFrame = curve->KeyGetTime(lastKeyIndex).GetFrameCount(eMode); + + // the final interval is the union of all node curve intervals + if (firstFrameIndex == -1 || firstCurveFrame < firstFrameIndex) { + firstFrameIndex = firstCurveFrame; + } + if (lastFrameIndex == -1 || lastCurveFrame > lastFrameIndex) { + lastFrameIndex = lastCurveFrame; + } + } + } } + RawAnimation animation; + animation.name = animStackName; + + fmt::printf( + "Animation %s: [%lu - %lu]\n", std::string(animStackName), firstFrameIndex, lastFrameIndex); + if (verboseOutput) { fmt::printf("animation %zu: %s (%d%%)", animIx, (const char*)animStackName, 0); } - FbxTime start = takeInfo->mLocalTimeSpan.GetStart(); - FbxTime end = takeInfo->mLocalTimeSpan.GetStop(); - - RawAnimation animation; - animation.name = animStackName; - - FbxLongLong firstFrameIndex = start.GetFrameCount(eMode); - FbxLongLong lastFrameIndex = end.GetFrameCount(eMode); for (FbxLongLong frameIndex = firstFrameIndex; frameIndex <= lastFrameIndex; frameIndex++) { FbxTime pTime; // first frame is always at t = 0.0 @@ -910,39 +954,61 @@ static void ReadAnimations(RawModel& raw, FbxScene* pScene) { } } -static std::string GetInferredFileName( +static std::string FindFileLoosely( const std::string& fbxFileName, const std::string& directory, const std::vector& directoryFileList) { if (FileUtils::FileExists(fbxFileName)) { return fbxFileName; } - // Get the file name with file extension. - const std::string fileName = - StringUtils::GetFileNameString(StringUtils::GetCleanPathString(fbxFileName)); + + // From e.g. C:/Assets/Texture.jpg, extract 'Texture.jpg' + const std::string fileName = FileUtils::GetFileName(fbxFileName); // Try to find a match with extension. for (const auto& file : directoryFileList) { - if (StringUtils::CompareNoCase(fileName, file) == 0) { - return std::string(directory) + file; + if (StringUtils::CompareNoCase(fileName, FileUtils::GetFileName(file)) == 0) { + return directory + "/" + file; } } // Get the file name without file extension. - const std::string fileBase = StringUtils::GetFileBaseString(fileName); + const std::string fileBase = FileUtils::GetFileBase(fileName); - // Try to find a match without file extension. + // Try to find a match that ignores file extension for (const auto& file : directoryFileList) { - // If the two extension-less base names match. - if (StringUtils::CompareNoCase(fileBase, StringUtils::GetFileBaseString(file)) == 0) { - // Return the name with extension of the file in the directory. - return std::string(directory) + file; + if (StringUtils::CompareNoCase(fileBase, FileUtils::GetFileBase(file)) == 0) { + return directory + "/" + file; } } return ""; } +/** + * Try to locate the best match to the given texture filename, as provided in the FBX, + * possibly searching through the provided folders for a reasonable-looking match. + * + * Returns empty string if no match can be found, else the absolute path of the file. + **/ +static std::string FindFbxTexture( + const std::string& textureFileName, + const std::vector& folders, + const std::vector>& folderContents) { + // it might exist exactly as-is on the running machine's filesystem + if (FileUtils::FileExists(textureFileName)) { + return textureFileName; + } + // else look in other designated folders + for (int ii = 0; ii < folders.size(); ii++) { + const auto& fileLocation = FindFileLoosely(textureFileName, folders[ii], folderContents[ii]); + if (!fileLocation.empty()) { + return FileUtils::GetAbsolutePath(fileLocation); + } + } + return ""; +} + /* The texture file names inside of the FBX often contain some long author-specific path with the wrong extensions. For instance, all of the art assets may be PSD @@ -954,50 +1020,60 @@ static std::string GetInferredFileName( */ static void FindFbxTextures( FbxScene* pScene, - const char* fbxFileName, - const char* extensions, + const std::string& fbxFileName, + const std::set& extensions, std::map& textureLocations) { - // Get the folder the FBX file is in. - const std::string folder = StringUtils::GetFolderString(fbxFileName); + // figure out what folder the FBX file is in, + const auto& fbxFolder = FileUtils::getFolder(fbxFileName); + std::vector folders{ + // first search filename.fbm folder which the SDK itself expands embedded textures into, + fbxFolder + "/" + FileUtils::GetFileBase(fbxFileName) + ".fbm", // filename.fbm + // then the FBX folder itself, + fbxFolder, + // then finally our working directory + FileUtils::GetCurrentFolder(), + }; - // Check if there is a filename.fbm folder to which embedded textures were extracted. - const std::string fbmFolderName = folder + StringUtils::GetFileBaseString(fbxFileName) + ".fbm/"; - - // Search either in the folder with embedded textures or in the same folder as the FBX file. - const std::string searchFolder = FileUtils::FolderExists(fbmFolderName) ? fbmFolderName : folder; - - // Get a list with all the texture files from either the folder with embedded textures or the same - // folder as the FBX file. - std::vector fileList = FileUtils::ListFolderFiles(searchFolder.c_str(), extensions); + // List the contents of each of these folders (if they exist) + std::vector> folderContents; + for (const auto& folder : folders) { + if (FileUtils::FolderExists(folder)) { + folderContents.push_back(FileUtils::ListFolderFiles(folder, extensions)); + } else { + folderContents.push_back({}); + } + } // Try to match the FBX texture names with the actual files on disk. for (int i = 0; i < pScene->GetTextureCount(); i++) { const FbxFileTexture* pFileTexture = FbxCast(pScene->GetTexture(i)); - if (pFileTexture == nullptr) { - continue; + if (pFileTexture != nullptr) { + const std::string fileLocation = + FindFbxTexture(pFileTexture->GetFileName(), folders, folderContents); + // always extend the mapping (even for files we didn't find) + textureLocations.emplace(pFileTexture, fileLocation.c_str()); + if (fileLocation.empty()) { + fmt::printf( + "Warning: could not find a image file for texture: %s.\n", pFileTexture->GetName()); + } else if (verboseOutput) { + fmt::printf("Found texture '%s' at: %s\n", pFileTexture->GetName(), fileLocation); + } } - const std::string inferredName = - GetInferredFileName(pFileTexture->GetFileName(), searchFolder, fileList); - if (inferredName.empty()) { - fmt::printf( - "Warning: could not find a local image file for texture: %s.\n" - "Original filename: %s\n", - pFileTexture->GetName(), - pFileTexture->GetFileName()); - } - // always extend the mapping, even for files we didn't find - textureLocations.emplace(pFileTexture, inferredName.c_str()); } } -bool LoadFBXFile(RawModel& raw, const char* fbxFileName, const char* textureExtensions) { +bool LoadFBXFile( + RawModel& raw, + const std::string fbxFileName, + const std::set& textureExtensions, + const GltfOptions& options) { FbxManager* pManager = FbxManager::Create(); FbxIOSettings* pIoSettings = FbxIOSettings::Create(pManager, IOSROOT); pManager->SetIOSettings(pIoSettings); FbxImporter* pImporter = FbxImporter::Create(pManager, ""); - if (!pImporter->Initialize(fbxFileName, -1, pManager->GetIOSettings())) { + if (!pImporter->Initialize(fbxFileName.c_str(), -1, pManager->GetIOSettings())) { if (verboseOutput) { fmt::printf("%s\n", pImporter->GetStatus().GetErrorString()); } @@ -1036,7 +1112,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..c7a555c 100644 --- a/src/fbx/Fbx2Raw.hpp +++ b/src/fbx/Fbx2Raw.hpp @@ -1,16 +1,19 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once #include "raw/RawModel.hpp" -bool LoadFBXFile(RawModel& raw, const char* fbxFileName, const char* textureExtensions); +bool LoadFBXFile( + RawModel& raw, + const std::string fbxFileName, + const std::set& textureExtensions, + const GltfOptions& options); json TranscribeProperty(FbxProperty& prop); \ No newline at end of file diff --git a/src/fbx/FbxBlendShapesAccess.cpp b/src/fbx/FbxBlendShapesAccess.cpp index 3530e23..7d9ee6f 100644 --- a/src/fbx/FbxBlendShapesAccess.cpp +++ b/src/fbx/FbxBlendShapesAccess.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "FbxBlendShapesAccess.hpp" diff --git a/src/fbx/FbxBlendShapesAccess.hpp b/src/fbx/FbxBlendShapesAccess.hpp index fc99ec9..5cb548c 100644 --- a/src/fbx/FbxBlendShapesAccess.hpp +++ b/src/fbx/FbxBlendShapesAccess.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once @@ -95,7 +94,7 @@ class FbxBlendShapesAccess { } FbxAnimCurve* GetAnimation(size_t channelIx, size_t animIx) const { - return channels.at(channelIx).ExtractAnimation(animIx); + return channels.at(channelIx).ExtractAnimation(to_uint32(animIx)); } private: diff --git a/src/fbx/FbxLayerElementAccess.hpp b/src/fbx/FbxLayerElementAccess.hpp index e335ca1..195cb4b 100644 --- a/src/fbx/FbxLayerElementAccess.hpp +++ b/src/fbx/FbxLayerElementAccess.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once #include "FBX2glTF.h" diff --git a/src/fbx/FbxSkinningAccess.cpp b/src/fbx/FbxSkinningAccess.cpp index b6a8541..6e70812 100644 --- a/src/fbx/FbxSkinningAccess.cpp +++ b/src/fbx/FbxSkinningAccess.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "FbxSkinningAccess.hpp" @@ -28,7 +27,9 @@ FbxSkinningAccess::FbxSkinningAccess(const FbxMesh* pMesh, FbxScene* pScene, Fbx const int* clusterIndices = cluster->GetControlPointIndices(); const double* clusterWeights = cluster->GetControlPointWeights(); - assert(cluster->GetLinkMode() == FbxCluster::eNormalize); + assert( + cluster->GetLinkMode() == FbxCluster::eNormalize || + cluster->GetLinkMode() == FbxCluster::eTotalOne); // Transform link matrix. FbxAMatrix transformLinkMatrix; diff --git a/src/fbx/FbxSkinningAccess.hpp b/src/fbx/FbxSkinningAccess.hpp index 07b0fe9..8c28bca 100644 --- a/src/fbx/FbxSkinningAccess.hpp +++ b/src/fbx/FbxSkinningAccess.hpp @@ -1,80 +1,79 @@ -/** - * 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. - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include "FBX2glTF.h" - -struct FbxVertexSkinningInfo { - int jointId; - float weight; -}; - - -class FbxSkinningAccess { - public: - - FbxSkinningAccess(const FbxMesh* pMesh, FbxScene* pScene, FbxNode* pNode); - - bool IsSkinned() const { - return (vertexSkinning.size() > 0); - } - - - int GetNodeCount() const { - return (int)jointNodes.size(); - } - - FbxNode* GetJointNode(const int jointIndex) const { - return jointNodes[jointIndex]; - } - - const long GetJointId(const int jointIndex) const { - return jointIds[jointIndex]; - } - - const FbxMatrix& GetJointSkinningTransform(const int jointIndex) const { - return jointSkinningTransforms[jointIndex]; - } - - const FbxMatrix& GetJointInverseGlobalTransforms(const int jointIndex) const { - return jointInverseGlobalTransforms[jointIndex]; - } - - const long GetRootNode() const { - assert(rootIndex != -1); - return jointIds[rootIndex]; - } - - const FbxAMatrix& GetInverseBindMatrix(const int jointIndex) const { - return inverseBindMatrices[jointIndex]; - } +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * 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. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "FBX2glTF.h" + +struct FbxVertexSkinningInfo { + int jointId; + float weight; +}; + + +class FbxSkinningAccess { + public: + + FbxSkinningAccess(const FbxMesh* pMesh, FbxScene* pScene, FbxNode* pNode); + + bool IsSkinned() const { + return (vertexSkinning.size() > 0); + } + + + int GetNodeCount() const { + return (int)jointNodes.size(); + } + + FbxNode* GetJointNode(const int jointIndex) const { + return jointNodes[jointIndex]; + } + + const uint64_t GetJointId(const int jointIndex) const { + return jointIds[jointIndex]; + } + + const FbxMatrix& GetJointSkinningTransform(const int jointIndex) const { + return jointSkinningTransforms[jointIndex]; + } + + const FbxMatrix& GetJointInverseGlobalTransforms(const int jointIndex) const { + return jointInverseGlobalTransforms[jointIndex]; + } + + const uint64_t GetRootNode() const { + assert(rootIndex != -1); + return jointIds[rootIndex]; + } + + const FbxAMatrix& GetInverseBindMatrix(const int jointIndex) const { + return inverseBindMatrices[jointIndex]; + } const std::vector GetVertexSkinningInfo(const int controlPointIndex) const { return vertexSkinning[controlPointIndex]; } - - private: - int rootIndex; - int maxBoneInfluences; - std::vector jointIds; - std::vector jointNodes; - std::vector jointSkinningTransforms; - std::vector jointInverseGlobalTransforms; - std::vector inverseBindMatrices; - std::vector> vertexSkinning; -}; + + private: + int rootIndex; + int maxBoneInfluences; + std::vector jointIds; + std::vector jointNodes; + std::vector jointSkinningTransforms; + std::vector jointInverseGlobalTransforms; + std::vector inverseBindMatrices; + std::vector> vertexSkinning; +}; diff --git a/src/fbx/materials/3dsMaxPhysicalMaterial.cpp b/src/fbx/materials/3dsMaxPhysicalMaterial.cpp index 362c3a7..1d17643 100644 --- a/src/fbx/materials/3dsMaxPhysicalMaterial.cpp +++ b/src/fbx/materials/3dsMaxPhysicalMaterial.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "RoughnessMetallicMaterials.hpp" diff --git a/src/fbx/materials/FbxMaterials.cpp b/src/fbx/materials/FbxMaterials.cpp index f7f5c07..7aeebcc 100644 --- a/src/fbx/materials/FbxMaterials.cpp +++ b/src/fbx/materials/FbxMaterials.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "fbx/Fbx2Raw.hpp" diff --git a/src/fbx/materials/FbxMaterials.hpp b/src/fbx/materials/FbxMaterials.hpp index c48a829..df9267a 100644 --- a/src/fbx/materials/FbxMaterials.hpp +++ b/src/fbx/materials/FbxMaterials.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once diff --git a/src/fbx/materials/RoughnessMetallicMaterials.hpp b/src/fbx/materials/RoughnessMetallicMaterials.hpp index ad430ae..110a19f 100644 --- a/src/fbx/materials/RoughnessMetallicMaterials.hpp +++ b/src/fbx/materials/RoughnessMetallicMaterials.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once diff --git a/src/fbx/materials/StingrayPBSMaterial.cpp b/src/fbx/materials/StingrayPBSMaterial.cpp index a17fb8f..f565fd1 100644 --- a/src/fbx/materials/StingrayPBSMaterial.cpp +++ b/src/fbx/materials/StingrayPBSMaterial.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "RoughnessMetallicMaterials.hpp" diff --git a/src/fbx/materials/TraditionalMaterials.cpp b/src/fbx/materials/TraditionalMaterials.cpp index 919dd99..d2a21b2 100644 --- a/src/fbx/materials/TraditionalMaterials.cpp +++ b/src/fbx/materials/TraditionalMaterials.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "TraditionalMaterials.hpp" diff --git a/src/fbx/materials/TraditionalMaterials.hpp b/src/fbx/materials/TraditionalMaterials.hpp index 31a3912..41fae7d 100644 --- a/src/fbx/materials/TraditionalMaterials.hpp +++ b/src/fbx/materials/TraditionalMaterials.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "FbxMaterials.hpp" diff --git a/src/gltf/GltfModel.cpp b/src/gltf/GltfModel.cpp index c3c6524..d4e981f 100644 --- a/src/gltf/GltfModel.cpp +++ b/src/gltf/GltfModel.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "GltfModel.hpp" @@ -12,7 +11,7 @@ std::shared_ptr GltfModel::GetAlignedBufferView( BufferData& buffer, const BufferViewData::GL_ArrayType target) { - unsigned long bufferSize = this->binary->size(); + uint32_t bufferSize = to_uint32(this->binary->size()); if ((bufferSize % 4) > 0) { bufferSize += (4 - (bufferSize % 4)); this->binary->resize(bufferSize); @@ -27,7 +26,7 @@ GltfModel::AddRawBufferView(BufferData& buffer, const char* source, uint32_t byt bufferView->byteLength = bytes; // make space for the new bytes (possibly moving the underlying data) - unsigned long bufferSize = this->binary->size(); + uint32_t bufferSize = to_uint32(this->binary->size()); this->binary->resize(bufferSize + bytes); // and copy them into place @@ -52,7 +51,7 @@ std::shared_ptr GltfModel::AddBufferViewForFile( std::vector fileBuffer(size); if (file.read(fileBuffer.data(), size)) { - result = AddRawBufferView(buffer, fileBuffer.data(), size); + result = AddRawBufferView(buffer, fileBuffer.data(), to_uint32(size)); } else { fmt::printf("Warning: Couldn't read %lu bytes from %s, skipping file.\n", size, filename); } diff --git a/src/gltf/GltfModel.hpp b/src/gltf/GltfModel.hpp index 502d37a..48939db 100644 --- a/src/gltf/GltfModel.hpp +++ b/src/gltf/GltfModel.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once @@ -44,7 +43,7 @@ template class Holder { public: std::shared_ptr hold(T* ptr) { - ptr->ix = ptrs.size(); + ptr->ix = to_uint32(ptrs.size()); ptrs.emplace_back(ptr); return ptrs.back(); } @@ -114,7 +113,7 @@ class GltfModel { primitive.AddDracoAttrib(attrDef, attribArr); accessor = accessors.hold(new AccessorData(attrDef.glType)); - accessor->count = attribArr.size(); + accessor->count = to_uint32(attribArr.size()); } else { auto bufferView = GetAlignedBufferView(buffer, BufferViewData::GL_ARRAY_BUFFER); accessor = AddAccessorWithView(*bufferView, attrDef.glType, attribArr, std::string("")); diff --git a/src/gltf/Raw2Gltf.cpp b/src/gltf/Raw2Gltf.cpp index 352e7c2..f763f93 100644 --- a/src/gltf/Raw2Gltf.cpp +++ b/src/gltf/Raw2Gltf.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "Raw2Gltf.hpp" @@ -256,29 +255,28 @@ ModelData* Raw2Gltf( if (material.info->shadingModel == RAW_SHADING_MODEL_PBR_MET_ROUGH) { /** * PBR FBX Material -> PBR Met/Rough glTF. + * + * METALLIC and ROUGHNESS textures are packed in G and B channels of a rough/met texture. + * Other values translate directly. */ RawMetRoughMatProps* props = (RawMetRoughMatProps*)material.info.get(); - // diffuse and emissive are noncontroversial - baseColorTex = simpleTex(RAW_TEXTURE_USAGE_ALBEDO); - diffuseFactor = props->diffuseFactor; - emissiveFactor = props->emissiveFactor; - emissiveIntensity = props->emissiveIntensity; - - // we always send the metallic/roughness factors onto the glTF generator - metallic = props->metallic; - roughness = props->roughness; - // determine if we need to generate a combined map bool hasMetallicMap = material.textures[RAW_TEXTURE_USAGE_METALLIC] >= 0; bool hasRoughnessMap = material.textures[RAW_TEXTURE_USAGE_ROUGHNESS] >= 0; bool hasOcclusionMap = material.textures[RAW_TEXTURE_USAGE_OCCLUSION] >= 0; bool atLeastTwoMaps = hasMetallicMap ? (hasRoughnessMap || hasOcclusionMap) : (hasRoughnessMap && hasMetallicMap); - if (atLeastTwoMaps) { - // if there's at least two of metallic/roughness/occlusion, it makes sense to - // merge them: occlusion into the red channel, metallic into blue channel, and - // roughness into the green. + if (!atLeastTwoMaps) { + // this handles the case of 0 or 1 maps supplied + aoMetRoughTex = hasMetallicMap + ? simpleTex(RAW_TEXTURE_USAGE_METALLIC) + : (hasRoughnessMap + ? simpleTex(RAW_TEXTURE_USAGE_ROUGHNESS) + : (hasOcclusionMap ? simpleTex(RAW_TEXTURE_USAGE_OCCLUSION) : nullptr)); + } else { + // otherwise merge occlusion into the red channel, metallic into blue channel, and + // roughness into the green, of a new combinatory texture aoMetRoughTex = textureBuilder.combine( { material.textures[RAW_TEXTURE_USAGE_OCCLUSION], @@ -289,27 +287,24 @@ ModelData* Raw2Gltf( [&](const std::vector pixels) -> TextureBuilder::pixel { const float occlusion = (*pixels[0])[0]; - const float metallic = (*pixels[1])[0]; - const float roughness = (*pixels[2])[0]; + const float metallic = (*pixels[1])[0] * (hasMetallicMap ? 1 : props->metallic); + const float roughness = + (*pixels[2])[0] * (hasRoughnessMap ? 1 : props->roughness); return {{occlusion, props->invertRoughnessMap ? 1.0f - roughness : roughness, metallic, 1}}; }, false); - if (hasOcclusionMap) { - // will only be true if there were actual non-trivial pixels - occlusionTexture = aoMetRoughTex.get(); - } - } else { - // this handles the case of 0 or 1 maps supplied - if (hasMetallicMap) { - aoMetRoughTex = simpleTex(RAW_TEXTURE_USAGE_METALLIC); - } else if (hasRoughnessMap) { - aoMetRoughTex = simpleTex(RAW_TEXTURE_USAGE_ROUGHNESS); - } - // else only occlusion map is possible: that check is handled further below } + baseColorTex = simpleTex(RAW_TEXTURE_USAGE_ALBEDO); + diffuseFactor = props->diffuseFactor; + metallic = props->metallic; + roughness = props->roughness; + emissiveFactor = props->emissiveFactor; + emissiveIntensity = props->emissiveIntensity; + // this will set occlusionTexture to null, if no actual occlusion map exists + occlusionTexture = aoMetRoughTex.get(); } else { /** * Traditional FBX Material -> PBR Met/Rough glTF. @@ -393,7 +388,6 @@ ModelData* Raw2Gltf( khrCmnUnlitMat.reset(new KHRCmnUnlitMaterial()); } - // after all the special cases have had a go, check if we need to look up occlusion map if (!occlusionTexture) { occlusionTexture = simpleTex(RAW_TEXTURE_USAGE_OCCLUSION).get(); } @@ -422,8 +416,6 @@ ModelData* Raw2Gltf( const RawMaterial& rawMaterial = surfaceModel.GetMaterial(surfaceModel.GetTriangle(0).materialIndex); - fmt::printf( - "Seeking material of id %ls, name %s...\n", rawMaterial.id, rawMaterial.name.c_str()); const MaterialData& mData = require(materialsById, rawMaterial.id); MeshData* mesh = nullptr; @@ -447,11 +439,11 @@ ModelData* Raw2Gltf( std::shared_ptr primitive; if (options.draco.enabled) { - int triangleCount = surfaceModel.GetTriangleCount(); + size_t triangleCount = surfaceModel.GetTriangleCount(); // initialize Draco mesh with vertex index information auto dracoMesh(std::make_shared()); - dracoMesh->SetNumFaces(static_cast(triangleCount)); + dracoMesh->SetNumFaces(triangleCount); dracoMesh->set_num_points(surfaceModel.GetVertexCount()); for (uint32_t ii = 0; ii < triangleCount; ii++) { @@ -464,7 +456,7 @@ ModelData* Raw2Gltf( AccessorData& indexes = *gltf->accessors.hold(new AccessorData(useLongIndices ? GLT_UINT : GLT_USHORT)); - indexes.count = 3 * triangleCount; + indexes.count = to_uint32(3 * triangleCount); primitive.reset(new PrimitiveData(indexes, mData, dracoMesh)); } else { const AccessorData& indexes = *gltf->AddAccessorWithView( @@ -499,11 +491,13 @@ ModelData* Raw2Gltf( GLT_VEC3F, draco::GeometryAttribute::NORMAL, draco::DT_FLOAT32); - gltf->AddAttributeToPrimitive(buffer, surfaceModel, *primitive, ATTR_NORMAL); + const auto _ = + gltf->AddAttributeToPrimitive(buffer, surfaceModel, *primitive, ATTR_NORMAL); } if ((surfaceModel.GetVertexAttributes() & RAW_VERTEX_ATTRIBUTE_TANGENT) != 0) { const AttributeDefinition ATTR_TANGENT("TANGENT", &RawVertex::tangent, GLT_VEC4F); - gltf->AddAttributeToPrimitive(buffer, surfaceModel, *primitive, ATTR_TANGENT); + const auto _ = gltf->AddAttributeToPrimitive( + buffer, surfaceModel, *primitive, ATTR_TANGENT); } if ((surfaceModel.GetVertexAttributes() & RAW_VERTEX_ATTRIBUTE_COLOR) != 0) { const AttributeDefinition ATTR_COLOR( @@ -512,7 +506,8 @@ ModelData* Raw2Gltf( GLT_VEC4F, draco::GeometryAttribute::COLOR, draco::DT_FLOAT32); - gltf->AddAttributeToPrimitive(buffer, surfaceModel, *primitive, ATTR_COLOR); + const auto _ = + gltf->AddAttributeToPrimitive(buffer, surfaceModel, *primitive, ATTR_COLOR); } if ((surfaceModel.GetVertexAttributes() & RAW_VERTEX_ATTRIBUTE_UV0) != 0) { const AttributeDefinition ATTR_TEXCOORD_0( @@ -521,7 +516,8 @@ ModelData* Raw2Gltf( GLT_VEC2F, draco::GeometryAttribute::TEX_COORD, draco::DT_FLOAT32); - gltf->AddAttributeToPrimitive(buffer, surfaceModel, *primitive, ATTR_TEXCOORD_0); + const auto _ = gltf->AddAttributeToPrimitive( + buffer, surfaceModel, *primitive, ATTR_TEXCOORD_0); } if ((surfaceModel.GetVertexAttributes() & RAW_VERTEX_ATTRIBUTE_UV1) != 0) { const AttributeDefinition ATTR_TEXCOORD_1( @@ -530,7 +526,8 @@ ModelData* Raw2Gltf( GLT_VEC2F, draco::GeometryAttribute::TEX_COORD, draco::DT_FLOAT32); - gltf->AddAttributeToPrimitive(buffer, surfaceModel, *primitive, ATTR_TEXCOORD_1); + const auto _ = gltf->AddAttributeToPrimitive( + buffer, surfaceModel, *primitive, ATTR_TEXCOORD_1); } if ((surfaceModel.GetVertexAttributes() & RAW_VERTEX_ATTRIBUTE_JOINT_INDICES) != 0) { for (int i = 0; i < surfaceModel.GetGlobalWeightCount(); i += 4) { @@ -639,7 +636,7 @@ ModelData* Raw2Gltf( draco::Status status = encoder.EncodeMeshToBuffer(*primitive->dracoMesh, &dracoBuffer); assert(status.code() == draco::Status::OK); - auto view = gltf->AddRawBufferView(buffer, dracoBuffer.data(), dracoBuffer.size()); + auto view = gltf->AddRawBufferView(buffer, dracoBuffer.data(), to_uint32(dracoBuffer.size())); primitive->NoteDracoBuffer(*view); } mesh->AddPrimitive(primitive); @@ -741,7 +738,7 @@ ModelData* Raw2Gltf( type = LightData::Type::Spot; break; } - gltf->lights.hold(new LightData( + const auto _ = gltf->lights.hold(new LightData( light.name, type, light.color, @@ -848,13 +845,13 @@ ModelData* Raw2Gltf( gltfOutStream.write(glb2BinaryHeader, 8); // append binary buffer directly to .glb file - uint32_t binaryLength = gltf->binary->size(); + size_t binaryLength = gltf->binary->size(); gltfOutStream.write((const char*)&(*gltf->binary)[0], binaryLength); while ((binaryLength % 4) != 0) { gltfOutStream.put('\0'); binaryLength++; } - uint32_t totalLength = (uint32_t)gltfOutStream.tellp(); + uint32_t totalLength = to_uint32(gltfOutStream.tellp()); // seek back to sub-header for json chunk gltfOutStream.seekp(8); diff --git a/src/gltf/Raw2Gltf.hpp b/src/gltf/Raw2Gltf.hpp index ec9dac0..d1cef7f 100644 --- a/src/gltf/Raw2Gltf.hpp +++ b/src/gltf/Raw2Gltf.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once @@ -120,7 +119,7 @@ const GLType GLT_QUATF = {CT_FLOAT, 4, "VEC4"}; * The base of any indexed glTF entity. */ struct Holdable { - uint32_t ix; + uint32_t ix = UINT_MAX; virtual json serialize() const = 0; }; diff --git a/src/gltf/TextureBuilder.cpp b/src/gltf/TextureBuilder.cpp index 4329c5f..7424a5a 100644 --- a/src/gltf/TextureBuilder.cpp +++ b/src/gltf/TextureBuilder.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "TextureBuilder.hpp" @@ -49,8 +48,7 @@ std::shared_ptr TextureBuilder::combine( if (rawTexIx >= 0) { const RawTexture& rawTex = raw.GetTexture(rawTexIx); const std::string& fileLoc = rawTex.fileLocation; - const std::string& name = - StringUtils::GetFileBaseString(StringUtils::GetFileNameString(fileLoc)); + const std::string& name = FileUtils::GetFileBase(FileUtils::GetFileName(fileLoc)); if (!fileLoc.empty()) { info.pixels = stbi_load(fileLoc.c_str(), &info.width, &info.height, &info.channels, 0); if (!info.pixels) { @@ -142,7 +140,7 @@ std::shared_ptr TextureBuilder::combine( ImageData* image; if (options.outputBinary) { const auto bufferView = - gltf.AddRawBufferView(*gltf.defaultBuffer, imgBuffer.data(), imgBuffer.size()); + gltf.AddRawBufferView(*gltf.defaultBuffer, imgBuffer.data(), to_uint32(imgBuffer.size())); image = new ImageData(mergedName, *bufferView, png ? "image/png" : "image/jpeg"); } else { const std::string imageFilename = mergedFilename + (png ? ".png" : ".jpg"); @@ -180,20 +178,30 @@ std::shared_ptr TextureBuilder::simple(int rawTexIndex, const std:: } const RawTexture& rawTexture = raw.GetTexture(rawTexIndex); - const std::string textureName = StringUtils::GetFileBaseString(rawTexture.name); - const std::string relativeFilename = StringUtils::GetFileNameString(rawTexture.fileLocation); + const std::string textureName = FileUtils::GetFileBase(rawTexture.name); + const std::string relativeFilename = FileUtils::GetFileName(rawTexture.fileLocation); ImageData* image = nullptr; if (options.outputBinary) { auto bufferView = gltf.AddBufferViewForFile(*gltf.defaultBuffer, rawTexture.fileLocation); if (bufferView) { - std::string suffix = StringUtils::GetFileSuffixString(rawTexture.fileLocation); - image = new ImageData(relativeFilename, *bufferView, ImageUtils::suffixToMimeType(suffix)); + const auto& suffix = FileUtils::GetFileSuffix(rawTexture.fileLocation); + std::string mimeType; + if (suffix) { + mimeType = ImageUtils::suffixToMimeType(suffix.value()); + } else { + mimeType = "image/jpeg"; + fmt::printf( + "Warning: Can't deduce mime type of texture '%s'; using %s.\n", + rawTexture.fileLocation, + mimeType); + } + image = new ImageData(relativeFilename, *bufferView, mimeType); } } else if (!relativeFilename.empty()) { image = new ImageData(relativeFilename, relativeFilename); - std::string outputPath = outputFolder + StringUtils::NormalizePath(relativeFilename); + std::string outputPath = outputFolder + "/" + relativeFilename; if (FileUtils::CopyFile(rawTexture.fileLocation, outputPath, true)) { if (verboseOutput) { fmt::printf("Copied texture '%s' to output folder: %s\n", textureName, outputPath); diff --git a/src/gltf/TextureBuilder.hpp b/src/gltf/TextureBuilder.hpp index c60368d..8d1bb44 100644 --- a/src/gltf/TextureBuilder.hpp +++ b/src/gltf/TextureBuilder.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once diff --git a/src/gltf/properties/AccessorData.cpp b/src/gltf/properties/AccessorData.cpp index 564260d..3626c4e 100644 --- a/src/gltf/properties/AccessorData.cpp +++ b/src/gltf/properties/AccessorData.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "AccessorData.hpp" diff --git a/src/gltf/properties/AccessorData.hpp b/src/gltf/properties/AccessorData.hpp index 06c93e6..5a72e70 100644 --- a/src/gltf/properties/AccessorData.hpp +++ b/src/gltf/properties/AccessorData.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once diff --git a/src/gltf/properties/AnimationData.cpp b/src/gltf/properties/AnimationData.cpp index a1dd09b..9b26d43 100644 --- a/src/gltf/properties/AnimationData.cpp +++ b/src/gltf/properties/AnimationData.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "AnimationData.hpp" @@ -24,7 +23,7 @@ void AnimationData::AddNodeChannel( const AccessorData& accessor, std::string path) { assert(channels.size() == samplers.size()); - uint32_t ix = channels.size(); + uint32_t ix = to_uint32(channels.size()); channels.emplace_back(channel_t(ix, node, std::move(path))); samplers.emplace_back(sampler_t(timeAccessor, accessor.ix)); } diff --git a/src/gltf/properties/AnimationData.hpp b/src/gltf/properties/AnimationData.hpp index 5703f25..31a1be6 100644 --- a/src/gltf/properties/AnimationData.hpp +++ b/src/gltf/properties/AnimationData.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once diff --git a/src/gltf/properties/BufferData.cpp b/src/gltf/properties/BufferData.cpp index 4fc8171..b4394e9 100644 --- a/src/gltf/properties/BufferData.cpp +++ b/src/gltf/properties/BufferData.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include diff --git a/src/gltf/properties/BufferData.hpp b/src/gltf/properties/BufferData.hpp index 58d1474..4ba38e9 100644 --- a/src/gltf/properties/BufferData.hpp +++ b/src/gltf/properties/BufferData.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once diff --git a/src/gltf/properties/BufferViewData.cpp b/src/gltf/properties/BufferViewData.cpp index 34f23ce..8e45480 100644 --- a/src/gltf/properties/BufferViewData.cpp +++ b/src/gltf/properties/BufferViewData.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "BufferViewData.hpp" diff --git a/src/gltf/properties/BufferViewData.hpp b/src/gltf/properties/BufferViewData.hpp index a65c6bf..8e85cc5 100644 --- a/src/gltf/properties/BufferViewData.hpp +++ b/src/gltf/properties/BufferViewData.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once diff --git a/src/gltf/properties/CameraData.cpp b/src/gltf/properties/CameraData.cpp index 78dcdc7..3426a0f 100644 --- a/src/gltf/properties/CameraData.cpp +++ b/src/gltf/properties/CameraData.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "CameraData.hpp" diff --git a/src/gltf/properties/CameraData.hpp b/src/gltf/properties/CameraData.hpp index 78fe500..cd2f241 100644 --- a/src/gltf/properties/CameraData.hpp +++ b/src/gltf/properties/CameraData.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once diff --git a/src/gltf/properties/ImageData.cpp b/src/gltf/properties/ImageData.cpp index b816c7e..202486f 100644 --- a/src/gltf/properties/ImageData.cpp +++ b/src/gltf/properties/ImageData.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "ImageData.hpp" diff --git a/src/gltf/properties/ImageData.hpp b/src/gltf/properties/ImageData.hpp index ece5aef..fdef782 100644 --- a/src/gltf/properties/ImageData.hpp +++ b/src/gltf/properties/ImageData.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once diff --git a/src/gltf/properties/LightData.cpp b/src/gltf/properties/LightData.cpp index 34bdd40..39b6f3a 100644 --- a/src/gltf/properties/LightData.cpp +++ b/src/gltf/properties/LightData.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "LightData.hpp" diff --git a/src/gltf/properties/LightData.hpp b/src/gltf/properties/LightData.hpp index 8445cd5..49d68ea 100644 --- a/src/gltf/properties/LightData.hpp +++ b/src/gltf/properties/LightData.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once diff --git a/src/gltf/properties/MaterialData.cpp b/src/gltf/properties/MaterialData.cpp index 8ac6bfa..dd5621e 100644 --- a/src/gltf/properties/MaterialData.cpp +++ b/src/gltf/properties/MaterialData.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "MaterialData.hpp" @@ -59,13 +58,15 @@ void to_json(json& j, const PBRMetallicRoughness& d) { if (d.baseColorFactor.LengthSquared() > 0) { j["baseColorFactor"] = toStdVec(d.baseColorFactor); } - // we always copy metallic/roughness straight to the glTF: - // - if there's a texture, they're linear multiplier - // - if there's no texture, they're constants - j["metallicFactor"] = d.metallic; - j["roughnessFactor"] = d.roughness; if (d.metRoughTexture != nullptr) { j["metallicRoughnessTexture"] = *d.metRoughTexture; + // if a texture is provided, throw away metallic/roughness values + j["roughnessFactor"] = 1.0f; + j["metallicFactor"] = 1.0f; + } else { + // without a texture, however, use metallic/roughness as constants + j["metallicFactor"] = d.metallic; + j["roughnessFactor"] = d.roughness; } } diff --git a/src/gltf/properties/MaterialData.hpp b/src/gltf/properties/MaterialData.hpp index 4a203df..d7a2ae5 100644 --- a/src/gltf/properties/MaterialData.hpp +++ b/src/gltf/properties/MaterialData.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once diff --git a/src/gltf/properties/MeshData.cpp b/src/gltf/properties/MeshData.cpp index c9e952a..0ec3cdd 100644 --- a/src/gltf/properties/MeshData.cpp +++ b/src/gltf/properties/MeshData.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "MeshData.hpp" diff --git a/src/gltf/properties/MeshData.hpp b/src/gltf/properties/MeshData.hpp index 786ea9a..a8eda7c 100644 --- a/src/gltf/properties/MeshData.hpp +++ b/src/gltf/properties/MeshData.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once diff --git a/src/gltf/properties/NodeData.cpp b/src/gltf/properties/NodeData.cpp index 2093421..3d7050b 100644 --- a/src/gltf/properties/NodeData.cpp +++ b/src/gltf/properties/NodeData.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "NodeData.hpp" diff --git a/src/gltf/properties/NodeData.hpp b/src/gltf/properties/NodeData.hpp index 6ee8315..5b1b483 100644 --- a/src/gltf/properties/NodeData.hpp +++ b/src/gltf/properties/NodeData.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once diff --git a/src/gltf/properties/PrimitiveData.cpp b/src/gltf/properties/PrimitiveData.cpp index fe6e7c0..9ee0bcc 100644 --- a/src/gltf/properties/PrimitiveData.cpp +++ b/src/gltf/properties/PrimitiveData.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "PrimitiveData.hpp" diff --git a/src/gltf/properties/PrimitiveData.hpp b/src/gltf/properties/PrimitiveData.hpp index 81ba4b1..c95ccd9 100644 --- a/src/gltf/properties/PrimitiveData.hpp +++ b/src/gltf/properties/PrimitiveData.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once @@ -49,7 +48,7 @@ struct PrimitiveData { componentCount * draco::DataTypeLength(attribute.dracoComponentType), 0); - const int dracoAttId = dracoMesh->AddAttribute(att, true, attribArr.size()); + const int dracoAttId = dracoMesh->AddAttribute(att, true, to_uint32(attribArr.size())); draco::PointAttribute* attPtr = dracoMesh->attribute(dracoAttId); std::vector buf(sizeof(T)); diff --git a/src/gltf/properties/SamplerData.hpp b/src/gltf/properties/SamplerData.hpp index 4361bba..5287ba1 100644 --- a/src/gltf/properties/SamplerData.hpp +++ b/src/gltf/properties/SamplerData.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once diff --git a/src/gltf/properties/SceneData.cpp b/src/gltf/properties/SceneData.cpp index dd68497..cf57f0b 100644 --- a/src/gltf/properties/SceneData.cpp +++ b/src/gltf/properties/SceneData.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "SceneData.hpp" diff --git a/src/gltf/properties/SceneData.hpp b/src/gltf/properties/SceneData.hpp index cfef6ab..4a008fb 100644 --- a/src/gltf/properties/SceneData.hpp +++ b/src/gltf/properties/SceneData.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once diff --git a/src/gltf/properties/SkinData.cpp b/src/gltf/properties/SkinData.cpp index 1c808bf..6b6fe33 100644 --- a/src/gltf/properties/SkinData.cpp +++ b/src/gltf/properties/SkinData.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "SkinData.hpp" diff --git a/src/gltf/properties/SkinData.hpp b/src/gltf/properties/SkinData.hpp index 1028ebd..0a43306 100644 --- a/src/gltf/properties/SkinData.hpp +++ b/src/gltf/properties/SkinData.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once diff --git a/src/gltf/properties/TextureData.cpp b/src/gltf/properties/TextureData.cpp index 79080a9..ee9208c 100644 --- a/src/gltf/properties/TextureData.cpp +++ b/src/gltf/properties/TextureData.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "TextureData.hpp" diff --git a/src/gltf/properties/TextureData.hpp b/src/gltf/properties/TextureData.hpp index 8c69f40..e886390 100644 --- a/src/gltf/properties/TextureData.hpp +++ b/src/gltf/properties/TextureData.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once diff --git a/src/mathfu.hpp b/src/mathfu.hpp index aaed7dd..6d54dfc 100644 --- a/src/mathfu.hpp +++ b/src/mathfu.hpp @@ -1,14 +1,15 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once +#include + #include #include diff --git a/src/raw/RawModel.cpp b/src/raw/RawModel.cpp index 5f75d28..40aedf5 100644 --- a/src/raw/RawModel.cpp +++ b/src/raw/RawModel.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "RawModel.hpp" diff --git a/src/raw/RawModel.hpp b/src/raw/RawModel.hpp index 99be544..b790a24 100644 --- a/src/raw/RawModel.hpp +++ b/src/raw/RawModel.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once diff --git a/src/utils/File_Utils.cpp b/src/utils/File_Utils.cpp index 4c044fe..1de773a 100644 --- a/src/utils/File_Utils.cpp +++ b/src/utils/File_Utils.cpp @@ -1,180 +1,55 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "File_Utils.hpp" #include +#include #include #include #include #include -#if defined(__unix__) || defined(__APPLE__) - -#include -#include -#include -#include -#include - -#define _getcwd getcwd -#define _mkdir(a) mkdir(a, 0777) -#elif defined(_WIN32) -#include -#include -#else -#include -#include -#endif - -#include - #include "FBX2glTF.h" #include "String_Utils.hpp" namespace FileUtils { -std::string GetCurrentFolder() { - char cwd[StringUtils::MAX_PATH_LENGTH]; - if (!_getcwd(cwd, sizeof(cwd))) { - return std::string(); - } - cwd[sizeof(cwd) - 1] = '\0'; - StringUtils::GetCleanPath(cwd, cwd, StringUtils::PATH_UNIX); - const size_t length = strlen(cwd); - if (cwd[length - 1] != '/' && length < StringUtils::MAX_PATH_LENGTH - 1) { - cwd[length + 0] = '/'; - cwd[length + 1] = '\0'; - } - return std::string(cwd); -} - -bool FileExists(const std::string& filePath) { - std::ifstream stream(filePath); - return stream.good(); -} - -bool FolderExists(const std::string& folderPath) { -#if defined(__unix__) || defined(__APPLE__) - DIR* dir = opendir(folderPath.c_str()); - if (dir) { - closedir(dir); - return true; - } - return false; -#else - const DWORD ftyp = GetFileAttributesA(folderPath.c_str()); - if (ftyp == INVALID_FILE_ATTRIBUTES) { - return false; // bad path - } - return (ftyp & FILE_ATTRIBUTE_DIRECTORY) != 0; -#endif -} - -bool MatchExtension(const char* fileExtension, const char* matchExtensions) { - if (matchExtensions[0] == '\0') { - return true; - } - if (fileExtension[0] == '.') { - fileExtension++; - } - for (const char* end = matchExtensions; end[0] != '\0';) { - for (; end[0] == ';'; end++) { - } - const char* ext = end; - for (; end[0] != ';' && end[0] != '\0'; end++) { - } -#if defined(__unix__) || defined(__APPLE__) - if (strncasecmp(fileExtension, ext, end - ext) == 0) -#else - if (_strnicmp(fileExtension, ext, end - ext) == 0) -#endif - { - return true; - } - } - return false; -} - -std::vector ListFolderFiles(const char* folder, const char* matchExtensions) { +std::vector ListFolderFiles( + std::string folder, + const std::set& matchExtensions) { std::vector fileList; -#if defined(__unix__) || defined(__APPLE__) - DIR* dir = opendir(strlen(folder) > 0 ? folder : "."); - if (dir != nullptr) { - for (;;) { - struct dirent* dp = readdir(dir); - if (dp == nullptr) { - break; + if (folder.empty()) { + folder = "."; + } + for (const auto& entry : boost::filesystem::directory_iterator(folder)) { + const auto& suffix = FileUtils::GetFileSuffix(entry.path().string()); + if (suffix.has_value()) { + const auto& suffix_str = StringUtils::ToLower(suffix.value()); + if (matchExtensions.find(suffix_str) != matchExtensions.end()) { + fileList.push_back(entry.path().filename().string()); } - - if (dp->d_type == DT_DIR) { - continue; - } - - const char* fileName = dp->d_name; - const char* fileExt = strrchr(fileName, '.'); - - if (!fileExt || !MatchExtension(fileExt, matchExtensions)) { - continue; - } - - fileList.emplace_back(fileName); } - - closedir(dir); } -#else - std::string pathStr = folder; - pathStr += "*"; - - WIN32_FIND_DATA FindFileData; - HANDLE hFind = FindFirstFile(pathStr.c_str(), &FindFileData); - if (hFind != INVALID_HANDLE_VALUE) { - do { - if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { - std::string fileName = FindFileData.cFileName; - std::string::size_type extPos = fileName.rfind('.'); - if (extPos != std::string::npos && - MatchExtension(fileName.substr(extPos + 1).c_str(), matchExtensions)) { - fileList.push_back(fileName); - } - } - } while (FindNextFile(hFind, &FindFileData)); - - FindClose(hFind); - } -#endif return fileList; } -bool CreatePath(const char* path) { -#if defined(__unix__) || defined(__APPLE__) - StringUtils::PathSeparator separator = StringUtils::PATH_UNIX; -#else - StringUtils::PathSeparator separator = StringUtils::PATH_WIN; -#endif - std::string folder = StringUtils::GetFolderString(path); - std::string clean = StringUtils::GetCleanPathString(folder, separator); - std::string build = clean; - for (int i = 0; i < clean.length(); i++) { - if (clean[i] == separator && i > 0) { - build[i] = '\0'; - if (i > 1 || build[1] != ':') { - if (_mkdir(build.c_str()) != 0 && errno != EEXIST) { - return false; - } - } - } - build[i] = clean[i]; +bool CreatePath(const std::string path) { + const auto& parent = boost::filesystem::path(path).parent_path(); + if (parent.empty()) { + // this is either CWD or boost::filesystem root; either way it exists + return true; } - return true; + if (boost::filesystem::exists(parent)) { + return boost::filesystem::is_directory(parent); + } + return boost::filesystem::create_directory(parent); } bool CopyFile(const std::string& srcFilename, const std::string& dstFilename, bool createPath) { diff --git a/src/utils/File_Utils.hpp b/src/utils/File_Utils.hpp index 0f9a702..7bd228d 100644 --- a/src/utils/File_Utils.hpp +++ b/src/utils/File_Utils.hpp @@ -1,17 +1,20 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once +#include #include #include +#include +#include + namespace FileUtils { std::string GetCurrentFolder(); @@ -19,13 +22,51 @@ std::string GetCurrentFolder(); bool FileExists(const std::string& folderPath); bool FolderExists(const std::string& folderPath); -bool MatchExtension(const char* fileExtension, const char* matchExtensions); -std::vector ListFolderFiles(const char* folder, const char* matchExtensions); +std::vector ListFolderFiles( + const std::string folder, + const std::set& matchExtensions); -bool CreatePath(const char* path); +bool CreatePath(std::string path); bool CopyFile( const std::string& srcFilename, const std::string& dstFilename, bool createPath = false); + +inline std::string GetAbsolutePath(const std::string& filePath) { + return boost::filesystem::absolute(filePath).string(); +} + +inline std::string GetCurrentFolder() { + return boost::filesystem::current_path().string(); +} + +inline bool FileExists(const std::string& filePath) { + return boost::filesystem::exists(filePath) && boost::filesystem::is_regular_file(filePath); +} + +inline bool FolderExists(const std::string& folderPath) { + return boost::filesystem::exists(folderPath) && boost::filesystem::is_directory(folderPath); +} + +inline std::string getFolder(const std::string& path) { + return boost::filesystem::path(path).parent_path().string(); +} + +inline std::string GetFileName(const std::string& path) { + return boost::filesystem::path(path).filename().string(); +} + +inline std::string GetFileBase(const std::string& path) { + return boost::filesystem::path(path).stem().string(); +} + +inline boost::optional GetFileSuffix(const std::string& path) { + const auto& extension = boost::filesystem::path(path).extension(); + if (extension.empty()) { + return boost::none; + } + return extension.string().substr(1); +} + } // namespace FileUtils diff --git a/src/utils/Image_Utils.cpp b/src/utils/Image_Utils.cpp index 23c107e..cbe8b33 100644 --- a/src/utils/Image_Utils.cpp +++ b/src/utils/Image_Utils.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #include "Image_Utils.hpp" diff --git a/src/utils/Image_Utils.hpp b/src/utils/Image_Utils.hpp index a391163..153919c 100644 --- a/src/utils/Image_Utils.hpp +++ b/src/utils/Image_Utils.hpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once diff --git a/src/utils/String_Utils.cpp b/src/utils/String_Utils.cpp deleted file mode 100644 index 8cf8063..0000000 --- a/src/utils/String_Utils.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/** - * 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. - */ - -#include "String_Utils.hpp" - -namespace StringUtils { - -PathSeparator operator!(const PathSeparator& s) { - return (s == PATH_WIN) ? PATH_UNIX : PATH_WIN; -} - -PathSeparator GetPathSeparator() { -#if defined(__unix__) || defined(__APPLE__) - return PATH_UNIX; -#else - return PATH_WIN; -#endif -} -const std::string NormalizePath(const std::string& path) { - PathSeparator separator = GetPathSeparator(); - char replace; - if (separator == PATH_WIN) { - replace = PATH_UNIX; - } else { - replace = PATH_WIN; - } - std::string normalizedPath = path; - for (size_t s = normalizedPath.find(replace, 0); s != std::string::npos; - s = normalizedPath.find(replace, s)) { - normalizedPath[s] = separator; - } - return normalizedPath; -} - -const std::string GetFolderString(const std::string& path) { - size_t s = path.rfind(PATH_WIN); - s = (s != std::string::npos) ? s : path.rfind(PATH_UNIX); - return path.substr(0, s + 1); -} - -const std::string GetCleanPathString(const std::string& path, const PathSeparator separator) { - std::string cleanPath = path; - for (size_t s = cleanPath.find(!separator, 0); s != std::string::npos; - s = cleanPath.find(!separator, s)) { - cleanPath[s] = separator; - } - return cleanPath; -} - -const std::string GetFileNameString(const std::string& path) { - size_t s = path.rfind(PATH_WIN); - s = (s != std::string::npos) ? s : path.rfind(PATH_UNIX); - return path.substr(s + 1, std::string::npos); -} - -const std::string GetFileBaseString(const std::string& path) { - const std::string fileName = GetFileNameString(path); - return fileName.substr(0, fileName.rfind('.')).c_str(); -} - -const std::string GetFileSuffixString(const std::string& path) { - const std::string fileName = GetFileNameString(path); - size_t pos = fileName.rfind('.'); - if (pos == std::string::npos) { - return ""; - } - return fileName.substr(++pos); -} - -int CompareNoCase(const std::string& s1, const std::string& s2) { - return strncasecmp(s1.c_str(), s2.c_str(), MAX_PATH_LENGTH); -} - -} // namespace StringUtils diff --git a/src/utils/String_Utils.hpp b/src/utils/String_Utils.hpp index f1a3a65..7060da2 100644 --- a/src/utils/String_Utils.hpp +++ b/src/utils/String_Utils.hpp @@ -1,14 +1,15 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. and its affiliates. * 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. + * LICENSE file in the root directory of this source tree. */ #pragma once +#include +#include #include #include #include @@ -16,39 +17,17 @@ #if defined(_MSC_VER) #define strncasecmp _strnicmp -#define strcasecmp _stricmp #endif namespace StringUtils { -static const unsigned int MAX_PATH_LENGTH = 1024; - -enum PathSeparator { PATH_WIN = '\\', PATH_UNIX = '/' }; - -PathSeparator operator!(const PathSeparator& s); - -PathSeparator GetPathSeparator(); -const std::string NormalizePath(const std::string& path); - -const std::string GetCleanPathString( - const std::string& path, - const PathSeparator separator = PATH_WIN); - -template -void GetCleanPath(char (&dest)[size], const char* path, const PathSeparator separator = PATH_WIN) { - size_t len = size - 1; - strncpy(dest, path, len); - char* destPtr = dest; - while ((destPtr = strchr(destPtr, !separator)) != nullptr) { - *destPtr = separator; - } +inline std::string ToLower(std::string s) { + std::transform(s.begin(), s.end(), s.begin(), [](uint8_t c) { return std::tolower(c); }); + return s; } -const std::string GetFolderString(const std::string& path); -const std::string GetFileNameString(const std::string& path); -const std::string GetFileBaseString(const std::string& path); -const std::string GetFileSuffixString(const std::string& path); - -int CompareNoCase(const std::string& s1, const std::string& s2); +inline int CompareNoCase(const std::string& s1, const std::string& s2) { + return strncasecmp(s1.c_str(), s2.c_str(), std::max(s1.length(), s2.length())); +} } // namespace StringUtils