From 8ad9c937f171bd716bbd5692af1c501acbaded88 Mon Sep 17 00:00:00 2001 From: Krishty Date: Tue, 4 May 2021 19:10:24 +0200 Subject: [PATCH 1/4] enabled debug information in MSVC release build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No effect on runtime speed/size. Slightly slower link time, but debugging experience improves by a million times. - /Zi – Store debug information in a .pdb file, not directly in the DLL/EXE - /DEBUG:FULL – generate debug information during link - /PDBALTPATH:%_PDB% – do not store the file system path of the .pdb, just the filename and hash (no disclose paths on distribution) - /OPT:REF /OPT:ICF – remove unreferenced functions and fold identical functions (this was enabled before, but requires explicit enabling if /DEBUG:FULL is specified) --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 97a3641f5..f1b60936d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -268,6 +268,8 @@ ELSEIF(MSVC) ADD_COMPILE_OPTIONS(/wd4351) ENDIF() SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od") + SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") + SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF") ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) IF(NOT ASSIMP_HUNTER_ENABLED) SET(CMAKE_CXX_STANDARD 11) From 53790e82736c022b2dd935db957036e1342ea624 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Fri, 21 May 2021 12:25:36 +0100 Subject: [PATCH 2/4] Update Draco to upstream e4103dc Fixes some MSVC and mingw compiler issues Sets VERSION and SO_VERSION https://github.com/google/draco/commit/e4103dc39fe1c70c6ad40d26a01248f4b5d3887b --- contrib/draco/.ruby-version | 1 - contrib/draco/.travis.yml | 31 --------- contrib/draco/CMakeLists.txt | 8 +-- contrib/draco/README.md | 6 +- .../draco/cmake/draco_build_definitions.cmake | 9 ++- contrib/draco/cmake/draco_features.cmake | 63 ------------------- contrib/draco/cmake/draco_flags.cmake | 9 +++ contrib/draco/cmake/draco_install.cmake | 2 +- contrib/draco/cmake/draco_sanitizer.cmake | 20 +++--- contrib/draco/cmake/draco_targets.cmake | 24 ++++--- contrib/draco/src/draco/core/cycle_timer.cc | 14 ++--- contrib/draco/src/draco/core/cycle_timer.h | 7 ++- contrib/draco/src/draco/io/parser_utils.cc | 3 +- contrib/draco/src/draco/io/ply_reader.cc | 4 +- .../draco/src/draco/io/stdio_file_reader.cc | 7 +++ 15 files changed, 69 insertions(+), 139 deletions(-) delete mode 100644 contrib/draco/.ruby-version delete mode 100644 contrib/draco/.travis.yml delete mode 100644 contrib/draco/cmake/draco_features.cmake diff --git a/contrib/draco/.ruby-version b/contrib/draco/.ruby-version deleted file mode 100644 index 276cbf9e2..000000000 --- a/contrib/draco/.ruby-version +++ /dev/null @@ -1 +0,0 @@ -2.3.0 diff --git a/contrib/draco/.travis.yml b/contrib/draco/.travis.yml deleted file mode 100644 index e9ef7123f..000000000 --- a/contrib/draco/.travis.yml +++ /dev/null @@ -1,31 +0,0 @@ -cache: ccache -language: cpp -matrix: - include: - - os: linux - dist: xenial - compiler: clang - - os: linux - dist: xenial - compiler: gcc - - os: osx - compiler: clang - -addons: - apt: - packages: - - cmake - -script: - # Output version info for compilers, cmake, and make - - ${CC} -v - - ${CXX} -v - - cmake --version - - make --version - # Clone googletest - - pushd .. && git clone https://github.com/google/googletest.git && popd - # Configure and build - - mkdir _travis_build && cd _travis_build - - cmake -G "Unix Makefiles" -DENABLE_TESTS=ON .. - - make -j10 - - ./draco_tests diff --git a/contrib/draco/CMakeLists.txt b/contrib/draco/CMakeLists.txt index 3da2c664a..5526e7f60 100644 --- a/contrib/draco/CMakeLists.txt +++ b/contrib/draco/CMakeLists.txt @@ -804,7 +804,7 @@ else() draco_points_enc) # Library targets that consume the object collections. - if(MSVC OR WIN32) + if(MSVC) # In order to produce a DLL and import library the Windows tools require # that the exported symbols are part of the DLL target. The unfortunate side # effect of this is that a single configuration cannot output both the @@ -889,9 +889,6 @@ else() # For Mac, we need to build a .bundle for the unity plugin. if(APPLE) set_target_properties(dracodec_unity PROPERTIES BUNDLE true) - elseif(NOT unity_decoder_lib_type STREQUAL STATIC) - set_target_properties(dracodec_unity - PROPERTIES SOVERSION ${DRACO_SOVERSION}) endif() endif() @@ -916,9 +913,6 @@ else() # For Mac, we need to build a .bundle for the plugin. if(APPLE) set_target_properties(draco_maya_wrapper PROPERTIES BUNDLE true) - else() - set_target_properties(draco_maya_wrapper - PROPERTIES SOVERSION ${DRACO_SOVERSION}) endif() endif() diff --git a/contrib/draco/README.md b/contrib/draco/README.md index add66edcb..0d980b387 100644 --- a/contrib/draco/README.md +++ b/contrib/draco/README.md @@ -2,16 +2,16 @@

-![Build Status: master](https://travis-ci.org/google/draco.svg?branch=master) +[![Build Status](https://github.com/google/draco/workflows/Build/badge.svg)](https://github.com/google/draco/actions?query=workflow%3ABuild) News ======= ### Version 1.4.1 release -* Using the versioned gstatic.com WASM and Javascript decoders is now +* Using the versioned www.gstatic.com WASM and Javascript decoders is now recommended. To use v1.4.1, use this URL: * https://www.gstatic.com/draco/versioned/decoders/1.4.1/* * Replace the * with the files to load. E.g. - * https://gstatic.com/draco/versioned/decoders/1.4.1/draco_decoder.js + * https://www.gstatic.com/draco/versioned/decoders/1.4.1/draco_decoder.js * This works with the v1.3.6 and v1.4.0 releases, and will work with future Draco releases. * Bug fixes diff --git a/contrib/draco/cmake/draco_build_definitions.cmake b/contrib/draco/cmake/draco_build_definitions.cmake index c1ada6206..f7354c15f 100644 --- a/contrib/draco/cmake/draco_build_definitions.cmake +++ b/contrib/draco/cmake/draco_build_definitions.cmake @@ -6,7 +6,7 @@ set(DRACO_CMAKE_DRACO_BUILD_DEFINITIONS_CMAKE_ 1) # Utility for controlling the main draco library dependency. This changes in # shared builds, and when an optional target requires a shared library build. macro(set_draco_target) - if(MSVC OR WIN32) + if(MSVC) set(draco_dependency draco) set(draco_plugin_dependency ${draco_dependency}) else() @@ -63,6 +63,11 @@ macro(draco_set_build_definitions) if(BUILD_SHARED_LIBS) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) endif() + else() + if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) + # Ensure 64-bit platforms can support large files. + list(APPEND draco_defines "_LARGEFILE_SOURCE" "_FILE_OFFSET_BITS=64") + endif() endif() if(ANDROID) @@ -114,4 +119,6 @@ macro(draco_set_build_definitions) draco_check_emscripten_environment() draco_get_required_emscripten_flags(FLAG_LIST_VAR draco_base_cxx_flags) endif() + + draco_configure_sanitizer() endmacro() diff --git a/contrib/draco/cmake/draco_features.cmake b/contrib/draco/cmake/draco_features.cmake deleted file mode 100644 index be444bf24..000000000 --- a/contrib/draco/cmake/draco_features.cmake +++ /dev/null @@ -1,63 +0,0 @@ -if(DRACO_CMAKE_DRACO_FEATURES_CMAKE_) - return() -endif() -set(DRACO_CMAKE_DRACO_FEATURES_CMAKE_ 1) - -set(draco_features_file_name "${draco_build_dir}/draco/draco_features.h") -set(draco_features_list) - -# Macro that handles tracking of Draco preprocessor symbols for the purpose of -# producing draco_features.h. -# -# draco_enable_feature(FEATURE [TARGETS ]) FEATURE -# is required. It should be a Draco preprocessor symbol. TARGETS is optional. It -# can be one or more draco targets. -# -# When the TARGETS argument is not present the preproc symbol is added to -# draco_features.h. When it is draco_features.h is unchanged, and -# target_compile_options() is called for each target specified. -macro(draco_enable_feature) - set(def_flags) - set(def_single_arg_opts FEATURE) - set(def_multi_arg_opts TARGETS) - cmake_parse_arguments(DEF "${def_flags}" "${def_single_arg_opts}" - "${def_multi_arg_opts}" ${ARGN}) - if("${DEF_FEATURE}" STREQUAL "") - message(FATAL_ERROR "Empty FEATURE passed to draco_enable_feature().") - endif() - - # Do nothing/return early if $DEF_FEATURE is already in the list. - list(FIND draco_features_list ${DEF_FEATURE} df_index) - if(NOT df_index EQUAL -1) - return() - endif() - - list(LENGTH DEF_TARGETS df_targets_list_length) - if(${df_targets_list_length} EQUAL 0) - list(APPEND draco_features_list ${DEF_FEATURE}) - else() - foreach(target ${DEF_TARGETS}) - target_compile_definitions(${target} PRIVATE ${DEF_FEATURE}) - endforeach() - endif() -endmacro() - -# Function for generating draco_features.h. -function(draco_generate_features_h) - file(WRITE "${draco_features_file_name}.new" - "// GENERATED FILE -- DO NOT EDIT\n\n" "#ifndef DRACO_FEATURES_H_\n" - "#define DRACO_FEATURES_H_\n\n") - - foreach(feature ${draco_features_list}) - file(APPEND "${draco_features_file_name}.new" "#define ${feature}\n") - endforeach() - - file(APPEND "${draco_features_file_name}.new" - "\n#endif // DRACO_FEATURES_H_") - - # Will replace ${draco_features_file_name} only if the file content has - # changed. This prevents forced Draco rebuilds after CMake runs. - configure_file("${draco_features_file_name}.new" - "${draco_features_file_name}") - file(REMOVE "${draco_features_file_name}.new") -endfunction() diff --git a/contrib/draco/cmake/draco_flags.cmake b/contrib/draco/cmake/draco_flags.cmake index cb9d489e6..0397859a4 100644 --- a/contrib/draco/cmake/draco_flags.cmake +++ b/contrib/draco/cmake/draco_flags.cmake @@ -80,6 +80,12 @@ macro(draco_test_cxx_flag) # Run the actual compile test. unset(draco_all_cxx_flags_pass CACHE) message("--- Running combined CXX flags test, flags: ${all_cxx_flags}") + + # check_cxx_compiler_flag() requires that the flags are a string. When flags + # are passed as a list it will remove the list separators, and attempt to run + # a compile command using list entries concatenated together as a single + # argument. Avoid the problem by forcing the argument to be a string. + draco_set_and_stringify(SOURCE_VARS all_cxx_flags DEST all_cxx_flags) check_cxx_compiler_flag("${all_cxx_flags}" draco_all_cxx_flags_pass) if(cxx_test_FLAG_REQUIRED AND NOT draco_all_cxx_flags_pass) @@ -194,6 +200,9 @@ macro(draco_test_exe_linker_flag) else() unset(CMAKE_EXE_LINKER_FLAGS) endif() + + list(APPEND DRACO_EXE_LINKER_FLAGS ${${link_FLAG_LIST_VAR_NAME}}) + list(REMOVE_DUPLICATES DRACO_EXE_LINKER_FLAGS) endmacro() # Runs the draco compiler tests. This macro builds up the list of list var(s) diff --git a/contrib/draco/cmake/draco_install.cmake b/contrib/draco/cmake/draco_install.cmake index 5c63ecb4a..09bfb591d 100644 --- a/contrib/draco/cmake/draco_install.cmake +++ b/contrib/draco/cmake/draco_install.cmake @@ -55,7 +55,7 @@ macro(draco_setup_install_target) install(TARGETS draco_encoder DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}") - if(WIN32) + if(MSVC) install(TARGETS draco DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") else() diff --git a/contrib/draco/cmake/draco_sanitizer.cmake b/contrib/draco/cmake/draco_sanitizer.cmake index ca8e23176..d2e41a6cb 100644 --- a/contrib/draco/cmake/draco_sanitizer.cmake +++ b/contrib/draco/cmake/draco_sanitizer.cmake @@ -5,28 +5,28 @@ set(DRACO_CMAKE_DRACO_SANITIZER_CMAKE_ 1) # Handles the details of enabling sanitizers. macro(draco_configure_sanitizer) - if(DRACO_SANITIZE AND NOT MSVC) + if(DRACO_SANITIZE AND NOT EMSCRIPTEN AND NOT MSVC) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") if(DRACO_SANITIZE MATCHES "cfi") - list(APPEND DRACO_CXX_FLAGS "-flto" "-fno-sanitize-trap=cfi") - list(APPEND DRACO_EXE_LINKER_FLAGS "-flto" "-fno-sanitize-trap=cfi" + list(APPEND SAN_CXX_FLAGS "-flto" "-fno-sanitize-trap=cfi") + list(APPEND SAN_LINKER_FLAGS "-flto" "-fno-sanitize-trap=cfi" "-fuse-ld=gold") endif() if(${CMAKE_SIZEOF_VOID_P} EQUAL 4 AND DRACO_SANITIZE MATCHES "integer|undefined") - list(APPEND DRACO_EXE_LINKER_FLAGS "--rtlib=compiler-rt" "-lgcc_s") + list(APPEND SAN_LINKER_FLAGS "--rtlib=compiler-rt" "-lgcc_s") endif() endif() - list(APPEND DRACO_CXX_FLAGS "-fsanitize=${DRACO_SANITIZE}") - list(APPEND DRACO_EXE_LINKER_FLAGS "-fsanitize=${DRACO_SANITIZE}") + list(APPEND SAN_CXX_FLAGS "-fsanitize=${DRACO_SANITIZE}") + list(APPEND SAN_LINKER_FLAGS "-fsanitize=${DRACO_SANITIZE}") # Make sanitizer callstacks accurate. - list(APPEND DRACO_CXX_FLAGS "-fno-omit-frame-pointer" - "-fno-optimize-sibling-calls") + list(APPEND SAN_CXX_FLAGS "-fno-omit-frame-pointer") + list(APPEND SAN_CXX_FLAGS "-fno-optimize-sibling-calls") - draco_test_cxx_flag(FLAG_LIST_VAR_NAMES DRACO_CXX_FLAGS FLAG_REQUIRED) - draco_test_exe_linker_flag(FLAG_LIST_VAR_NAME DRACO_EXE_LINKER_FLAGS) + draco_test_cxx_flag(FLAG_LIST_VAR_NAMES SAN_CXX_FLAGS FLAG_REQUIRED) + draco_test_exe_linker_flag(FLAG_LIST_VAR_NAME SAN_LINKER_FLAGS) endif() endmacro() diff --git a/contrib/draco/cmake/draco_targets.cmake b/contrib/draco/cmake/draco_targets.cmake index 6dfa6a0c4..0456c4d7b 100644 --- a/contrib/draco/cmake/draco_targets.cmake +++ b/contrib/draco/cmake/draco_targets.cmake @@ -87,6 +87,7 @@ macro(draco_add_executable) endif() add_executable(${exe_NAME} ${exe_SOURCES}) + set_target_properties(${exe_NAME} PROPERTIES VERSION ${DRACO_VERSION}) if(exe_OUTPUT_NAME) set_target_properties(${exe_NAME} PROPERTIES OUTPUT_NAME ${exe_OUTPUT_NAME}) @@ -109,10 +110,11 @@ macro(draco_add_executable) if(exe_LINK_FLAGS OR DRACO_EXE_LINKER_FLAGS) if(${CMAKE_VERSION} VERSION_LESS "3.13") - set(link_flags ${exe_LINK_FLAGS} ${DRACO_EXE_LINKER_FLAGS}) + list(APPEND exe_LINK_FLAGS "${DRACO_EXE_LINKER_FLAGS}") + # LINK_FLAGS is managed as a string. + draco_set_and_stringify(SOURCE "${exe_LINK_FLAGS}" DEST exe_LINK_FLAGS) set_target_properties(${exe_NAME} - PROPERTIES LINK_FLAGS ${exe_LINK_FLAGS} - ${DRACO_EXE_LINKER_FLAGS}) + PROPERTIES LINK_FLAGS "${exe_LINK_FLAGS}") else() target_link_options(${exe_NAME} PRIVATE ${exe_LINK_FLAGS} ${DRACO_EXE_LINKER_FLAGS}) @@ -130,7 +132,7 @@ macro(draco_add_executable) endif() if(BUILD_SHARED_LIBS AND (MSVC OR WIN32)) - target_compile_definitions(${lib_NAME} PRIVATE "DRACO_BUILDING_DLL=0") + target_compile_definitions(${exe_NAME} PRIVATE "DRACO_BUILDING_DLL=0") endif() if(exe_LIB_DEPS) @@ -163,8 +165,8 @@ endmacro() # cmake-format: off # - OUTPUT_NAME: Override output file basename. Target basename defaults to # NAME. OUTPUT_NAME is ignored when BUILD_SHARED_LIBS is enabled and CMake -# is generating a build for which MSVC or WIN32 are true. This is to avoid -# output basename collisions with DLL import libraries. +# is generating a build for which MSVC is true. This is to avoid output +# basename collisions with DLL import libraries. # - TEST: Flag. Presence means treat library as a test. # - DEFINES: List of preprocessor macro definitions. # - INCLUDES: list of include directories for the target. @@ -259,7 +261,7 @@ macro(draco_add_library) endif() if(lib_OUTPUT_NAME) - if(NOT (BUILD_SHARED_LIBS AND (MSVC OR WIN32))) + if(NOT (BUILD_SHARED_LIBS AND MSVC)) set_target_properties(${lib_NAME} PROPERTIES OUTPUT_NAME ${lib_OUTPUT_NAME}) endif() @@ -318,8 +320,12 @@ macro(draco_add_library) set_target_properties(${lib_NAME} PROPERTIES PREFIX "") endif() - if(lib_TYPE STREQUAL SHARED AND NOT MSVC) - set_target_properties(${lib_NAME} PROPERTIES SOVERSION ${DRACO_SOVERSION}) + # VERSION and SOVERSION as necessary + if(NOT lib_TYPE STREQUAL STATIC AND NOT lib_TYPE STREQUAL MODULE) + set_target_properties(${lib_NAME} PROPERTIES VERSION ${DRACO_VERSION}) + if(NOT MSVC) + set_target_properties(${lib_NAME} PROPERTIES SOVERSION ${DRACO_SOVERSION}) + endif() endif() if(BUILD_SHARED_LIBS AND (MSVC OR WIN32)) diff --git a/contrib/draco/src/draco/core/cycle_timer.cc b/contrib/draco/src/draco/core/cycle_timer.cc index 94b4b28b2..58df4df77 100644 --- a/contrib/draco/src/draco/core/cycle_timer.cc +++ b/contrib/draco/src/draco/core/cycle_timer.cc @@ -17,31 +17,31 @@ namespace draco { void DracoTimer::Start() { #ifdef _WIN32 - QueryPerformanceCounter(&tv_start); + QueryPerformanceCounter(&tv_start_); #else - gettimeofday(&tv_start, nullptr); + gettimeofday(&tv_start_, nullptr); #endif } void DracoTimer::Stop() { #ifdef _WIN32 - QueryPerformanceCounter(&tv_end); + QueryPerformanceCounter(&tv_end_); #else - gettimeofday(&tv_end, nullptr); + gettimeofday(&tv_end_, nullptr); #endif } int64_t DracoTimer::GetInMs() { #ifdef _WIN32 LARGE_INTEGER elapsed = {0}; - elapsed.QuadPart = tv_end.QuadPart - tv_start.QuadPart; + elapsed.QuadPart = tv_end_.QuadPart - tv_start_.QuadPart; LARGE_INTEGER frequency = {0}; QueryPerformanceFrequency(&frequency); return elapsed.QuadPart * 1000 / frequency.QuadPart; #else - const int64_t seconds = (tv_end.tv_sec - tv_start.tv_sec) * 1000; - const int64_t milliseconds = (tv_end.tv_usec - tv_start.tv_usec) / 1000; + const int64_t seconds = (tv_end_.tv_sec - tv_start_.tv_sec) * 1000; + const int64_t milliseconds = (tv_end_.tv_usec - tv_start_.tv_usec) / 1000; return seconds + milliseconds; #endif } diff --git a/contrib/draco/src/draco/core/cycle_timer.h b/contrib/draco/src/draco/core/cycle_timer.h index 172f1c2e9..f480cc9d3 100644 --- a/contrib/draco/src/draco/core/cycle_timer.h +++ b/contrib/draco/src/draco/core/cycle_timer.h @@ -20,9 +20,10 @@ #define WIN32_LEAN_AND_MEAN #endif #include -typedef LARGE_INTEGER timeval; +typedef LARGE_INTEGER DracoTimeVal; #else #include +typedef timeval DracoTimeVal; #endif #include @@ -39,8 +40,8 @@ class DracoTimer { int64_t GetInMs(); private: - timeval tv_start; - timeval tv_end; + DracoTimeVal tv_start_; + DracoTimeVal tv_end_; }; typedef DracoTimer CycleTimer; diff --git a/contrib/draco/src/draco/io/parser_utils.cc b/contrib/draco/src/draco/io/parser_utils.cc index 4f95f6f84..12afacff6 100644 --- a/contrib/draco/src/draco/io/parser_utils.cc +++ b/contrib/draco/src/draco/io/parser_utils.cc @@ -18,6 +18,7 @@ #include #include #include +#include namespace draco { namespace parser { @@ -252,7 +253,7 @@ DecoderBuffer ParseLineIntoDecoderBuffer(DecoderBuffer *buffer) { std::string ToLower(const std::string &str) { std::string out; - std::transform(str.begin(), str.end(), std::back_inserter(out), [](unsigned char c){return tolower(c);}); + std::transform(str.begin(), str.end(), std::back_inserter(out), tolower); return out; } diff --git a/contrib/draco/src/draco/io/ply_reader.cc b/contrib/draco/src/draco/io/ply_reader.cc index cb32df225..ea7f2689a 100644 --- a/contrib/draco/src/draco/io/ply_reader.cc +++ b/contrib/draco/src/draco/io/ply_reader.cc @@ -268,14 +268,14 @@ std::vector PlyReader::SplitWords(const std::string &line) { while ((end = line.find_first_of(" \t\n\v\f\r", start)) != std::string::npos) { const std::string word(line.substr(start, end - start)); - if (!std::all_of(word.begin(), word.end(), [](unsigned char c){return isspace(c);})) { + if (!std::all_of(word.begin(), word.end(), isspace)) { output.push_back(word); } start = end + 1; } const std::string last_word(line.substr(start)); - if (!std::all_of(last_word.begin(), last_word.end(), [](unsigned char c){return isspace(c);})) { + if (!std::all_of(last_word.begin(), last_word.end(), isspace)) { output.push_back(last_word); } return output; diff --git a/contrib/draco/src/draco/io/stdio_file_reader.cc b/contrib/draco/src/draco/io/stdio_file_reader.cc index 560c3e9e8..a99c96f8f 100644 --- a/contrib/draco/src/draco/io/stdio_file_reader.cc +++ b/contrib/draco/src/draco/io/stdio_file_reader.cc @@ -87,7 +87,14 @@ size_t StdioFileReader::GetFileSize() { return false; } +#if _FILE_OFFSET_BITS == 64 + const size_t file_size = static_cast(ftello(file_)); +#elif defined _WIN64 + const size_t file_size = static_cast(_ftelli64(file_)); +#else const size_t file_size = static_cast(ftell(file_)); +#endif + rewind(file_); return file_size; From f13515a39109f717c13ee1201e9000da6eab786a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Verdon?= Date: Sun, 23 May 2021 19:06:16 +0200 Subject: [PATCH 3/4] Adding basic support for lights in FBX exporter --- code/AssetLib/FBX/FBXExporter.cpp | 77 +++++++++++++++++++++++++++++-- code/AssetLib/FBX/FBXExporter.h | 2 + 2 files changed, 74 insertions(+), 5 deletions(-) diff --git a/code/AssetLib/FBX/FBXExporter.cpp b/code/AssetLib/FBX/FBXExporter.cpp index e519f7e77..f2cae00b2 100644 --- a/code/AssetLib/FBX/FBXExporter.cpp +++ b/code/AssetLib/FBX/FBXExporter.cpp @@ -2196,7 +2196,65 @@ void FBXExporter::WriteObjects () bpnode.Dump(outstream, binary, indent); }*/ - // TODO: cameras, lights + // lights + indent = 1; + lights_uids.clear(); + for (size_t li = 0; li < mScene->mNumLights; ++li) { + aiLight* l = mScene->mLights[li]; + + int64_t uid = generate_uid(); + const std::string lightNodeAttributeName = l->mName.C_Str() + FBX::SEPARATOR + "NodeAttribute"; + + FBX::Node lna("NodeAttribute"); + lna.AddProperties(uid, lightNodeAttributeName, "Light"); + FBX::Node lnap("Properties70"); + + // Light color. + lnap.AddP70colorA("Color", l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b); + + // TODO Assimp light description is quite concise and do not handle light intensity. + // Default value to 1000W. + lnap.AddP70numberA("Intensity", 1000); + + // FBXLight::EType conversion + switch (l->mType) { + case aiLightSource_POINT: + lnap.AddP70enum("LightType", 0); + break; + case aiLightSource_DIRECTIONAL: + lnap.AddP70enum("LightType", 1); + break; + case aiLightSource_SPOT: + lnap.AddP70enum("LightType", 2); + lnap.AddP70numberA("InnerAngle", AI_RAD_TO_DEG(l->mAngleInnerCone)); + lnap.AddP70numberA("OuterAngle", AI_RAD_TO_DEG(l->mAngleOuterCone)); + break; + // TODO Assimp do not handle 'area' nor 'volume' lights, but FBX does. + /*case aiLightSource_AREA: + lnap.AddP70enum("LightType", 3); + lnap.AddP70enum("AreaLightShape", 0); // 0=Rectangle, 1=Sphere + break; + case aiLightSource_VOLUME: + lnap.AddP70enum("LightType", 4); + break;*/ + default: + break; + } + + // Did not understood how to configure the decay so disabling attenuation. + lnap.AddP70enum("DecayType", 0); + + // Dump to FBX stream + lna.AddChild(lnap); + lna.AddChild("TypeFlags", FBX::FBXExportProperty("Light")); + lna.AddChild("GeometryVersion", FBX::FBXExportProperty(int32_t(124))); + lna.Dump(outstream, binary, indent); + + // Store name and uid (will be used later when parsing scene nodes) + lights_uids[l->mName.C_Str()] = uid; + } + + // TODO: cameras // write nodes (i.e. model hierarchy) // start at root node @@ -2600,10 +2658,19 @@ void FBXExporter::WriteModelNodes( // and connect them connections.emplace_back("C", "OO", node_attribute_uid, node_uid); } else { - // generate a null node so we can add children to it - WriteModelNode( - outstream, binary, node, node_uid, "Null", transform_chain - ); + const auto& lightIt = lights_uids.find(node->mName.C_Str()); + if(lightIt != lights_uids.end()) { + // Node has a light connected to it. + WriteModelNode( + outstream, binary, node, node_uid, "Light", transform_chain + ); + connections.emplace_back("C", "OO", lightIt->second, node_uid); + } else { + // generate a null node so we can add children to it + WriteModelNode( + outstream, binary, node, node_uid, "Null", transform_chain + ); + } } // if more than one child mesh, make nodes for each mesh diff --git a/code/AssetLib/FBX/FBXExporter.h b/code/AssetLib/FBX/FBXExporter.h index dcd1d2727..563183268 100644 --- a/code/AssetLib/FBX/FBXExporter.h +++ b/code/AssetLib/FBX/FBXExporter.h @@ -63,6 +63,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct aiScene; struct aiNode; +struct aiLight; //struct aiMaterial; namespace Assimp @@ -95,6 +96,7 @@ namespace Assimp std::vector mesh_uids; std::vector material_uids; std::map node_uids; + std::map lights_uids; // this crude unique-ID system is actually fine int64_t last_uid = 999999; From 444fc9c373ae3fb407bc4bfe3a6c5558175e3fba Mon Sep 17 00:00:00 2001 From: Scott Baldric Date: Tue, 1 Jun 2021 17:08:26 -0500 Subject: [PATCH 4/4] Increasing length of mDataLength if rewriting the texture index increases magnitutde of index. --- code/Common/SceneCombiner.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/code/Common/SceneCombiner.cpp b/code/Common/SceneCombiner.cpp index 555d46b6a..8f10d6308 100644 --- a/code/Common/SceneCombiner.cpp +++ b/code/Common/SceneCombiner.cpp @@ -406,11 +406,25 @@ void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vector, // where n is the index of the texture. - aiString &s = *((aiString *)prop->mData); + // Copy here because we overwrite the string data in-place and the buffer inside of aiString + // will be a lie if we just reinterpret from prop->mData. The size of mData is not guaranteed to be + // MAXLEN in size. + aiString s(*(aiString *)prop->mData); if ('*' == s.data[0]) { // Offset the index and write it back .. const unsigned int idx = strtoul10(&s.data[1]) + offset[n]; - ASSIMP_itoa10(&s.data[1], sizeof(s.data) - 1, idx); + const unsigned int oldLen = s.length; + + s.length = 1 + ASSIMP_itoa10(&s.data[1], sizeof(s.data) - 1, idx); + + // The string changed in size so we need to reallocate the buffer for the property. + if (oldLen < s.length) { + prop->mDataLength += s.length - oldLen; + delete[] prop->mData; + prop->mData = new char[prop->mDataLength]; + } + + memcpy(prop->mData, static_cast(&s), prop->mDataLength); } }