Merge remote-tracking branch 'upstream/master'

This commit is contained in:
hhalen 2019-06-25 15:21:48 -07:00
commit 8aebb1eb2a
77 changed files with 1046 additions and 913 deletions

3
.dockerignore Normal file
View File

@ -0,0 +1,3 @@
.dockerignore
Dockerfile
sdk

9
.gitattributes vendored
View File

@ -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

63
.travis.yml Normal file
View File

@ -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

View File

@ -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=<INSTALL_DIR>
)
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"
)

29
Dockerfile Normal file
View File

@ -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

View File

@ -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")

View File

@ -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:

33
PATENTS
View File

@ -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
Facebooks 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.

156
README.md
View File

@ -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...] [<FBX File>]
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 <FBX2glTF directory>
> 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
<TODO> 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).

58
appveyor.yml Normal file
View File

@ -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

101
azure-pipelines.yml Normal file
View File

@ -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'

33
conanfile.py Normal file
View File

@ -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()

5
docker-compose.yaml Normal file
View File

@ -0,0 +1,5 @@
version: '3.7'
services:
fbx2gltf:
build:
context: .

View File

@ -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:

View File

@ -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
Facebooks 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.

View File

@ -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.
```

View File

@ -19,7 +19,6 @@
"homepage": "https://github.com/facebookincubator/FBX2glTF",
"files": [
"LICENSE",
"PATENTS",
"README.md",
"bin",
"index.js"

View File

@ -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 <fstream>
@ -13,13 +12,6 @@
#include <unordered_map>
#include <vector>
#if defined(__unix__) || defined(__APPLE__)
#include <sys/stat.h>
#define _stricmp strcasecmp
#endif
#include <CLI11.hpp>
#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<std::string> 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;
}

View File

@ -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 <climits>
#include <string>
#if defined ( _WIN32 )
#if defined(_WIN32)
// Tell Windows not to define min() and max() macros
#define NOMINMAX
#include <Windows.h>
@ -20,20 +20,22 @@
#define FBX2GLTF_VERSION std::string("0.9.6")
#include <fmt/printf.h>
#include <fbxsdk.h>
#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 <json.hpp>
#include <fifo_map.hpp>
#include <json.hpp>
template<class K, class V, class ignore, class A>
template <class K, class V, class ignore, class A>
using workaround_fifo_map = nlohmann::fifo_map<K, V, nlohmann::fifo_map_compare<K>, A>;
using json = nlohmann::basic_json<workaround_fifo_map>;
@ -41,70 +43,87 @@ using json = nlohmann::basic_json<workaround_fifo_map>;
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<uint32_t>(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;
};

View File

@ -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<FbxAnimStack>();
@ -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<FbxAnimLayer>(layerIx);
for (int nodeIx = 0; nodeIx < layer->GetMemberCount(); nodeIx++) {
auto* node = layer->GetMember<FbxAnimCurveNode>(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<std::string>& 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<std::string>& folders,
const std::vector<std::vector<std::string>>& 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<std::string>& extensions,
std::map<const FbxTexture*, FbxString>& 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<std::string> 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<std::string> fileList = FileUtils::ListFolderFiles(searchFolder.c_str(), extensions);
// List the contents of each of these folders (if they exist)
std::vector<std::vector<std::string>> 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<FbxFileTexture>(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<std::string>& 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();

View File

@ -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<std::string>& textureExtensions,
const GltfOptions& options);
json TranscribeProperty(FbxProperty& prop);

View File

@ -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"

View File

@ -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:

View File

@ -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"

View File

@ -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;

View File

@ -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
@ -43,7 +42,7 @@ class FbxSkinningAccess {
return jointNodes[jointIndex];
}
const long GetJointId(const int jointIndex) const {
const uint64_t GetJointId(const int jointIndex) const {
return jointIds[jointIndex];
}
@ -55,7 +54,7 @@ class FbxSkinningAccess {
return jointInverseGlobalTransforms[jointIndex];
}
const long GetRootNode() const {
const uint64_t GetRootNode() const {
assert(rootIndex != -1);
return jointIds[rootIndex];
}
@ -71,7 +70,7 @@ class FbxSkinningAccess {
private:
int rootIndex;
int maxBoneInfluences;
std::vector<long> jointIds;
std::vector<uint64_t> jointIds;
std::vector<FbxNode*> jointNodes;
std::vector<FbxMatrix> jointSkinningTransforms;
std::vector<FbxMatrix> jointInverseGlobalTransforms;

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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<BufferViewData> 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<BufferViewData> GltfModel::AddBufferViewForFile(
std::vector<char> 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);
}

View File

@ -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 <typename T>
class Holder {
public:
std::shared_ptr<T> 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(""));

View File

@ -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<const TextureBuilder::pixel*> 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<PrimitiveData> 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<draco::Mesh>());
dracoMesh->SetNumFaces(static_cast<size_t>(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<Vec3f>(buffer, surfaceModel, *primitive, ATTR_NORMAL);
const auto _ =
gltf->AddAttributeToPrimitive<Vec3f>(buffer, surfaceModel, *primitive, ATTR_NORMAL);
}
if ((surfaceModel.GetVertexAttributes() & RAW_VERTEX_ATTRIBUTE_TANGENT) != 0) {
const AttributeDefinition<Vec4f> ATTR_TANGENT("TANGENT", &RawVertex::tangent, GLT_VEC4F);
gltf->AddAttributeToPrimitive<Vec4f>(buffer, surfaceModel, *primitive, ATTR_TANGENT);
const auto _ = gltf->AddAttributeToPrimitive<Vec4f>(
buffer, surfaceModel, *primitive, ATTR_TANGENT);
}
if ((surfaceModel.GetVertexAttributes() & RAW_VERTEX_ATTRIBUTE_COLOR) != 0) {
const AttributeDefinition<Vec4f> ATTR_COLOR(
@ -512,7 +506,8 @@ ModelData* Raw2Gltf(
GLT_VEC4F,
draco::GeometryAttribute::COLOR,
draco::DT_FLOAT32);
gltf->AddAttributeToPrimitive<Vec4f>(buffer, surfaceModel, *primitive, ATTR_COLOR);
const auto _ =
gltf->AddAttributeToPrimitive<Vec4f>(buffer, surfaceModel, *primitive, ATTR_COLOR);
}
if ((surfaceModel.GetVertexAttributes() & RAW_VERTEX_ATTRIBUTE_UV0) != 0) {
const AttributeDefinition<Vec2f> ATTR_TEXCOORD_0(
@ -521,7 +516,8 @@ ModelData* Raw2Gltf(
GLT_VEC2F,
draco::GeometryAttribute::TEX_COORD,
draco::DT_FLOAT32);
gltf->AddAttributeToPrimitive<Vec2f>(buffer, surfaceModel, *primitive, ATTR_TEXCOORD_0);
const auto _ = gltf->AddAttributeToPrimitive<Vec2f>(
buffer, surfaceModel, *primitive, ATTR_TEXCOORD_0);
}
if ((surfaceModel.GetVertexAttributes() & RAW_VERTEX_ATTRIBUTE_UV1) != 0) {
const AttributeDefinition<Vec2f> ATTR_TEXCOORD_1(
@ -530,7 +526,8 @@ ModelData* Raw2Gltf(
GLT_VEC2F,
draco::GeometryAttribute::TEX_COORD,
draco::DT_FLOAT32);
gltf->AddAttributeToPrimitive<Vec2f>(buffer, surfaceModel, *primitive, ATTR_TEXCOORD_1);
const auto _ = gltf->AddAttributeToPrimitive<Vec2f>(
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);

View File

@ -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;
};

View File

@ -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<TextureData> 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<TextureData> 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<TextureData> 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);

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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));
}

View File

@ -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

View File

@ -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 <cppcodec/base64_default_rfc4648.hpp>

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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<uint8_t> buf(sizeof(T));

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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 <vector>
#include <fbxsdk.h>
#include <mathfu/matrix.h>

View File

@ -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"

View File

@ -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

View File

@ -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 <fstream>
#include <set>
#include <string>
#include <vector>
#include <stdint.h>
#include <stdio.h>
#if defined(__unix__) || defined(__APPLE__)
#include <dirent.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#define _getcwd getcwd
#define _mkdir(a) mkdir(a, 0777)
#elif defined(_WIN32)
#include <direct.h>
#include <process.h>
#else
#include <direct.h>
#include <process.h>
#endif
#include <sys/stat.h>
#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<std::string> ListFolderFiles(const char* folder, const char* matchExtensions) {
std::vector<std::string> ListFolderFiles(
std::string folder,
const std::set<std::string>& matchExtensions) {
std::vector<std::string> 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) {

View File

@ -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 <set>
#include <string>
#include <vector>
#include <boost/filesystem.hpp>
#include <boost/optional.hpp>
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<std::string> ListFolderFiles(const char* folder, const char* matchExtensions);
std::vector<std::string> ListFolderFiles(
const std::string folder,
const std::set<std::string>& 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<std::string> 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

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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 <algorithm>
#include <cctype>
#include <cstdarg>
#include <cstdio>
#include <cstring>
@ -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 <size_t size>
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